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"
22 #include "buffer_funcs.h"
28 #include "LaTeXFeatures.h"
30 #include "ModuleList.h"
35 #include "TextClassList.h"
36 #include "OutputParams.h"
40 #include "PDFOptions.h"
42 #include "frontends/alert.h"
43 #include "insets/InsetListingsParams.h"
45 #include "support/convert.h"
46 #include "support/filetools.h"
47 #include "support/Translator.h"
48 #include "support/lstrings.h"
50 #include <boost/array.hpp>
59 using std::istringstream;
61 using std::ostringstream;
64 using lyx::support::FileName;
65 using lyx::support::libFileSearch;
66 using lyx::support::bformat;
67 using lyx::support::rtrim;
68 using lyx::support::tokenPos;
69 using lyx::support::prefixIs;
72 static char const * const string_paragraph_separation[] = {
77 static char const * const string_quotes_language[] = {
78 "english", "swedish", "german", "polish", "french", "danish", ""
82 static char const * const string_papersize[] = {
83 "default", "custom", "letterpaper", "executivepaper", "legalpaper",
84 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
88 static char const * const string_orientation[] = {
89 "portrait", "landscape", ""
93 static char const * const string_footnotekinds[] = {
94 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
98 static char const * const tex_graphics[] = {
99 "default", "dvips", "dvitops", "emtex",
100 "ln", "oztex", "textures", "none", ""
109 // Paragraph separation
110 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
113 ParSepTranslator const init_parseptranslator()
115 ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
116 translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
121 ParSepTranslator const & parseptranslator()
123 static ParSepTranslator translator = init_parseptranslator();
129 typedef Translator<string, InsetQuotes::quote_language> QuotesLangTranslator;
132 QuotesLangTranslator const init_quoteslangtranslator()
134 QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
135 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
136 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
137 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
138 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
139 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
144 QuotesLangTranslator const & quoteslangtranslator()
146 static QuotesLangTranslator translator = init_quoteslangtranslator();
152 typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
155 PaperSizeTranslator const init_papersizetranslator()
157 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
158 translator.addPair(string_papersize[1], PAPER_CUSTOM);
159 translator.addPair(string_papersize[2], PAPER_USLETTER);
160 translator.addPair(string_papersize[3], PAPER_USLEGAL);
161 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
162 translator.addPair(string_papersize[5], PAPER_A3);
163 translator.addPair(string_papersize[6], PAPER_A4);
164 translator.addPair(string_papersize[7], PAPER_A5);
165 translator.addPair(string_papersize[8], PAPER_B3);
166 translator.addPair(string_papersize[9], PAPER_B4);
167 translator.addPair(string_papersize[10], PAPER_B5);
172 PaperSizeTranslator const & papersizetranslator()
174 static PaperSizeTranslator translator = init_papersizetranslator();
180 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
183 PaperOrientationTranslator const init_paperorientationtranslator()
185 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
186 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
191 PaperOrientationTranslator const & paperorientationtranslator()
193 static PaperOrientationTranslator translator = init_paperorientationtranslator();
199 typedef Translator<int, TextClass::PageSides> SidesTranslator;
202 SidesTranslator const init_sidestranslator()
204 SidesTranslator translator(1, TextClass::OneSide);
205 translator.addPair(2, TextClass::TwoSides);
210 SidesTranslator const & sidestranslator()
212 static SidesTranslator translator = init_sidestranslator();
218 typedef Translator<int, BufferParams::Package> PackageTranslator;
221 PackageTranslator const init_packagetranslator()
223 PackageTranslator translator(0, BufferParams::package_off);
224 translator.addPair(1, BufferParams::package_auto);
225 translator.addPair(2, BufferParams::package_on);
230 PackageTranslator const & packagetranslator()
232 static PackageTranslator translator = init_packagetranslator();
238 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
241 CiteEngineTranslator const init_citeenginetranslator()
243 CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
244 translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
245 translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
246 translator.addPair("jurabib", biblio::ENGINE_JURABIB);
251 CiteEngineTranslator const & citeenginetranslator()
253 static CiteEngineTranslator translator = init_citeenginetranslator();
259 typedef Translator<string, Spacing::Space> SpaceTranslator;
262 SpaceTranslator const init_spacetranslator()
264 SpaceTranslator translator("default", Spacing::Default);
265 translator.addPair("single", Spacing::Single);
266 translator.addPair("onehalf", Spacing::Onehalf);
267 translator.addPair("double", Spacing::Double);
268 translator.addPair("other", Spacing::Other);
273 SpaceTranslator const & spacetranslator()
275 static SpaceTranslator translator = init_spacetranslator();
283 class BufferParams::Impl
288 AuthorList authorlist;
289 BranchList branchlist;
290 boost::array<Bullet, 4> temp_bullets;
291 boost::array<Bullet, 4> user_defined_bullets;
293 /** This is the amount of space used for paragraph_separation "skip",
294 * and for detached paragraphs in "indented" documents.
297 PDFOptions pdfoptions;
301 BufferParams::Impl::Impl()
302 : defskip(VSpace::MEDSKIP)
304 // set initial author
306 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
311 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
315 return new BufferParams::Impl(*ptr);
319 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
325 BufferParams::BufferParams()
328 setBaseClass(defaultTextclass());
329 paragraph_separation = PARSEP_INDENT;
330 quotes_language = InsetQuotes::EnglishQ;
331 fontsize = "default";
334 papersize = PAPER_DEFAULT;
335 orientation = ORIENTATION_PORTRAIT;
336 use_geometry = false;
337 use_amsmath = package_auto;
338 use_esint = package_auto;
339 cite_engine_ = biblio::ENGINE_BASIC;
340 use_bibtopic = false;
341 trackChanges = false;
342 outputChanges = false;
345 language = default_language;
346 fontsRoman = "default";
347 fontsSans = "default";
348 fontsTypewriter = "default";
349 fontsDefaultFamily = "default";
352 fontsSansScale = 100;
353 fontsTypewriterScale = 100;
355 graphicsDriver = "default";
356 sides = TextClass::OneSide;
358 listings_params = string();
359 pagestyle = "default";
362 for (int iter = 0; iter < 4; ++iter) {
363 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
364 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
369 BufferParams::~BufferParams()
373 docstring const BufferParams::B_(string const & l10n) const
375 BOOST_ASSERT(language);
376 return getMessages(language->code()).get(l10n);
380 AuthorList & BufferParams::authors()
382 return pimpl_->authorlist;
386 AuthorList const & BufferParams::authors() const
388 return pimpl_->authorlist;
392 BranchList & BufferParams::branchlist()
394 return pimpl_->branchlist;
398 BranchList const & BufferParams::branchlist() const
400 return pimpl_->branchlist;
404 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
406 BOOST_ASSERT(index < 4);
407 return pimpl_->temp_bullets[index];
411 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
413 BOOST_ASSERT(index < 4);
414 return pimpl_->temp_bullets[index];
418 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
420 BOOST_ASSERT(index < 4);
421 return pimpl_->user_defined_bullets[index];
425 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
427 BOOST_ASSERT(index < 4);
428 return pimpl_->user_defined_bullets[index];
432 Spacing & BufferParams::spacing()
434 return pimpl_->spacing;
438 Spacing const & BufferParams::spacing() const
440 return pimpl_->spacing;
444 PDFOptions & BufferParams::pdfoptions()
446 return pimpl_->pdfoptions;
450 PDFOptions const & BufferParams::pdfoptions() const
452 return pimpl_->pdfoptions;
456 VSpace const & BufferParams::getDefSkip() const
458 return pimpl_->defskip;
462 void BufferParams::setDefSkip(VSpace const & vs)
464 pimpl_->defskip = vs;
468 string const BufferParams::readToken(Lexer & lex, string const & token)
470 if (token == "\\textclass") {
472 string const classname = lex.getString();
473 pair<bool, lyx::textclass_type> pp =
474 textclasslist.numberOfClass(classname);
476 setBaseClass(pp.second);
478 // if text class does not exist, try to load it from filepath
479 pp = textclasslist.addTextClass(classname, filepath);
481 setBaseClass(pp.second);
483 setBaseClass(defaultTextclass());
487 if (!getTextClass().isTeXClassAvailable()) {
488 docstring const msg =
489 bformat(_("The layout file requested by this document,\n"
491 "is not usable. This is probably because a LaTeX\n"
492 "class or style file required by it is not\n"
493 "available. See the Customization documentation\n"
494 "for more information.\n"), from_utf8(classname));
495 frontend::Alert::warning(_("Document class not available"),
496 msg + _("LyX will not be able to produce output."));
499 } else if (token == "\\begin_preamble") {
501 } else if (token == "\\begin_modules") {
504 } else if (token == "\\options") {
506 options = lex.getString();
507 } else if (token == "\\language") {
509 } else if (token == "\\inputencoding") {
511 } else if (token == "\\graphics") {
512 readGraphicsDriver(lex);
513 } else if (token == "\\font_roman") {
515 } else if (token == "\\font_sans") {
517 } else if (token == "\\font_typewriter") {
518 lex >> fontsTypewriter;
519 } else if (token == "\\font_default_family") {
520 lex >> fontsDefaultFamily;
521 } else if (token == "\\font_sc") {
523 } else if (token == "\\font_osf") {
525 } else if (token == "\\font_sf_scale") {
526 lex >> fontsSansScale;
527 } else if (token == "\\font_tt_scale") {
528 lex >> fontsTypewriterScale;
529 } else if (token == "\\paragraph_separation") {
532 paragraph_separation = parseptranslator().find(parsep);
533 } else if (token == "\\defskip") {
535 pimpl_->defskip = VSpace(lex.getString());
536 } else if (token == "\\quotes_language") {
539 quotes_language = quoteslangtranslator().find(quotes_lang);
540 } else if (token == "\\papersize") {
543 papersize = papersizetranslator().find(ppsize);
544 } else if (token == "\\use_geometry") {
546 } else if (token == "\\use_amsmath") {
549 use_amsmath = packagetranslator().find(use_ams);
550 } else if (token == "\\use_esint") {
553 use_esint = packagetranslator().find(useesint);
554 } else if (token == "\\cite_engine") {
557 cite_engine_ = citeenginetranslator().find(engine);
558 } else if (token == "\\use_bibtopic") {
560 } else if (token == "\\tracking_changes") {
562 } else if (token == "\\output_changes") {
563 lex >> outputChanges;
564 } else if (token == "\\branch") {
566 docstring branch = lex.getDocString();
567 branchlist().add(branch);
570 string const tok = lex.getString();
571 if (tok == "\\end_branch")
573 Branch * branch_ptr = branchlist().find(branch);
574 if (tok == "\\selected") {
577 branch_ptr->setSelected(lex.getInteger());
579 // not yet operational
580 if (tok == "\\color") {
582 string color = lex.getString();
584 branch_ptr->setColor(color);
585 // Update also the Color table:
587 color = lcolor.getX11Name(Color::background);
589 lcolor.setColor(to_utf8(branch), color);
593 } else if (token == "\\author") {
595 istringstream ss(lex.getString());
598 author_map.push_back(pimpl_->authorlist.record(a));
599 } else if (token == "\\paperorientation") {
602 orientation = paperorientationtranslator().find(orient);
603 } else if (token == "\\paperwidth") {
605 } else if (token == "\\paperheight") {
607 } else if (token == "\\leftmargin") {
609 } else if (token == "\\topmargin") {
611 } else if (token == "\\rightmargin") {
613 } else if (token == "\\bottommargin") {
615 } else if (token == "\\headheight") {
617 } else if (token == "\\headsep") {
619 } else if (token == "\\footskip") {
621 } else if (token == "\\paperfontsize") {
623 } else if (token == "\\papercolumns") {
625 } else if (token == "\\listings_params") {
628 listings_params = InsetListingsParams(par).params();
629 } else if (token == "\\papersides") {
632 sides = sidestranslator().find(psides);
633 } else if (token == "\\paperpagestyle") {
635 } else if (token == "\\bullet") {
637 } else if (token == "\\bulletLaTeX") {
638 readBulletsLaTeX(lex);
639 } else if (token == "\\secnumdepth") {
641 } else if (token == "\\tocdepth") {
643 } else if (token == "\\spacing") {
647 if (nspacing == "other") {
650 spacing().set(spacetranslator().find(nspacing), tmp_val);
651 } else if (token == "\\float_placement") {
652 lex >> float_placement;
654 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
655 string toktmp = pdfoptions().readToken(lex, token);
656 if (!toktmp.empty()) {
657 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
662 lyxerr << "BufferParams::readToken(): Unknown token: " <<
671 void BufferParams::writeFile(ostream & os) const
673 // The top of the file is written by the buffer.
674 // Prints out the buffer info into the .lyx file given by file
677 os << "\\textclass " << textclasslist[baseClass_].name() << '\n';
680 if (!preamble.empty()) {
681 // remove '\n' from the end of preamble
682 string const tmppreamble = rtrim(preamble, "\n");
683 os << "\\begin_preamble\n"
685 << "\n\\end_preamble\n";
689 if (!options.empty()) {
690 os << "\\options " << options << '\n';
694 if (!layoutModules_.empty()) {
695 os << "\\begin_modules" << '\n';
696 LayoutModuleList::const_iterator it = layoutModules_.begin();
697 for (; it != layoutModules_.end(); it++)
699 os << "\\end_modules" << '\n';
702 // then the text parameters
703 if (language != ignore_language)
704 os << "\\language " << language->lang() << '\n';
705 os << "\\inputencoding " << inputenc
706 << "\n\\font_roman " << fontsRoman
707 << "\n\\font_sans " << fontsSans
708 << "\n\\font_typewriter " << fontsTypewriter
709 << "\n\\font_default_family " << fontsDefaultFamily
710 << "\n\\font_sc " << convert<string>(fontsSC)
711 << "\n\\font_osf " << convert<string>(fontsOSF)
712 << "\n\\font_sf_scale " << fontsSansScale
713 << "\n\\font_tt_scale " << fontsTypewriterScale
714 << "\n\\graphics " << graphicsDriver << '\n';
716 if (!float_placement.empty()) {
717 os << "\\float_placement " << float_placement << '\n';
719 os << "\\paperfontsize " << fontsize << '\n';
721 spacing().writeFile(os);
722 pdfoptions().writeFile(os);
724 os << "\\papersize " << string_papersize[papersize]
725 << "\n\\use_geometry " << convert<string>(use_geometry)
726 << "\n\\use_amsmath " << use_amsmath
727 << "\n\\use_esint " << use_esint
728 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
729 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
730 << "\n\\paperorientation " << string_orientation[orientation]
733 BranchList::const_iterator it = branchlist().begin();
734 BranchList::const_iterator end = branchlist().end();
735 for (; it != end; ++it) {
736 os << "\\branch " << to_utf8(it->getBranch())
737 << "\n\\selected " << it->getSelected()
738 << "\n\\color " << lyx::X11hexname(it->getColor())
743 if (!paperwidth.empty())
744 os << "\\paperwidth "
745 << VSpace(paperwidth).asLyXCommand() << '\n';
746 if (!paperheight.empty())
747 os << "\\paperheight "
748 << VSpace(paperheight).asLyXCommand() << '\n';
749 if (!leftmargin.empty())
750 os << "\\leftmargin "
751 << VSpace(leftmargin).asLyXCommand() << '\n';
752 if (!topmargin.empty())
754 << VSpace(topmargin).asLyXCommand() << '\n';
755 if (!rightmargin.empty())
756 os << "\\rightmargin "
757 << VSpace(rightmargin).asLyXCommand() << '\n';
758 if (!bottommargin.empty())
759 os << "\\bottommargin "
760 << VSpace(bottommargin).asLyXCommand() << '\n';
761 if (!headheight.empty())
762 os << "\\headheight "
763 << VSpace(headheight).asLyXCommand() << '\n';
764 if (!headsep.empty())
766 << VSpace(headsep).asLyXCommand() << '\n';
767 if (!footskip.empty())
769 << VSpace(footskip).asLyXCommand() << '\n';
770 os << "\\secnumdepth " << secnumdepth
771 << "\n\\tocdepth " << tocdepth
772 << "\n\\paragraph_separation "
773 << string_paragraph_separation[paragraph_separation]
774 << "\n\\defskip " << getDefSkip().asLyXCommand()
775 << "\n\\quotes_language "
776 << string_quotes_language[quotes_language]
777 << "\n\\papercolumns " << columns
778 << "\n\\papersides " << sides
779 << "\n\\paperpagestyle " << pagestyle << '\n';
780 if (!listings_params.empty())
781 os << "\\listings_params \"" <<
782 InsetListingsParams(listings_params).encodedString() << "\"\n";
783 for (int i = 0; i < 4; ++i) {
784 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
785 if (user_defined_bullet(i).getFont() != -1) {
786 os << "\\bullet " << i << " "
787 << user_defined_bullet(i).getFont() << " "
788 << user_defined_bullet(i).getCharacter() << " "
789 << user_defined_bullet(i).getSize() << "\n";
793 os << "\\bulletLaTeX " << i << " \""
794 << lyx::to_ascii(user_defined_bullet(i).getText())
800 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
801 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
803 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
804 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
805 for (; a_it != a_end; ++a_it) {
806 if (a_it->second.used())
807 os << "\\author " << a_it->second << "\n";
809 os << "\\author " << Author() << "\n";
814 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
815 TexRow & texrow) const
817 os << "\\documentclass";
819 TextClass const & tclass = getTextClass();
821 ostringstream clsoptions; // the document class options.
823 if (tokenPos(tclass.opt_fontsize(),
824 '|', fontsize) >= 0) {
825 // only write if existing in list (and not default)
826 clsoptions << fontsize << "pt,";
829 // custom, A3, B3 and B4 paper sizes need geometry
830 bool nonstandard_papersize = papersize == PAPER_B3
831 || papersize == PAPER_B4
832 || papersize == PAPER_A3
833 || papersize == PAPER_CUSTOM;
838 clsoptions << "a4paper,";
841 clsoptions << "letterpaper,";
844 clsoptions << "a5paper,";
847 clsoptions << "b5paper,";
849 case PAPER_USEXECUTIVE:
850 clsoptions << "executivepaper,";
853 clsoptions << "legalpaper,";
865 if (sides != tclass.sides()) {
867 case TextClass::OneSide:
868 clsoptions << "oneside,";
870 case TextClass::TwoSides:
871 clsoptions << "twoside,";
877 if (columns != tclass.columns()) {
879 clsoptions << "twocolumn,";
881 clsoptions << "onecolumn,";
885 && orientation == ORIENTATION_LANDSCAPE)
886 clsoptions << "landscape,";
888 // language should be a parameter to \documentclass
889 if (language->babel() == "hebrew"
890 && default_language->babel() != "hebrew")
891 // This seems necessary
892 features.useLanguage(default_language);
894 ostringstream language_options;
895 bool const use_babel = features.useBabel();
897 language_options << features.getLanguages();
898 if (!language->babel().empty()) {
899 if (!language_options.str().empty())
900 language_options << ',';
901 language_options << language->babel();
903 // when Vietnamese is used, babel must directly be loaded with the
904 // language options, not in the class options
905 int viet = language_options.str().find("vietnam");
906 // viet = string::npos when not found
907 if (lyxrc.language_global_options && !language_options.str().empty()
908 && viet == string::npos)
909 clsoptions << language_options.str() << ',';
912 // the user-defined options
913 if (!options.empty()) {
914 clsoptions << options << ',';
917 string strOptions(clsoptions.str());
918 if (!strOptions.empty()) {
919 strOptions = rtrim(strOptions, ",");
921 os << '[' << from_utf8(strOptions) << ']';
924 os << '{' << from_ascii(tclass.latexname()) << "}\n";
926 // end of \documentclass defs
928 // font selection must be done before loading fontenc.sty
930 loadFonts(fontsRoman, fontsSans,
931 fontsTypewriter, fontsSC, fontsOSF,
932 fontsSansScale, fontsTypewriterScale);
933 if (!fonts.empty()) {
934 os << from_ascii(fonts);
937 if (fontsDefaultFamily != "default")
938 os << "\\renewcommand{\\familydefault}{\\"
939 << from_ascii(fontsDefaultFamily) << "}\n";
942 // this one is not per buffer
943 // for arabic_arabi and farsi we also need to load the LAE and LFE encoding
944 if (lyxrc.fontenc != "default") {
945 if (language->lang() == "arabic_arabi" || language->lang() == "farsi") {
946 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
947 << ",LFE,LAE]{fontenc}\n";
950 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
956 // handle inputenc etc.
957 writeEncodingPreamble(os, features, texrow);
959 if (!listings_params.empty()) {
960 os << "\\usepackage{listings}\n";
963 // do not test validity because listings_params is supposed to be valid
964 string par = InsetListingsParams(listings_params).separatedParams(true);
965 os << from_ascii(par);
966 // count the number of newlines
967 for (size_t i = 0; i < par.size(); ++i)
973 if (use_geometry || nonstandard_papersize) {
974 os << "\\usepackage{geometry}\n";
976 os << "\\geometry{verbose";
977 if (orientation == ORIENTATION_LANDSCAPE)
981 if (!paperwidth.empty())
983 << from_ascii(paperwidth);
984 if (!paperheight.empty())
985 os << ",paperheight="
986 << from_ascii(paperheight);
989 os << ",letterpaper";
994 case PAPER_USEXECUTIVE:
995 os << ",executivepaper";
1016 // default papersize ie PAPER_DEFAULT
1017 switch (lyxrc.default_papersize) {
1018 case PAPER_DEFAULT: // keep compiler happy
1019 case PAPER_USLETTER:
1020 os << ",letterpaper";
1023 os << ",legalpaper";
1025 case PAPER_USEXECUTIVE:
1026 os << ",executivepaper";
1046 if (!topmargin.empty())
1047 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1048 if (!bottommargin.empty())
1049 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1050 if (!leftmargin.empty())
1051 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1052 if (!rightmargin.empty())
1053 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1054 if (!headheight.empty())
1055 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1056 if (!headsep.empty())
1057 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1058 if (!footskip.empty())
1059 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1064 if (tokenPos(tclass.opt_pagestyle(),
1065 '|', pagestyle) >= 0) {
1066 if (pagestyle == "fancy") {
1067 os << "\\usepackage{fancyhdr}\n";
1070 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1074 // Only if class has a ToC hierarchy
1075 if (tclass.hasTocLevels()) {
1076 if (secnumdepth != tclass.secnumdepth()) {
1077 os << "\\setcounter{secnumdepth}{"
1082 if (tocdepth != tclass.tocdepth()) {
1083 os << "\\setcounter{tocdepth}{"
1090 if (paragraph_separation) {
1091 switch (getDefSkip().kind()) {
1092 case VSpace::SMALLSKIP:
1093 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1095 case VSpace::MEDSKIP:
1096 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1098 case VSpace::BIGSKIP:
1099 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1101 case VSpace::LENGTH:
1102 os << "\\setlength{\\parskip}{"
1103 << from_utf8(getDefSkip().length().asLatexString())
1106 default: // should never happen // Then delete it.
1107 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1112 os << "\\setlength{\\parindent}{0pt}\n";
1116 // If we use jurabib, we have to call babel here.
1117 if (use_babel && features.isRequired("jurabib")) {
1118 os << from_ascii(babelCall(language_options.str()))
1120 << from_ascii(features.getBabelOptions());
1124 // Now insert the LyX specific LaTeX commands...
1126 // The optional packages;
1127 docstring lyxpreamble(from_ascii(features.getPackages()));
1129 // We try to load babel late, in case it interferes
1130 // with other packages. But some packages also need babel to be loaded
1131 // before, e.g. jurabib has to be called after babel.
1132 // So load babel after the optional packages but before the user-defined
1133 // preamble. This allows the users to redefine babel commands, e.g. to
1134 // translate the word "Index" to the German "Stichwortverzeichnis".
1135 // For more infos why this place was chosen, see
1136 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg128425.html
1137 // if you encounter problem, you can shift babel to its old place behind
1138 // the user-defined preamble
1139 if (use_babel && !features.isRequired("jurabib")) {
1141 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1142 lyxpreamble += from_utf8(features.getBabelOptions());
1145 // When the language "japanese-plain" is used, the package "japanese" must
1146 // be loaded behind babel (it provides babel support for Japanese)
1147 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
1148 if (language->lang() == "japanese-plain")
1149 lyxpreamble += "\\usepackage{japanese}\n";
1152 // * Hyperref manual: "Make sure it comes last of your loaded
1153 // packages, to give it a fighting chance of not being over-written,
1154 // since its job is to redefine many LATEX commands."
1155 // * Email from Heiko Oberdiek: "It is usually better to load babel
1156 // before hyperref. Then hyperref has a chance to detect babel.
1157 // * Has to be loaded before the "LyX specific LaTeX commands" to
1158 // avoid errors with algorithm floats.
1159 odocstringstream oss;
1160 pdfoptions().writeLaTeX(oss);
1161 lyxpreamble += oss.str();
1163 // this might be useful...
1164 lyxpreamble += "\n\\makeatletter\n";
1166 // Some macros LyX will need
1167 docstring tmppreamble(from_ascii(features.getMacros()));
1169 if (!tmppreamble.empty()) {
1170 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1171 "LyX specific LaTeX commands.\n"
1172 + tmppreamble + '\n';
1175 // the text class specific preamble
1176 tmppreamble = features.getTClassPreamble();
1177 if (!tmppreamble.empty()) {
1178 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1179 "Textclass specific LaTeX commands.\n"
1180 + tmppreamble + '\n';
1183 /* the user-defined preamble */
1184 if (!preamble.empty()) {
1186 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1187 "User specified LaTeX commands.\n"
1188 + from_utf8(preamble) + '\n';
1191 // Itemize bullet settings need to be last in case the user
1192 // defines their own bullets that use a package included
1193 // in the user-defined preamble -- ARRae
1194 // Actually it has to be done much later than that
1195 // since some packages like frenchb make modifications
1196 // at \begin{document} time -- JMarc
1197 docstring bullets_def;
1198 for (int i = 0; i < 4; ++i) {
1199 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1200 if (bullets_def.empty())
1201 bullets_def += "\\AtBeginDocument{\n";
1202 bullets_def += " \\def\\labelitemi";
1204 // `i' is one less than the item to modify
1211 bullets_def += "ii";
1217 bullets_def += '{' +
1218 user_defined_bullet(i).getText()
1223 if (!bullets_def.empty())
1224 lyxpreamble += bullets_def + "}\n\n";
1226 lyxpreamble += "\\makeatother\n\n";
1229 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1230 for (int j = 0; j != nlines; ++j) {
1239 void BufferParams::useClassDefaults()
1241 TextClass const & tclass = textclasslist[baseClass_];
1243 sides = tclass.sides();
1244 columns = tclass.columns();
1245 pagestyle = tclass.pagestyle();
1246 options = tclass.options();
1247 // Only if class has a ToC hierarchy
1248 if (tclass.hasTocLevels()) {
1249 secnumdepth = tclass.secnumdepth();
1250 tocdepth = tclass.tocdepth();
1255 bool BufferParams::hasClassDefaults() const
1257 TextClass const & tclass = textclasslist[baseClass_];
1259 return (sides == tclass.sides()
1260 && columns == tclass.columns()
1261 && pagestyle == tclass.pagestyle()
1262 && options == tclass.options()
1263 && secnumdepth == tclass.secnumdepth()
1264 && tocdepth == tclass.tocdepth());
1268 TextClass const & BufferParams::getTextClass() const
1274 TextClassPtr BufferParams::getTextClassPtr() const {
1279 void BufferParams::setTextClass(TextClassPtr tc) {
1284 bool BufferParams::setBaseClass(textclass_type tc)
1287 if (textclasslist[tc].load())
1291 bformat(_("The document class %1$s could not be loaded."),
1292 from_utf8(textclasslist[tc].name()));
1293 frontend::Alert::error(_("Could not load class"), s);
1301 void BufferParams::setJustBaseClass(textclass_type tc)
1307 textclass_type BufferParams::getBaseClass() const
1313 void BufferParams::makeTextClass()
1315 textClass_.reset(new TextClass(textclasslist[getBaseClass()]));
1316 //FIXME It might be worth loading the children's modules here,
1317 //just as we load their bibliographies and such, instead of just
1318 //doing a check in InsetInclude.
1319 LayoutModuleList::const_iterator it = layoutModules_.begin();
1320 for (; it != layoutModules_.end(); it++) {
1321 string const modName = *it;
1322 LyXModule * lm = moduleList[modName];
1324 docstring const msg =
1325 bformat(_("The module %1$s has been requested by\n"
1326 "this document but has not been found in the list of\n"
1327 "available modules. If you recently installed it, you\n"
1328 "probalby need to reconfigure LyX.\n"), from_utf8(modName));
1329 frontend::Alert::warning(_("Module not available"),
1330 msg + _("Some layouts may not be available."));
1331 lyxerr << "BufferParams::makeTextClass(): Module " <<
1332 modName << " requested but not found in module list." <<
1336 FileName layout_file = libFileSearch("layouts", lm->filename);
1337 textClass_->read(layout_file, TextClass::MODULE);
1342 std::vector<string> const & BufferParams::getModules() const {
1343 return layoutModules_;
1348 bool BufferParams::addLayoutModule(string modName, bool makeClass) {
1349 LayoutModuleList::const_iterator it = layoutModules_.begin();
1350 LayoutModuleList::const_iterator end = layoutModules_.end();
1351 for (; it != end; it++) {
1355 if (it != layoutModules_.end())
1357 layoutModules_.push_back(modName);
1364 bool BufferParams::addLayoutModules(std::vector<string>modNames)
1367 std::vector<string>::const_iterator it = modNames.begin();
1368 std::vector<string>::const_iterator end = modNames.end();
1369 for (; it != end; ++it)
1370 retval &= addLayoutModule(*it, false);
1376 void BufferParams::clearLayoutModules() {
1377 layoutModules_.clear();
1382 Font const BufferParams::getFont() const
1384 Font f = getTextClass().defaultfont();
1385 f.setLanguage(language);
1386 if (fontsDefaultFamily == "rmdefault")
1387 f.setFamily(Font::ROMAN_FAMILY);
1388 else if (fontsDefaultFamily == "sfdefault")
1389 f.setFamily(Font::SANS_FAMILY);
1390 else if (fontsDefaultFamily == "ttdefault")
1391 f.setFamily(Font::TYPEWRITER_FAMILY);
1396 void BufferParams::readPreamble(Lexer & lex)
1398 if (lex.getString() != "\\begin_preamble")
1399 lyxerr << "Error (BufferParams::readPreamble):"
1400 "consistency check failed." << endl;
1402 preamble = lex.getLongString("\\end_preamble");
1406 void BufferParams::readLanguage(Lexer & lex)
1408 if (!lex.next()) return;
1410 string const tmptok = lex.getString();
1412 // check if tmptok is part of tex_babel in tex-defs.h
1413 language = languages.getLanguage(tmptok);
1415 // Language tmptok was not found
1416 language = default_language;
1417 lyxerr << "Warning: Setting language `"
1418 << tmptok << "' to `" << language->lang()
1424 void BufferParams::readGraphicsDriver(Lexer & lex)
1426 if (!lex.next()) return;
1428 string const tmptok = lex.getString();
1429 // check if tmptok is part of tex_graphics in tex_defs.h
1432 string const test = tex_graphics[n++];
1434 if (test == tmptok) {
1435 graphicsDriver = tmptok;
1437 } else if (test == "") {
1439 "Warning: graphics driver `$$Token' not recognized!\n"
1440 " Setting graphics driver to `default'.\n");
1441 graphicsDriver = "default";
1448 void BufferParams::readBullets(Lexer & lex)
1450 if (!lex.next()) return;
1452 int const index = lex.getInteger();
1454 int temp_int = lex.getInteger();
1455 user_defined_bullet(index).setFont(temp_int);
1456 temp_bullet(index).setFont(temp_int);
1458 user_defined_bullet(index).setCharacter(temp_int);
1459 temp_bullet(index).setCharacter(temp_int);
1461 user_defined_bullet(index).setSize(temp_int);
1462 temp_bullet(index).setSize(temp_int);
1466 void BufferParams::readBulletsLaTeX(Lexer & lex)
1468 // The bullet class should be able to read this.
1469 if (!lex.next()) return;
1470 int const index = lex.getInteger();
1472 docstring const temp_str = lex.getDocString();
1474 user_defined_bullet(index).setText(temp_str);
1475 temp_bullet(index).setText(temp_str);
1479 void BufferParams::readModules(Lexer & lex)
1481 if (!lex.eatLine()) {
1482 lyxerr << "Error (BufferParams::readModules):"
1483 "Unexpected end of input." << endl;
1487 string mod = lex.getString();
1488 if (mod == "\\end_modules")
1490 addLayoutModule(mod);
1496 string const BufferParams::paperSizeName() const
1498 char real_papersize = papersize;
1499 if (real_papersize == PAPER_DEFAULT)
1500 real_papersize = lyxrc.default_papersize;
1502 switch (real_papersize) {
1511 case PAPER_USEXECUTIVE:
1515 case PAPER_USLETTER:
1522 string const BufferParams::dvips_options() const
1527 && papersize == PAPER_CUSTOM
1528 && !lyxrc.print_paper_dimension_flag.empty()
1529 && !paperwidth.empty()
1530 && !paperheight.empty()) {
1531 // using a custom papersize
1532 result = lyxrc.print_paper_dimension_flag;
1533 result += ' ' + paperwidth;
1534 result += ',' + paperheight;
1536 string const paper_option = paperSizeName();
1537 if (paper_option != "letter" ||
1538 orientation != ORIENTATION_LANDSCAPE) {
1539 // dvips won't accept -t letter -t landscape.
1540 // In all other cases, include the paper size
1542 result = lyxrc.print_paper_flag;
1543 result += ' ' + paper_option;
1546 if (orientation == ORIENTATION_LANDSCAPE &&
1547 papersize != PAPER_CUSTOM)
1548 result += ' ' + lyxrc.print_landscape_flag;
1553 string const BufferParams::babelCall(string const & lang_opts) const
1555 string lang_pack = lyxrc.language_package;
1556 if (lang_pack != "\\usepackage{babel}")
1558 // suppress the babel call when there is no babel language defined
1559 // for the document language in the lib/languages file and if no
1560 // other languages are used (lang_opts is then empty)
1561 if (lang_opts.empty())
1563 // when Vietnamese is used, babel must directly be loaded with the
1565 int viet = lang_opts.find("vietnam");
1566 // viet = string::npos when not found
1567 if (!lyxrc.language_global_options || viet != string::npos)
1568 return "\\usepackage[" + lang_opts + "]{babel}";
1573 void BufferParams::writeEncodingPreamble(odocstream & os,
1574 LaTeXFeatures & features, TexRow & texrow) const
1576 if (inputenc == "auto") {
1577 string const doc_encoding =
1578 language->encoding()->latexName();
1579 Encoding::Package const package =
1580 language->encoding()->package();
1582 // Create a list with all the input encodings used
1584 std::set<string> encodings =
1585 features.getEncodingSet(doc_encoding);
1587 // When the encodings EUC-JP-plain, JIS-plain, or SJIS-plainare used, the
1588 // package inputenc must be omitted. Therefore set the encoding to empty.
1589 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
1590 if (doc_encoding == "EUC-JP-plain" || doc_encoding == "JIS-plain" ||
1591 doc_encoding == "SJIS-plain")
1594 if (!encodings.empty() || package == Encoding::inputenc) {
1595 os << "\\usepackage[";
1596 std::set<string>::const_iterator it = encodings.begin();
1597 std::set<string>::const_iterator const end = encodings.end();
1599 os << from_ascii(*it);
1602 for (; it != end; ++it)
1603 os << ',' << from_ascii(*it);
1604 if (package == Encoding::inputenc) {
1605 if (!encodings.empty())
1607 os << from_ascii(doc_encoding);
1609 os << "]{inputenc}\n";
1612 if (package == Encoding::CJK) {
1613 os << "\\usepackage{CJK}\n";
1616 } else if (inputenc != "default") {
1617 switch (encoding().package()) {
1618 case Encoding::none:
1620 case Encoding::inputenc:
1621 os << "\\usepackage[" << from_ascii(inputenc)
1626 os << "\\usepackage{CJK}\n";
1632 // The encoding "armscii8" is only available when the package "armtex" is loaded.
1633 // armscii8 is used for Armenian.
1634 if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
1635 os << "\\usepackage{armtex}\n";
1641 string const BufferParams::loadFonts(string const & rm,
1642 string const & sf, string const & tt,
1643 bool const & sc, bool const & osf,
1644 int const & sfscale, int const & ttscale) const
1646 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1647 several packages have been replaced by others, that might not
1648 be installed on every system. We have to take care for that
1649 (see psnfss.pdf). We try to support all psnfss fonts as well
1650 as the fonts that have become de facto standard in the LaTeX
1651 world (e.g. Latin Modern). We do not support obsolete fonts
1652 (like PSLatex). In general, it should be possible to mix any
1653 rm font with any sf or tt font, respectively. (JSpitzm)
1655 -- separate math fonts.
1658 if (rm == "default" && sf == "default" && tt == "default")
1665 // Computer Modern (must be explicitely selectable -- there might be classes
1666 // that define a different default font!
1668 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1669 // osf for Computer Modern needs eco.sty
1671 os << "\\usepackage{eco}\n";
1673 // Latin Modern Roman
1674 else if (rm == "lmodern")
1675 os << "\\usepackage{lmodern}\n";
1677 else if (rm == "ae") {
1678 // not needed when using OT1 font encoding.
1679 if (lyxrc.fontenc != "default")
1680 os << "\\usepackage{ae,aecompl}\n";
1683 else if (rm == "times") {
1684 // try to load the best available package
1685 if (LaTeXFeatures::isAvailable("mathptmx"))
1686 os << "\\usepackage{mathptmx}\n";
1687 else if (LaTeXFeatures::isAvailable("mathptm"))
1688 os << "\\usepackage{mathptm}\n";
1690 os << "\\usepackage{times}\n";
1693 else if (rm == "palatino") {
1694 // try to load the best available package
1695 if (LaTeXFeatures::isAvailable("mathpazo")) {
1696 os << "\\usepackage";
1702 // "osf" includes "sc"!
1706 os << "{mathpazo}\n";
1708 else if (LaTeXFeatures::isAvailable("mathpple"))
1709 os << "\\usepackage{mathpple}\n";
1711 os << "\\usepackage{palatino}\n";
1714 else if (rm == "utopia") {
1715 // fourier supersedes utopia.sty, but does
1716 // not work with OT1 encoding.
1717 if (LaTeXFeatures::isAvailable("fourier")
1718 && lyxrc.fontenc != "default") {
1719 os << "\\usepackage";
1730 os << "{fourier}\n";
1733 os << "\\usepackage{utopia}\n";
1735 // Bera (complete fontset)
1736 else if (rm == "bera" && sf == "default" && tt == "default")
1737 os << "\\usepackage{bera}\n";
1739 else if (rm != "default")
1740 os << "\\usepackage" << "{" << rm << "}\n";
1743 // Helvetica, Bera Sans
1744 if (sf == "helvet" || sf == "berasans") {
1746 os << "\\usepackage[scaled=" << float(sfscale) / 100
1747 << "]{" << sf << "}\n";
1749 os << "\\usepackage{" << sf << "}\n";
1752 else if (sf == "avant")
1753 os << "\\usepackage{" << sf << "}\n";
1754 // Computer Modern, Latin Modern, CM Bright
1755 else if (sf != "default")
1756 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1758 // monospaced/typewriter
1759 // Courier, LuxiMono
1760 if (tt == "luximono" || tt == "beramono") {
1762 os << "\\usepackage[scaled=" << float(ttscale) / 100
1763 << "]{" << tt << "}\n";
1765 os << "\\usepackage{" << tt << "}\n";
1768 else if (tt == "courier" )
1769 os << "\\usepackage{" << tt << "}\n";
1770 // Computer Modern, Latin Modern, CM Bright
1771 else if (tt != "default")
1772 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1778 Encoding const & BufferParams::encoding() const
1780 if (inputenc == "auto" || inputenc == "default")
1781 return *(language->encoding());
1782 Encoding const * const enc =
1783 encodings.getFromLaTeXName(inputenc);
1786 lyxerr << "Unknown inputenc value `" << inputenc
1787 << "'. Using `auto' instead." << endl;
1788 return *(language->encoding());
1792 biblio::CiteEngine BufferParams::getEngine() const
1794 // FIXME the class should provide the numerical/
1795 // authoryear choice
1796 if (getTextClass().provides("natbib")
1797 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1798 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1799 return cite_engine_;
1803 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1805 cite_engine_ = cite_engine;