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";
697 os << "\\bulletLaTeX " << i << " \""
698 << user_defined_bullet(i).getText()
704 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
705 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
708 // FIXME: Change tracking (MG)
709 AuthorList::Authors::const_iterator it = pimpl_->authorlist.begin();
710 AuthorList::Authors::const_iterator end = pimpl_->authorlist.end();
711 for (; it != end; ++it) {
712 os << "\\author " << it->second << "\n";
718 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
719 TexRow & texrow) const
721 os << "\\documentclass";
723 LyXTextClass const & tclass = getLyXTextClass();
725 ostringstream clsoptions; // the document class options.
727 if (tokenPos(tclass.opt_fontsize(),
728 '|', fontsize) >= 0) {
729 // only write if existing in list (and not default)
730 clsoptions << fontsize << "pt,";
733 // custom, A3, B3 and B4 paper sizes need geometry
734 bool nonstandard_papersize = (papersize == PAPER_B3) ||
735 (papersize == PAPER_B4) ||
736 (papersize == PAPER_A3) ||
737 (papersize == PAPER_CUSTOM);
742 clsoptions << "a4paper,";
745 clsoptions << "letterpaper,";
748 clsoptions << "a5paper,";
751 clsoptions << "b5paper,";
753 case PAPER_USEXECUTIVE:
754 clsoptions << "executivepaper,";
757 clsoptions << "legalpaper,";
769 if (sides != tclass.sides()) {
771 case LyXTextClass::OneSide:
772 clsoptions << "oneside,";
774 case LyXTextClass::TwoSides:
775 clsoptions << "twoside,";
781 if (columns != tclass.columns()) {
783 clsoptions << "twocolumn,";
785 clsoptions << "onecolumn,";
789 && orientation == ORIENTATION_LANDSCAPE)
790 clsoptions << "landscape,";
792 // language should be a parameter to \documentclass
793 if (language->babel() == "hebrew"
794 && default_language->babel() != "hebrew")
795 // This seems necessary
796 features.useLanguage(default_language);
798 ostringstream language_options;
799 bool const use_babel = features.useBabel();
801 language_options << features.getLanguages();
802 language_options << language->babel();
803 if (lyxrc.language_global_options)
804 clsoptions << language_options.str() << ',';
807 // the user-defined options
808 if (!options.empty()) {
809 clsoptions << options << ',';
812 string strOptions(clsoptions.str());
813 if (!strOptions.empty()) {
814 strOptions = rtrim(strOptions, ",");
816 os << '[' << lyx::from_utf8(strOptions) << ']';
819 os << '{' << lyx::from_ascii(tclass.latexname()) << "}\n";
821 // end of \documentclass defs
823 // font selection must be done before loading fontenc.sty
825 loadFonts(features, fontsRoman, fontsSans,
826 fontsTypewriter, fontsSC, fontsOSF,
827 fontsSansScale, fontsTypewriterScale);
828 if (!fonts.empty()) {
829 os << lyx::from_ascii(fonts);
832 if (fontsDefaultFamily != "default")
833 os << "\\renewcommand{\\familydefault}{\\"
834 << lyx::from_ascii(fontsDefaultFamily) << "}\n";
835 // this one is not per buffer
836 if (lyxrc.fontenc != "default") {
837 os << "\\usepackage[" << lyx::from_ascii(lyxrc.fontenc)
842 // TODO: Some people want to support more encodings than UTF-8. They can have a field day around here
844 os << "\\usepackage[utf8]{inputenc}\n";
847 if (inputenc == "auto") {
848 string const doc_encoding =
849 language->encoding()->latexName();
851 // Create a list with all the input encodings used
853 std::set<string> encodings =
854 features.getEncodingSet(doc_encoding);
856 os << "\\usepackage[";
857 std::set<string>::const_iterator it = encodings.begin();
858 std::set<string>::const_iterator const end = encodings.end();
859 for (; it != end; ++it)
860 os << lyx::from_ascii(*it) << ',';
861 os << lyx::from_ascii(doc_encoding) << "]{inputenc}\n";
863 } else if (inputenc != "default") {
864 os << "\\usepackage[" << lyx::from_ascii(inputenc)
870 if (use_geometry || nonstandard_papersize) {
871 os << "\\usepackage{geometry}\n";
873 os << "\\geometry{verbose";
874 if (orientation == ORIENTATION_LANDSCAPE)
878 if (!paperwidth.empty())
880 << lyx::from_ascii(paperwidth);
881 if (!paperheight.empty())
882 os << ",paperheight="
883 << lyx::from_ascii(paperheight);
886 os << ",letterpaper";
891 case PAPER_USEXECUTIVE:
892 os << ",executivepaper";
913 // default papersize ie PAPER_DEFAULT
914 switch (lyxrc.default_papersize) {
915 case PAPER_DEFAULT: // keep compiler happy
917 os << ",letterpaper";
922 case PAPER_USEXECUTIVE:
923 os << ",executivepaper";
943 if (!topmargin.empty())
944 os << ",tmargin=" << lyx::from_ascii(topmargin);
945 if (!bottommargin.empty())
946 os << ",bmargin=" << lyx::from_ascii(bottommargin);
947 if (!leftmargin.empty())
948 os << ",lmargin=" << lyx::from_ascii(leftmargin);
949 if (!rightmargin.empty())
950 os << ",rmargin=" << lyx::from_ascii(rightmargin);
951 if (!headheight.empty())
952 os << ",headheight=" << lyx::from_ascii(headheight);
953 if (!headsep.empty())
954 os << ",headsep=" << lyx::from_ascii(headsep);
955 if (!footskip.empty())
956 os << ",footskip=" << lyx::from_ascii(footskip);
961 if (tokenPos(tclass.opt_pagestyle(),
962 '|', pagestyle) >= 0) {
963 if (pagestyle == "fancy") {
964 os << "\\usepackage{fancyhdr}\n";
967 os << "\\pagestyle{" << lyx::from_ascii(pagestyle) << "}\n";
971 // Only if class has a ToC hierarchy
972 if (tclass.hasTocLevels()) {
973 if (secnumdepth != tclass.secnumdepth()) {
974 os << "\\setcounter{secnumdepth}{"
979 if (tocdepth != tclass.tocdepth()) {
980 os << "\\setcounter{tocdepth}{"
987 if (paragraph_separation) {
988 switch (getDefSkip().kind()) {
989 case VSpace::SMALLSKIP:
990 os << "\\setlength\\parskip{\\smallskipamount}\n";
992 case VSpace::MEDSKIP:
993 os << "\\setlength\\parskip{\\medskipamount}\n";
995 case VSpace::BIGSKIP:
996 os << "\\setlength\\parskip{\\bigskipamount}\n";
999 os << "\\setlength\\parskip{"
1000 << lyx::from_ascii(getDefSkip().length().asLatexString())
1003 default: // should never happen // Then delete it.
1004 os << "\\setlength\\parskip{\\medskipamount}\n";
1009 os << "\\setlength\\parindent{0pt}\n";
1013 // If we use jurabib, we have to call babel here.
1014 if (use_babel && features.isRequired("jurabib")) {
1015 os << lyx::from_ascii(babelCall(language_options.str()))
1017 << lyx::from_ascii(features.getBabelOptions());
1021 // Now insert the LyX specific LaTeX commands...
1023 // The optional packages;
1024 string lyxpreamble(features.getPackages());
1026 // this might be useful...
1027 lyxpreamble += "\n\\makeatletter\n";
1029 // Some macros LyX will need
1030 string tmppreamble(features.getMacros());
1032 if (!tmppreamble.empty()) {
1033 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1034 "LyX specific LaTeX commands.\n"
1035 + tmppreamble + '\n';
1038 // the text class specific preamble
1039 tmppreamble = features.getTClassPreamble();
1040 if (!tmppreamble.empty()) {
1041 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1042 "Textclass specific LaTeX commands.\n"
1043 + tmppreamble + '\n';
1046 /* the user-defined preamble */
1047 if (!preamble.empty()) {
1048 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1049 "User specified LaTeX commands.\n"
1053 // Itemize bullet settings need to be last in case the user
1054 // defines their own bullets that use a package included
1055 // in the user-defined preamble -- ARRae
1056 // Actually it has to be done much later than that
1057 // since some packages like frenchb make modifications
1058 // at \begin{document} time -- JMarc
1060 for (int i = 0; i < 4; ++i) {
1061 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1062 if (bullets_def.empty())
1063 bullets_def="\\AtBeginDocument{\n";
1064 bullets_def += " \\def\\labelitemi";
1066 // `i' is one less than the item to modify
1073 bullets_def += "ii";
1079 bullets_def += '{' +
1080 user_defined_bullet(i).getText()
1085 if (!bullets_def.empty())
1086 lyxpreamble += bullets_def + "}\n\n";
1088 // We try to load babel late, in case it interferes
1089 // with other packages.
1090 // Jurabib has to be called after babel, though.
1091 if (use_babel && !features.isRequired("jurabib")) {
1092 lyxpreamble += babelCall(language_options.str()) + '\n';
1093 lyxpreamble += features.getBabelOptions();
1096 lyxpreamble += "\\makeatother\n";
1098 // dvipost settings come after everything else
1099 if (features.isAvailable("dvipost") && outputChanges) {
1102 "\\dvipost{osstart color push Red}\n"
1103 "\\dvipost{osend color pop}\n"
1104 "\\dvipost{cbstart color push Blue}\n"
1105 "\\dvipost{cbend color pop}\n";
1109 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1110 for (int j = 0; j != nlines; ++j) {
1115 os << lyx::from_utf8(lyxpreamble);
1120 void BufferParams::useClassDefaults()
1122 LyXTextClass const & tclass = textclasslist[textclass];
1124 sides = tclass.sides();
1125 columns = tclass.columns();
1126 pagestyle = tclass.pagestyle();
1127 options = tclass.options();
1128 // Only if class has a ToC hierarchy
1129 if (tclass.hasTocLevels()) {
1130 secnumdepth = tclass.secnumdepth();
1131 tocdepth = tclass.tocdepth();
1136 bool BufferParams::hasClassDefaults() const
1138 LyXTextClass const & tclass = textclasslist[textclass];
1140 return (sides == tclass.sides()
1141 && columns == tclass.columns()
1142 && pagestyle == tclass.pagestyle()
1143 && options == tclass.options()
1144 && secnumdepth == tclass.secnumdepth()
1145 && tocdepth == tclass.tocdepth());
1149 LyXTextClass const & BufferParams::getLyXTextClass() const
1151 return textclasslist[textclass];
1155 LyXFont const BufferParams::getFont() const
1157 LyXFont f = getLyXTextClass().defaultfont();
1158 f.setLanguage(language);
1159 if (fontsDefaultFamily == "rmdefault")
1160 f.setFamily(LyXFont::ROMAN_FAMILY);
1161 else if (fontsDefaultFamily == "sfdefault")
1162 f.setFamily(LyXFont::SANS_FAMILY);
1163 else if (fontsDefaultFamily == "ttdefault")
1164 f.setFamily(LyXFont::TYPEWRITER_FAMILY);
1169 void BufferParams::readPreamble(LyXLex & lex)
1171 if (lex.getString() != "\\begin_preamble")
1172 lyxerr << "Error (BufferParams::readPreamble):"
1173 "consistency check failed." << endl;
1175 preamble = lex.getLongString("\\end_preamble");
1179 void BufferParams::readLanguage(LyXLex & lex)
1181 if (!lex.next()) return;
1183 string const tmptok = lex.getString();
1185 // check if tmptok is part of tex_babel in tex-defs.h
1186 language = languages.getLanguage(tmptok);
1188 // Language tmptok was not found
1189 language = default_language;
1190 lyxerr << "Warning: Setting language `"
1191 << tmptok << "' to `" << language->lang()
1197 void BufferParams::readGraphicsDriver(LyXLex & lex)
1199 if (!lex.next()) return;
1201 string const tmptok = lex.getString();
1202 // check if tmptok is part of tex_graphics in tex_defs.h
1205 string const test = tex_graphics[n++];
1207 if (test == tmptok) {
1208 graphicsDriver = tmptok;
1210 } else if (test == "") {
1212 "Warning: graphics driver `$$Token' not recognized!\n"
1213 " Setting graphics driver to `default'.\n");
1214 graphicsDriver = "default";
1221 void BufferParams::readBullets(LyXLex & lex)
1223 if (!lex.next()) return;
1225 int const index = lex.getInteger();
1227 int temp_int = lex.getInteger();
1228 user_defined_bullet(index).setFont(temp_int);
1229 temp_bullet(index).setFont(temp_int);
1231 user_defined_bullet(index).setCharacter(temp_int);
1232 temp_bullet(index).setCharacter(temp_int);
1234 user_defined_bullet(index).setSize(temp_int);
1235 temp_bullet(index).setSize(temp_int);
1239 void BufferParams::readBulletsLaTeX(LyXLex & lex)
1241 // The bullet class should be able to read this.
1242 if (!lex.next()) return;
1243 int const index = lex.getInteger();
1245 string const temp_str = lex.getString();
1247 user_defined_bullet(index).setText(temp_str);
1248 temp_bullet(index).setText(temp_str);
1252 string const BufferParams::paperSizeName() const
1254 char real_papersize = papersize;
1255 if (real_papersize == PAPER_DEFAULT)
1256 real_papersize = lyxrc.default_papersize;
1258 switch (real_papersize) {
1267 case PAPER_USEXECUTIVE:
1271 case PAPER_USLETTER:
1278 string const BufferParams::dvips_options() const
1283 && papersize == PAPER_CUSTOM
1284 && !lyxrc.print_paper_dimension_flag.empty()
1285 && !paperwidth.empty()
1286 && !paperheight.empty()) {
1287 // using a custom papersize
1288 result = lyxrc.print_paper_dimension_flag;
1289 result += ' ' + paperwidth;
1290 result += ',' + paperheight;
1292 string const paper_option = paperSizeName();
1293 if (paper_option != "letter" ||
1294 orientation != ORIENTATION_LANDSCAPE) {
1295 // dvips won't accept -t letter -t landscape.
1296 // In all other cases, include the paper size
1298 result = lyxrc.print_paper_flag;
1299 result += ' ' + paper_option;
1302 if (orientation == ORIENTATION_LANDSCAPE &&
1303 papersize != PAPER_CUSTOM)
1304 result += ' ' + lyxrc.print_landscape_flag;
1309 string const BufferParams::babelCall(string const & lang_opts) const
1311 string tmp = lyxrc.language_package;
1312 if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1313 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1318 string const BufferParams::loadFonts(LaTeXFeatures & features, string const & rm,
1319 string const & sf, string const & tt,
1320 bool const & sc, bool const & osf,
1321 int const & sfscale, int const & ttscale) const
1323 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1324 several packages have been replaced by others, that might not
1325 be installed on every system. We have to take care for that
1326 (see psnfss.pdf). We try to support all psnfss fonts as well
1327 as the fonts that have become de facto standard in the LaTeX
1328 world (e.g. Latin Modern). We do not support obsolete fonts
1329 (like PSLatex). In general, it should be possible to mix any
1330 rm font with any sf or tt font, respectively. (JSpitzm)
1332 -- separate math fonts.
1335 if (rm == "default" && sf == "default" && tt == "default")
1342 // Computer Modern (must be explicitely selectable -- there might be classes
1343 // that define a different default font!
1345 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1346 // osf for Computer Modern needs eco.sty
1348 os << "\\usepackage{eco}\n";
1350 // Latin Modern Roman
1351 else if (rm == "lmodern")
1352 os << "\\usepackage{lmodern}\n";
1354 else if (rm == "ae") {
1355 // not needed when using OT1 font encoding.
1356 if (lyxrc.fontenc != "default")
1357 os << "\\usepackage{ae,aecompl}\n";
1360 else if (rm == "times") {
1361 // try to load the best available package
1362 if (features.isAvailable("mathptmx"))
1363 os << "\\usepackage{mathptmx}\n";
1364 else if (features.isAvailable("mathptm"))
1365 os << "\\usepackage{mathptm}\n";
1367 os << "\\usepackage{times}\n";
1370 else if (rm == "palatino") {
1371 // try to load the best available package
1372 if (features.isAvailable("mathpazo")) {
1373 os << "\\usepackage";
1379 // "osf" includes "sc"!
1383 os << "{mathpazo}\n";
1385 else if (features.isAvailable("mathpple"))
1386 os << "\\usepackage{mathpple}\n";
1388 os << "\\usepackage{palatino}\n";
1391 else if (rm == "utopia") {
1392 // fourier supersedes utopia.sty, but does
1393 // not work with OT1 encoding.
1394 if (features.isAvailable("fourier")
1395 && lyxrc.fontenc != "default") {
1396 os << "\\usepackage";
1407 os << "{fourier}\n";
1410 os << "\\usepackage{utopia}\n";
1412 // Bera (complete fontset)
1413 else if (rm == "bera" && sf == "default" && tt == "default")
1414 os << "\\usepackage{bera}\n";
1416 else if (rm != "default")
1417 os << "\\usepackage" << "{" << rm << "}\n";
1420 // Helvetica, Bera Sans
1421 if (sf == "helvet" || sf == "berasans") {
1423 os << "\\usepackage[scaled=" << float(sfscale) / 100
1424 << "]{" << sf << "}\n";
1426 os << "\\usepackage{" << sf << "}\n";
1429 else if (sf == "avant")
1430 os << "\\usepackage{" << sf << "}\n";
1431 // Computer Modern, Latin Modern, CM Bright
1432 else if (sf != "default")
1433 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1435 // monospaced/typewriter
1436 // Courier, LuxiMono
1437 if (tt == "luximono" || tt == "beramono") {
1439 os << "\\usepackage[scaled=" << float(ttscale) / 100
1440 << "]{" << tt << "}\n";
1442 os << "\\usepackage{" << tt << "}\n";
1445 else if (tt == "courier" )
1446 os << "\\usepackage{" << tt << "}\n";
1447 // Computer Modern, Latin Modern, CM Bright
1448 else if (tt != "default")
1449 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";