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";
707 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
708 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
709 for (; a_it != a_end; ++a_it) {
710 os << "\\author " << a_it->second << "\n";
715 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
716 TexRow & texrow) const
718 os << "\\documentclass";
720 LyXTextClass const & tclass = getLyXTextClass();
722 ostringstream clsoptions; // the document class options.
724 if (tokenPos(tclass.opt_fontsize(),
725 '|', fontsize) >= 0) {
726 // only write if existing in list (and not default)
727 clsoptions << fontsize << "pt,";
730 // custom, A3, B3 and B4 paper sizes need geometry
731 bool nonstandard_papersize = (papersize == PAPER_B3) ||
732 (papersize == PAPER_B4) ||
733 (papersize == PAPER_A3) ||
734 (papersize == PAPER_CUSTOM);
739 clsoptions << "a4paper,";
742 clsoptions << "letterpaper,";
745 clsoptions << "a5paper,";
748 clsoptions << "b5paper,";
750 case PAPER_USEXECUTIVE:
751 clsoptions << "executivepaper,";
754 clsoptions << "legalpaper,";
766 if (sides != tclass.sides()) {
768 case LyXTextClass::OneSide:
769 clsoptions << "oneside,";
771 case LyXTextClass::TwoSides:
772 clsoptions << "twoside,";
778 if (columns != tclass.columns()) {
780 clsoptions << "twocolumn,";
782 clsoptions << "onecolumn,";
786 && orientation == ORIENTATION_LANDSCAPE)
787 clsoptions << "landscape,";
789 // language should be a parameter to \documentclass
790 if (language->babel() == "hebrew"
791 && default_language->babel() != "hebrew")
792 // This seems necessary
793 features.useLanguage(default_language);
795 ostringstream language_options;
796 bool const use_babel = features.useBabel();
798 language_options << features.getLanguages();
799 language_options << language->babel();
800 if (lyxrc.language_global_options)
801 clsoptions << language_options.str() << ',';
804 // the user-defined options
805 if (!options.empty()) {
806 clsoptions << options << ',';
809 string strOptions(clsoptions.str());
810 if (!strOptions.empty()) {
811 strOptions = rtrim(strOptions, ",");
813 os << '[' << lyx::from_utf8(strOptions) << ']';
816 os << '{' << lyx::from_ascii(tclass.latexname()) << "}\n";
818 // end of \documentclass defs
820 // font selection must be done before loading fontenc.sty
822 loadFonts(features, fontsRoman, fontsSans,
823 fontsTypewriter, fontsSC, fontsOSF,
824 fontsSansScale, fontsTypewriterScale);
825 if (!fonts.empty()) {
826 os << lyx::from_ascii(fonts);
829 if (fontsDefaultFamily != "default")
830 os << "\\renewcommand{\\familydefault}{\\"
831 << lyx::from_ascii(fontsDefaultFamily) << "}\n";
832 // this one is not per buffer
833 if (lyxrc.fontenc != "default") {
834 os << "\\usepackage[" << lyx::from_ascii(lyxrc.fontenc)
839 // TODO: Some people want to support more encodings than UTF-8. They can have a field day around here
841 os << "\\usepackage[utf8]{inputenc}\n";
844 if (inputenc == "auto") {
845 string const doc_encoding =
846 language->encoding()->latexName();
848 // Create a list with all the input encodings used
850 std::set<string> encodings =
851 features.getEncodingSet(doc_encoding);
853 os << "\\usepackage[";
854 std::set<string>::const_iterator it = encodings.begin();
855 std::set<string>::const_iterator const end = encodings.end();
856 for (; it != end; ++it)
857 os << lyx::from_ascii(*it) << ',';
858 os << lyx::from_ascii(doc_encoding) << "]{inputenc}\n";
860 } else if (inputenc != "default") {
861 os << "\\usepackage[" << lyx::from_ascii(inputenc)
867 if (use_geometry || nonstandard_papersize) {
868 os << "\\usepackage{geometry}\n";
870 os << "\\geometry{verbose";
871 if (orientation == ORIENTATION_LANDSCAPE)
875 if (!paperwidth.empty())
877 << lyx::from_ascii(paperwidth);
878 if (!paperheight.empty())
879 os << ",paperheight="
880 << lyx::from_ascii(paperheight);
883 os << ",letterpaper";
888 case PAPER_USEXECUTIVE:
889 os << ",executivepaper";
910 // default papersize ie PAPER_DEFAULT
911 switch (lyxrc.default_papersize) {
912 case PAPER_DEFAULT: // keep compiler happy
914 os << ",letterpaper";
919 case PAPER_USEXECUTIVE:
920 os << ",executivepaper";
940 if (!topmargin.empty())
941 os << ",tmargin=" << lyx::from_ascii(topmargin);
942 if (!bottommargin.empty())
943 os << ",bmargin=" << lyx::from_ascii(bottommargin);
944 if (!leftmargin.empty())
945 os << ",lmargin=" << lyx::from_ascii(leftmargin);
946 if (!rightmargin.empty())
947 os << ",rmargin=" << lyx::from_ascii(rightmargin);
948 if (!headheight.empty())
949 os << ",headheight=" << lyx::from_ascii(headheight);
950 if (!headsep.empty())
951 os << ",headsep=" << lyx::from_ascii(headsep);
952 if (!footskip.empty())
953 os << ",footskip=" << lyx::from_ascii(footskip);
958 if (tokenPos(tclass.opt_pagestyle(),
959 '|', pagestyle) >= 0) {
960 if (pagestyle == "fancy") {
961 os << "\\usepackage{fancyhdr}\n";
964 os << "\\pagestyle{" << lyx::from_ascii(pagestyle) << "}\n";
968 // Only if class has a ToC hierarchy
969 if (tclass.hasTocLevels()) {
970 if (secnumdepth != tclass.secnumdepth()) {
971 os << "\\setcounter{secnumdepth}{"
976 if (tocdepth != tclass.tocdepth()) {
977 os << "\\setcounter{tocdepth}{"
984 if (paragraph_separation) {
985 switch (getDefSkip().kind()) {
986 case VSpace::SMALLSKIP:
987 os << "\\setlength\\parskip{\\smallskipamount}\n";
989 case VSpace::MEDSKIP:
990 os << "\\setlength\\parskip{\\medskipamount}\n";
992 case VSpace::BIGSKIP:
993 os << "\\setlength\\parskip{\\bigskipamount}\n";
996 os << "\\setlength\\parskip{"
997 << lyx::from_ascii(getDefSkip().length().asLatexString())
1000 default: // should never happen // Then delete it.
1001 os << "\\setlength\\parskip{\\medskipamount}\n";
1006 os << "\\setlength\\parindent{0pt}\n";
1010 // If we use jurabib, we have to call babel here.
1011 if (use_babel && features.isRequired("jurabib")) {
1012 os << lyx::from_ascii(babelCall(language_options.str()))
1014 << lyx::from_ascii(features.getBabelOptions());
1018 // Now insert the LyX specific LaTeX commands...
1020 // The optional packages;
1021 string lyxpreamble(features.getPackages());
1023 // this might be useful...
1024 lyxpreamble += "\n\\makeatletter\n";
1026 // Some macros LyX will need
1027 string tmppreamble(features.getMacros());
1029 if (!tmppreamble.empty()) {
1030 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1031 "LyX specific LaTeX commands.\n"
1032 + tmppreamble + '\n';
1035 // the text class specific preamble
1036 tmppreamble = features.getTClassPreamble();
1037 if (!tmppreamble.empty()) {
1038 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1039 "Textclass specific LaTeX commands.\n"
1040 + tmppreamble + '\n';
1043 /* the user-defined preamble */
1044 if (!preamble.empty()) {
1045 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1046 "User specified LaTeX commands.\n"
1050 // Itemize bullet settings need to be last in case the user
1051 // defines their own bullets that use a package included
1052 // in the user-defined preamble -- ARRae
1053 // Actually it has to be done much later than that
1054 // since some packages like frenchb make modifications
1055 // at \begin{document} time -- JMarc
1057 for (int i = 0; i < 4; ++i) {
1058 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1059 if (bullets_def.empty())
1060 bullets_def="\\AtBeginDocument{\n";
1061 bullets_def += " \\def\\labelitemi";
1063 // `i' is one less than the item to modify
1070 bullets_def += "ii";
1076 bullets_def += '{' +
1077 user_defined_bullet(i).getText()
1082 if (!bullets_def.empty())
1083 lyxpreamble += bullets_def + "}\n\n";
1085 // We try to load babel late, in case it interferes
1086 // with other packages.
1087 // Jurabib has to be called after babel, though.
1088 if (use_babel && !features.isRequired("jurabib")) {
1089 lyxpreamble += babelCall(language_options.str()) + '\n';
1090 lyxpreamble += features.getBabelOptions();
1093 lyxpreamble += "\\makeatother\n";
1095 // dvipost settings come after everything else
1096 if (features.isAvailable("dvipost") && outputChanges) {
1099 "\\dvipost{osstart color push Red}\n"
1100 "\\dvipost{osend color pop}\n"
1101 "\\dvipost{cbstart color push Blue}\n"
1102 "\\dvipost{cbend color pop}\n";
1106 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1107 for (int j = 0; j != nlines; ++j) {
1112 os << lyx::from_utf8(lyxpreamble);
1117 void BufferParams::useClassDefaults()
1119 LyXTextClass const & tclass = textclasslist[textclass];
1121 sides = tclass.sides();
1122 columns = tclass.columns();
1123 pagestyle = tclass.pagestyle();
1124 options = tclass.options();
1125 // Only if class has a ToC hierarchy
1126 if (tclass.hasTocLevels()) {
1127 secnumdepth = tclass.secnumdepth();
1128 tocdepth = tclass.tocdepth();
1133 bool BufferParams::hasClassDefaults() const
1135 LyXTextClass const & tclass = textclasslist[textclass];
1137 return (sides == tclass.sides()
1138 && columns == tclass.columns()
1139 && pagestyle == tclass.pagestyle()
1140 && options == tclass.options()
1141 && secnumdepth == tclass.secnumdepth()
1142 && tocdepth == tclass.tocdepth());
1146 LyXTextClass const & BufferParams::getLyXTextClass() const
1148 return textclasslist[textclass];
1152 LyXFont const BufferParams::getFont() const
1154 LyXFont f = getLyXTextClass().defaultfont();
1155 f.setLanguage(language);
1156 if (fontsDefaultFamily == "rmdefault")
1157 f.setFamily(LyXFont::ROMAN_FAMILY);
1158 else if (fontsDefaultFamily == "sfdefault")
1159 f.setFamily(LyXFont::SANS_FAMILY);
1160 else if (fontsDefaultFamily == "ttdefault")
1161 f.setFamily(LyXFont::TYPEWRITER_FAMILY);
1166 void BufferParams::readPreamble(LyXLex & lex)
1168 if (lex.getString() != "\\begin_preamble")
1169 lyxerr << "Error (BufferParams::readPreamble):"
1170 "consistency check failed." << endl;
1172 preamble = lex.getLongString("\\end_preamble");
1176 void BufferParams::readLanguage(LyXLex & lex)
1178 if (!lex.next()) return;
1180 string const tmptok = lex.getString();
1182 // check if tmptok is part of tex_babel in tex-defs.h
1183 language = languages.getLanguage(tmptok);
1185 // Language tmptok was not found
1186 language = default_language;
1187 lyxerr << "Warning: Setting language `"
1188 << tmptok << "' to `" << language->lang()
1194 void BufferParams::readGraphicsDriver(LyXLex & lex)
1196 if (!lex.next()) return;
1198 string const tmptok = lex.getString();
1199 // check if tmptok is part of tex_graphics in tex_defs.h
1202 string const test = tex_graphics[n++];
1204 if (test == tmptok) {
1205 graphicsDriver = tmptok;
1207 } else if (test == "") {
1209 "Warning: graphics driver `$$Token' not recognized!\n"
1210 " Setting graphics driver to `default'.\n");
1211 graphicsDriver = "default";
1218 void BufferParams::readBullets(LyXLex & lex)
1220 if (!lex.next()) return;
1222 int const index = lex.getInteger();
1224 int temp_int = lex.getInteger();
1225 user_defined_bullet(index).setFont(temp_int);
1226 temp_bullet(index).setFont(temp_int);
1228 user_defined_bullet(index).setCharacter(temp_int);
1229 temp_bullet(index).setCharacter(temp_int);
1231 user_defined_bullet(index).setSize(temp_int);
1232 temp_bullet(index).setSize(temp_int);
1236 void BufferParams::readBulletsLaTeX(LyXLex & lex)
1238 // The bullet class should be able to read this.
1239 if (!lex.next()) return;
1240 int const index = lex.getInteger();
1242 string const temp_str = lex.getString();
1244 user_defined_bullet(index).setText(temp_str);
1245 temp_bullet(index).setText(temp_str);
1249 string const BufferParams::paperSizeName() const
1251 char real_papersize = papersize;
1252 if (real_papersize == PAPER_DEFAULT)
1253 real_papersize = lyxrc.default_papersize;
1255 switch (real_papersize) {
1264 case PAPER_USEXECUTIVE:
1268 case PAPER_USLETTER:
1275 string const BufferParams::dvips_options() const
1280 && papersize == PAPER_CUSTOM
1281 && !lyxrc.print_paper_dimension_flag.empty()
1282 && !paperwidth.empty()
1283 && !paperheight.empty()) {
1284 // using a custom papersize
1285 result = lyxrc.print_paper_dimension_flag;
1286 result += ' ' + paperwidth;
1287 result += ',' + paperheight;
1289 string const paper_option = paperSizeName();
1290 if (paper_option != "letter" ||
1291 orientation != ORIENTATION_LANDSCAPE) {
1292 // dvips won't accept -t letter -t landscape.
1293 // In all other cases, include the paper size
1295 result = lyxrc.print_paper_flag;
1296 result += ' ' + paper_option;
1299 if (orientation == ORIENTATION_LANDSCAPE &&
1300 papersize != PAPER_CUSTOM)
1301 result += ' ' + lyxrc.print_landscape_flag;
1306 string const BufferParams::babelCall(string const & lang_opts) const
1308 string tmp = lyxrc.language_package;
1309 if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1310 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1315 string const BufferParams::loadFonts(LaTeXFeatures & features, string const & rm,
1316 string const & sf, string const & tt,
1317 bool const & sc, bool const & osf,
1318 int const & sfscale, int const & ttscale) const
1320 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1321 several packages have been replaced by others, that might not
1322 be installed on every system. We have to take care for that
1323 (see psnfss.pdf). We try to support all psnfss fonts as well
1324 as the fonts that have become de facto standard in the LaTeX
1325 world (e.g. Latin Modern). We do not support obsolete fonts
1326 (like PSLatex). In general, it should be possible to mix any
1327 rm font with any sf or tt font, respectively. (JSpitzm)
1329 -- separate math fonts.
1332 if (rm == "default" && sf == "default" && tt == "default")
1339 // Computer Modern (must be explicitely selectable -- there might be classes
1340 // that define a different default font!
1342 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1343 // osf for Computer Modern needs eco.sty
1345 os << "\\usepackage{eco}\n";
1347 // Latin Modern Roman
1348 else if (rm == "lmodern")
1349 os << "\\usepackage{lmodern}\n";
1351 else if (rm == "ae") {
1352 // not needed when using OT1 font encoding.
1353 if (lyxrc.fontenc != "default")
1354 os << "\\usepackage{ae,aecompl}\n";
1357 else if (rm == "times") {
1358 // try to load the best available package
1359 if (features.isAvailable("mathptmx"))
1360 os << "\\usepackage{mathptmx}\n";
1361 else if (features.isAvailable("mathptm"))
1362 os << "\\usepackage{mathptm}\n";
1364 os << "\\usepackage{times}\n";
1367 else if (rm == "palatino") {
1368 // try to load the best available package
1369 if (features.isAvailable("mathpazo")) {
1370 os << "\\usepackage";
1376 // "osf" includes "sc"!
1380 os << "{mathpazo}\n";
1382 else if (features.isAvailable("mathpple"))
1383 os << "\\usepackage{mathpple}\n";
1385 os << "\\usepackage{palatino}\n";
1388 else if (rm == "utopia") {
1389 // fourier supersedes utopia.sty, but does
1390 // not work with OT1 encoding.
1391 if (features.isAvailable("fourier")
1392 && lyxrc.fontenc != "default") {
1393 os << "\\usepackage";
1404 os << "{fourier}\n";
1407 os << "\\usepackage{utopia}\n";
1409 // Bera (complete fontset)
1410 else if (rm == "bera" && sf == "default" && tt == "default")
1411 os << "\\usepackage{bera}\n";
1413 else if (rm != "default")
1414 os << "\\usepackage" << "{" << rm << "}\n";
1417 // Helvetica, Bera Sans
1418 if (sf == "helvet" || sf == "berasans") {
1420 os << "\\usepackage[scaled=" << float(sfscale) / 100
1421 << "]{" << sf << "}\n";
1423 os << "\\usepackage{" << sf << "}\n";
1426 else if (sf == "avant")
1427 os << "\\usepackage{" << sf << "}\n";
1428 // Computer Modern, Latin Modern, CM Bright
1429 else if (sf != "default")
1430 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1432 // monospaced/typewriter
1433 // Courier, LuxiMono
1434 if (tt == "luximono" || tt == "beramono") {
1436 os << "\\usepackage[scaled=" << float(ttscale) / 100
1437 << "]{" << tt << "}\n";
1439 os << "\\usepackage{" << tt << "}\n";
1442 else if (tt == "courier" )
1443 os << "\\usepackage{" << tt << "}\n";
1444 // Computer Modern, Latin Modern, CM Bright
1445 else if (tt != "default")
1446 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";