2 * \file BufferParams.cpp
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"
33 #include "TextClassList.h"
34 #include "OutputParams.h"
39 #include "frontends/alert.h"
40 #include "insets/InsetListingsParams.h"
42 #include "support/lyxalgo.h" // for lyx::count
43 #include "support/convert.h"
44 #include "support/Translator.h"
46 #include <boost/array.hpp>
52 using std::istringstream;
54 using std::ostringstream;
57 using lyx::support::bformat;
58 using lyx::support::rtrim;
59 using lyx::support::tokenPos;
62 static char const * const string_paragraph_separation[] = {
67 static char const * const string_quotes_language[] = {
68 "english", "swedish", "german", "polish", "french", "danish", ""
72 static char const * const string_papersize[] = {
73 "default", "custom", "letterpaper", "executivepaper", "legalpaper",
74 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
78 static char const * const string_orientation[] = {
79 "portrait", "landscape", ""
83 static char const * const string_footnotekinds[] = {
84 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
88 static char const * const tex_graphics[] = {
89 "default", "dvips", "dvitops", "emtex",
90 "ln", "oztex", "textures", "none", ""
99 // Paragraph separation
100 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
103 ParSepTranslator const init_parseptranslator()
105 ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
106 translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
111 ParSepTranslator const & parseptranslator()
113 static ParSepTranslator translator = init_parseptranslator();
119 typedef Translator<string, InsetQuotes::quote_language> QuotesLangTranslator;
122 QuotesLangTranslator const init_quoteslangtranslator()
124 QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
125 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
126 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
127 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
128 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
129 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
134 QuotesLangTranslator const & quoteslangtranslator()
136 static QuotesLangTranslator translator = init_quoteslangtranslator();
142 typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
145 PaperSizeTranslator const init_papersizetranslator()
147 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
148 translator.addPair(string_papersize[1], PAPER_CUSTOM);
149 translator.addPair(string_papersize[2], PAPER_USLETTER);
150 translator.addPair(string_papersize[3], PAPER_USLEGAL);
151 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
152 translator.addPair(string_papersize[5], PAPER_A3);
153 translator.addPair(string_papersize[6], PAPER_A4);
154 translator.addPair(string_papersize[7], PAPER_A5);
155 translator.addPair(string_papersize[8], PAPER_B3);
156 translator.addPair(string_papersize[9], PAPER_B4);
157 translator.addPair(string_papersize[10], PAPER_B5);
162 PaperSizeTranslator const & papersizetranslator()
164 static PaperSizeTranslator translator = init_papersizetranslator();
170 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
173 PaperOrientationTranslator const init_paperorientationtranslator()
175 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
176 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
181 PaperOrientationTranslator const & paperorientationtranslator()
183 static PaperOrientationTranslator translator = init_paperorientationtranslator();
189 typedef Translator<int, TextClass::PageSides> SidesTranslator;
192 SidesTranslator const init_sidestranslator()
194 SidesTranslator translator(1, TextClass::OneSide);
195 translator.addPair(2, TextClass::TwoSides);
200 SidesTranslator const & sidestranslator()
202 static SidesTranslator translator = init_sidestranslator();
208 typedef Translator<int, BufferParams::Package> PackageTranslator;
211 PackageTranslator const init_packagetranslator()
213 PackageTranslator translator(0, BufferParams::package_off);
214 translator.addPair(1, BufferParams::package_auto);
215 translator.addPair(2, BufferParams::package_on);
220 PackageTranslator const & packagetranslator()
222 static PackageTranslator translator = init_packagetranslator();
228 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
231 CiteEngineTranslator const init_citeenginetranslator()
233 CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
234 translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
235 translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
236 translator.addPair("jurabib", biblio::ENGINE_JURABIB);
241 CiteEngineTranslator const & citeenginetranslator()
243 static CiteEngineTranslator translator = init_citeenginetranslator();
249 typedef Translator<string, Spacing::Space> SpaceTranslator;
252 SpaceTranslator const init_spacetranslator()
254 SpaceTranslator translator("default", Spacing::Default);
255 translator.addPair("single", Spacing::Single);
256 translator.addPair("onehalf", Spacing::Onehalf);
257 translator.addPair("double", Spacing::Double);
258 translator.addPair("other", Spacing::Other);
263 SpaceTranslator const & spacetranslator()
265 static SpaceTranslator translator = init_spacetranslator();
270 textclass_type defaultTextclass()
272 // Initialize textclass to point to article. if `first' is
273 // true in the returned pair, then `second' is the textclass
274 // number; if it is false, second is 0. In both cases, second
276 return textclasslist.numberOfClass("article").second;
282 class BufferParams::Impl
287 AuthorList authorlist;
288 BranchList branchlist;
289 boost::array<Bullet, 4> temp_bullets;
290 boost::array<Bullet, 4> user_defined_bullets;
292 /** This is the amount of space used for paragraph_separation "skip",
293 * and for detached paragraphs in "indented" documents.
299 BufferParams::Impl::Impl()
300 : defskip(VSpace::MEDSKIP)
302 // set initial author
304 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
309 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
313 return new BufferParams::Impl(*ptr);
317 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
323 BufferParams::BufferParams()
324 : textclass(defaultTextclass()), pimpl_(new Impl)
326 paragraph_separation = PARSEP_INDENT;
327 quotes_language = InsetQuotes::EnglishQ;
328 fontsize = "default";
331 papersize = PAPER_DEFAULT;
332 orientation = ORIENTATION_PORTRAIT;
333 use_geometry = false;
334 use_amsmath = package_auto;
335 use_esint = package_auto;
336 cite_engine_ = biblio::ENGINE_BASIC;
337 use_bibtopic = false;
338 trackChanges = false;
339 outputChanges = false;
342 language = default_language;
343 fontsRoman = "default";
344 fontsSans = "default";
345 fontsTypewriter = "default";
346 fontsDefaultFamily = "default";
349 fontsSansScale = 100;
350 fontsTypewriterScale = 100;
352 graphicsDriver = "default";
353 sides = TextClass::OneSide;
355 listings_params = string();
356 pagestyle = "default";
358 for (int iter = 0; iter < 4; ++iter) {
359 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
360 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
365 BufferParams::~BufferParams()
369 docstring const BufferParams::B_(string const & l10n) const
371 BOOST_ASSERT(language);
372 return getMessages(language->code()).get(l10n);
376 AuthorList & BufferParams::authors()
378 return pimpl_->authorlist;
382 AuthorList const & BufferParams::authors() const
384 return pimpl_->authorlist;
388 BranchList & BufferParams::branchlist()
390 return pimpl_->branchlist;
394 BranchList const & BufferParams::branchlist() const
396 return pimpl_->branchlist;
400 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
402 BOOST_ASSERT(index < 4);
403 return pimpl_->temp_bullets[index];
407 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
409 BOOST_ASSERT(index < 4);
410 return pimpl_->temp_bullets[index];
414 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
416 BOOST_ASSERT(index < 4);
417 return pimpl_->user_defined_bullets[index];
421 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
423 BOOST_ASSERT(index < 4);
424 return pimpl_->user_defined_bullets[index];
428 Spacing & BufferParams::spacing()
430 return pimpl_->spacing;
434 Spacing const & BufferParams::spacing() const
436 return pimpl_->spacing;
440 VSpace const & BufferParams::getDefSkip() const
442 return pimpl_->defskip;
446 void BufferParams::setDefSkip(VSpace const & vs)
448 pimpl_->defskip = vs;
452 string const BufferParams::readToken(Lexer & lex, string const & token)
454 if (token == "\\textclass") {
456 string const classname = lex.getString();
457 pair<bool, lyx::textclass_type> pp =
458 textclasslist.numberOfClass(classname);
460 textclass = pp.second;
462 // if text class does not exist, try to load it from filepath
463 pp = textclasslist.addTextClass(classname, filepath);
465 textclass = pp.second;
467 textclass = defaultTextclass();
471 // FIXME: isTeXClassAvailable will try to load the layout file, but will
472 // fail because of the lack of path info. Warnings will be given although
473 // the layout file will be correctly loaded later.
474 if (!getTextClass().isTeXClassAvailable()) {
475 docstring const msg =
476 bformat(_("The layout file requested by this document,\n"
478 "is not usable. This is probably because a LaTeX\n"
479 "class or style file required by it is not\n"
480 "available. See the Customization documentation\n"
481 "for more information.\n"), from_utf8(classname));
482 frontend::Alert::warning(_("Document class not available"),
483 msg + _("LyX will not be able to produce output."));
485 } else if (token == "\\begin_preamble") {
487 } else if (token == "\\options") {
489 options = lex.getString();
490 } else if (token == "\\language") {
492 } else if (token == "\\inputencoding") {
494 } else if (token == "\\graphics") {
495 readGraphicsDriver(lex);
496 } else if (token == "\\font_roman") {
498 } else if (token == "\\font_sans") {
500 } else if (token == "\\font_typewriter") {
501 lex >> fontsTypewriter;
502 } else if (token == "\\font_default_family") {
503 lex >> fontsDefaultFamily;
504 } else if (token == "\\font_sc") {
506 } else if (token == "\\font_osf") {
508 } else if (token == "\\font_sf_scale") {
509 lex >> fontsSansScale;
510 } else if (token == "\\font_tt_scale") {
511 lex >> fontsTypewriterScale;
512 } else if (token == "\\paragraph_separation") {
515 paragraph_separation = parseptranslator().find(parsep);
516 } else if (token == "\\defskip") {
518 pimpl_->defskip = VSpace(lex.getString());
519 } else if (token == "\\quotes_language") {
522 quotes_language = quoteslangtranslator().find(quotes_lang);
523 } else if (token == "\\papersize") {
526 papersize = papersizetranslator().find(ppsize);
527 } else if (token == "\\use_geometry") {
529 } else if (token == "\\use_amsmath") {
532 use_amsmath = packagetranslator().find(use_ams);
533 } else if (token == "\\use_esint") {
536 use_esint = packagetranslator().find(useesint);
537 } else if (token == "\\cite_engine") {
540 cite_engine_ = citeenginetranslator().find(engine);
541 } else if (token == "\\use_bibtopic") {
543 } else if (token == "\\tracking_changes") {
545 } else if (token == "\\output_changes") {
546 lex >> outputChanges;
547 } else if (token == "\\branch") {
549 docstring branch = lex.getDocString();
550 branchlist().add(branch);
553 string const tok = lex.getString();
554 if (tok == "\\end_branch")
556 Branch * branch_ptr = branchlist().find(branch);
557 if (tok == "\\selected") {
560 branch_ptr->setSelected(lex.getInteger());
562 // not yet operational
563 if (tok == "\\color") {
565 string color = lex.getString();
567 branch_ptr->setColor(color);
568 // Update also the Color table:
570 color = lcolor.getX11Name(Color::background);
572 lcolor.setColor(to_utf8(branch), color);
576 } else if (token == "\\author") {
578 istringstream ss(lex.getString());
581 author_map.push_back(pimpl_->authorlist.record(a));
582 } else if (token == "\\paperorientation") {
585 orientation = paperorientationtranslator().find(orient);
586 } else if (token == "\\paperwidth") {
588 } else if (token == "\\paperheight") {
590 } else if (token == "\\leftmargin") {
592 } else if (token == "\\topmargin") {
594 } else if (token == "\\rightmargin") {
596 } else if (token == "\\bottommargin") {
598 } else if (token == "\\headheight") {
600 } else if (token == "\\headsep") {
602 } else if (token == "\\footskip") {
604 } else if (token == "\\paperfontsize") {
606 } else if (token == "\\papercolumns") {
608 } else if (token == "\\listings_params") {
611 // validate par and produce a valid listings parameter string
613 listings_params = InsetListingsParams(par).params();
614 } catch (invalidParam & e) {
615 lyxerr << "Invalid parameter string " << par << endl;
616 lyxerr << e.what() << endl;
617 listings_params = string();
619 } else if (token == "\\papersides") {
622 sides = sidestranslator().find(psides);
623 } else if (token == "\\paperpagestyle") {
625 } else if (token == "\\bullet") {
627 } else if (token == "\\bulletLaTeX") {
628 readBulletsLaTeX(lex);
629 } else if (token == "\\secnumdepth") {
631 } else if (token == "\\tocdepth") {
633 } else if (token == "\\spacing") {
637 if (nspacing == "other") {
640 spacing().set(spacetranslator().find(nspacing), tmp_val);
641 } else if (token == "\\float_placement") {
642 lex >> float_placement;
651 void BufferParams::writeFile(ostream & os) const
653 // The top of the file is written by the buffer.
654 // Prints out the buffer info into the .lyx file given by file
657 os << "\\textclass " << textclasslist[textclass].name() << '\n';
660 if (!preamble.empty()) {
661 // remove '\n' from the end of preamble
662 string const tmppreamble = rtrim(preamble, "\n");
663 os << "\\begin_preamble\n"
665 << "\n\\end_preamble\n";
669 if (!options.empty()) {
670 os << "\\options " << options << '\n';
673 // then the text parameters
674 if (language != ignore_language)
675 os << "\\language " << language->lang() << '\n';
676 os << "\\inputencoding " << inputenc
677 << "\n\\font_roman " << fontsRoman
678 << "\n\\font_sans " << fontsSans
679 << "\n\\font_typewriter " << fontsTypewriter
680 << "\n\\font_default_family " << fontsDefaultFamily
681 << "\n\\font_sc " << convert<string>(fontsSC)
682 << "\n\\font_osf " << convert<string>(fontsOSF)
683 << "\n\\font_sf_scale " << fontsSansScale
684 << "\n\\font_tt_scale " << fontsTypewriterScale
685 << "\n\\graphics " << graphicsDriver << '\n';
687 if (!float_placement.empty()) {
688 os << "\\float_placement " << float_placement << '\n';
690 os << "\\paperfontsize " << fontsize << '\n';
692 spacing().writeFile(os);
694 os << "\\papersize " << string_papersize[papersize]
695 << "\n\\use_geometry " << convert<string>(use_geometry)
696 << "\n\\use_amsmath " << use_amsmath
697 << "\n\\use_esint " << use_esint
698 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
699 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
700 << "\n\\paperorientation " << string_orientation[orientation]
703 BranchList::const_iterator it = branchlist().begin();
704 BranchList::const_iterator end = branchlist().end();
705 for (; it != end; ++it) {
706 os << "\\branch " << to_utf8(it->getBranch())
707 << "\n\\selected " << it->getSelected()
708 << "\n\\color " << lyx::X11hexname(it->getColor())
713 if (!paperwidth.empty())
714 os << "\\paperwidth "
715 << VSpace(paperwidth).asLyXCommand() << '\n';
716 if (!paperheight.empty())
717 os << "\\paperheight "
718 << VSpace(paperheight).asLyXCommand() << '\n';
719 if (!leftmargin.empty())
720 os << "\\leftmargin "
721 << VSpace(leftmargin).asLyXCommand() << '\n';
722 if (!topmargin.empty())
724 << VSpace(topmargin).asLyXCommand() << '\n';
725 if (!rightmargin.empty())
726 os << "\\rightmargin "
727 << VSpace(rightmargin).asLyXCommand() << '\n';
728 if (!bottommargin.empty())
729 os << "\\bottommargin "
730 << VSpace(bottommargin).asLyXCommand() << '\n';
731 if (!headheight.empty())
732 os << "\\headheight "
733 << VSpace(headheight).asLyXCommand() << '\n';
734 if (!headsep.empty())
736 << VSpace(headsep).asLyXCommand() << '\n';
737 if (!footskip.empty())
739 << VSpace(footskip).asLyXCommand() << '\n';
740 os << "\\secnumdepth " << secnumdepth
741 << "\n\\tocdepth " << tocdepth
742 << "\n\\paragraph_separation "
743 << string_paragraph_separation[paragraph_separation]
744 << "\n\\defskip " << getDefSkip().asLyXCommand()
745 << "\n\\quotes_language "
746 << string_quotes_language[quotes_language]
747 << "\n\\papercolumns " << columns
748 << "\n\\papersides " << sides
749 << "\n\\paperpagestyle " << pagestyle << '\n';
750 if (!listings_params.empty())
751 os << "\\listings_params \"" <<
752 InsetListingsParams(listings_params).encodedString() << "\"\n";
753 for (int i = 0; i < 4; ++i) {
754 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
755 if (user_defined_bullet(i).getFont() != -1) {
756 os << "\\bullet " << i << " "
757 << user_defined_bullet(i).getFont() << " "
758 << user_defined_bullet(i).getCharacter() << " "
759 << user_defined_bullet(i).getSize() << "\n";
763 os << "\\bulletLaTeX " << i << " \""
764 << lyx::to_ascii(user_defined_bullet(i).getText())
770 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
771 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
773 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
774 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
775 for (; a_it != a_end; ++a_it) {
776 os << "\\author " << a_it->second << "\n";
781 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
782 TexRow & texrow) const
784 os << "\\documentclass";
786 TextClass const & tclass = getTextClass();
788 ostringstream clsoptions; // the document class options.
790 if (tokenPos(tclass.opt_fontsize(),
791 '|', fontsize) >= 0) {
792 // only write if existing in list (and not default)
793 clsoptions << fontsize << "pt,";
796 // custom, A3, B3 and B4 paper sizes need geometry
797 bool nonstandard_papersize = papersize == PAPER_B3
798 || papersize == PAPER_B4
799 || papersize == PAPER_A3
800 || papersize == PAPER_CUSTOM;
805 clsoptions << "a4paper,";
808 clsoptions << "letterpaper,";
811 clsoptions << "a5paper,";
814 clsoptions << "b5paper,";
816 case PAPER_USEXECUTIVE:
817 clsoptions << "executivepaper,";
820 clsoptions << "legalpaper,";
832 if (sides != tclass.sides()) {
834 case TextClass::OneSide:
835 clsoptions << "oneside,";
837 case TextClass::TwoSides:
838 clsoptions << "twoside,";
844 if (columns != tclass.columns()) {
846 clsoptions << "twocolumn,";
848 clsoptions << "onecolumn,";
852 && orientation == ORIENTATION_LANDSCAPE)
853 clsoptions << "landscape,";
855 // language should be a parameter to \documentclass
856 if (language->babel() == "hebrew"
857 && default_language->babel() != "hebrew")
858 // This seems necessary
859 features.useLanguage(default_language);
861 ostringstream language_options;
862 bool const use_babel = features.useBabel();
864 language_options << features.getLanguages();
865 if (!language->babel().empty()) {
866 if (!language_options.str().empty())
867 language_options << ',';
868 language_options << language->babel();
870 if (lyxrc.language_global_options && !language_options.str().empty())
871 clsoptions << language_options.str() << ',';
874 // the user-defined options
875 if (!options.empty()) {
876 clsoptions << options << ',';
879 string strOptions(clsoptions.str());
880 if (!strOptions.empty()) {
881 strOptions = rtrim(strOptions, ",");
883 os << '[' << from_utf8(strOptions) << ']';
886 os << '{' << from_ascii(tclass.latexname()) << "}\n";
888 // end of \documentclass defs
890 // font selection must be done before loading fontenc.sty
892 loadFonts(fontsRoman, fontsSans,
893 fontsTypewriter, fontsSC, fontsOSF,
894 fontsSansScale, fontsTypewriterScale);
895 if (!fonts.empty()) {
896 os << from_ascii(fonts);
899 if (fontsDefaultFamily != "default")
900 os << "\\renewcommand{\\familydefault}{\\"
901 << from_ascii(fontsDefaultFamily) << "}\n";
902 // this one is not per buffer
903 if (lyxrc.fontenc != "default") {
904 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
909 if (inputenc == "auto") {
910 string const doc_encoding =
911 language->encoding()->latexName();
912 Encoding::Package const package =
913 language->encoding()->package();
915 // Create a list with all the input encodings used
917 std::set<string> encodings =
918 features.getEncodingSet(doc_encoding);
920 if (!encodings.empty() || package == Encoding::inputenc) {
921 os << "\\usepackage[";
922 std::set<string>::const_iterator it = encodings.begin();
923 std::set<string>::const_iterator const end = encodings.end();
925 os << from_ascii(*it);
928 for (; it != end; ++it)
929 os << ',' << from_ascii(*it);
930 if (package == Encoding::inputenc) {
931 if (!encodings.empty())
933 os << from_ascii(doc_encoding);
935 os << "]{inputenc}\n";
938 if (package == Encoding::CJK) {
939 os << "\\usepackage{CJK}\n";
942 } else if (inputenc != "default") {
943 switch (language->encoding()->package()) {
946 case Encoding::inputenc:
947 os << "\\usepackage[" << from_ascii(inputenc)
952 os << "\\usepackage{CJK}\n";
958 // The encoding "armscii8" is only available when the package "armtex" is loaded.
959 // armscii8 is used for Armenian.
960 if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
961 os << "\\usepackage{armtex}\n";
965 if (!listings_params.empty()) {
966 os << "\\usepackage{listings}\n";
969 // do not test validity because listings_params is supposed to be valid
970 string par = InsetListingsParams(listings_params).separatedParams(true);
971 os << from_ascii(par);
972 // count the number of newlines
973 for (size_t i = 0; i < par.size(); ++i)
979 if (use_geometry || nonstandard_papersize) {
980 os << "\\usepackage{geometry}\n";
982 os << "\\geometry{verbose";
983 if (orientation == ORIENTATION_LANDSCAPE)
987 if (!paperwidth.empty())
989 << from_ascii(paperwidth);
990 if (!paperheight.empty())
991 os << ",paperheight="
992 << from_ascii(paperheight);
995 os << ",letterpaper";
1000 case PAPER_USEXECUTIVE:
1001 os << ",executivepaper";
1022 // default papersize ie PAPER_DEFAULT
1023 switch (lyxrc.default_papersize) {
1024 case PAPER_DEFAULT: // keep compiler happy
1025 case PAPER_USLETTER:
1026 os << ",letterpaper";
1029 os << ",legalpaper";
1031 case PAPER_USEXECUTIVE:
1032 os << ",executivepaper";
1052 if (!topmargin.empty())
1053 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1054 if (!bottommargin.empty())
1055 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1056 if (!leftmargin.empty())
1057 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1058 if (!rightmargin.empty())
1059 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1060 if (!headheight.empty())
1061 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1062 if (!headsep.empty())
1063 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1064 if (!footskip.empty())
1065 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1070 if (tokenPos(tclass.opt_pagestyle(),
1071 '|', pagestyle) >= 0) {
1072 if (pagestyle == "fancy") {
1073 os << "\\usepackage{fancyhdr}\n";
1076 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1080 // Only if class has a ToC hierarchy
1081 if (tclass.hasTocLevels()) {
1082 if (secnumdepth != tclass.secnumdepth()) {
1083 os << "\\setcounter{secnumdepth}{"
1088 if (tocdepth != tclass.tocdepth()) {
1089 os << "\\setcounter{tocdepth}{"
1096 if (paragraph_separation) {
1097 switch (getDefSkip().kind()) {
1098 case VSpace::SMALLSKIP:
1099 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1101 case VSpace::MEDSKIP:
1102 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1104 case VSpace::BIGSKIP:
1105 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1107 case VSpace::LENGTH:
1108 os << "\\setlength{\\parskip}{"
1109 << from_utf8(getDefSkip().length().asLatexString())
1112 default: // should never happen // Then delete it.
1113 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1118 os << "\\setlength{\\parindent}{0pt}\n";
1122 // If we use jurabib, we have to call babel here.
1123 if (use_babel && features.isRequired("jurabib")) {
1124 os << from_ascii(babelCall(language_options.str()))
1126 << from_ascii(features.getBabelOptions());
1130 // Now insert the LyX specific LaTeX commands...
1132 // The optional packages;
1133 docstring lyxpreamble(from_ascii(features.getPackages()));
1135 // this might be useful...
1136 lyxpreamble += "\n\\makeatletter\n";
1138 // Some macros LyX will need
1139 docstring tmppreamble(from_ascii(features.getMacros()));
1141 if (!tmppreamble.empty()) {
1142 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1143 "LyX specific LaTeX commands.\n"
1144 + tmppreamble + '\n';
1147 // the text class specific preamble
1148 tmppreamble = features.getTClassPreamble();
1149 if (!tmppreamble.empty()) {
1150 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1151 "Textclass specific LaTeX commands.\n"
1152 + tmppreamble + '\n';
1155 /* the user-defined preamble */
1156 if (!preamble.empty()) {
1158 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1159 "User specified LaTeX commands.\n"
1160 + from_utf8(preamble) + '\n';
1163 // Itemize bullet settings need to be last in case the user
1164 // defines their own bullets that use a package included
1165 // in the user-defined preamble -- ARRae
1166 // Actually it has to be done much later than that
1167 // since some packages like frenchb make modifications
1168 // at \begin{document} time -- JMarc
1169 docstring bullets_def;
1170 for (int i = 0; i < 4; ++i) {
1171 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1172 if (bullets_def.empty())
1173 bullets_def += "\\AtBeginDocument{\n";
1174 bullets_def += " \\def\\labelitemi";
1176 // `i' is one less than the item to modify
1183 bullets_def += "ii";
1189 bullets_def += '{' +
1190 user_defined_bullet(i).getText()
1195 if (!bullets_def.empty())
1196 lyxpreamble += bullets_def + "}\n\n";
1198 // We try to load babel late, in case it interferes
1199 // with other packages.
1200 // Jurabib has to be called after babel, though.
1201 if (use_babel && !features.isRequired("jurabib")) {
1203 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1204 lyxpreamble += from_utf8(features.getBabelOptions());
1207 lyxpreamble += "\\makeatother\n";
1210 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1211 for (int j = 0; j != nlines; ++j) {
1220 void BufferParams::useClassDefaults()
1222 TextClass const & tclass = textclasslist[textclass];
1224 sides = tclass.sides();
1225 columns = tclass.columns();
1226 pagestyle = tclass.pagestyle();
1227 options = tclass.options();
1228 // Only if class has a ToC hierarchy
1229 if (tclass.hasTocLevels()) {
1230 secnumdepth = tclass.secnumdepth();
1231 tocdepth = tclass.tocdepth();
1236 bool BufferParams::hasClassDefaults() const
1238 TextClass const & tclass = textclasslist[textclass];
1240 return (sides == tclass.sides()
1241 && columns == tclass.columns()
1242 && pagestyle == tclass.pagestyle()
1243 && options == tclass.options()
1244 && secnumdepth == tclass.secnumdepth()
1245 && tocdepth == tclass.tocdepth());
1249 TextClass const & BufferParams::getTextClass() const
1251 return textclasslist[textclass];
1255 Font const BufferParams::getFont() const
1257 Font f = getTextClass().defaultfont();
1258 f.setLanguage(language);
1259 if (fontsDefaultFamily == "rmdefault")
1260 f.setFamily(Font::ROMAN_FAMILY);
1261 else if (fontsDefaultFamily == "sfdefault")
1262 f.setFamily(Font::SANS_FAMILY);
1263 else if (fontsDefaultFamily == "ttdefault")
1264 f.setFamily(Font::TYPEWRITER_FAMILY);
1269 void BufferParams::readPreamble(Lexer & lex)
1271 if (lex.getString() != "\\begin_preamble")
1272 lyxerr << "Error (BufferParams::readPreamble):"
1273 "consistency check failed." << endl;
1275 preamble = lex.getLongString("\\end_preamble");
1279 void BufferParams::readLanguage(Lexer & lex)
1281 if (!lex.next()) return;
1283 string const tmptok = lex.getString();
1285 // check if tmptok is part of tex_babel in tex-defs.h
1286 language = languages.getLanguage(tmptok);
1288 // Language tmptok was not found
1289 language = default_language;
1290 lyxerr << "Warning: Setting language `"
1291 << tmptok << "' to `" << language->lang()
1297 void BufferParams::readGraphicsDriver(Lexer & lex)
1299 if (!lex.next()) return;
1301 string const tmptok = lex.getString();
1302 // check if tmptok is part of tex_graphics in tex_defs.h
1305 string const test = tex_graphics[n++];
1307 if (test == tmptok) {
1308 graphicsDriver = tmptok;
1310 } else if (test == "") {
1312 "Warning: graphics driver `$$Token' not recognized!\n"
1313 " Setting graphics driver to `default'.\n");
1314 graphicsDriver = "default";
1321 void BufferParams::readBullets(Lexer & lex)
1323 if (!lex.next()) return;
1325 int const index = lex.getInteger();
1327 int temp_int = lex.getInteger();
1328 user_defined_bullet(index).setFont(temp_int);
1329 temp_bullet(index).setFont(temp_int);
1331 user_defined_bullet(index).setCharacter(temp_int);
1332 temp_bullet(index).setCharacter(temp_int);
1334 user_defined_bullet(index).setSize(temp_int);
1335 temp_bullet(index).setSize(temp_int);
1339 void BufferParams::readBulletsLaTeX(Lexer & lex)
1341 // The bullet class should be able to read this.
1342 if (!lex.next()) return;
1343 int const index = lex.getInteger();
1345 docstring const temp_str = lex.getDocString();
1347 user_defined_bullet(index).setText(temp_str);
1348 temp_bullet(index).setText(temp_str);
1352 string const BufferParams::paperSizeName() const
1354 char real_papersize = papersize;
1355 if (real_papersize == PAPER_DEFAULT)
1356 real_papersize = lyxrc.default_papersize;
1358 switch (real_papersize) {
1367 case PAPER_USEXECUTIVE:
1371 case PAPER_USLETTER:
1378 string const BufferParams::dvips_options() const
1383 && papersize == PAPER_CUSTOM
1384 && !lyxrc.print_paper_dimension_flag.empty()
1385 && !paperwidth.empty()
1386 && !paperheight.empty()) {
1387 // using a custom papersize
1388 result = lyxrc.print_paper_dimension_flag;
1389 result += ' ' + paperwidth;
1390 result += ',' + paperheight;
1392 string const paper_option = paperSizeName();
1393 if (paper_option != "letter" ||
1394 orientation != ORIENTATION_LANDSCAPE) {
1395 // dvips won't accept -t letter -t landscape.
1396 // In all other cases, include the paper size
1398 result = lyxrc.print_paper_flag;
1399 result += ' ' + paper_option;
1402 if (orientation == ORIENTATION_LANDSCAPE &&
1403 papersize != PAPER_CUSTOM)
1404 result += ' ' + lyxrc.print_landscape_flag;
1409 string const BufferParams::babelCall(string const & lang_opts) const
1411 string lang_pack = lyxrc.language_package;
1412 if (lang_pack != "\\usepackage{babel}")
1414 // suppress the babel call when there is no babel language defined
1415 // for the document language in the lib/languages file and if no
1416 // other languages are used (lang_opts is then empty)
1417 if (lang_opts.empty())
1419 if (!lyxrc.language_global_options)
1420 return string("\\usepackage[") + lang_opts + "]{babel}";
1425 string const BufferParams::loadFonts(string const & rm,
1426 string const & sf, string const & tt,
1427 bool const & sc, bool const & osf,
1428 int const & sfscale, int const & ttscale) const
1430 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1431 several packages have been replaced by others, that might not
1432 be installed on every system. We have to take care for that
1433 (see psnfss.pdf). We try to support all psnfss fonts as well
1434 as the fonts that have become de facto standard in the LaTeX
1435 world (e.g. Latin Modern). We do not support obsolete fonts
1436 (like PSLatex). In general, it should be possible to mix any
1437 rm font with any sf or tt font, respectively. (JSpitzm)
1439 -- separate math fonts.
1442 if (rm == "default" && sf == "default" && tt == "default")
1449 // Computer Modern (must be explicitely selectable -- there might be classes
1450 // that define a different default font!
1452 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1453 // osf for Computer Modern needs eco.sty
1455 os << "\\usepackage{eco}\n";
1457 // Latin Modern Roman
1458 else if (rm == "lmodern")
1459 os << "\\usepackage{lmodern}\n";
1461 else if (rm == "ae") {
1462 // not needed when using OT1 font encoding.
1463 if (lyxrc.fontenc != "default")
1464 os << "\\usepackage{ae,aecompl}\n";
1467 else if (rm == "times") {
1468 // try to load the best available package
1469 if (LaTeXFeatures::isAvailable("mathptmx"))
1470 os << "\\usepackage{mathptmx}\n";
1471 else if (LaTeXFeatures::isAvailable("mathptm"))
1472 os << "\\usepackage{mathptm}\n";
1474 os << "\\usepackage{times}\n";
1477 else if (rm == "palatino") {
1478 // try to load the best available package
1479 if (LaTeXFeatures::isAvailable("mathpazo")) {
1480 os << "\\usepackage";
1486 // "osf" includes "sc"!
1490 os << "{mathpazo}\n";
1492 else if (LaTeXFeatures::isAvailable("mathpple"))
1493 os << "\\usepackage{mathpple}\n";
1495 os << "\\usepackage{palatino}\n";
1498 else if (rm == "utopia") {
1499 // fourier supersedes utopia.sty, but does
1500 // not work with OT1 encoding.
1501 if (LaTeXFeatures::isAvailable("fourier")
1502 && lyxrc.fontenc != "default") {
1503 os << "\\usepackage";
1514 os << "{fourier}\n";
1517 os << "\\usepackage{utopia}\n";
1519 // Bera (complete fontset)
1520 else if (rm == "bera" && sf == "default" && tt == "default")
1521 os << "\\usepackage{bera}\n";
1523 else if (rm != "default")
1524 os << "\\usepackage" << "{" << rm << "}\n";
1527 // Helvetica, Bera Sans
1528 if (sf == "helvet" || sf == "berasans") {
1530 os << "\\usepackage[scaled=" << float(sfscale) / 100
1531 << "]{" << sf << "}\n";
1533 os << "\\usepackage{" << sf << "}\n";
1536 else if (sf == "avant")
1537 os << "\\usepackage{" << sf << "}\n";
1538 // Computer Modern, Latin Modern, CM Bright
1539 else if (sf != "default")
1540 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1542 // monospaced/typewriter
1543 // Courier, LuxiMono
1544 if (tt == "luximono" || tt == "beramono") {
1546 os << "\\usepackage[scaled=" << float(ttscale) / 100
1547 << "]{" << tt << "}\n";
1549 os << "\\usepackage{" << tt << "}\n";
1552 else if (tt == "courier" )
1553 os << "\\usepackage{" << tt << "}\n";
1554 // Computer Modern, Latin Modern, CM Bright
1555 else if (tt != "default")
1556 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1562 Encoding const & BufferParams::encoding() const
1564 if (inputenc == "auto" || inputenc == "default")
1565 return *(language->encoding());
1566 Encoding const * const enc =
1567 encodings.getFromLaTeXName(inputenc);
1570 lyxerr << "Unknown inputenc value `" << inputenc
1571 << "'. Using `auto' instead." << endl;
1572 return *(language->encoding());
1576 biblio::CiteEngine BufferParams::getEngine() const
1578 // FIXME the class should provide the numerical/
1579 // authoryear choice
1580 if (getTextClass().provides("natbib")
1581 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1582 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1583 return cite_engine_;
1587 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1589 cite_engine_ = cite_engine;