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 os << "\\usepackage[";
855 std::set<string>::const_iterator it = encodings.begin();
856 std::set<string>::const_iterator const end = encodings.end();
857 for (; it != end; ++it)
858 os << from_ascii(*it) << ',';
859 os << from_ascii(doc_encoding) << "]{inputenc}\n";
861 } else if (inputenc != "default") {
862 os << "\\usepackage[" << 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 << from_ascii(paperwidth);
878 if (!paperheight.empty())
879 os << ",paperheight="
880 << 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=" << from_ascii(topmargin);
942 if (!bottommargin.empty())
943 os << ",bmargin=" << from_ascii(bottommargin);
944 if (!leftmargin.empty())
945 os << ",lmargin=" << from_ascii(leftmargin);
946 if (!rightmargin.empty())
947 os << ",rmargin=" << from_ascii(rightmargin);
948 if (!headheight.empty())
949 os << ",headheight=" << from_ascii(headheight);
950 if (!headsep.empty())
951 os << ",headsep=" << from_ascii(headsep);
952 if (!footskip.empty())
953 os << ",footskip=" << from_ascii(footskip);
958 if (tokenPos(tclass.opt_pagestyle(),
959 '|', pagestyle) >= 0) {
960 if (pagestyle == "fancy") {
961 os << "\\usepackage{fancyhdr}\n";
964 os << "\\pagestyle{" << 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 << from_utf8(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 << from_ascii(babelCall(language_options.str()))
1014 << from_ascii(features.getBabelOptions());
1018 // Now insert the LyX specific LaTeX commands...
1020 // The optional packages;
1021 docstring lyxpreamble(from_ascii(features.getPackages()));
1023 // this might be useful...
1024 lyxpreamble += "\n\\makeatletter\n";
1026 // Some macros LyX will need
1027 docstring tmppreamble(from_ascii(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()) {
1046 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1047 "User specified LaTeX commands.\n"
1048 + from_utf8(preamble) + '\n';
1051 // Itemize bullet settings need to be last in case the user
1052 // defines their own bullets that use a package included
1053 // in the user-defined preamble -- ARRae
1054 // Actually it has to be done much later than that
1055 // since some packages like frenchb make modifications
1056 // at \begin{document} time -- JMarc
1057 docstring bullets_def;
1058 for (int i = 0; i < 4; ++i) {
1059 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1060 if (bullets_def.empty())
1061 bullets_def += "\\AtBeginDocument{\n";
1062 bullets_def += " \\def\\labelitemi";
1064 // `i' is one less than the item to modify
1071 bullets_def += "ii";
1077 bullets_def += '{' +
1078 user_defined_bullet(i).getText()
1083 if (!bullets_def.empty())
1084 lyxpreamble += bullets_def + "}\n\n";
1086 // We try to load babel late, in case it interferes
1087 // with other packages.
1088 // Jurabib has to be called after babel, though.
1089 if (use_babel && !features.isRequired("jurabib")) {
1091 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1092 lyxpreamble += from_utf8(features.getBabelOptions());
1095 lyxpreamble += "\\makeatother\n";
1097 // dvipost settings come after everything else
1098 if (features.isAvailable("dvipost") && outputChanges) {
1101 "\\dvipost{osstart color push Red}\n"
1102 "\\dvipost{osend color pop}\n"
1103 "\\dvipost{cbstart color push Blue}\n"
1104 "\\dvipost{cbend color pop}\n";
1108 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1109 for (int j = 0; j != nlines; ++j) {
1118 void BufferParams::useClassDefaults()
1120 LyXTextClass const & tclass = textclasslist[textclass];
1122 sides = tclass.sides();
1123 columns = tclass.columns();
1124 pagestyle = tclass.pagestyle();
1125 options = tclass.options();
1126 // Only if class has a ToC hierarchy
1127 if (tclass.hasTocLevels()) {
1128 secnumdepth = tclass.secnumdepth();
1129 tocdepth = tclass.tocdepth();
1134 bool BufferParams::hasClassDefaults() const
1136 LyXTextClass const & tclass = textclasslist[textclass];
1138 return (sides == tclass.sides()
1139 && columns == tclass.columns()
1140 && pagestyle == tclass.pagestyle()
1141 && options == tclass.options()
1142 && secnumdepth == tclass.secnumdepth()
1143 && tocdepth == tclass.tocdepth());
1147 LyXTextClass const & BufferParams::getLyXTextClass() const
1149 return textclasslist[textclass];
1153 LyXFont const BufferParams::getFont() const
1155 LyXFont f = getLyXTextClass().defaultfont();
1156 f.setLanguage(language);
1157 if (fontsDefaultFamily == "rmdefault")
1158 f.setFamily(LyXFont::ROMAN_FAMILY);
1159 else if (fontsDefaultFamily == "sfdefault")
1160 f.setFamily(LyXFont::SANS_FAMILY);
1161 else if (fontsDefaultFamily == "ttdefault")
1162 f.setFamily(LyXFont::TYPEWRITER_FAMILY);
1167 void BufferParams::readPreamble(LyXLex & lex)
1169 if (lex.getString() != "\\begin_preamble")
1170 lyxerr << "Error (BufferParams::readPreamble):"
1171 "consistency check failed." << endl;
1173 preamble = lex.getLongString("\\end_preamble");
1177 void BufferParams::readLanguage(LyXLex & lex)
1179 if (!lex.next()) return;
1181 string const tmptok = lex.getString();
1183 // check if tmptok is part of tex_babel in tex-defs.h
1184 language = languages.getLanguage(tmptok);
1186 // Language tmptok was not found
1187 language = default_language;
1188 lyxerr << "Warning: Setting language `"
1189 << tmptok << "' to `" << language->lang()
1195 void BufferParams::readGraphicsDriver(LyXLex & lex)
1197 if (!lex.next()) return;
1199 string const tmptok = lex.getString();
1200 // check if tmptok is part of tex_graphics in tex_defs.h
1203 string const test = tex_graphics[n++];
1205 if (test == tmptok) {
1206 graphicsDriver = tmptok;
1208 } else if (test == "") {
1210 "Warning: graphics driver `$$Token' not recognized!\n"
1211 " Setting graphics driver to `default'.\n");
1212 graphicsDriver = "default";
1219 void BufferParams::readBullets(LyXLex & lex)
1221 if (!lex.next()) return;
1223 int const index = lex.getInteger();
1225 int temp_int = lex.getInteger();
1226 user_defined_bullet(index).setFont(temp_int);
1227 temp_bullet(index).setFont(temp_int);
1229 user_defined_bullet(index).setCharacter(temp_int);
1230 temp_bullet(index).setCharacter(temp_int);
1232 user_defined_bullet(index).setSize(temp_int);
1233 temp_bullet(index).setSize(temp_int);
1237 void BufferParams::readBulletsLaTeX(LyXLex & lex)
1239 // The bullet class should be able to read this.
1240 if (!lex.next()) return;
1241 int const index = lex.getInteger();
1243 docstring const temp_str = lex.getDocString();
1245 user_defined_bullet(index).setText(temp_str);
1246 temp_bullet(index).setText(temp_str);
1250 string const BufferParams::paperSizeName() const
1252 char real_papersize = papersize;
1253 if (real_papersize == PAPER_DEFAULT)
1254 real_papersize = lyxrc.default_papersize;
1256 switch (real_papersize) {
1265 case PAPER_USEXECUTIVE:
1269 case PAPER_USLETTER:
1276 string const BufferParams::dvips_options() const
1281 && papersize == PAPER_CUSTOM
1282 && !lyxrc.print_paper_dimension_flag.empty()
1283 && !paperwidth.empty()
1284 && !paperheight.empty()) {
1285 // using a custom papersize
1286 result = lyxrc.print_paper_dimension_flag;
1287 result += ' ' + paperwidth;
1288 result += ',' + paperheight;
1290 string const paper_option = paperSizeName();
1291 if (paper_option != "letter" ||
1292 orientation != ORIENTATION_LANDSCAPE) {
1293 // dvips won't accept -t letter -t landscape.
1294 // In all other cases, include the paper size
1296 result = lyxrc.print_paper_flag;
1297 result += ' ' + paper_option;
1300 if (orientation == ORIENTATION_LANDSCAPE &&
1301 papersize != PAPER_CUSTOM)
1302 result += ' ' + lyxrc.print_landscape_flag;
1307 string const BufferParams::babelCall(string const & lang_opts) const
1309 string tmp = lyxrc.language_package;
1310 if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1311 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1316 string const BufferParams::loadFonts(LaTeXFeatures & features, string const & rm,
1317 string const & sf, string const & tt,
1318 bool const & sc, bool const & osf,
1319 int const & sfscale, int const & ttscale) const
1321 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1322 several packages have been replaced by others, that might not
1323 be installed on every system. We have to take care for that
1324 (see psnfss.pdf). We try to support all psnfss fonts as well
1325 as the fonts that have become de facto standard in the LaTeX
1326 world (e.g. Latin Modern). We do not support obsolete fonts
1327 (like PSLatex). In general, it should be possible to mix any
1328 rm font with any sf or tt font, respectively. (JSpitzm)
1330 -- separate math fonts.
1333 if (rm == "default" && sf == "default" && tt == "default")
1340 // Computer Modern (must be explicitely selectable -- there might be classes
1341 // that define a different default font!
1343 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1344 // osf for Computer Modern needs eco.sty
1346 os << "\\usepackage{eco}\n";
1348 // Latin Modern Roman
1349 else if (rm == "lmodern")
1350 os << "\\usepackage{lmodern}\n";
1352 else if (rm == "ae") {
1353 // not needed when using OT1 font encoding.
1354 if (lyxrc.fontenc != "default")
1355 os << "\\usepackage{ae,aecompl}\n";
1358 else if (rm == "times") {
1359 // try to load the best available package
1360 if (features.isAvailable("mathptmx"))
1361 os << "\\usepackage{mathptmx}\n";
1362 else if (features.isAvailable("mathptm"))
1363 os << "\\usepackage{mathptm}\n";
1365 os << "\\usepackage{times}\n";
1368 else if (rm == "palatino") {
1369 // try to load the best available package
1370 if (features.isAvailable("mathpazo")) {
1371 os << "\\usepackage";
1377 // "osf" includes "sc"!
1381 os << "{mathpazo}\n";
1383 else if (features.isAvailable("mathpple"))
1384 os << "\\usepackage{mathpple}\n";
1386 os << "\\usepackage{palatino}\n";
1389 else if (rm == "utopia") {
1390 // fourier supersedes utopia.sty, but does
1391 // not work with OT1 encoding.
1392 if (features.isAvailable("fourier")
1393 && lyxrc.fontenc != "default") {
1394 os << "\\usepackage";
1405 os << "{fourier}\n";
1408 os << "\\usepackage{utopia}\n";
1410 // Bera (complete fontset)
1411 else if (rm == "bera" && sf == "default" && tt == "default")
1412 os << "\\usepackage{bera}\n";
1414 else if (rm != "default")
1415 os << "\\usepackage" << "{" << rm << "}\n";
1418 // Helvetica, Bera Sans
1419 if (sf == "helvet" || sf == "berasans") {
1421 os << "\\usepackage[scaled=" << float(sfscale) / 100
1422 << "]{" << sf << "}\n";
1424 os << "\\usepackage{" << sf << "}\n";
1427 else if (sf == "avant")
1428 os << "\\usepackage{" << sf << "}\n";
1429 // Computer Modern, Latin Modern, CM Bright
1430 else if (sf != "default")
1431 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1433 // monospaced/typewriter
1434 // Courier, LuxiMono
1435 if (tt == "luximono" || tt == "beramono") {
1437 os << "\\usepackage[scaled=" << float(ttscale) / 100
1438 << "]{" << tt << "}\n";
1440 os << "\\usepackage{" << tt << "}\n";
1443 else if (tt == "courier" )
1444 os << "\\usepackage{" << tt << "}\n";
1445 // Computer Modern, Latin Modern, CM Bright
1446 else if (tt != "default")
1447 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1453 Encoding const & BufferParams::encoding() const
1455 if (inputenc == "auto")
1456 return *(language->encoding());
1457 Encoding const * const enc = encodings.getFromLaTeXName(inputenc);
1460 lyxerr << "Unknown inputenc value `" << inputenc
1461 << "'. Using `auto' instead." << endl;
1462 return *(language->encoding());