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>
58 using std::istringstream;
60 using std::ostringstream;
63 using lyx::support::FileName;
64 using lyx::support::libFileSearch;
65 using lyx::support::bformat;
66 using lyx::support::rtrim;
67 using lyx::support::tokenPos;
68 using lyx::support::prefixIs;
71 static char const * const string_paragraph_separation[] = {
76 static char const * const string_quotes_language[] = {
77 "english", "swedish", "german", "polish", "french", "danish", ""
81 static char const * const string_papersize[] = {
82 "default", "custom", "letterpaper", "executivepaper", "legalpaper",
83 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
87 static char const * const string_orientation[] = {
88 "portrait", "landscape", ""
92 static char const * const string_footnotekinds[] = {
93 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
97 static char const * const tex_graphics[] = {
98 "default", "dvips", "dvitops", "emtex",
99 "ln", "oztex", "textures", "none", ""
108 // Paragraph separation
109 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
112 ParSepTranslator const init_parseptranslator()
114 ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
115 translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
120 ParSepTranslator const & parseptranslator()
122 static ParSepTranslator translator = init_parseptranslator();
128 typedef Translator<string, InsetQuotes::quote_language> QuotesLangTranslator;
131 QuotesLangTranslator const init_quoteslangtranslator()
133 QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
134 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
135 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
136 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
137 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
138 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
143 QuotesLangTranslator const & quoteslangtranslator()
145 static QuotesLangTranslator translator = init_quoteslangtranslator();
151 typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
154 PaperSizeTranslator const init_papersizetranslator()
156 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
157 translator.addPair(string_papersize[1], PAPER_CUSTOM);
158 translator.addPair(string_papersize[2], PAPER_USLETTER);
159 translator.addPair(string_papersize[3], PAPER_USLEGAL);
160 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
161 translator.addPair(string_papersize[5], PAPER_A3);
162 translator.addPair(string_papersize[6], PAPER_A4);
163 translator.addPair(string_papersize[7], PAPER_A5);
164 translator.addPair(string_papersize[8], PAPER_B3);
165 translator.addPair(string_papersize[9], PAPER_B4);
166 translator.addPair(string_papersize[10], PAPER_B5);
171 PaperSizeTranslator const & papersizetranslator()
173 static PaperSizeTranslator translator = init_papersizetranslator();
179 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
182 PaperOrientationTranslator const init_paperorientationtranslator()
184 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
185 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
190 PaperOrientationTranslator const & paperorientationtranslator()
192 static PaperOrientationTranslator translator = init_paperorientationtranslator();
198 typedef Translator<int, TextClass::PageSides> SidesTranslator;
201 SidesTranslator const init_sidestranslator()
203 SidesTranslator translator(1, TextClass::OneSide);
204 translator.addPair(2, TextClass::TwoSides);
209 SidesTranslator const & sidestranslator()
211 static SidesTranslator translator = init_sidestranslator();
217 typedef Translator<int, BufferParams::Package> PackageTranslator;
220 PackageTranslator const init_packagetranslator()
222 PackageTranslator translator(0, BufferParams::package_off);
223 translator.addPair(1, BufferParams::package_auto);
224 translator.addPair(2, BufferParams::package_on);
229 PackageTranslator const & packagetranslator()
231 static PackageTranslator translator = init_packagetranslator();
237 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
240 CiteEngineTranslator const init_citeenginetranslator()
242 CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
243 translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
244 translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
245 translator.addPair("jurabib", biblio::ENGINE_JURABIB);
250 CiteEngineTranslator const & citeenginetranslator()
252 static CiteEngineTranslator translator = init_citeenginetranslator();
258 typedef Translator<string, Spacing::Space> SpaceTranslator;
261 SpaceTranslator const init_spacetranslator()
263 SpaceTranslator translator("default", Spacing::Default);
264 translator.addPair("single", Spacing::Single);
265 translator.addPair("onehalf", Spacing::Onehalf);
266 translator.addPair("double", Spacing::Double);
267 translator.addPair("other", Spacing::Other);
272 SpaceTranslator const & spacetranslator()
274 static SpaceTranslator translator = init_spacetranslator();
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.
296 PDFOptions pdfoptions;
300 BufferParams::Impl::Impl()
301 : defskip(VSpace::MEDSKIP)
303 // set initial author
305 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
310 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
314 return new BufferParams::Impl(*ptr);
318 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
324 BufferParams::BufferParams()
327 setBaseClass(defaultTextclass());
328 paragraph_separation = PARSEP_INDENT;
329 quotes_language = InsetQuotes::EnglishQ;
330 fontsize = "default";
333 papersize = PAPER_DEFAULT;
334 orientation = ORIENTATION_PORTRAIT;
335 use_geometry = false;
336 use_amsmath = package_auto;
337 use_esint = package_auto;
338 cite_engine_ = biblio::ENGINE_BASIC;
339 use_bibtopic = false;
340 trackChanges = false;
341 outputChanges = false;
344 language = default_language;
345 fontsRoman = "default";
346 fontsSans = "default";
347 fontsTypewriter = "default";
348 fontsDefaultFamily = "default";
351 fontsSansScale = 100;
352 fontsTypewriterScale = 100;
354 graphicsDriver = "default";
355 sides = TextClass::OneSide;
357 listings_params = string();
358 pagestyle = "default";
361 for (int iter = 0; iter < 4; ++iter) {
362 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
363 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
368 BufferParams::~BufferParams()
372 docstring const BufferParams::B_(string const & l10n) const
374 BOOST_ASSERT(language);
375 return getMessages(language->code()).get(l10n);
379 AuthorList & BufferParams::authors()
381 return pimpl_->authorlist;
385 AuthorList const & BufferParams::authors() const
387 return pimpl_->authorlist;
391 BranchList & BufferParams::branchlist()
393 return pimpl_->branchlist;
397 BranchList const & BufferParams::branchlist() const
399 return pimpl_->branchlist;
403 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
405 BOOST_ASSERT(index < 4);
406 return pimpl_->temp_bullets[index];
410 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
412 BOOST_ASSERT(index < 4);
413 return pimpl_->temp_bullets[index];
417 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
419 BOOST_ASSERT(index < 4);
420 return pimpl_->user_defined_bullets[index];
424 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
426 BOOST_ASSERT(index < 4);
427 return pimpl_->user_defined_bullets[index];
431 Spacing & BufferParams::spacing()
433 return pimpl_->spacing;
437 Spacing const & BufferParams::spacing() const
439 return pimpl_->spacing;
442 PDFOptions & BufferParams::pdfoptions()
444 return pimpl_->pdfoptions;
448 PDFOptions const & BufferParams::pdfoptions() const
450 return pimpl_->pdfoptions;
453 VSpace const & BufferParams::getDefSkip() const
455 return pimpl_->defskip;
459 void BufferParams::setDefSkip(VSpace const & vs)
461 pimpl_->defskip = vs;
465 string const BufferParams::readToken(Lexer & lex, string const & token)
467 if (token == "\\textclass") {
469 string const classname = lex.getString();
470 pair<bool, lyx::textclass_type> pp =
471 textclasslist.numberOfClass(classname);
473 setBaseClass(pp.second);
475 // if text class does not exist, try to load it from filepath
476 pp = textclasslist.addTextClass(classname, filepath);
478 setBaseClass(pp.second);
480 setBaseClass(defaultTextclass());
484 if (!getTextClass().isTeXClassAvailable()) {
485 docstring const msg =
486 bformat(_("The layout file requested by this document,\n"
488 "is not usable. This is probably because a LaTeX\n"
489 "class or style file required by it is not\n"
490 "available. See the Customization documentation\n"
491 "for more information.\n"), from_utf8(classname));
492 frontend::Alert::warning(_("Document class not available"),
493 msg + _("LyX will not be able to produce output."));
496 } else if (token == "\\begin_preamble") {
498 } else if (token == "\\begin_modules") {
501 } else if (token == "\\options") {
503 options = lex.getString();
504 } else if (token == "\\language") {
506 } else if (token == "\\inputencoding") {
508 } else if (token == "\\graphics") {
509 readGraphicsDriver(lex);
510 } else if (token == "\\font_roman") {
512 } else if (token == "\\font_sans") {
514 } else if (token == "\\font_typewriter") {
515 lex >> fontsTypewriter;
516 } else if (token == "\\font_default_family") {
517 lex >> fontsDefaultFamily;
518 } else if (token == "\\font_sc") {
520 } else if (token == "\\font_osf") {
522 } else if (token == "\\font_sf_scale") {
523 lex >> fontsSansScale;
524 } else if (token == "\\font_tt_scale") {
525 lex >> fontsTypewriterScale;
526 } else if (token == "\\paragraph_separation") {
529 paragraph_separation = parseptranslator().find(parsep);
530 } else if (token == "\\defskip") {
532 pimpl_->defskip = VSpace(lex.getString());
533 } else if (token == "\\quotes_language") {
536 quotes_language = quoteslangtranslator().find(quotes_lang);
537 } else if (token == "\\papersize") {
540 papersize = papersizetranslator().find(ppsize);
541 } else if (token == "\\use_geometry") {
543 } else if (token == "\\use_amsmath") {
546 use_amsmath = packagetranslator().find(use_ams);
547 } else if (token == "\\use_esint") {
550 use_esint = packagetranslator().find(useesint);
551 } else if (token == "\\cite_engine") {
554 cite_engine_ = citeenginetranslator().find(engine);
555 } else if (token == "\\use_bibtopic") {
557 } else if (token == "\\tracking_changes") {
559 } else if (token == "\\output_changes") {
560 lex >> outputChanges;
561 } else if (token == "\\branch") {
563 docstring branch = lex.getDocString();
564 branchlist().add(branch);
567 string const tok = lex.getString();
568 if (tok == "\\end_branch")
570 Branch * branch_ptr = branchlist().find(branch);
571 if (tok == "\\selected") {
574 branch_ptr->setSelected(lex.getInteger());
576 // not yet operational
577 if (tok == "\\color") {
579 string color = lex.getString();
581 branch_ptr->setColor(color);
582 // Update also the Color table:
584 color = lcolor.getX11Name(Color::background);
586 lcolor.setColor(to_utf8(branch), color);
590 } else if (token == "\\author") {
592 istringstream ss(lex.getString());
595 author_map.push_back(pimpl_->authorlist.record(a));
596 } else if (token == "\\paperorientation") {
599 orientation = paperorientationtranslator().find(orient);
600 } else if (token == "\\paperwidth") {
602 } else if (token == "\\paperheight") {
604 } else if (token == "\\leftmargin") {
606 } else if (token == "\\topmargin") {
608 } else if (token == "\\rightmargin") {
610 } else if (token == "\\bottommargin") {
612 } else if (token == "\\headheight") {
614 } else if (token == "\\headsep") {
616 } else if (token == "\\footskip") {
618 } else if (token == "\\paperfontsize") {
620 } else if (token == "\\papercolumns") {
622 } else if (token == "\\listings_params") {
625 listings_params = InsetListingsParams(par).params();
626 } else if (token == "\\papersides") {
629 sides = sidestranslator().find(psides);
630 } else if (token == "\\paperpagestyle") {
632 } else if (token == "\\bullet") {
634 } else if (token == "\\bulletLaTeX") {
635 readBulletsLaTeX(lex);
636 } else if (token == "\\secnumdepth") {
638 } else if (token == "\\tocdepth") {
640 } else if (token == "\\spacing") {
644 if (nspacing == "other") {
647 spacing().set(spacetranslator().find(nspacing), tmp_val);
648 } else if (token == "\\float_placement") {
649 lex >> float_placement;
651 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
653 toktmp = pdfoptions().readToken(lex, token);
654 if (!toktmp.empty()) {
655 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
660 lyxerr << "BufferParams::readToken(): Unknown token: " <<
669 void BufferParams::writeFile(ostream & os) const
671 // The top of the file is written by the buffer.
672 // Prints out the buffer info into the .lyx file given by file
675 os << "\\textclass " << textclasslist[baseClass_].name() << '\n';
678 if (!preamble.empty()) {
679 // remove '\n' from the end of preamble
680 string const tmppreamble = rtrim(preamble, "\n");
681 os << "\\begin_preamble\n"
683 << "\n\\end_preamble\n";
687 if (!options.empty()) {
688 os << "\\options " << options << '\n';
692 if (!layoutModules_.empty()) {
693 os << "\\begin_modules" << '\n';
694 LayoutModuleList::const_iterator it = layoutModules_.begin();
695 for (; it != layoutModules_.end(); it++)
697 os << "\\end_modules" << '\n';
700 // then the text parameters
701 if (language != ignore_language)
702 os << "\\language " << language->lang() << '\n';
703 os << "\\inputencoding " << inputenc
704 << "\n\\font_roman " << fontsRoman
705 << "\n\\font_sans " << fontsSans
706 << "\n\\font_typewriter " << fontsTypewriter
707 << "\n\\font_default_family " << fontsDefaultFamily
708 << "\n\\font_sc " << convert<string>(fontsSC)
709 << "\n\\font_osf " << convert<string>(fontsOSF)
710 << "\n\\font_sf_scale " << fontsSansScale
711 << "\n\\font_tt_scale " << fontsTypewriterScale
712 << "\n\\graphics " << graphicsDriver << '\n';
714 if (!float_placement.empty()) {
715 os << "\\float_placement " << float_placement << '\n';
717 os << "\\paperfontsize " << fontsize << '\n';
719 spacing().writeFile(os);
720 pdfoptions().writeFile(os);
722 os << "\\papersize " << string_papersize[papersize]
723 << "\n\\use_geometry " << convert<string>(use_geometry)
724 << "\n\\use_amsmath " << use_amsmath
725 << "\n\\use_esint " << use_esint
726 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
727 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
728 << "\n\\paperorientation " << string_orientation[orientation]
731 BranchList::const_iterator it = branchlist().begin();
732 BranchList::const_iterator end = branchlist().end();
733 for (; it != end; ++it) {
734 os << "\\branch " << to_utf8(it->getBranch())
735 << "\n\\selected " << it->getSelected()
736 << "\n\\color " << lyx::X11hexname(it->getColor())
741 if (!paperwidth.empty())
742 os << "\\paperwidth "
743 << VSpace(paperwidth).asLyXCommand() << '\n';
744 if (!paperheight.empty())
745 os << "\\paperheight "
746 << VSpace(paperheight).asLyXCommand() << '\n';
747 if (!leftmargin.empty())
748 os << "\\leftmargin "
749 << VSpace(leftmargin).asLyXCommand() << '\n';
750 if (!topmargin.empty())
752 << VSpace(topmargin).asLyXCommand() << '\n';
753 if (!rightmargin.empty())
754 os << "\\rightmargin "
755 << VSpace(rightmargin).asLyXCommand() << '\n';
756 if (!bottommargin.empty())
757 os << "\\bottommargin "
758 << VSpace(bottommargin).asLyXCommand() << '\n';
759 if (!headheight.empty())
760 os << "\\headheight "
761 << VSpace(headheight).asLyXCommand() << '\n';
762 if (!headsep.empty())
764 << VSpace(headsep).asLyXCommand() << '\n';
765 if (!footskip.empty())
767 << VSpace(footskip).asLyXCommand() << '\n';
768 os << "\\secnumdepth " << secnumdepth
769 << "\n\\tocdepth " << tocdepth
770 << "\n\\paragraph_separation "
771 << string_paragraph_separation[paragraph_separation]
772 << "\n\\defskip " << getDefSkip().asLyXCommand()
773 << "\n\\quotes_language "
774 << string_quotes_language[quotes_language]
775 << "\n\\papercolumns " << columns
776 << "\n\\papersides " << sides
777 << "\n\\paperpagestyle " << pagestyle << '\n';
778 if (!listings_params.empty())
779 os << "\\listings_params \"" <<
780 InsetListingsParams(listings_params).encodedString() << "\"\n";
781 for (int i = 0; i < 4; ++i) {
782 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
783 if (user_defined_bullet(i).getFont() != -1) {
784 os << "\\bullet " << i << " "
785 << user_defined_bullet(i).getFont() << " "
786 << user_defined_bullet(i).getCharacter() << " "
787 << user_defined_bullet(i).getSize() << "\n";
791 os << "\\bulletLaTeX " << i << " \""
792 << lyx::to_ascii(user_defined_bullet(i).getText())
798 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
799 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
801 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
802 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
803 for (; a_it != a_end; ++a_it) {
804 if (a_it->second.used())
805 os << "\\author " << a_it->second << "\n";
807 os << "\\author " << Author() << "\n";
812 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
813 TexRow & texrow) const
815 os << "\\documentclass";
817 TextClass const & tclass = getTextClass();
819 ostringstream clsoptions; // the document class options.
821 if (tokenPos(tclass.opt_fontsize(),
822 '|', fontsize) >= 0) {
823 // only write if existing in list (and not default)
824 clsoptions << fontsize << "pt,";
827 // custom, A3, B3 and B4 paper sizes need geometry
828 bool nonstandard_papersize = papersize == PAPER_B3
829 || papersize == PAPER_B4
830 || papersize == PAPER_A3
831 || papersize == PAPER_CUSTOM;
836 clsoptions << "a4paper,";
839 clsoptions << "letterpaper,";
842 clsoptions << "a5paper,";
845 clsoptions << "b5paper,";
847 case PAPER_USEXECUTIVE:
848 clsoptions << "executivepaper,";
851 clsoptions << "legalpaper,";
863 if (sides != tclass.sides()) {
865 case TextClass::OneSide:
866 clsoptions << "oneside,";
868 case TextClass::TwoSides:
869 clsoptions << "twoside,";
875 if (columns != tclass.columns()) {
877 clsoptions << "twocolumn,";
879 clsoptions << "onecolumn,";
883 && orientation == ORIENTATION_LANDSCAPE)
884 clsoptions << "landscape,";
886 // language should be a parameter to \documentclass
887 if (language->babel() == "hebrew"
888 && default_language->babel() != "hebrew")
889 // This seems necessary
890 features.useLanguage(default_language);
892 ostringstream language_options;
893 bool const use_babel = features.useBabel();
895 language_options << features.getLanguages();
896 if (!language->babel().empty()) {
897 if (!language_options.str().empty())
898 language_options << ',';
899 language_options << language->babel();
901 if (lyxrc.language_global_options && !language_options.str().empty())
902 clsoptions << language_options.str() << ',';
905 // the user-defined options
906 if (!options.empty()) {
907 clsoptions << options << ',';
910 string strOptions(clsoptions.str());
911 if (!strOptions.empty()) {
912 strOptions = rtrim(strOptions, ",");
914 os << '[' << from_utf8(strOptions) << ']';
917 os << '{' << from_ascii(tclass.latexname()) << "}\n";
919 // end of \documentclass defs
921 // font selection must be done before loading fontenc.sty
923 loadFonts(fontsRoman, fontsSans,
924 fontsTypewriter, fontsSC, fontsOSF,
925 fontsSansScale, fontsTypewriterScale);
926 if (!fonts.empty()) {
927 os << from_ascii(fonts);
930 if (fontsDefaultFamily != "default")
931 os << "\\renewcommand{\\familydefault}{\\"
932 << from_ascii(fontsDefaultFamily) << "}\n";
935 // this one is not per buffer
936 // for arabic_arabi and farsi we also need to load the LAE and LFE encoding
937 if (lyxrc.fontenc != "default") {
938 if (language->lang() == "arabic_arabi" || language->lang() == "farsi") {
939 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
940 << ",LFE,LAE]{fontenc}\n";
943 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
949 // handle inputenc etc.
950 writeEncodingPreamble(os, features, texrow);
952 if (!listings_params.empty()) {
953 os << "\\usepackage{listings}\n";
956 // do not test validity because listings_params is supposed to be valid
957 string par = InsetListingsParams(listings_params).separatedParams(true);
958 os << from_ascii(par);
959 // count the number of newlines
960 for (size_t i = 0; i < par.size(); ++i)
966 if (use_geometry || nonstandard_papersize) {
967 os << "\\usepackage{geometry}\n";
969 os << "\\geometry{verbose";
970 if (orientation == ORIENTATION_LANDSCAPE)
974 if (!paperwidth.empty())
976 << from_ascii(paperwidth);
977 if (!paperheight.empty())
978 os << ",paperheight="
979 << from_ascii(paperheight);
982 os << ",letterpaper";
987 case PAPER_USEXECUTIVE:
988 os << ",executivepaper";
1009 // default papersize ie PAPER_DEFAULT
1010 switch (lyxrc.default_papersize) {
1011 case PAPER_DEFAULT: // keep compiler happy
1012 case PAPER_USLETTER:
1013 os << ",letterpaper";
1016 os << ",legalpaper";
1018 case PAPER_USEXECUTIVE:
1019 os << ",executivepaper";
1039 if (!topmargin.empty())
1040 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1041 if (!bottommargin.empty())
1042 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1043 if (!leftmargin.empty())
1044 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1045 if (!rightmargin.empty())
1046 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1047 if (!headheight.empty())
1048 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1049 if (!headsep.empty())
1050 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1051 if (!footskip.empty())
1052 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1057 if (tokenPos(tclass.opt_pagestyle(),
1058 '|', pagestyle) >= 0) {
1059 if (pagestyle == "fancy") {
1060 os << "\\usepackage{fancyhdr}\n";
1063 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1067 // Only if class has a ToC hierarchy
1068 if (tclass.hasTocLevels()) {
1069 if (secnumdepth != tclass.secnumdepth()) {
1070 os << "\\setcounter{secnumdepth}{"
1075 if (tocdepth != tclass.tocdepth()) {
1076 os << "\\setcounter{tocdepth}{"
1083 if (paragraph_separation) {
1084 switch (getDefSkip().kind()) {
1085 case VSpace::SMALLSKIP:
1086 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1088 case VSpace::MEDSKIP:
1089 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1091 case VSpace::BIGSKIP:
1092 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1094 case VSpace::LENGTH:
1095 os << "\\setlength{\\parskip}{"
1096 << from_utf8(getDefSkip().length().asLatexString())
1099 default: // should never happen // Then delete it.
1100 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1105 os << "\\setlength{\\parindent}{0pt}\n";
1109 // If we use jurabib, we have to call babel here.
1110 if (use_babel && features.isRequired("jurabib")) {
1111 os << from_ascii(babelCall(language_options.str()))
1113 << from_ascii(features.getBabelOptions());
1117 // Now insert the LyX specific LaTeX commands...
1119 // The optional packages;
1120 docstring lyxpreamble(from_ascii(features.getPackages()));
1122 // this might be useful...
1123 lyxpreamble += "\n\\makeatletter\n";
1125 // Some macros LyX will need
1126 docstring tmppreamble(from_ascii(features.getMacros()));
1128 if (!tmppreamble.empty()) {
1129 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1130 "LyX specific LaTeX commands.\n"
1131 + tmppreamble + '\n';
1134 // the text class specific preamble
1135 tmppreamble = features.getTClassPreamble();
1136 if (!tmppreamble.empty()) {
1137 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1138 "Textclass specific LaTeX commands.\n"
1139 + tmppreamble + '\n';
1142 /* the user-defined preamble */
1143 if (!preamble.empty()) {
1145 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1146 "User specified LaTeX commands.\n"
1147 + from_utf8(preamble) + '\n';
1150 // Itemize bullet settings need to be last in case the user
1151 // defines their own bullets that use a package included
1152 // in the user-defined preamble -- ARRae
1153 // Actually it has to be done much later than that
1154 // since some packages like frenchb make modifications
1155 // at \begin{document} time -- JMarc
1156 docstring bullets_def;
1157 for (int i = 0; i < 4; ++i) {
1158 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1159 if (bullets_def.empty())
1160 bullets_def += "\\AtBeginDocument{\n";
1161 bullets_def += " \\def\\labelitemi";
1163 // `i' is one less than the item to modify
1170 bullets_def += "ii";
1176 bullets_def += '{' +
1177 user_defined_bullet(i).getText()
1182 if (!bullets_def.empty())
1183 lyxpreamble += bullets_def + "}\n\n";
1185 // We try to load babel late, in case it interferes
1186 // with other packages.
1187 // Jurabib has to be called after babel, though.
1188 if (use_babel && !features.isRequired("jurabib")) {
1190 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1191 lyxpreamble += from_utf8(features.getBabelOptions());
1194 // PDF support. Hypreref manual: "Make sure it comes last of your loaded
1195 // packages, to give it a fighting chance of not being over-written,
1196 // since its job is to redefine many LATEX commands."
1197 // Has to be put into lyxpreamble (preserving line-counting for error
1199 odocstringstream oss;
1200 pdfoptions().writeLaTeX(oss);
1201 lyxpreamble += oss.str();
1203 lyxpreamble += "\\makeatother\n\n";
1206 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1207 for (int j = 0; j != nlines; ++j) {
1216 void BufferParams::useClassDefaults()
1218 TextClass const & tclass = textclasslist[baseClass_];
1220 sides = tclass.sides();
1221 columns = tclass.columns();
1222 pagestyle = tclass.pagestyle();
1223 options = tclass.options();
1224 // Only if class has a ToC hierarchy
1225 if (tclass.hasTocLevels()) {
1226 secnumdepth = tclass.secnumdepth();
1227 tocdepth = tclass.tocdepth();
1232 bool BufferParams::hasClassDefaults() const
1234 TextClass const & tclass = textclasslist[baseClass_];
1236 return (sides == tclass.sides()
1237 && columns == tclass.columns()
1238 && pagestyle == tclass.pagestyle()
1239 && options == tclass.options()
1240 && secnumdepth == tclass.secnumdepth()
1241 && tocdepth == tclass.tocdepth());
1245 TextClass const & BufferParams::getTextClass() const
1251 TextClassPtr BufferParams::getTextClassPtr() const {
1256 void BufferParams::setTextClass(TextClassPtr tc) {
1261 bool BufferParams::setBaseClass(textclass_type tc)
1264 if (textclasslist[tc].load())
1268 bformat(_("The document class %1$s could not be loaded."),
1269 from_utf8(textclasslist[tc].name()));
1270 frontend::Alert::error(_("Could not load class"), s);
1278 void BufferParams::setJustBaseClass(textclass_type tc)
1284 textclass_type BufferParams::getBaseClass() const
1290 void BufferParams::makeTextClass()
1292 textClass_.reset(new TextClass(textclasslist[getBaseClass()]));
1293 //FIXME It might be worth loading the children's modules here,
1294 //just as we load their bibliographies and such, instead of just
1295 //doing a check in InsetInclude.
1296 LayoutModuleList::const_iterator it = layoutModules_.begin();
1297 for (; it != layoutModules_.end(); it++) {
1298 string const modName = *it;
1299 LyXModule * lm = moduleList[modName];
1301 docstring const msg =
1302 bformat(_("The module %1$s has been requested by\n"
1303 "this document but has not been found in the list of\n"
1304 "available modules. If you recently installed it, you\n"
1305 "probalby need to reconfigure LyX.\n"), from_utf8(modName));
1306 frontend::Alert::warning(_("Module not available"),
1307 msg + _("Some layouts may not be available."));
1308 lyxerr << "BufferParams::makeTextClass(): Module " <<
1309 modName << " requested but not found in module list." <<
1313 FileName layout_file = libFileSearch("layouts", lm->filename);
1314 textClass_->read(layout_file, TextClass::MODULE);
1319 std::vector<string> const & BufferParams::getModules() const {
1320 return layoutModules_;
1325 bool BufferParams::addLayoutModule(string modName, bool makeClass) {
1326 LayoutModuleList::const_iterator it = layoutModules_.begin();
1327 LayoutModuleList::const_iterator end = layoutModules_.end();
1328 for (; it != end; it++) {
1332 if (it != layoutModules_.end())
1334 layoutModules_.push_back(modName);
1341 bool BufferParams::addLayoutModules(std::vector<string>modNames)
1344 std::vector<string>::const_iterator it = modNames.begin();
1345 std::vector<string>::const_iterator end = modNames.end();
1346 for (; it != end; ++it)
1347 retval &= addLayoutModule(*it, false);
1353 void BufferParams::clearLayoutModules() {
1354 layoutModules_.clear();
1359 Font const BufferParams::getFont() const
1361 Font f = getTextClass().defaultfont();
1362 f.setLanguage(language);
1363 if (fontsDefaultFamily == "rmdefault")
1364 f.setFamily(Font::ROMAN_FAMILY);
1365 else if (fontsDefaultFamily == "sfdefault")
1366 f.setFamily(Font::SANS_FAMILY);
1367 else if (fontsDefaultFamily == "ttdefault")
1368 f.setFamily(Font::TYPEWRITER_FAMILY);
1373 void BufferParams::readPreamble(Lexer & lex)
1375 if (lex.getString() != "\\begin_preamble")
1376 lyxerr << "Error (BufferParams::readPreamble):"
1377 "consistency check failed." << endl;
1379 preamble = lex.getLongString("\\end_preamble");
1383 void BufferParams::readLanguage(Lexer & lex)
1385 if (!lex.next()) return;
1387 string const tmptok = lex.getString();
1389 // check if tmptok is part of tex_babel in tex-defs.h
1390 language = languages.getLanguage(tmptok);
1392 // Language tmptok was not found
1393 language = default_language;
1394 lyxerr << "Warning: Setting language `"
1395 << tmptok << "' to `" << language->lang()
1401 void BufferParams::readGraphicsDriver(Lexer & lex)
1403 if (!lex.next()) return;
1405 string const tmptok = lex.getString();
1406 // check if tmptok is part of tex_graphics in tex_defs.h
1409 string const test = tex_graphics[n++];
1411 if (test == tmptok) {
1412 graphicsDriver = tmptok;
1414 } else if (test == "") {
1416 "Warning: graphics driver `$$Token' not recognized!\n"
1417 " Setting graphics driver to `default'.\n");
1418 graphicsDriver = "default";
1425 void BufferParams::readBullets(Lexer & lex)
1427 if (!lex.next()) return;
1429 int const index = lex.getInteger();
1431 int temp_int = lex.getInteger();
1432 user_defined_bullet(index).setFont(temp_int);
1433 temp_bullet(index).setFont(temp_int);
1435 user_defined_bullet(index).setCharacter(temp_int);
1436 temp_bullet(index).setCharacter(temp_int);
1438 user_defined_bullet(index).setSize(temp_int);
1439 temp_bullet(index).setSize(temp_int);
1443 void BufferParams::readBulletsLaTeX(Lexer & lex)
1445 // The bullet class should be able to read this.
1446 if (!lex.next()) return;
1447 int const index = lex.getInteger();
1449 docstring const temp_str = lex.getDocString();
1451 user_defined_bullet(index).setText(temp_str);
1452 temp_bullet(index).setText(temp_str);
1456 void BufferParams::readModules(Lexer & lex)
1458 if (!lex.eatLine()) {
1459 lyxerr << "Error (BufferParams::readModules):"
1460 "Unexpected end of input." << endl;
1464 string mod = lex.getString();
1465 if (mod == "\\end_modules")
1467 addLayoutModule(mod);
1473 string const BufferParams::paperSizeName() const
1475 char real_papersize = papersize;
1476 if (real_papersize == PAPER_DEFAULT)
1477 real_papersize = lyxrc.default_papersize;
1479 switch (real_papersize) {
1488 case PAPER_USEXECUTIVE:
1492 case PAPER_USLETTER:
1499 string const BufferParams::dvips_options() const
1504 && papersize == PAPER_CUSTOM
1505 && !lyxrc.print_paper_dimension_flag.empty()
1506 && !paperwidth.empty()
1507 && !paperheight.empty()) {
1508 // using a custom papersize
1509 result = lyxrc.print_paper_dimension_flag;
1510 result += ' ' + paperwidth;
1511 result += ',' + paperheight;
1513 string const paper_option = paperSizeName();
1514 if (paper_option != "letter" ||
1515 orientation != ORIENTATION_LANDSCAPE) {
1516 // dvips won't accept -t letter -t landscape.
1517 // In all other cases, include the paper size
1519 result = lyxrc.print_paper_flag;
1520 result += ' ' + paper_option;
1523 if (orientation == ORIENTATION_LANDSCAPE &&
1524 papersize != PAPER_CUSTOM)
1525 result += ' ' + lyxrc.print_landscape_flag;
1530 string const BufferParams::babelCall(string const & lang_opts) const
1532 string lang_pack = lyxrc.language_package;
1533 if (lang_pack != "\\usepackage{babel}")
1535 // suppress the babel call when there is no babel language defined
1536 // for the document language in the lib/languages file and if no
1537 // other languages are used (lang_opts is then empty)
1538 if (lang_opts.empty())
1540 if (!lyxrc.language_global_options)
1541 return "\\usepackage[" + lang_opts + "]{babel}";
1546 void BufferParams::writeEncodingPreamble(odocstream & os,
1547 LaTeXFeatures & features, TexRow & texrow) const
1549 if (inputenc == "auto") {
1550 string const doc_encoding =
1551 language->encoding()->latexName();
1552 Encoding::Package const package =
1553 language->encoding()->package();
1555 // Create a list with all the input encodings used
1557 std::set<string> encodings =
1558 features.getEncodingSet(doc_encoding);
1560 if (!encodings.empty() || package == Encoding::inputenc) {
1561 os << "\\usepackage[";
1562 std::set<string>::const_iterator it = encodings.begin();
1563 std::set<string>::const_iterator const end = encodings.end();
1565 os << from_ascii(*it);
1568 for (; it != end; ++it)
1569 os << ',' << from_ascii(*it);
1570 if (package == Encoding::inputenc) {
1571 if (!encodings.empty())
1573 os << from_ascii(doc_encoding);
1575 os << "]{inputenc}\n";
1578 if (package == Encoding::CJK) {
1579 os << "\\usepackage{CJK}\n";
1582 } else if (inputenc != "default") {
1583 switch (encoding().package()) {
1584 case Encoding::none:
1586 case Encoding::inputenc:
1587 os << "\\usepackage[" << from_ascii(inputenc)
1592 os << "\\usepackage{CJK}\n";
1598 // The encoding "armscii8" is only available when the package "armtex" is loaded.
1599 // armscii8 is used for Armenian.
1600 if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
1601 os << "\\usepackage{armtex}\n";
1607 string const BufferParams::loadFonts(string const & rm,
1608 string const & sf, string const & tt,
1609 bool const & sc, bool const & osf,
1610 int const & sfscale, int const & ttscale) const
1612 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1613 several packages have been replaced by others, that might not
1614 be installed on every system. We have to take care for that
1615 (see psnfss.pdf). We try to support all psnfss fonts as well
1616 as the fonts that have become de facto standard in the LaTeX
1617 world (e.g. Latin Modern). We do not support obsolete fonts
1618 (like PSLatex). In general, it should be possible to mix any
1619 rm font with any sf or tt font, respectively. (JSpitzm)
1621 -- separate math fonts.
1624 if (rm == "default" && sf == "default" && tt == "default")
1631 // Computer Modern (must be explicitely selectable -- there might be classes
1632 // that define a different default font!
1634 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1635 // osf for Computer Modern needs eco.sty
1637 os << "\\usepackage{eco}\n";
1639 // Latin Modern Roman
1640 else if (rm == "lmodern")
1641 os << "\\usepackage{lmodern}\n";
1643 else if (rm == "ae") {
1644 // not needed when using OT1 font encoding.
1645 if (lyxrc.fontenc != "default")
1646 os << "\\usepackage{ae,aecompl}\n";
1649 else if (rm == "times") {
1650 // try to load the best available package
1651 if (LaTeXFeatures::isAvailable("mathptmx"))
1652 os << "\\usepackage{mathptmx}\n";
1653 else if (LaTeXFeatures::isAvailable("mathptm"))
1654 os << "\\usepackage{mathptm}\n";
1656 os << "\\usepackage{times}\n";
1659 else if (rm == "palatino") {
1660 // try to load the best available package
1661 if (LaTeXFeatures::isAvailable("mathpazo")) {
1662 os << "\\usepackage";
1668 // "osf" includes "sc"!
1672 os << "{mathpazo}\n";
1674 else if (LaTeXFeatures::isAvailable("mathpple"))
1675 os << "\\usepackage{mathpple}\n";
1677 os << "\\usepackage{palatino}\n";
1680 else if (rm == "utopia") {
1681 // fourier supersedes utopia.sty, but does
1682 // not work with OT1 encoding.
1683 if (LaTeXFeatures::isAvailable("fourier")
1684 && lyxrc.fontenc != "default") {
1685 os << "\\usepackage";
1696 os << "{fourier}\n";
1699 os << "\\usepackage{utopia}\n";
1701 // Bera (complete fontset)
1702 else if (rm == "bera" && sf == "default" && tt == "default")
1703 os << "\\usepackage{bera}\n";
1705 else if (rm != "default")
1706 os << "\\usepackage" << "{" << rm << "}\n";
1709 // Helvetica, Bera Sans
1710 if (sf == "helvet" || sf == "berasans") {
1712 os << "\\usepackage[scaled=" << float(sfscale) / 100
1713 << "]{" << sf << "}\n";
1715 os << "\\usepackage{" << sf << "}\n";
1718 else if (sf == "avant")
1719 os << "\\usepackage{" << sf << "}\n";
1720 // Computer Modern, Latin Modern, CM Bright
1721 else if (sf != "default")
1722 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1724 // monospaced/typewriter
1725 // Courier, LuxiMono
1726 if (tt == "luximono" || tt == "beramono") {
1728 os << "\\usepackage[scaled=" << float(ttscale) / 100
1729 << "]{" << tt << "}\n";
1731 os << "\\usepackage{" << tt << "}\n";
1734 else if (tt == "courier" )
1735 os << "\\usepackage{" << tt << "}\n";
1736 // Computer Modern, Latin Modern, CM Bright
1737 else if (tt != "default")
1738 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1744 Encoding const & BufferParams::encoding() const
1746 if (inputenc == "auto" || inputenc == "default")
1747 return *(language->encoding());
1748 Encoding const * const enc =
1749 encodings.getFromLaTeXName(inputenc);
1752 lyxerr << "Unknown inputenc value `" << inputenc
1753 << "'. Using `auto' instead." << endl;
1754 return *(language->encoding());
1758 biblio::CiteEngine BufferParams::getEngine() const
1760 // FIXME the class should provide the numerical/
1761 // authoryear choice
1762 if (getTextClass().provides("natbib")
1763 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1764 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1765 return cite_engine_;
1769 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1771 cite_engine_ = cite_engine;