3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Alfredo Braunstein
7 * \author Lars Gullik Bjønnes
8 * \author Jean-Marc Lasgouttes
10 * \author André Pönitz
11 * \author Martin Vermeer
13 * Full author contact details are available in file CREDITS.
18 #include "bufferparams.h"
21 #include "BranchList.h"
27 #include "LaTeXFeatures.h"
32 #include "lyxtextclasslist.h"
33 #include "outputparams.h"
34 #include "tex-strings.h"
39 #include "frontends/Alert.h"
41 #include "support/lyxalgo.h" // for lyx::count
42 #include "support/convert.h"
43 #include "support/translator.h"
45 #include <boost/array.hpp>
52 using support::bformat;
54 using support::tokenPos;
58 using std::istringstream;
60 using std::ostringstream;
63 namespace Alert = lyx::frontend::Alert;
69 // Paragraph separation
70 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
73 ParSepTranslator const init_parseptranslator()
75 ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
76 translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
81 ParSepTranslator const & parseptranslator()
83 static ParSepTranslator translator = init_parseptranslator();
89 typedef Translator<string, InsetQuotes::quote_language> QuotesLangTranslator;
92 QuotesLangTranslator const init_quoteslangtranslator()
94 QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
95 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
96 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
97 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
98 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
99 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
104 QuotesLangTranslator const & quoteslangtranslator()
106 static QuotesLangTranslator translator = init_quoteslangtranslator();
112 typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
115 PaperSizeTranslator const init_papersizetranslator()
117 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
118 translator.addPair(string_papersize[1], PAPER_CUSTOM);
119 translator.addPair(string_papersize[2], PAPER_USLETTER);
120 translator.addPair(string_papersize[3], PAPER_USLEGAL);
121 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
122 translator.addPair(string_papersize[5], PAPER_A3);
123 translator.addPair(string_papersize[6], PAPER_A4);
124 translator.addPair(string_papersize[7], PAPER_A5);
125 translator.addPair(string_papersize[8], PAPER_B3);
126 translator.addPair(string_papersize[9], PAPER_B4);
127 translator.addPair(string_papersize[10], PAPER_B5);
132 PaperSizeTranslator const & papersizetranslator()
134 static PaperSizeTranslator translator = init_papersizetranslator();
140 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
143 PaperOrientationTranslator const init_paperorientationtranslator()
145 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
146 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
151 PaperOrientationTranslator const & paperorientationtranslator()
153 static PaperOrientationTranslator translator = init_paperorientationtranslator();
159 typedef Translator<int, LyXTextClass::PageSides> SidesTranslator;
162 SidesTranslator const init_sidestranslator()
164 SidesTranslator translator(1, LyXTextClass::OneSide);
165 translator.addPair(2, LyXTextClass::TwoSides);
170 SidesTranslator const & sidestranslator()
172 static SidesTranslator translator = init_sidestranslator();
178 typedef Translator<int, BufferParams::Package> PackageTranslator;
181 PackageTranslator const init_packagetranslator()
183 PackageTranslator translator(0, BufferParams::package_off);
184 translator.addPair(1, BufferParams::package_auto);
185 translator.addPair(2, BufferParams::package_on);
190 PackageTranslator const & packagetranslator()
192 static PackageTranslator translator = init_packagetranslator();
198 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
201 CiteEngineTranslator const init_citeenginetranslator()
203 CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
204 translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
205 translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
206 translator.addPair("jurabib", biblio::ENGINE_JURABIB);
211 CiteEngineTranslator const & citeenginetranslator()
213 static CiteEngineTranslator translator = init_citeenginetranslator();
219 typedef Translator<string, Spacing::Space> SpaceTranslator;
222 SpaceTranslator const init_spacetranslator()
224 SpaceTranslator translator("default", Spacing::Default);
225 translator.addPair("single", Spacing::Single);
226 translator.addPair("onehalf", Spacing::Onehalf);
227 translator.addPair("double", Spacing::Double);
228 translator.addPair("other", Spacing::Other);
233 SpaceTranslator const & spacetranslator()
235 static SpaceTranslator translator = init_spacetranslator();
239 // ends annonym namespace
243 class BufferParams::Impl
248 AuthorList authorlist;
249 BranchList branchlist;
250 boost::array<Bullet, 4> temp_bullets;
251 boost::array<Bullet, 4> user_defined_bullets;
253 /** This is the amount of space used for paragraph_separation "skip",
254 * and for detached paragraphs in "indented" documents.
260 BufferParams::Impl::Impl()
261 : defskip(VSpace::MEDSKIP)
263 // set initial author
265 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
270 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
274 return new BufferParams::Impl(*ptr);
278 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
284 BufferParams::BufferParams()
285 : // Initialize textclass to point to article. if `first' is
286 // true in the returned pair, then `second' is the textclass
287 // number; if it is false, second is 0. In both cases, second
289 textclass(textclasslist.numberOfClass("article").second),
292 paragraph_separation = PARSEP_INDENT;
293 quotes_language = InsetQuotes::EnglishQ;
294 fontsize = "default";
297 papersize = PAPER_DEFAULT;
298 orientation = ORIENTATION_PORTRAIT;
299 use_geometry = false;
300 use_amsmath = package_auto;
301 use_esint = package_auto;
302 cite_engine = biblio::ENGINE_BASIC;
303 use_bibtopic = false;
304 trackChanges = false;
305 outputChanges = false;
308 language = default_language;
309 fontsRoman = "default";
310 fontsSans = "default";
311 fontsTypewriter = "default";
312 fontsDefaultFamily = "default";
315 fontsSansScale = 100;
316 fontsTypewriterScale = 100;
318 graphicsDriver = "default";
319 sides = LyXTextClass::OneSide;
321 pagestyle = "default";
323 for (int iter = 0; iter < 4; ++iter) {
324 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
325 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
330 BufferParams::~BufferParams()
334 AuthorList & BufferParams::authors()
336 return pimpl_->authorlist;
340 AuthorList const & BufferParams::authors() const
342 return pimpl_->authorlist;
346 BranchList & BufferParams::branchlist()
348 return pimpl_->branchlist;
352 BranchList const & BufferParams::branchlist() const
354 return pimpl_->branchlist;
358 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
360 BOOST_ASSERT(index < 4);
361 return pimpl_->temp_bullets[index];
365 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
367 BOOST_ASSERT(index < 4);
368 return pimpl_->temp_bullets[index];
372 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
374 BOOST_ASSERT(index < 4);
375 return pimpl_->user_defined_bullets[index];
379 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
381 BOOST_ASSERT(index < 4);
382 return pimpl_->user_defined_bullets[index];
386 Spacing & BufferParams::spacing()
388 return pimpl_->spacing;
392 Spacing const & BufferParams::spacing() const
394 return pimpl_->spacing;
398 VSpace const & BufferParams::getDefSkip() const
400 return pimpl_->defskip;
404 void BufferParams::setDefSkip(VSpace const & vs)
406 pimpl_->defskip = vs;
410 string const BufferParams::readToken(LyXLex & lex, string const & token)
412 if (token == "\\textclass") {
414 string const classname = lex.getString();
415 pair<bool, lyx::textclass_type> pp =
416 textclasslist.numberOfClass(classname);
418 textclass = pp.second;
420 // if text class does not exist, try to load it from filepath
421 pp = textclasslist.addTextClass(classname, filepath);
423 textclass = pp.second;
429 // FIXME: isTeXClassAvailable will try to load the layout file, but will
430 // fail because of the lack of path info. Warnings will be given although
431 // the layout file will be correctly loaded later.
432 if (!getLyXTextClass().isTeXClassAvailable()) {
433 docstring const msg =
434 bformat(_("The document uses a missing "
435 "TeX class \"%1$s\".\n"), from_utf8(classname));
436 Alert::warning(_("Document class not available"),
437 msg + _("LyX will not be able to produce output."));
439 } else if (token == "\\begin_preamble") {
441 } else if (token == "\\options") {
443 options = lex.getString();
444 } else if (token == "\\language") {
446 } else if (token == "\\inputencoding") {
448 } else if (token == "\\graphics") {
449 readGraphicsDriver(lex);
450 } else if (token == "\\font_roman") {
452 } else if (token == "\\font_sans") {
454 } else if (token == "\\font_typewriter") {
455 lex >> fontsTypewriter;
456 } else if (token == "\\font_default_family") {
457 lex >> fontsDefaultFamily;
458 } else if (token == "\\font_sc") {
460 } else if (token == "\\font_osf") {
462 } else if (token == "\\font_sf_scale") {
463 lex >> fontsSansScale;
464 } else if (token == "\\font_tt_scale") {
465 lex >> fontsTypewriterScale;
466 } else if (token == "\\paragraph_separation") {
469 paragraph_separation = parseptranslator().find(parsep);
470 } else if (token == "\\defskip") {
472 pimpl_->defskip = VSpace(lex.getString());
473 } else if (token == "\\quotes_language") {
476 quotes_language = quoteslangtranslator().find(quotes_lang);
477 } else if (token == "\\papersize") {
480 papersize = papersizetranslator().find(ppsize);
481 } else if (token == "\\use_geometry") {
483 } else if (token == "\\use_amsmath") {
486 use_amsmath = packagetranslator().find(use_ams);
487 } else if (token == "\\use_esint") {
490 use_esint = packagetranslator().find(useesint);
491 } else if (token == "\\cite_engine") {
494 cite_engine = citeenginetranslator().find(engine);
495 } else if (token == "\\use_bibtopic") {
497 } else if (token == "\\tracking_changes") {
499 } else if (token == "\\output_changes") {
500 lex >> outputChanges;
501 } else if (token == "\\branch") {
503 docstring branch = lex.getDocString();
504 branchlist().add(branch);
507 string const tok = lex.getString();
508 if (tok == "\\end_branch")
510 Branch * branch_ptr = branchlist().find(branch);
511 if (tok == "\\selected") {
514 branch_ptr->setSelected(lex.getInteger());
516 // not yet operational
517 if (tok == "\\color") {
519 string color = lex.getString();
521 branch_ptr->setColor(color);
522 // Update also the LColor table:
524 color = lcolor.getX11Name(LColor::background);
526 lcolor.setColor(to_utf8(branch), color);
530 } else if (token == "\\author") {
532 istringstream ss(lex.getString());
535 author_map.push_back(pimpl_->authorlist.record(a));
536 } else if (token == "\\paperorientation") {
539 orientation = paperorientationtranslator().find(orient);
540 } else if (token == "\\paperwidth") {
542 } else if (token == "\\paperheight") {
544 } else if (token == "\\leftmargin") {
546 } else if (token == "\\topmargin") {
548 } else if (token == "\\rightmargin") {
550 } else if (token == "\\bottommargin") {
552 } else if (token == "\\headheight") {
554 } else if (token == "\\headsep") {
556 } else if (token == "\\footskip") {
558 } else if (token == "\\paperfontsize") {
560 } else if (token == "\\papercolumns") {
562 } else if (token == "\\papersides") {
565 sides = sidestranslator().find(psides);
566 } else if (token == "\\paperpagestyle") {
568 } else if (token == "\\bullet") {
570 } else if (token == "\\bulletLaTeX") {
571 readBulletsLaTeX(lex);
572 } else if (token == "\\secnumdepth") {
574 } else if (token == "\\tocdepth") {
576 } else if (token == "\\spacing") {
580 if (nspacing == "other") {
583 spacing().set(spacetranslator().find(nspacing), tmp_val);
584 } else if (token == "\\float_placement") {
585 lex >> float_placement;
594 void BufferParams::writeFile(ostream & os) const
596 // The top of the file is written by the buffer.
597 // Prints out the buffer info into the .lyx file given by file
600 os << "\\textclass " << textclasslist[textclass].name() << '\n';
602 // then the the preamble
603 if (!preamble.empty()) {
604 // remove '\n' from the end of preamble
605 string const tmppreamble = rtrim(preamble, "\n");
606 os << "\\begin_preamble\n"
608 << "\n\\end_preamble\n";
612 if (!options.empty()) {
613 os << "\\options " << options << '\n';
616 // then the text parameters
617 if (language != ignore_language)
618 os << "\\language " << language->lang() << '\n';
619 os << "\\inputencoding " << inputenc
620 << "\n\\font_roman " << fontsRoman
621 << "\n\\font_sans " << fontsSans
622 << "\n\\font_typewriter " << fontsTypewriter
623 << "\n\\font_default_family " << fontsDefaultFamily
624 << "\n\\font_sc " << convert<string>(fontsSC)
625 << "\n\\font_osf " << convert<string>(fontsOSF)
626 << "\n\\font_sf_scale " << fontsSansScale
627 << "\n\\font_tt_scale " << fontsTypewriterScale
628 << "\n\\graphics " << graphicsDriver << '\n';
630 if (!float_placement.empty()) {
631 os << "\\float_placement " << float_placement << '\n';
633 os << "\\paperfontsize " << fontsize << '\n';
635 spacing().writeFile(os);
637 os << "\\papersize " << string_papersize[papersize]
638 << "\n\\use_geometry " << convert<string>(use_geometry)
639 << "\n\\use_amsmath " << use_amsmath
640 << "\n\\use_esint " << use_esint
641 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine)
642 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
643 << "\n\\paperorientation " << string_orientation[orientation]
646 BranchList::const_iterator it = branchlist().begin();
647 BranchList::const_iterator end = branchlist().end();
648 for (; it != end; ++it) {
649 os << "\\branch " << to_utf8(it->getBranch())
650 << "\n\\selected " << it->getSelected()
651 << "\n\\color " << lyx::X11hexname(it->getColor())
656 if (!paperwidth.empty())
657 os << "\\paperwidth "
658 << VSpace(paperwidth).asLyXCommand() << '\n';
659 if (!paperheight.empty())
660 os << "\\paperheight "
661 << VSpace(paperheight).asLyXCommand() << '\n';
662 if (!leftmargin.empty())
663 os << "\\leftmargin "
664 << VSpace(leftmargin).asLyXCommand() << '\n';
665 if (!topmargin.empty())
667 << VSpace(topmargin).asLyXCommand() << '\n';
668 if (!rightmargin.empty())
669 os << "\\rightmargin "
670 << VSpace(rightmargin).asLyXCommand() << '\n';
671 if (!bottommargin.empty())
672 os << "\\bottommargin "
673 << VSpace(bottommargin).asLyXCommand() << '\n';
674 if (!headheight.empty())
675 os << "\\headheight "
676 << VSpace(headheight).asLyXCommand() << '\n';
677 if (!headsep.empty())
679 << VSpace(headsep).asLyXCommand() << '\n';
680 if (!footskip.empty())
682 << VSpace(footskip).asLyXCommand() << '\n';
683 os << "\\secnumdepth " << secnumdepth
684 << "\n\\tocdepth " << tocdepth
685 << "\n\\paragraph_separation "
686 << string_paragraph_separation[paragraph_separation]
687 << "\n\\defskip " << getDefSkip().asLyXCommand()
688 << "\n\\quotes_language "
689 << string_quotes_language[quotes_language]
690 << "\n\\papercolumns " << columns
691 << "\n\\papersides " << sides
692 << "\n\\paperpagestyle " << pagestyle << '\n';
693 for (int i = 0; i < 4; ++i) {
694 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
695 if (user_defined_bullet(i).getFont() != -1) {
696 os << "\\bullet " << i << " "
697 << user_defined_bullet(i).getFont() << " "
698 << user_defined_bullet(i).getCharacter() << " "
699 << user_defined_bullet(i).getSize() << "\n";
703 os << "\\bulletLaTeX " << i << " \""
704 << lyx::to_ascii(user_defined_bullet(i).getText())
710 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
711 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
713 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
714 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
715 for (; a_it != a_end; ++a_it) {
716 os << "\\author " << a_it->second << "\n";
721 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
722 TexRow & texrow) const
724 os << "\\documentclass";
726 LyXTextClass const & tclass = getLyXTextClass();
728 ostringstream clsoptions; // the document class options.
730 if (tokenPos(tclass.opt_fontsize(),
731 '|', fontsize) >= 0) {
732 // only write if existing in list (and not default)
733 clsoptions << fontsize << "pt,";
736 // custom, A3, B3 and B4 paper sizes need geometry
737 bool nonstandard_papersize = papersize == PAPER_B3
738 || papersize == PAPER_B4
739 || papersize == PAPER_A3
740 || papersize == PAPER_CUSTOM;
745 clsoptions << "a4paper,";
748 clsoptions << "letterpaper,";
751 clsoptions << "a5paper,";
754 clsoptions << "b5paper,";
756 case PAPER_USEXECUTIVE:
757 clsoptions << "executivepaper,";
760 clsoptions << "legalpaper,";
772 if (sides != tclass.sides()) {
774 case LyXTextClass::OneSide:
775 clsoptions << "oneside,";
777 case LyXTextClass::TwoSides:
778 clsoptions << "twoside,";
784 if (columns != tclass.columns()) {
786 clsoptions << "twocolumn,";
788 clsoptions << "onecolumn,";
792 && orientation == ORIENTATION_LANDSCAPE)
793 clsoptions << "landscape,";
795 // language should be a parameter to \documentclass
796 if (language->babel() == "hebrew"
797 && default_language->babel() != "hebrew")
798 // This seems necessary
799 features.useLanguage(default_language);
801 ostringstream language_options;
802 bool const use_babel = features.useBabel();
804 language_options << features.getLanguages();
805 language_options << language->babel();
806 if (lyxrc.language_global_options)
807 clsoptions << language_options.str() << ',';
810 // the user-defined options
811 if (!options.empty()) {
812 clsoptions << options << ',';
815 string strOptions(clsoptions.str());
816 if (!strOptions.empty()) {
817 strOptions = rtrim(strOptions, ",");
819 os << '[' << from_utf8(strOptions) << ']';
822 os << '{' << from_ascii(tclass.latexname()) << "}\n";
824 // end of \documentclass defs
826 // font selection must be done before loading fontenc.sty
828 loadFonts(features, fontsRoman, fontsSans,
829 fontsTypewriter, fontsSC, fontsOSF,
830 fontsSansScale, fontsTypewriterScale);
831 if (!fonts.empty()) {
832 os << from_ascii(fonts);
835 if (fontsDefaultFamily != "default")
836 os << "\\renewcommand{\\familydefault}{\\"
837 << from_ascii(fontsDefaultFamily) << "}\n";
838 // this one is not per buffer
839 if (lyxrc.fontenc != "default") {
840 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
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 // thailatex does not use the inputenc package, but sets up
855 // babel directly for tis620-0 encoding, therefore we must
856 // not request inputenc for tis620-0 encoding
857 if (!encodings.empty() || doc_encoding != "tis620-0") {
858 os << "\\usepackage[";
859 std::set<string>::const_iterator it = encodings.begin();
860 std::set<string>::const_iterator const end = encodings.end();
862 os << from_ascii(*it);
865 for (; it != end; ++it)
866 os << ',' << from_ascii(*it);
867 if (doc_encoding != "tis620-0") {
868 if (!encodings.empty())
870 os << from_ascii(doc_encoding);
872 os << "]{inputenc}\n";
875 } else if (inputenc != "default" && inputenc != "tis620-0") {
876 os << "\\usepackage[" << from_ascii(inputenc)
881 if (use_geometry || nonstandard_papersize) {
882 os << "\\usepackage{geometry}\n";
884 os << "\\geometry{verbose";
885 if (orientation == ORIENTATION_LANDSCAPE)
889 if (!paperwidth.empty())
891 << from_ascii(paperwidth);
892 if (!paperheight.empty())
893 os << ",paperheight="
894 << from_ascii(paperheight);
897 os << ",letterpaper";
902 case PAPER_USEXECUTIVE:
903 os << ",executivepaper";
924 // default papersize ie PAPER_DEFAULT
925 switch (lyxrc.default_papersize) {
926 case PAPER_DEFAULT: // keep compiler happy
928 os << ",letterpaper";
933 case PAPER_USEXECUTIVE:
934 os << ",executivepaper";
954 if (!topmargin.empty())
955 os << ",tmargin=" << from_ascii(topmargin);
956 if (!bottommargin.empty())
957 os << ",bmargin=" << from_ascii(bottommargin);
958 if (!leftmargin.empty())
959 os << ",lmargin=" << from_ascii(leftmargin);
960 if (!rightmargin.empty())
961 os << ",rmargin=" << from_ascii(rightmargin);
962 if (!headheight.empty())
963 os << ",headheight=" << from_ascii(headheight);
964 if (!headsep.empty())
965 os << ",headsep=" << from_ascii(headsep);
966 if (!footskip.empty())
967 os << ",footskip=" << from_ascii(footskip);
972 if (tokenPos(tclass.opt_pagestyle(),
973 '|', pagestyle) >= 0) {
974 if (pagestyle == "fancy") {
975 os << "\\usepackage{fancyhdr}\n";
978 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
982 // Only if class has a ToC hierarchy
983 if (tclass.hasTocLevels()) {
984 if (secnumdepth != tclass.secnumdepth()) {
985 os << "\\setcounter{secnumdepth}{"
990 if (tocdepth != tclass.tocdepth()) {
991 os << "\\setcounter{tocdepth}{"
998 if (paragraph_separation) {
999 switch (getDefSkip().kind()) {
1000 case VSpace::SMALLSKIP:
1001 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1003 case VSpace::MEDSKIP:
1004 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1006 case VSpace::BIGSKIP:
1007 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1009 case VSpace::LENGTH:
1010 os << "\\setlength{\\parskip}{"
1011 << from_utf8(getDefSkip().length().asLatexString())
1014 default: // should never happen // Then delete it.
1015 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1020 os << "\\setlength{\\parindent}{0pt}\n";
1024 // If we use jurabib, we have to call babel here.
1025 if (use_babel && features.isRequired("jurabib")) {
1026 os << from_ascii(babelCall(language_options.str()))
1028 << from_ascii(features.getBabelOptions());
1032 // Now insert the LyX specific LaTeX commands...
1034 // The optional packages;
1035 docstring lyxpreamble(from_ascii(features.getPackages()));
1037 // this might be useful...
1038 lyxpreamble += "\n\\makeatletter\n";
1040 // Some macros LyX will need
1041 docstring tmppreamble(from_ascii(features.getMacros()));
1043 if (!tmppreamble.empty()) {
1044 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1045 "LyX specific LaTeX commands.\n"
1046 + tmppreamble + '\n';
1049 // the text class specific preamble
1050 tmppreamble = features.getTClassPreamble();
1051 if (!tmppreamble.empty()) {
1052 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1053 "Textclass specific LaTeX commands.\n"
1054 + tmppreamble + '\n';
1057 /* the user-defined preamble */
1058 if (!preamble.empty()) {
1060 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1061 "User specified LaTeX commands.\n"
1062 + from_utf8(preamble) + '\n';
1065 // Itemize bullet settings need to be last in case the user
1066 // defines their own bullets that use a package included
1067 // in the user-defined preamble -- ARRae
1068 // Actually it has to be done much later than that
1069 // since some packages like frenchb make modifications
1070 // at \begin{document} time -- JMarc
1071 docstring bullets_def;
1072 for (int i = 0; i < 4; ++i) {
1073 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1074 if (bullets_def.empty())
1075 bullets_def += "\\AtBeginDocument{\n";
1076 bullets_def += " \\def\\labelitemi";
1078 // `i' is one less than the item to modify
1085 bullets_def += "ii";
1091 bullets_def += '{' +
1092 user_defined_bullet(i).getText()
1097 if (!bullets_def.empty())
1098 lyxpreamble += bullets_def + "}\n\n";
1100 // We try to load babel late, in case it interferes
1101 // with other packages.
1102 // Jurabib has to be called after babel, though.
1103 if (use_babel && !features.isRequired("jurabib")) {
1105 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1106 lyxpreamble += from_utf8(features.getBabelOptions());
1109 lyxpreamble += "\\makeatother\n";
1111 // dvipost settings come after everything else
1112 if (features.isAvailable("dvipost") && outputChanges) {
1115 "\\dvipost{osstart color push Red}\n"
1116 "\\dvipost{osend color pop}\n"
1117 "\\dvipost{cbstart color push Blue}\n"
1118 "\\dvipost{cbend color pop}\n";
1122 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1123 for (int j = 0; j != nlines; ++j) {
1132 void BufferParams::useClassDefaults()
1134 LyXTextClass const & tclass = textclasslist[textclass];
1136 sides = tclass.sides();
1137 columns = tclass.columns();
1138 pagestyle = tclass.pagestyle();
1139 options = tclass.options();
1140 // Only if class has a ToC hierarchy
1141 if (tclass.hasTocLevels()) {
1142 secnumdepth = tclass.secnumdepth();
1143 tocdepth = tclass.tocdepth();
1148 bool BufferParams::hasClassDefaults() const
1150 LyXTextClass const & tclass = textclasslist[textclass];
1152 return (sides == tclass.sides()
1153 && columns == tclass.columns()
1154 && pagestyle == tclass.pagestyle()
1155 && options == tclass.options()
1156 && secnumdepth == tclass.secnumdepth()
1157 && tocdepth == tclass.tocdepth());
1161 LyXTextClass const & BufferParams::getLyXTextClass() const
1163 return textclasslist[textclass];
1167 LyXFont const BufferParams::getFont() const
1169 LyXFont f = getLyXTextClass().defaultfont();
1170 f.setLanguage(language);
1171 if (fontsDefaultFamily == "rmdefault")
1172 f.setFamily(LyXFont::ROMAN_FAMILY);
1173 else if (fontsDefaultFamily == "sfdefault")
1174 f.setFamily(LyXFont::SANS_FAMILY);
1175 else if (fontsDefaultFamily == "ttdefault")
1176 f.setFamily(LyXFont::TYPEWRITER_FAMILY);
1181 void BufferParams::readPreamble(LyXLex & lex)
1183 if (lex.getString() != "\\begin_preamble")
1184 lyxerr << "Error (BufferParams::readPreamble):"
1185 "consistency check failed." << endl;
1187 preamble = lex.getLongString("\\end_preamble");
1191 void BufferParams::readLanguage(LyXLex & lex)
1193 if (!lex.next()) return;
1195 string const tmptok = lex.getString();
1197 // check if tmptok is part of tex_babel in tex-defs.h
1198 language = languages.getLanguage(tmptok);
1200 // Language tmptok was not found
1201 language = default_language;
1202 lyxerr << "Warning: Setting language `"
1203 << tmptok << "' to `" << language->lang()
1209 void BufferParams::readGraphicsDriver(LyXLex & lex)
1211 if (!lex.next()) return;
1213 string const tmptok = lex.getString();
1214 // check if tmptok is part of tex_graphics in tex_defs.h
1217 string const test = tex_graphics[n++];
1219 if (test == tmptok) {
1220 graphicsDriver = tmptok;
1222 } else if (test == "") {
1224 "Warning: graphics driver `$$Token' not recognized!\n"
1225 " Setting graphics driver to `default'.\n");
1226 graphicsDriver = "default";
1233 void BufferParams::readBullets(LyXLex & lex)
1235 if (!lex.next()) return;
1237 int const index = lex.getInteger();
1239 int temp_int = lex.getInteger();
1240 user_defined_bullet(index).setFont(temp_int);
1241 temp_bullet(index).setFont(temp_int);
1243 user_defined_bullet(index).setCharacter(temp_int);
1244 temp_bullet(index).setCharacter(temp_int);
1246 user_defined_bullet(index).setSize(temp_int);
1247 temp_bullet(index).setSize(temp_int);
1251 void BufferParams::readBulletsLaTeX(LyXLex & lex)
1253 // The bullet class should be able to read this.
1254 if (!lex.next()) return;
1255 int const index = lex.getInteger();
1257 docstring const temp_str = lex.getDocString();
1259 user_defined_bullet(index).setText(temp_str);
1260 temp_bullet(index).setText(temp_str);
1264 string const BufferParams::paperSizeName() const
1266 char real_papersize = papersize;
1267 if (real_papersize == PAPER_DEFAULT)
1268 real_papersize = lyxrc.default_papersize;
1270 switch (real_papersize) {
1279 case PAPER_USEXECUTIVE:
1283 case PAPER_USLETTER:
1290 string const BufferParams::dvips_options() const
1295 && papersize == PAPER_CUSTOM
1296 && !lyxrc.print_paper_dimension_flag.empty()
1297 && !paperwidth.empty()
1298 && !paperheight.empty()) {
1299 // using a custom papersize
1300 result = lyxrc.print_paper_dimension_flag;
1301 result += ' ' + paperwidth;
1302 result += ',' + paperheight;
1304 string const paper_option = paperSizeName();
1305 if (paper_option != "letter" ||
1306 orientation != ORIENTATION_LANDSCAPE) {
1307 // dvips won't accept -t letter -t landscape.
1308 // In all other cases, include the paper size
1310 result = lyxrc.print_paper_flag;
1311 result += ' ' + paper_option;
1314 if (orientation == ORIENTATION_LANDSCAPE &&
1315 papersize != PAPER_CUSTOM)
1316 result += ' ' + lyxrc.print_landscape_flag;
1321 string const BufferParams::babelCall(string const & lang_opts) const
1323 string tmp = lyxrc.language_package;
1324 if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1325 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1330 string const BufferParams::loadFonts(LaTeXFeatures & features, string const & rm,
1331 string const & sf, string const & tt,
1332 bool const & sc, bool const & osf,
1333 int const & sfscale, int const & ttscale) const
1335 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1336 several packages have been replaced by others, that might not
1337 be installed on every system. We have to take care for that
1338 (see psnfss.pdf). We try to support all psnfss fonts as well
1339 as the fonts that have become de facto standard in the LaTeX
1340 world (e.g. Latin Modern). We do not support obsolete fonts
1341 (like PSLatex). In general, it should be possible to mix any
1342 rm font with any sf or tt font, respectively. (JSpitzm)
1344 -- separate math fonts.
1347 if (rm == "default" && sf == "default" && tt == "default")
1354 // Computer Modern (must be explicitely selectable -- there might be classes
1355 // that define a different default font!
1357 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1358 // osf for Computer Modern needs eco.sty
1360 os << "\\usepackage{eco}\n";
1362 // Latin Modern Roman
1363 else if (rm == "lmodern")
1364 os << "\\usepackage{lmodern}\n";
1366 else if (rm == "ae") {
1367 // not needed when using OT1 font encoding.
1368 if (lyxrc.fontenc != "default")
1369 os << "\\usepackage{ae,aecompl}\n";
1372 else if (rm == "times") {
1373 // try to load the best available package
1374 if (features.isAvailable("mathptmx"))
1375 os << "\\usepackage{mathptmx}\n";
1376 else if (features.isAvailable("mathptm"))
1377 os << "\\usepackage{mathptm}\n";
1379 os << "\\usepackage{times}\n";
1382 else if (rm == "palatino") {
1383 // try to load the best available package
1384 if (features.isAvailable("mathpazo")) {
1385 os << "\\usepackage";
1391 // "osf" includes "sc"!
1395 os << "{mathpazo}\n";
1397 else if (features.isAvailable("mathpple"))
1398 os << "\\usepackage{mathpple}\n";
1400 os << "\\usepackage{palatino}\n";
1403 else if (rm == "utopia") {
1404 // fourier supersedes utopia.sty, but does
1405 // not work with OT1 encoding.
1406 if (features.isAvailable("fourier")
1407 && lyxrc.fontenc != "default") {
1408 os << "\\usepackage";
1419 os << "{fourier}\n";
1422 os << "\\usepackage{utopia}\n";
1424 // Bera (complete fontset)
1425 else if (rm == "bera" && sf == "default" && tt == "default")
1426 os << "\\usepackage{bera}\n";
1428 else if (rm != "default")
1429 os << "\\usepackage" << "{" << rm << "}\n";
1432 // Helvetica, Bera Sans
1433 if (sf == "helvet" || sf == "berasans") {
1435 os << "\\usepackage[scaled=" << float(sfscale) / 100
1436 << "]{" << sf << "}\n";
1438 os << "\\usepackage{" << sf << "}\n";
1441 else if (sf == "avant")
1442 os << "\\usepackage{" << sf << "}\n";
1443 // Computer Modern, Latin Modern, CM Bright
1444 else if (sf != "default")
1445 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1447 // monospaced/typewriter
1448 // Courier, LuxiMono
1449 if (tt == "luximono" || tt == "beramono") {
1451 os << "\\usepackage[scaled=" << float(ttscale) / 100
1452 << "]{" << tt << "}\n";
1454 os << "\\usepackage{" << tt << "}\n";
1457 else if (tt == "courier" )
1458 os << "\\usepackage{" << tt << "}\n";
1459 // Computer Modern, Latin Modern, CM Bright
1460 else if (tt != "default")
1461 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1467 Encoding const & BufferParams::encoding() const
1469 if (inputenc == "auto")
1470 return *(language->encoding());
1471 Encoding const * const enc = (inputenc == "default") ?
1472 encodings.getFromLyXName("iso8859-1") :
1473 encodings.getFromLaTeXName(inputenc);
1476 if (inputenc == "default")
1477 lyxerr << "Could not find iso8859-1 encoding for inputenc "
1478 "value `default'. Using inputenc `auto' instead."
1481 lyxerr << "Unknown inputenc value `" << inputenc
1482 << "'. Using `auto' instead." << endl;
1483 return *(language->encoding());