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"
29 #include "LaTeXFeatures.h"
31 #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/docstream.h"
47 #include "support/filetools.h"
48 #include "support/Translator.h"
49 #include "support/lstrings.h"
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, PageSides> SidesTranslator;
201 SidesTranslator const init_sidestranslator()
203 SidesTranslator translator(1, OneSide);
204 translator.addPair(2, 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 Bullet temp_bullets[4];
290 Bullet user_defined_bullets[4];
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";
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;
443 PDFOptions & BufferParams::pdfoptions()
445 return pimpl_->pdfoptions;
449 PDFOptions const & BufferParams::pdfoptions() const
451 return pimpl_->pdfoptions;
455 VSpace const & BufferParams::getDefSkip() const
457 return pimpl_->defskip;
461 void BufferParams::setDefSkip(VSpace const & vs)
463 pimpl_->defskip = vs;
467 string const BufferParams::readToken(Lexer & lex, string const & token)
469 if (token == "\\textclass") {
471 string const classname = lex.getString();
472 pair<bool, lyx::textclass_type> pp =
473 textclasslist.numberOfClass(classname);
475 setBaseClass(pp.second);
477 // if text class does not exist, try to load it from filepath
478 pp = textclasslist.addTextClass(classname, filepath);
480 setBaseClass(pp.second);
482 setBaseClass(defaultTextclass());
486 if (!getTextClass().isTeXClassAvailable()) {
487 docstring const msg =
488 bformat(_("The layout file requested by this document,\n"
490 "is not usable. This is probably because a LaTeX\n"
491 "class or style file required by it is not\n"
492 "available. See the Customization documentation\n"
493 "for more information.\n"), from_utf8(classname));
494 frontend::Alert::warning(_("Document class not available"),
495 msg + _("LyX will not be able to produce output."));
498 } else if (token == "\\begin_preamble") {
500 } else if (token == "\\begin_modules") {
503 } else if (token == "\\options") {
505 options = lex.getString();
506 } else if (token == "\\language") {
508 } else if (token == "\\inputencoding") {
510 } else if (token == "\\graphics") {
511 readGraphicsDriver(lex);
512 } else if (token == "\\font_roman") {
514 } else if (token == "\\font_sans") {
516 } else if (token == "\\font_typewriter") {
517 lex >> fontsTypewriter;
518 } else if (token == "\\font_default_family") {
519 lex >> fontsDefaultFamily;
520 } else if (token == "\\font_sc") {
522 } else if (token == "\\font_osf") {
524 } else if (token == "\\font_sf_scale") {
525 lex >> fontsSansScale;
526 } else if (token == "\\font_tt_scale") {
527 lex >> fontsTypewriterScale;
528 } else if (token == "\\paragraph_separation") {
531 paragraph_separation = parseptranslator().find(parsep);
532 } else if (token == "\\defskip") {
534 pimpl_->defskip = VSpace(lex.getString());
535 } else if (token == "\\quotes_language") {
538 quotes_language = quoteslangtranslator().find(quotes_lang);
539 } else if (token == "\\papersize") {
542 papersize = papersizetranslator().find(ppsize);
543 } else if (token == "\\use_geometry") {
545 } else if (token == "\\use_amsmath") {
548 use_amsmath = packagetranslator().find(use_ams);
549 } else if (token == "\\use_esint") {
552 use_esint = packagetranslator().find(useesint);
553 } else if (token == "\\cite_engine") {
556 cite_engine_ = citeenginetranslator().find(engine);
557 } else if (token == "\\use_bibtopic") {
559 } else if (token == "\\tracking_changes") {
561 } else if (token == "\\output_changes") {
562 lex >> outputChanges;
563 } else if (token == "\\branch") {
565 docstring branch = lex.getDocString();
566 branchlist().add(branch);
569 string const tok = lex.getString();
570 if (tok == "\\end_branch")
572 Branch * branch_ptr = branchlist().find(branch);
573 if (tok == "\\selected") {
576 branch_ptr->setSelected(lex.getInteger());
578 // not yet operational
579 if (tok == "\\color") {
581 string color = lex.getString();
583 branch_ptr->setColor(color);
584 // Update also the Color table:
586 color = lcolor.getX11Name(Color_background);
588 lcolor.setColor(to_utf8(branch), color);
592 } else if (token == "\\author") {
594 istringstream ss(lex.getString());
597 author_map.push_back(pimpl_->authorlist.record(a));
598 } else if (token == "\\paperorientation") {
601 orientation = paperorientationtranslator().find(orient);
602 } else if (token == "\\paperwidth") {
604 } else if (token == "\\paperheight") {
606 } else if (token == "\\leftmargin") {
608 } else if (token == "\\topmargin") {
610 } else if (token == "\\rightmargin") {
612 } else if (token == "\\bottommargin") {
614 } else if (token == "\\headheight") {
616 } else if (token == "\\headsep") {
618 } else if (token == "\\footskip") {
620 } else if (token == "\\paperfontsize") {
622 } else if (token == "\\papercolumns") {
624 } else if (token == "\\listings_params") {
627 listings_params = InsetListingsParams(par).params();
628 } else if (token == "\\papersides") {
631 sides = sidestranslator().find(psides);
632 } else if (token == "\\paperpagestyle") {
634 } else if (token == "\\bullet") {
636 } else if (token == "\\bulletLaTeX") {
637 readBulletsLaTeX(lex);
638 } else if (token == "\\secnumdepth") {
640 } else if (token == "\\tocdepth") {
642 } else if (token == "\\spacing") {
646 if (nspacing == "other") {
649 spacing().set(spacetranslator().find(nspacing), tmp_val);
650 } else if (token == "\\float_placement") {
651 lex >> float_placement;
653 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
654 string toktmp = pdfoptions().readToken(lex, token);
655 if (!toktmp.empty()) {
656 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
661 lyxerr << "BufferParams::readToken(): Unknown token: " <<
670 void BufferParams::writeFile(ostream & os) const
672 // The top of the file is written by the buffer.
673 // Prints out the buffer info into the .lyx file given by file
676 os << "\\textclass " << textclasslist[baseClass_].name() << '\n';
679 if (!preamble.empty()) {
680 // remove '\n' from the end of preamble
681 string const tmppreamble = rtrim(preamble, "\n");
682 os << "\\begin_preamble\n"
684 << "\n\\end_preamble\n";
688 if (!options.empty()) {
689 os << "\\options " << options << '\n';
693 if (!layoutModules_.empty()) {
694 os << "\\begin_modules" << '\n';
695 LayoutModuleList::const_iterator it = layoutModules_.begin();
696 for (; it != layoutModules_.end(); it++)
698 os << "\\end_modules" << '\n';
701 // then the text parameters
702 if (language != ignore_language)
703 os << "\\language " << language->lang() << '\n';
704 os << "\\inputencoding " << inputenc
705 << "\n\\font_roman " << fontsRoman
706 << "\n\\font_sans " << fontsSans
707 << "\n\\font_typewriter " << fontsTypewriter
708 << "\n\\font_default_family " << fontsDefaultFamily
709 << "\n\\font_sc " << convert<string>(fontsSC)
710 << "\n\\font_osf " << convert<string>(fontsOSF)
711 << "\n\\font_sf_scale " << fontsSansScale
712 << "\n\\font_tt_scale " << fontsTypewriterScale
713 << "\n\\graphics " << graphicsDriver << '\n';
715 if (!float_placement.empty()) {
716 os << "\\float_placement " << float_placement << '\n';
718 os << "\\paperfontsize " << fontsize << '\n';
720 spacing().writeFile(os);
721 pdfoptions().writeFile(os);
723 os << "\\papersize " << string_papersize[papersize]
724 << "\n\\use_geometry " << convert<string>(use_geometry)
725 << "\n\\use_amsmath " << use_amsmath
726 << "\n\\use_esint " << use_esint
727 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
728 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
729 << "\n\\paperorientation " << string_orientation[orientation]
732 BranchList::const_iterator it = branchlist().begin();
733 BranchList::const_iterator end = branchlist().end();
734 for (; it != end; ++it) {
735 os << "\\branch " << to_utf8(it->getBranch())
736 << "\n\\selected " << it->getSelected()
737 << "\n\\color " << lyx::X11hexname(it->getColor())
742 if (!paperwidth.empty())
743 os << "\\paperwidth "
744 << VSpace(paperwidth).asLyXCommand() << '\n';
745 if (!paperheight.empty())
746 os << "\\paperheight "
747 << VSpace(paperheight).asLyXCommand() << '\n';
748 if (!leftmargin.empty())
749 os << "\\leftmargin "
750 << VSpace(leftmargin).asLyXCommand() << '\n';
751 if (!topmargin.empty())
753 << VSpace(topmargin).asLyXCommand() << '\n';
754 if (!rightmargin.empty())
755 os << "\\rightmargin "
756 << VSpace(rightmargin).asLyXCommand() << '\n';
757 if (!bottommargin.empty())
758 os << "\\bottommargin "
759 << VSpace(bottommargin).asLyXCommand() << '\n';
760 if (!headheight.empty())
761 os << "\\headheight "
762 << VSpace(headheight).asLyXCommand() << '\n';
763 if (!headsep.empty())
765 << VSpace(headsep).asLyXCommand() << '\n';
766 if (!footskip.empty())
768 << VSpace(footskip).asLyXCommand() << '\n';
769 os << "\\secnumdepth " << secnumdepth
770 << "\n\\tocdepth " << tocdepth
771 << "\n\\paragraph_separation "
772 << string_paragraph_separation[paragraph_separation]
773 << "\n\\defskip " << getDefSkip().asLyXCommand()
774 << "\n\\quotes_language "
775 << string_quotes_language[quotes_language]
776 << "\n\\papercolumns " << columns
777 << "\n\\papersides " << sides
778 << "\n\\paperpagestyle " << pagestyle << '\n';
779 if (!listings_params.empty())
780 os << "\\listings_params \"" <<
781 InsetListingsParams(listings_params).encodedString() << "\"\n";
782 for (int i = 0; i < 4; ++i) {
783 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
784 if (user_defined_bullet(i).getFont() != -1) {
785 os << "\\bullet " << i << " "
786 << user_defined_bullet(i).getFont() << " "
787 << user_defined_bullet(i).getCharacter() << " "
788 << user_defined_bullet(i).getSize() << "\n";
792 os << "\\bulletLaTeX " << i << " \""
793 << lyx::to_ascii(user_defined_bullet(i).getText())
799 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
800 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
802 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
803 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
804 for (; a_it != a_end; ++a_it) {
805 if (a_it->second.used())
806 os << "\\author " << a_it->second << "\n";
808 os << "\\author " << Author() << "\n";
813 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
814 TexRow & texrow) const
816 os << "\\documentclass";
818 TextClass const & tclass = getTextClass();
820 ostringstream clsoptions; // the document class options.
822 if (tokenPos(tclass.opt_fontsize(),
823 '|', fontsize) >= 0) {
824 // only write if existing in list (and not default)
825 clsoptions << fontsize << "pt,";
828 // custom, A3, B3 and B4 paper sizes need geometry
829 bool nonstandard_papersize = papersize == PAPER_B3
830 || papersize == PAPER_B4
831 || papersize == PAPER_A3
832 || papersize == PAPER_CUSTOM;
837 clsoptions << "a4paper,";
840 clsoptions << "letterpaper,";
843 clsoptions << "a5paper,";
846 clsoptions << "b5paper,";
848 case PAPER_USEXECUTIVE:
849 clsoptions << "executivepaper,";
852 clsoptions << "legalpaper,";
864 if (sides != tclass.sides()) {
867 clsoptions << "oneside,";
870 clsoptions << "twoside,";
876 if (columns != tclass.columns()) {
878 clsoptions << "twocolumn,";
880 clsoptions << "onecolumn,";
884 && orientation == ORIENTATION_LANDSCAPE)
885 clsoptions << "landscape,";
887 // language should be a parameter to \documentclass
888 if (language->babel() == "hebrew"
889 && default_language->babel() != "hebrew")
890 // This seems necessary
891 features.useLanguage(default_language);
893 ostringstream language_options;
894 bool const use_babel = features.useBabel();
896 language_options << features.getLanguages();
897 if (!language->babel().empty()) {
898 if (!language_options.str().empty())
899 language_options << ',';
900 language_options << language->babel();
902 // when Vietnamese is used, babel must directly be loaded with the
903 // language options, not in the class options, see
904 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
905 size_t 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 problems, you can shift babel to its old place behind
1138 // the user-defined preamble. But in this case you must change the Vietnamese
1139 // support from currently "\usepackage[vietnamese]{babel}" to:
1140 // \usepackage{vietnamese}
1141 // \usepackage{babel}
1142 // because vietnamese must be loaded before hyperref
1143 if (use_babel && !features.isRequired("jurabib")) {
1145 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1146 lyxpreamble += from_utf8(features.getBabelOptions());
1149 // When the language "japanese-plain" is used, the package "japanese" must
1150 // be loaded behind babel (it provides babel support for Japanese) but before
1152 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
1153 if (language->lang() == "japanese-plain" &&
1154 !getTextClass().provides("japanese")) {
1155 //load babel in case it was not loaded due to an empty language list
1156 if (language_options.str().empty())
1157 lyxpreamble += "\\usepackage{babel}\n";
1158 lyxpreamble += "\\usepackage{japanese}\n";
1162 // * Hyperref manual: "Make sure it comes last of your loaded
1163 // packages, to give it a fighting chance of not being over-written,
1164 // since its job is to redefine many LATEX commands."
1165 // * Email from Heiko Oberdiek: "It is usually better to load babel
1166 // before hyperref. Then hyperref has a chance to detect babel.
1167 // * Has to be loaded before the "LyX specific LaTeX commands" to
1168 // avoid errors with algorithm floats.
1169 odocstringstream oss;
1170 // use hyperref explicitely when it is required
1171 pdfoptions().writeLaTeX(oss, features.isRequired("hyperref"));
1172 lyxpreamble += oss.str();
1174 // this might be useful...
1175 lyxpreamble += "\n\\makeatletter\n";
1177 // Some macros LyX will need
1178 docstring tmppreamble(from_ascii(features.getMacros()));
1180 if (!tmppreamble.empty()) {
1181 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1182 "LyX specific LaTeX commands.\n"
1183 + tmppreamble + '\n';
1186 // the text class specific preamble
1187 tmppreamble = features.getTClassPreamble();
1188 if (!tmppreamble.empty()) {
1189 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1190 "Textclass specific LaTeX commands.\n"
1191 + tmppreamble + '\n';
1194 /* the user-defined preamble */
1195 if (!preamble.empty()) {
1197 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1198 "User specified LaTeX commands.\n"
1199 + from_utf8(preamble) + '\n';
1202 // Itemize bullet settings need to be last in case the user
1203 // defines their own bullets that use a package included
1204 // in the user-defined preamble -- ARRae
1205 // Actually it has to be done much later than that
1206 // since some packages like frenchb make modifications
1207 // at \begin{document} time -- JMarc
1208 docstring bullets_def;
1209 for (int i = 0; i < 4; ++i) {
1210 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1211 if (bullets_def.empty())
1212 bullets_def += "\\AtBeginDocument{\n";
1213 bullets_def += " \\def\\labelitemi";
1215 // `i' is one less than the item to modify
1222 bullets_def += "ii";
1228 bullets_def += '{' +
1229 user_defined_bullet(i).getText()
1234 if (!bullets_def.empty())
1235 lyxpreamble += bullets_def + "}\n\n";
1237 lyxpreamble += "\\makeatother\n\n";
1240 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1241 for (int j = 0; j != nlines; ++j) {
1250 void BufferParams::useClassDefaults()
1252 TextClass const & tclass = textclasslist[baseClass_];
1254 sides = tclass.sides();
1255 columns = tclass.columns();
1256 pagestyle = tclass.pagestyle();
1257 options = tclass.options();
1258 // Only if class has a ToC hierarchy
1259 if (tclass.hasTocLevels()) {
1260 secnumdepth = tclass.secnumdepth();
1261 tocdepth = tclass.tocdepth();
1266 bool BufferParams::hasClassDefaults() const
1268 TextClass const & tclass = textclasslist[baseClass_];
1270 return (sides == tclass.sides()
1271 && columns == tclass.columns()
1272 && pagestyle == tclass.pagestyle()
1273 && options == tclass.options()
1274 && secnumdepth == tclass.secnumdepth()
1275 && tocdepth == tclass.tocdepth());
1279 TextClass const & BufferParams::getTextClass() const
1285 TextClassPtr BufferParams::getTextClassPtr() const {
1290 void BufferParams::setTextClass(TextClassPtr tc) {
1295 bool BufferParams::setBaseClass(textclass_type tc)
1298 if (textclasslist[tc].load())
1302 bformat(_("The document class %1$s could not be loaded."),
1303 from_utf8(textclasslist[tc].name()));
1304 frontend::Alert::error(_("Could not load class"), s);
1312 void BufferParams::setJustBaseClass(textclass_type tc)
1318 textclass_type BufferParams::getBaseClass() const
1324 void BufferParams::makeTextClass()
1326 textClass_.reset(new TextClass(textclasslist[getBaseClass()]));
1327 //FIXME It might be worth loading the children's modules here,
1328 //just as we load their bibliographies and such, instead of just
1329 //doing a check in InsetInclude.
1330 LayoutModuleList::const_iterator it = layoutModules_.begin();
1331 for (; it != layoutModules_.end(); it++) {
1332 string const modName = *it;
1333 LyXModule * lm = moduleList[modName];
1335 docstring const msg =
1336 bformat(_("The module %1$s has been requested by\n"
1337 "this document but has not been found in the list of\n"
1338 "available modules. If you recently installed it, you\n"
1339 "probalby need to reconfigure LyX.\n"), from_utf8(modName));
1340 frontend::Alert::warning(_("Module not available"),
1341 msg + _("Some layouts may not be available."));
1342 lyxerr << "BufferParams::makeTextClass(): Module " <<
1343 modName << " requested but not found in module list." <<
1347 FileName layout_file = libFileSearch("layouts", lm->filename);
1348 textClass_->read(layout_file, TextClass::MODULE);
1353 std::vector<string> const & BufferParams::getModules() const {
1354 return layoutModules_;
1359 bool BufferParams::addLayoutModule(string modName, bool makeClass) {
1360 LayoutModuleList::const_iterator it = layoutModules_.begin();
1361 LayoutModuleList::const_iterator end = layoutModules_.end();
1362 for (; it != end; it++) {
1366 if (it != layoutModules_.end())
1368 layoutModules_.push_back(modName);
1375 bool BufferParams::addLayoutModules(std::vector<string>modNames)
1378 std::vector<string>::const_iterator it = modNames.begin();
1379 std::vector<string>::const_iterator end = modNames.end();
1380 for (; it != end; ++it)
1381 retval &= addLayoutModule(*it, false);
1387 void BufferParams::clearLayoutModules() {
1388 layoutModules_.clear();
1393 Font const BufferParams::getFont() const
1395 FontInfo f = getTextClass().defaultfont();
1396 if (fontsDefaultFamily == "rmdefault")
1397 f.setFamily(ROMAN_FAMILY);
1398 else if (fontsDefaultFamily == "sfdefault")
1399 f.setFamily(SANS_FAMILY);
1400 else if (fontsDefaultFamily == "ttdefault")
1401 f.setFamily(TYPEWRITER_FAMILY);
1402 return Font(f, language);
1406 void BufferParams::readPreamble(Lexer & lex)
1408 if (lex.getString() != "\\begin_preamble")
1409 lyxerr << "Error (BufferParams::readPreamble):"
1410 "consistency check failed." << endl;
1412 preamble = lex.getLongString("\\end_preamble");
1416 void BufferParams::readLanguage(Lexer & lex)
1418 if (!lex.next()) return;
1420 string const tmptok = lex.getString();
1422 // check if tmptok is part of tex_babel in tex-defs.h
1423 language = languages.getLanguage(tmptok);
1425 // Language tmptok was not found
1426 language = default_language;
1427 lyxerr << "Warning: Setting language `"
1428 << tmptok << "' to `" << language->lang()
1434 void BufferParams::readGraphicsDriver(Lexer & lex)
1436 if (!lex.next()) return;
1438 string const tmptok = lex.getString();
1439 // check if tmptok is part of tex_graphics in tex_defs.h
1442 string const test = tex_graphics[n++];
1444 if (test == tmptok) {
1445 graphicsDriver = tmptok;
1447 } else if (test == "") {
1449 "Warning: graphics driver `$$Token' not recognized!\n"
1450 " Setting graphics driver to `default'.\n");
1451 graphicsDriver = "default";
1458 void BufferParams::readBullets(Lexer & lex)
1460 if (!lex.next()) return;
1462 int const index = lex.getInteger();
1464 int temp_int = lex.getInteger();
1465 user_defined_bullet(index).setFont(temp_int);
1466 temp_bullet(index).setFont(temp_int);
1468 user_defined_bullet(index).setCharacter(temp_int);
1469 temp_bullet(index).setCharacter(temp_int);
1471 user_defined_bullet(index).setSize(temp_int);
1472 temp_bullet(index).setSize(temp_int);
1476 void BufferParams::readBulletsLaTeX(Lexer & lex)
1478 // The bullet class should be able to read this.
1479 if (!lex.next()) return;
1480 int const index = lex.getInteger();
1482 docstring const temp_str = lex.getDocString();
1484 user_defined_bullet(index).setText(temp_str);
1485 temp_bullet(index).setText(temp_str);
1489 void BufferParams::readModules(Lexer & lex)
1491 if (!lex.eatLine()) {
1492 lyxerr << "Error (BufferParams::readModules):"
1493 "Unexpected end of input." << endl;
1497 string mod = lex.getString();
1498 if (mod == "\\end_modules")
1500 addLayoutModule(mod);
1506 string const BufferParams::paperSizeName() const
1508 char real_papersize = papersize;
1509 if (real_papersize == PAPER_DEFAULT)
1510 real_papersize = lyxrc.default_papersize;
1512 switch (real_papersize) {
1521 case PAPER_USEXECUTIVE:
1525 case PAPER_USLETTER:
1532 string const BufferParams::dvips_options() const
1537 && papersize == PAPER_CUSTOM
1538 && !lyxrc.print_paper_dimension_flag.empty()
1539 && !paperwidth.empty()
1540 && !paperheight.empty()) {
1541 // using a custom papersize
1542 result = lyxrc.print_paper_dimension_flag;
1543 result += ' ' + paperwidth;
1544 result += ',' + paperheight;
1546 string const paper_option = paperSizeName();
1547 if (paper_option != "letter" ||
1548 orientation != ORIENTATION_LANDSCAPE) {
1549 // dvips won't accept -t letter -t landscape.
1550 // In all other cases, include the paper size
1552 result = lyxrc.print_paper_flag;
1553 result += ' ' + paper_option;
1556 if (orientation == ORIENTATION_LANDSCAPE &&
1557 papersize != PAPER_CUSTOM)
1558 result += ' ' + lyxrc.print_landscape_flag;
1563 string const BufferParams::babelCall(string const & lang_opts) const
1565 string lang_pack = lyxrc.language_package;
1566 if (lang_pack != "\\usepackage{babel}")
1568 // suppress the babel call when there is no babel language defined
1569 // for the document language in the lib/languages file and if no
1570 // other languages are used (lang_opts is then empty)
1571 if (lang_opts.empty())
1573 // when Vietnamese is used, babel must directly be loaded with the
1574 // language options, see
1575 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1576 size_t viet = lang_opts.find("vietnam");
1577 // viet = string::npos when not found
1578 if (!lyxrc.language_global_options || viet != string::npos)
1579 return "\\usepackage[" + lang_opts + "]{babel}";
1584 void BufferParams::writeEncodingPreamble(odocstream & os,
1585 LaTeXFeatures & features, TexRow & texrow) const
1587 if (inputenc == "auto") {
1588 string const doc_encoding =
1589 language->encoding()->latexName();
1590 Encoding::Package const package =
1591 language->encoding()->package();
1593 // Create a list with all the input encodings used
1595 std::set<string> encodings =
1596 features.getEncodingSet(doc_encoding);
1598 // When the encodings EUC-JP-plain, JIS-plain, or SJIS-plainare used, the
1599 // package inputenc must be omitted. Therefore set the encoding to empty.
1600 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
1601 if (doc_encoding == "EUC-JP-plain" || doc_encoding == "JIS-plain" ||
1602 doc_encoding == "SJIS-plain")
1605 if (!encodings.empty() || package == Encoding::inputenc) {
1606 os << "\\usepackage[";
1607 std::set<string>::const_iterator it = encodings.begin();
1608 std::set<string>::const_iterator const end = encodings.end();
1610 os << from_ascii(*it);
1613 for (; it != end; ++it)
1614 os << ',' << from_ascii(*it);
1615 if (package == Encoding::inputenc) {
1616 if (!encodings.empty())
1618 os << from_ascii(doc_encoding);
1620 os << "]{inputenc}\n";
1623 if (package == Encoding::CJK) {
1624 os << "\\usepackage{CJK}\n";
1627 } else if (inputenc != "default") {
1628 switch (encoding().package()) {
1629 case Encoding::none:
1631 case Encoding::inputenc:
1632 os << "\\usepackage[" << from_ascii(inputenc)
1637 os << "\\usepackage{CJK}\n";
1643 // The encoding "armscii8" is only available when the package "armtex" is loaded.
1644 // armscii8 is used for Armenian.
1645 if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
1646 os << "\\usepackage{armtex}\n";
1652 string const BufferParams::loadFonts(string const & rm,
1653 string const & sf, string const & tt,
1654 bool const & sc, bool const & osf,
1655 int const & sfscale, int const & ttscale) const
1657 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1658 several packages have been replaced by others, that might not
1659 be installed on every system. We have to take care for that
1660 (see psnfss.pdf). We try to support all psnfss fonts as well
1661 as the fonts that have become de facto standard in the LaTeX
1662 world (e.g. Latin Modern). We do not support obsolete fonts
1663 (like PSLatex). In general, it should be possible to mix any
1664 rm font with any sf or tt font, respectively. (JSpitzm)
1666 -- separate math fonts.
1669 if (rm == "default" && sf == "default" && tt == "default")
1676 // Computer Modern (must be explicitely selectable -- there might be classes
1677 // that define a different default font!
1679 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1680 // osf for Computer Modern needs eco.sty
1682 os << "\\usepackage{eco}\n";
1684 // Latin Modern Roman
1685 else if (rm == "lmodern")
1686 os << "\\usepackage{lmodern}\n";
1688 else if (rm == "ae") {
1689 // not needed when using OT1 font encoding.
1690 if (lyxrc.fontenc != "default")
1691 os << "\\usepackage{ae,aecompl}\n";
1694 else if (rm == "times") {
1695 // try to load the best available package
1696 if (LaTeXFeatures::isAvailable("mathptmx"))
1697 os << "\\usepackage{mathptmx}\n";
1698 else if (LaTeXFeatures::isAvailable("mathptm"))
1699 os << "\\usepackage{mathptm}\n";
1701 os << "\\usepackage{times}\n";
1704 else if (rm == "palatino") {
1705 // try to load the best available package
1706 if (LaTeXFeatures::isAvailable("mathpazo")) {
1707 os << "\\usepackage";
1713 // "osf" includes "sc"!
1717 os << "{mathpazo}\n";
1719 else if (LaTeXFeatures::isAvailable("mathpple"))
1720 os << "\\usepackage{mathpple}\n";
1722 os << "\\usepackage{palatino}\n";
1725 else if (rm == "utopia") {
1726 // fourier supersedes utopia.sty, but does
1727 // not work with OT1 encoding.
1728 if (LaTeXFeatures::isAvailable("fourier")
1729 && lyxrc.fontenc != "default") {
1730 os << "\\usepackage";
1741 os << "{fourier}\n";
1744 os << "\\usepackage{utopia}\n";
1746 // Bera (complete fontset)
1747 else if (rm == "bera" && sf == "default" && tt == "default")
1748 os << "\\usepackage{bera}\n";
1750 else if (rm != "default")
1751 os << "\\usepackage" << "{" << rm << "}\n";
1754 // Helvetica, Bera Sans
1755 if (sf == "helvet" || sf == "berasans") {
1757 os << "\\usepackage[scaled=" << float(sfscale) / 100
1758 << "]{" << sf << "}\n";
1760 os << "\\usepackage{" << sf << "}\n";
1763 else if (sf == "avant")
1764 os << "\\usepackage{" << sf << "}\n";
1765 // Computer Modern, Latin Modern, CM Bright
1766 else if (sf != "default")
1767 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1769 // monospaced/typewriter
1770 // Courier, LuxiMono
1771 if (tt == "luximono" || tt == "beramono") {
1773 os << "\\usepackage[scaled=" << float(ttscale) / 100
1774 << "]{" << tt << "}\n";
1776 os << "\\usepackage{" << tt << "}\n";
1779 else if (tt == "courier" )
1780 os << "\\usepackage{" << tt << "}\n";
1781 // Computer Modern, Latin Modern, CM Bright
1782 else if (tt != "default")
1783 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1789 Encoding const & BufferParams::encoding() const
1791 if (inputenc == "auto" || inputenc == "default")
1792 return *(language->encoding());
1793 Encoding const * const enc =
1794 encodings.getFromLaTeXName(inputenc);
1797 lyxerr << "Unknown inputenc value `" << inputenc
1798 << "'. Using `auto' instead." << endl;
1799 return *(language->encoding());
1803 biblio::CiteEngine BufferParams::getEngine() const
1805 // FIXME the class should provide the numerical/
1806 // authoryear choice
1807 if (getTextClass().provides("natbib")
1808 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1809 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1810 return cite_engine_;
1814 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1816 cite_engine_ = cite_engine;