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 "LayoutFile.h"
22 #include "BranchList.h"
23 #include "buffer_funcs.h"
28 #include "LaTeXFeatures.h"
29 #include "ModuleList.h"
33 #include "OutputParams.h"
37 #include "PDFOptions.h"
39 #include "frontends/alert.h"
41 #include "insets/InsetListingsParams.h"
43 #include "support/convert.h"
44 #include "support/debug.h"
45 #include "support/docstream.h"
46 #include "support/FileName.h"
47 #include "support/filetools.h"
48 #include "support/gettext.h"
49 #include "support/Messages.h"
50 #include "support/Translator.h"
51 #include "support/lstrings.h"
57 using namespace lyx::support;
60 static char const * const string_paragraph_separation[] = {
65 static char const * const string_quotes_language[] = {
66 "english", "swedish", "german", "polish", "french", "danish", ""
70 static char const * const string_papersize[] = {
71 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
72 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
76 static char const * const string_orientation[] = {
77 "portrait", "landscape", ""
81 static char const * const string_footnotekinds[] = {
82 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
86 static char const * const tex_graphics[] = {
87 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
88 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
89 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
90 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
100 // Paragraph separation
101 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
104 ParSepTranslator const init_parseptranslator()
106 ParSepTranslator translator
107 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
108 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
113 ParSepTranslator const & parseptranslator()
115 static ParSepTranslator translator = init_parseptranslator();
121 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
124 QuotesLangTranslator const init_quoteslangtranslator()
126 QuotesLangTranslator translator
127 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
128 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
129 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
130 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
131 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
132 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
137 QuotesLangTranslator const & quoteslangtranslator()
139 static QuotesLangTranslator translator = init_quoteslangtranslator();
145 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
148 static PaperSizeTranslator initPaperSizeTranslator()
150 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
151 translator.addPair(string_papersize[1], PAPER_CUSTOM);
152 translator.addPair(string_papersize[2], PAPER_USLETTER);
153 translator.addPair(string_papersize[3], PAPER_USLEGAL);
154 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
155 translator.addPair(string_papersize[5], PAPER_A3);
156 translator.addPair(string_papersize[6], PAPER_A4);
157 translator.addPair(string_papersize[7], PAPER_A5);
158 translator.addPair(string_papersize[8], PAPER_B3);
159 translator.addPair(string_papersize[9], PAPER_B4);
160 translator.addPair(string_papersize[10], PAPER_B5);
165 PaperSizeTranslator const & papersizetranslator()
167 static PaperSizeTranslator translator = initPaperSizeTranslator();
173 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
176 PaperOrientationTranslator const init_paperorientationtranslator()
178 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
179 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
184 PaperOrientationTranslator const & paperorientationtranslator()
186 static PaperOrientationTranslator translator = init_paperorientationtranslator();
192 typedef Translator<int, PageSides> SidesTranslator;
195 SidesTranslator const init_sidestranslator()
197 SidesTranslator translator(1, OneSide);
198 translator.addPair(2, TwoSides);
203 SidesTranslator const & sidestranslator()
205 static SidesTranslator translator = init_sidestranslator();
211 typedef Translator<int, BufferParams::Package> PackageTranslator;
214 PackageTranslator const init_packagetranslator()
216 PackageTranslator translator(0, BufferParams::package_off);
217 translator.addPair(1, BufferParams::package_auto);
218 translator.addPair(2, BufferParams::package_on);
223 PackageTranslator const & packagetranslator()
225 static PackageTranslator translator = init_packagetranslator();
231 typedef Translator<string, CiteEngine> CiteEngineTranslator;
234 CiteEngineTranslator const init_citeenginetranslator()
236 CiteEngineTranslator translator("basic", ENGINE_BASIC);
237 translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
238 translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
239 translator.addPair("jurabib", ENGINE_JURABIB);
244 CiteEngineTranslator const & citeenginetranslator()
246 static CiteEngineTranslator translator = init_citeenginetranslator();
252 typedef Translator<string, Spacing::Space> SpaceTranslator;
255 SpaceTranslator const init_spacetranslator()
257 SpaceTranslator translator("default", Spacing::Default);
258 translator.addPair("single", Spacing::Single);
259 translator.addPair("onehalf", Spacing::Onehalf);
260 translator.addPair("double", Spacing::Double);
261 translator.addPair("other", Spacing::Other);
266 SpaceTranslator const & spacetranslator()
268 static SpaceTranslator translator = init_spacetranslator();
276 class BufferParams::Impl
281 AuthorList authorlist;
282 BranchList branchlist;
283 Bullet temp_bullets[4];
284 Bullet user_defined_bullets[4];
286 /** This is the amount of space used for paragraph_separation "skip",
287 * and for detached paragraphs in "indented" documents.
290 PDFOptions pdfoptions;
291 LayoutFileIndex baseClass_;
295 BufferParams::Impl::Impl()
296 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
298 // set initial author
300 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
305 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
309 return new BufferParams::Impl(*ptr);
313 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
319 BufferParams::BufferParams()
322 setBaseClass(defaultBaseclass());
324 paragraph_separation = ParagraphIndentSeparation;
325 quotes_language = InsetQuotes::EnglishQuotes;
326 fontsize = "default";
329 papersize = PAPER_DEFAULT;
330 orientation = ORIENTATION_PORTRAIT;
331 use_geometry = false;
332 use_amsmath = package_auto;
333 use_esint = package_auto;
334 cite_engine_ = ENGINE_BASIC;
335 use_bibtopic = false;
336 trackChanges = false;
337 outputChanges = false;
338 use_default_options = true;
341 language = default_language;
342 fontsRoman = "default";
343 fontsSans = "default";
344 fontsTypewriter = "default";
345 fontsDefaultFamily = "default";
348 fontsSansScale = 100;
349 fontsTypewriterScale = 100;
351 graphicsDriver = "default";
354 listings_params = string();
355 pagestyle = "default";
357 for (int iter = 0; iter < 4; ++iter) {
358 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
359 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
364 docstring BufferParams::B_(string const & l10n) const
366 LASSERT(language, /**/);
367 return getMessages(language->code()).get(l10n);
371 AuthorList & BufferParams::authors()
373 return pimpl_->authorlist;
377 AuthorList const & BufferParams::authors() const
379 return pimpl_->authorlist;
383 BranchList & BufferParams::branchlist()
385 return pimpl_->branchlist;
389 BranchList const & BufferParams::branchlist() const
391 return pimpl_->branchlist;
395 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
397 LASSERT(index < 4, /**/);
398 return pimpl_->temp_bullets[index];
402 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
404 LASSERT(index < 4, /**/);
405 return pimpl_->temp_bullets[index];
409 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
411 LASSERT(index < 4, /**/);
412 return pimpl_->user_defined_bullets[index];
416 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
418 LASSERT(index < 4, /**/);
419 return pimpl_->user_defined_bullets[index];
423 Spacing & BufferParams::spacing()
425 return pimpl_->spacing;
429 Spacing const & BufferParams::spacing() const
431 return pimpl_->spacing;
435 PDFOptions & BufferParams::pdfoptions()
437 return pimpl_->pdfoptions;
441 PDFOptions const & BufferParams::pdfoptions() const
443 return pimpl_->pdfoptions;
447 VSpace const & BufferParams::getDefSkip() const
449 return pimpl_->defskip;
453 void BufferParams::setDefSkip(VSpace const & vs)
455 pimpl_->defskip = vs;
459 string BufferParams::readToken(Lexer & lex, string const & token,
460 FileName const & filepath)
462 if (token == "\\textclass") {
464 string const classname = lex.getString();
465 // if there exists a local layout file, ignore the system one
466 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
468 LayoutFileList & bcl = LayoutFileList::get();
469 if (tcp.empty() && !filepath.empty())
470 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
474 setBaseClass(classname);
475 // We assume that a tex class exists for local or unknown layouts so this warning
476 // will only be given for system layouts.
477 if (!baseClass()->isTeXClassAvailable()) {
478 docstring const msg =
479 bformat(_("The layout file requested by this document,\n"
481 "is not usable. This is probably because a LaTeX\n"
482 "class or style file required by it is not\n"
483 "available. See the Customization documentation\n"
484 "for more information.\n"), from_utf8(classname));
485 frontend::Alert::warning(_("Document class not available"),
486 msg + _("LyX will not be able to produce output."));
488 } else if (token == "\\begin_preamble") {
490 } else if (token == "\\begin_local_layout") {
491 readLocalLayout(lex);
492 } else if (token == "\\begin_modules") {
494 } else if (token == "\\begin_removed_modules") {
495 readRemovedModules(lex);
496 } else if (token == "\\options") {
498 options = lex.getString();
499 } else if (token == "\\use_default_options") {
500 lex >> use_default_options;
501 } else if (token == "\\master") {
503 master = 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 == "\\font_cjk") {
528 } else if (token == "\\paragraph_separation") {
531 paragraph_separation = parseptranslator().find(parsep);
532 } else if (token == "\\defskip") {
534 string defskip = lex.getString();
535 if (defskip == "defskip")
538 pimpl_->defskip = VSpace(defskip);
539 } else if (token == "\\quotes_language") {
542 quotes_language = quoteslangtranslator().find(quotes_lang);
543 } else if (token == "\\papersize") {
546 papersize = papersizetranslator().find(ppsize);
547 } else if (token == "\\use_geometry") {
549 } else if (token == "\\use_amsmath") {
552 use_amsmath = packagetranslator().find(use_ams);
553 } else if (token == "\\use_esint") {
556 use_esint = packagetranslator().find(useesint);
557 } else if (token == "\\cite_engine") {
560 cite_engine_ = citeenginetranslator().find(engine);
561 } else if (token == "\\use_bibtopic") {
563 } else if (token == "\\tracking_changes") {
565 } else if (token == "\\output_changes") {
566 lex >> outputChanges;
567 } else if (token == "\\branch") {
569 docstring branch = lex.getDocString();
570 branchlist().add(branch);
573 string const tok = lex.getString();
574 if (tok == "\\end_branch")
576 Branch * branch_ptr = branchlist().find(branch);
577 if (tok == "\\selected") {
580 branch_ptr->setSelected(lex.getInteger());
582 // not yet operational
583 if (tok == "\\color") {
585 string color = lex.getString();
587 branch_ptr->setColor(color);
588 // Update also the Color table:
590 color = lcolor.getX11Name(Color_background);
592 lcolor.setColor(to_utf8(branch), color);
596 } else if (token == "\\author") {
598 istringstream ss(lex.getString());
601 author_map.push_back(pimpl_->authorlist.record(a));
602 } else if (token == "\\paperorientation") {
605 orientation = paperorientationtranslator().find(orient);
606 } else if (token == "\\paperwidth") {
608 } else if (token == "\\paperheight") {
610 } else if (token == "\\leftmargin") {
612 } else if (token == "\\topmargin") {
614 } else if (token == "\\rightmargin") {
616 } else if (token == "\\bottommargin") {
618 } else if (token == "\\headheight") {
620 } else if (token == "\\headsep") {
622 } else if (token == "\\footskip") {
624 } else if (token == "\\columnsep") {
626 } else if (token == "\\paperfontsize") {
628 } else if (token == "\\papercolumns") {
630 } else if (token == "\\listings_params") {
633 listings_params = InsetListingsParams(par).params();
634 } else if (token == "\\papersides") {
637 sides = sidestranslator().find(psides);
638 } else if (token == "\\paperpagestyle") {
640 } else if (token == "\\bullet") {
642 } else if (token == "\\bulletLaTeX") {
643 readBulletsLaTeX(lex);
644 } else if (token == "\\secnumdepth") {
646 } else if (token == "\\tocdepth") {
648 } else if (token == "\\spacing") {
652 if (nspacing == "other") {
655 spacing().set(spacetranslator().find(nspacing), tmp_val);
656 } else if (token == "\\float_placement") {
657 lex >> float_placement;
659 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
660 string toktmp = pdfoptions().readToken(lex, token);
661 if (!toktmp.empty()) {
662 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
667 lyxerr << "BufferParams::readToken(): Unknown token: " <<
676 void BufferParams::writeFile(ostream & os) const
678 // The top of the file is written by the buffer.
679 // Prints out the buffer info into the .lyx file given by file
682 os << "\\textclass " << baseClass()->name() << '\n';
685 if (!preamble.empty()) {
686 // remove '\n' from the end of preamble
687 string const tmppreamble = rtrim(preamble, "\n");
688 os << "\\begin_preamble\n"
690 << "\n\\end_preamble\n";
694 if (!options.empty()) {
695 os << "\\options " << options << '\n';
698 // use the class options defined in the layout?
699 os << "\\use_default_options "
700 << convert<string>(use_default_options) << "\n";
702 // the master document
703 if (!master.empty()) {
704 os << "\\master " << master << '\n';
708 if (!removedModules_.empty()) {
709 os << "\\begin_removed_modules" << '\n';
710 set<string>::const_iterator it = removedModules_.begin();
711 set<string>::const_iterator en = removedModules_.end();
712 for (; it != en; it++)
714 os << "\\end_removed_modules" << '\n';
718 if (!layoutModules_.empty()) {
719 os << "\\begin_modules" << '\n';
720 LayoutModuleList::const_iterator it = layoutModules_.begin();
721 LayoutModuleList::const_iterator en = layoutModules_.end();
722 for (; it != en; it++)
724 os << "\\end_modules" << '\n';
727 // local layout information
728 if (!local_layout.empty()) {
729 // remove '\n' from the end
730 string const tmplocal = rtrim(local_layout, "\n");
731 os << "\\begin_local_layout\n"
733 << "\n\\end_local_layout\n";
736 // then the text parameters
737 if (language != ignore_language)
738 os << "\\language " << language->lang() << '\n';
739 os << "\\inputencoding " << inputenc
740 << "\n\\font_roman " << fontsRoman
741 << "\n\\font_sans " << fontsSans
742 << "\n\\font_typewriter " << fontsTypewriter
743 << "\n\\font_default_family " << fontsDefaultFamily
744 << "\n\\font_sc " << convert<string>(fontsSC)
745 << "\n\\font_osf " << convert<string>(fontsOSF)
746 << "\n\\font_sf_scale " << fontsSansScale
747 << "\n\\font_tt_scale " << fontsTypewriterScale
749 if (!fontsCJK.empty()) {
750 os << "\\font_cjk " << fontsCJK << '\n';
752 os << "\n\\graphics " << graphicsDriver << '\n';
754 if (!float_placement.empty()) {
755 os << "\\float_placement " << float_placement << '\n';
757 os << "\\paperfontsize " << fontsize << '\n';
759 spacing().writeFile(os);
760 pdfoptions().writeFile(os);
762 os << "\\papersize " << string_papersize[papersize]
763 << "\n\\use_geometry " << convert<string>(use_geometry)
764 << "\n\\use_amsmath " << use_amsmath
765 << "\n\\use_esint " << use_esint
766 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
767 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
768 << "\n\\paperorientation " << string_orientation[orientation]
771 BranchList::const_iterator it = branchlist().begin();
772 BranchList::const_iterator end = branchlist().end();
773 for (; it != end; ++it) {
774 os << "\\branch " << to_utf8(it->branch())
775 << "\n\\selected " << it->isSelected()
776 << "\n\\color " << lyx::X11hexname(it->color())
781 if (!paperwidth.empty())
782 os << "\\paperwidth "
783 << VSpace(paperwidth).asLyXCommand() << '\n';
784 if (!paperheight.empty())
785 os << "\\paperheight "
786 << VSpace(paperheight).asLyXCommand() << '\n';
787 if (!leftmargin.empty())
788 os << "\\leftmargin "
789 << VSpace(leftmargin).asLyXCommand() << '\n';
790 if (!topmargin.empty())
792 << VSpace(topmargin).asLyXCommand() << '\n';
793 if (!rightmargin.empty())
794 os << "\\rightmargin "
795 << VSpace(rightmargin).asLyXCommand() << '\n';
796 if (!bottommargin.empty())
797 os << "\\bottommargin "
798 << VSpace(bottommargin).asLyXCommand() << '\n';
799 if (!headheight.empty())
800 os << "\\headheight "
801 << VSpace(headheight).asLyXCommand() << '\n';
802 if (!headsep.empty())
804 << VSpace(headsep).asLyXCommand() << '\n';
805 if (!footskip.empty())
807 << VSpace(footskip).asLyXCommand() << '\n';
808 if (!columnsep.empty())
810 << VSpace(columnsep).asLyXCommand() << '\n';
811 os << "\\secnumdepth " << secnumdepth
812 << "\n\\tocdepth " << tocdepth
813 << "\n\\paragraph_separation "
814 << string_paragraph_separation[paragraph_separation]
815 << "\n\\defskip " << getDefSkip().asLyXCommand()
816 << "\n\\quotes_language "
817 << string_quotes_language[quotes_language]
818 << "\n\\papercolumns " << columns
819 << "\n\\papersides " << sides
820 << "\n\\paperpagestyle " << pagestyle << '\n';
821 if (!listings_params.empty())
822 os << "\\listings_params \"" <<
823 InsetListingsParams(listings_params).encodedString() << "\"\n";
824 for (int i = 0; i < 4; ++i) {
825 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
826 if (user_defined_bullet(i).getFont() != -1) {
827 os << "\\bullet " << i << " "
828 << user_defined_bullet(i).getFont() << " "
829 << user_defined_bullet(i).getCharacter() << " "
830 << user_defined_bullet(i).getSize() << "\n";
834 os << "\\bulletLaTeX " << i << " \""
835 << lyx::to_ascii(user_defined_bullet(i).getText())
841 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
842 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
844 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
845 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
846 for (; a_it != a_end; ++a_it) {
847 if (a_it->second.used())
848 os << "\\author " << a_it->second << "\n";
850 os << "\\author " << Author() << "\n";
855 void BufferParams::validate(LaTeXFeatures & features) const
857 features.require(documentClass().requires());
860 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
861 bool xcolorsoul = LaTeXFeatures::isAvailable("soul") &&
862 LaTeXFeatures::isAvailable("xcolor");
864 switch (features.runparams().flavor) {
865 case OutputParams::LATEX:
867 features.require("ct-dvipost");
868 features.require("dvipost");
869 } else if (xcolorsoul) {
870 features.require("ct-xcolor-soul");
871 features.require("soul");
872 features.require("xcolor");
874 features.require("ct-none");
877 case OutputParams::PDFLATEX:
879 features.require("ct-xcolor-soul");
880 features.require("soul");
881 features.require("xcolor");
882 // improves color handling in PDF output
883 features.require("pdfcolmk");
885 features.require("ct-none");
893 // Floats with 'Here definitely' as default setting.
894 if (float_placement.find('H') != string::npos)
895 features.require("float");
897 // AMS Style is at document level
898 if (use_amsmath == package_on
899 || documentClass().provides("amsmath"))
900 features.require("amsmath");
901 if (use_esint == package_on)
902 features.require("esint");
904 // Document-level line spacing
905 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
906 features.require("setspace");
908 // the bullet shapes are buffer level not paragraph level
909 // so they are tested here
910 for (int i = 0; i < 4; ++i) {
911 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
913 int const font = user_defined_bullet(i).getFont();
915 int const c = user_defined_bullet(i).getCharacter();
921 features.require("latexsym");
923 } else if (font == 1) {
924 features.require("amssymb");
925 } else if (font >= 2 && font <= 5) {
926 features.require("pifont");
930 if (pdfoptions().use_hyperref) {
931 features.require("hyperref");
932 // due to interferences with babel and hyperref, the color package has to
933 // be loaded after hyperref when hyperref is used with the colorlinks
934 // option, see http://bugzilla.lyx.org/show_bug.cgi?id=5291
935 if (pdfoptions().colorlinks)
936 features.require("color");
939 if (language->lang() == "vietnamese")
940 features.require("vietnamese");
941 else if (language->lang() == "japanese")
942 features.require("japanese");
945 /// Find out if we need special treatment for babel.
946 static bool needsSpecialBabelCall(LaTeXFeatures const & features)
948 // FIXME: don't hardcode this!!
949 // If Vietnamese is used, babel must directly be loaded with the
950 // language options, see
951 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
953 // viet = string::npos when not found
954 // the same is for all other languages that are not directly supported by
955 // babel, but where LaTeX-packages add babel support.
956 // this is currently the case for Latvian, Lithuanian, and Mongolian
958 // If Japanese is used, babel must directly be loaded with the
959 // language options, see
960 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
961 return !lyxrc.language_global_options
962 || features.hasLanguage("vietnam")
963 || features.hasLanguage("latvian")
964 || features.hasLanguage("japanese")
965 || features.hasLanguage("lithuanian")
966 || features.hasLanguage("mongolian");
969 /// set up if and how babel is called
970 static docstring babelCall(LaTeXFeatures const & features,
971 string const & lang_opts)
973 string babel_call = lyxrc.language_package;
974 if (babel_call != "\\usepackage{babel}")
975 return from_utf8(babel_call);
976 // suppress the babel call when there is no babel language defined
977 // for the document language in the lib/languages file and if no
978 // other languages are used (lang_opts is then empty)
979 if (!features.hasLanguages())
982 if (needsSpecialBabelCall(features))
983 babel_call = "\\usepackage[" + lang_opts + "]{babel}";
985 return from_utf8(babel_call);
989 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
990 TexRow & texrow) const
992 os << "\\documentclass";
994 DocumentClass const & tclass = documentClass();
996 ostringstream clsoptions; // the document class options.
998 if (tokenPos(tclass.opt_fontsize(),
999 '|', fontsize) >= 0) {
1000 // only write if existing in list (and not default)
1001 clsoptions << fontsize << "pt,";
1004 // custom, A3, B3 and B4 paper sizes need geometry
1005 bool nonstandard_papersize = papersize == PAPER_B3
1006 || papersize == PAPER_B4
1007 || papersize == PAPER_A3
1008 || papersize == PAPER_CUSTOM;
1010 if (!use_geometry) {
1011 switch (papersize) {
1013 clsoptions << "a4paper,";
1015 case PAPER_USLETTER:
1016 clsoptions << "letterpaper,";
1019 clsoptions << "a5paper,";
1022 clsoptions << "b5paper,";
1024 case PAPER_USEXECUTIVE:
1025 clsoptions << "executivepaper,";
1028 clsoptions << "legalpaper,";
1040 if (sides != tclass.sides()) {
1043 clsoptions << "oneside,";
1046 clsoptions << "twoside,";
1052 if (columns != tclass.columns()) {
1054 clsoptions << "twocolumn,";
1056 clsoptions << "onecolumn,";
1060 && orientation == ORIENTATION_LANDSCAPE)
1061 clsoptions << "landscape,";
1063 // language should be a parameter to \documentclass
1064 if (language->babel() == "hebrew"
1065 && default_language->babel() != "hebrew")
1066 // This seems necessary
1067 features.useLanguage(default_language);
1069 ostringstream language_options;
1070 bool const use_babel = features.useBabel();
1072 language_options << features.getLanguages();
1073 if (!language->babel().empty()) {
1074 if (!language_options.str().empty())
1075 language_options << ',';
1076 language_options << language->babel();
1078 if (!language_options.str().empty()
1079 && !needsSpecialBabelCall(features))
1080 clsoptions << language_options.str() << ',';
1083 // the predefined options from the layout
1084 if (use_default_options && !tclass.options().empty())
1085 clsoptions << tclass.options() << ',';
1087 // the user-defined options
1088 if (!options.empty()) {
1089 clsoptions << options << ',';
1092 string strOptions(clsoptions.str());
1093 if (!strOptions.empty()) {
1094 strOptions = rtrim(strOptions, ",");
1096 os << '[' << from_utf8(strOptions) << ']';
1099 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1101 // end of \documentclass defs
1103 // font selection must be done before loading fontenc.sty
1104 string const fonts =
1105 loadFonts(fontsRoman, fontsSans,
1106 fontsTypewriter, fontsSC, fontsOSF,
1107 fontsSansScale, fontsTypewriterScale);
1108 if (!fonts.empty()) {
1109 os << from_ascii(fonts);
1112 if (fontsDefaultFamily != "default")
1113 os << "\\renewcommand{\\familydefault}{\\"
1114 << from_ascii(fontsDefaultFamily) << "}\n";
1116 // set font encoding
1117 // this one is not per buffer
1118 // for arabic_arabi and farsi we also need to load the LAE and
1120 if (lyxrc.fontenc != "default" && language->lang() != "japanese") {
1121 if (language->lang() == "arabic_arabi"
1122 || language->lang() == "farsi") {
1123 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1124 << ",LFE,LAE]{fontenc}\n";
1127 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1133 // handle inputenc etc.
1134 writeEncodingPreamble(os, features, texrow);
1136 if (!listings_params.empty() || features.isRequired("listings")) {
1137 os << "\\usepackage{listings}\n";
1140 if (!listings_params.empty()) {
1142 // do not test validity because listings_params is
1143 // supposed to be valid
1145 InsetListingsParams(listings_params).separatedParams(true);
1146 // we can't support all packages, but we should load the color package
1147 if (par.find("\\color", 0) != string::npos)
1148 features.require("color");
1149 os << from_utf8(par);
1150 // count the number of newlines
1151 for (size_t i = 0; i < par.size(); ++i)
1157 if (use_geometry || nonstandard_papersize) {
1158 os << "\\usepackage{geometry}\n";
1160 os << "\\geometry{verbose";
1161 if (orientation == ORIENTATION_LANDSCAPE)
1163 switch (papersize) {
1165 if (!paperwidth.empty())
1166 os << ",paperwidth="
1167 << from_ascii(paperwidth);
1168 if (!paperheight.empty())
1169 os << ",paperheight="
1170 << from_ascii(paperheight);
1172 case PAPER_USLETTER:
1173 os << ",letterpaper";
1176 os << ",legalpaper";
1178 case PAPER_USEXECUTIVE:
1179 os << ",executivepaper";
1200 // default papersize ie PAPER_DEFAULT
1201 switch (lyxrc.default_papersize) {
1202 case PAPER_DEFAULT: // keep compiler happy
1203 case PAPER_USLETTER:
1204 os << ",letterpaper";
1207 os << ",legalpaper";
1209 case PAPER_USEXECUTIVE:
1210 os << ",executivepaper";
1230 if (!topmargin.empty())
1231 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1232 if (!bottommargin.empty())
1233 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1234 if (!leftmargin.empty())
1235 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1236 if (!rightmargin.empty())
1237 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1238 if (!headheight.empty())
1239 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1240 if (!headsep.empty())
1241 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1242 if (!footskip.empty())
1243 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1244 if (!columnsep.empty())
1245 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1248 } else if (orientation == ORIENTATION_LANDSCAPE) {
1249 features.require("papersize");
1252 if (tokenPos(tclass.opt_pagestyle(),
1253 '|', pagestyle) >= 0) {
1254 if (pagestyle == "fancy") {
1255 os << "\\usepackage{fancyhdr}\n";
1258 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1262 // Only if class has a ToC hierarchy
1263 if (tclass.hasTocLevels()) {
1264 if (secnumdepth != tclass.secnumdepth()) {
1265 os << "\\setcounter{secnumdepth}{"
1270 if (tocdepth != tclass.tocdepth()) {
1271 os << "\\setcounter{tocdepth}{"
1278 if (paragraph_separation) {
1279 switch (getDefSkip().kind()) {
1280 case VSpace::SMALLSKIP:
1281 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1283 case VSpace::MEDSKIP:
1284 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1286 case VSpace::BIGSKIP:
1287 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1289 case VSpace::LENGTH:
1290 os << "\\setlength{\\parskip}{"
1291 << from_utf8(getDefSkip().length().asLatexString())
1294 default: // should never happen // Then delete it.
1295 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1300 os << "\\setlength{\\parindent}{0pt}\n";
1304 // Now insert the LyX specific LaTeX commands...
1305 docstring lyxpreamble;
1307 // due to interferences with babel and hyperref, the color package has to
1308 // be loaded (when it is not already loaded) before babel when hyperref
1309 // is used with the colorlinks option, see
1310 // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1311 // we decided therefore to load color always before babel, see
1312 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1313 lyxpreamble += from_ascii(features.getColorOptions());
1315 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1317 && (features.isRequired("jurabib")
1318 || features.isRequired("hyperref")
1319 || features.isRequired("vietnamese")
1320 || features.isRequired("japanese") ) ) {
1322 lyxpreamble += babelCall(features, language_options.str()) + '\n';
1323 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1326 // The optional packages;
1327 lyxpreamble += from_ascii(features.getPackages());
1330 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1333 // * Hyperref manual: "Make sure it comes last of your loaded
1334 // packages, to give it a fighting chance of not being over-written,
1335 // since its job is to redefine many LaTeX commands."
1336 // * Email from Heiko Oberdiek: "It is usually better to load babel
1337 // before hyperref. Then hyperref has a chance to detect babel.
1338 // * Has to be loaded before the "LyX specific LaTeX commands" to
1339 // avoid errors with algorithm floats.
1340 // use hyperref explicitely when it is required
1341 if (features.isRequired("hyperref")) {
1342 odocstringstream oss;
1343 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1344 lyxpreamble += oss.str();
1347 // Will be surrounded by \makeatletter and \makeatother when needed
1348 docstring atlyxpreamble;
1350 // Some macros LyX will need
1351 docstring tmppreamble(from_ascii(features.getMacros()));
1353 if (!tmppreamble.empty())
1354 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1355 "LyX specific LaTeX commands.\n"
1356 + tmppreamble + '\n';
1358 // the text class specific preamble
1359 tmppreamble = features.getTClassPreamble();
1360 if (!tmppreamble.empty())
1361 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1362 "Textclass specific LaTeX commands.\n"
1363 + tmppreamble + '\n';
1365 /* the user-defined preamble */
1366 if (!preamble.empty())
1368 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1369 "User specified LaTeX commands.\n"
1370 + from_utf8(preamble) + '\n';
1372 // subfig loads internally the LaTeX package "caption". As
1373 // caption is a very popular package, users will load it in
1374 // the preamble. Therefore we must load subfig behind the
1375 // user-defined preamble and check if the caption package was
1376 // loaded or not. For the case that caption is loaded before
1377 // subfig, there is the subfig option "caption=false". This
1378 // option also works when a koma-script class is used and
1379 // koma's own caption commands are used instead of caption. We
1380 // use \PassOptionsToPackage here because the user could have
1381 // already loaded subfig in the preamble.
1382 if (features.isRequired("subfig")) {
1383 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1384 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1385 "\\usepackage{subfig}\n";
1388 // Itemize bullet settings need to be last in case the user
1389 // defines their own bullets that use a package included
1390 // in the user-defined preamble -- ARRae
1391 // Actually it has to be done much later than that
1392 // since some packages like frenchb make modifications
1393 // at \begin{document} time -- JMarc
1394 docstring bullets_def;
1395 for (int i = 0; i < 4; ++i) {
1396 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1397 if (bullets_def.empty())
1398 bullets_def += "\\AtBeginDocument{\n";
1399 bullets_def += " \\def\\labelitemi";
1401 // `i' is one less than the item to modify
1408 bullets_def += "ii";
1414 bullets_def += '{' +
1415 user_defined_bullet(i).getText()
1420 if (!bullets_def.empty())
1421 atlyxpreamble += bullets_def + "}\n\n";
1423 if (atlyxpreamble.find(from_ascii("@")) != docstring::npos)
1424 lyxpreamble += "\n\\makeatletter\n"
1425 + atlyxpreamble + "\\makeatother\n\n";
1427 lyxpreamble += '\n' + atlyxpreamble;
1429 // We try to load babel late, in case it interferes with other packages.
1430 // Jurabib and Hyperref have to be called after babel, though.
1431 if (use_babel && !features.isRequired("jurabib")
1432 && !features.isRequired("hyperref")
1433 && !features.isRequired("vietnamese")
1434 && !features.isRequired("japanese")) {
1436 lyxpreamble += babelCall(features, language_options.str()) + '\n';
1437 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1441 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1442 for (int j = 0; j != nlines; ++j) {
1451 void BufferParams::useClassDefaults()
1453 DocumentClass const & tclass = documentClass();
1455 sides = tclass.sides();
1456 columns = tclass.columns();
1457 pagestyle = tclass.pagestyle();
1458 use_default_options = true;
1459 // Only if class has a ToC hierarchy
1460 if (tclass.hasTocLevels()) {
1461 secnumdepth = tclass.secnumdepth();
1462 tocdepth = tclass.tocdepth();
1467 bool BufferParams::hasClassDefaults() const
1469 DocumentClass const & tclass = documentClass();
1471 return sides == tclass.sides()
1472 && columns == tclass.columns()
1473 && pagestyle == tclass.pagestyle()
1474 && use_default_options
1475 && secnumdepth == tclass.secnumdepth()
1476 && tocdepth == tclass.tocdepth();
1480 DocumentClass const & BufferParams::documentClass() const
1486 DocumentClass const * BufferParams::documentClassPtr() const {
1491 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1492 // evil, but this function is evil
1493 doc_class_ = const_cast<DocumentClass *>(tc);
1497 bool BufferParams::setBaseClass(string const & classname)
1499 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1500 LayoutFileList & bcl = LayoutFileList::get();
1501 if (!bcl.haveClass(classname)) {
1503 bformat(_("The document class %1$s could not be found. "
1504 "A default textclass with default layouts will be used. "
1505 "LyX might not be able to produce output unless a correct "
1506 "textclass is selected from the document settings dialog."),
1507 from_utf8(classname));
1508 frontend::Alert::error(_("Document class not found"), s);
1509 bcl.addEmptyClass(classname);
1512 bool const success = bcl[classname].load();
1515 bformat(_("The document class %1$s could not be loaded."),
1516 from_utf8(classname));
1517 frontend::Alert::error(_("Could not load class"), s);
1521 pimpl_->baseClass_ = classname;
1523 // add any required modules not already in use
1524 list<string> const & mods = baseClass()->defaultModules();
1525 list<string>::const_iterator mit = mods.begin();
1526 list<string>::const_iterator men = mods.end();
1527 for (; mit != men; mit++) {
1528 string const & modName = *mit;
1529 // see if we're already in use
1530 if (find(layoutModules_.begin(), layoutModules_.end(), modName) !=
1531 layoutModules_.end()) {
1532 LYXERR(Debug::TCLASS, "Default module `" << modName <<
1533 "' not added because already used.");
1536 // make sure the user hasn't removed it
1537 if (find(removedModules_.begin(), removedModules_.end(), modName) !=
1538 removedModules_.end()) {
1539 LYXERR(Debug::TCLASS, "Default module `" << modName <<
1540 "' not added because removed by user.");
1543 // Now we want to check the list of selected modules to see if any of them
1544 // exclude this one.
1545 bool foundit = false;
1546 // so iterate over the selected modules...
1547 LayoutModuleList::const_iterator lit = layoutModules_.begin();
1548 LayoutModuleList::const_iterator len = layoutModules_.end();
1549 for (; lit != len; lit++) {
1550 LyXModule * lm = moduleList[*lit];
1553 vector<string> const & exc = lm->getExcludedModules();
1554 // ...and see if this one excludes us.
1555 if (find(exc.begin(), exc.end(), modName) != exc.end()) {
1557 LYXERR(Debug::TCLASS, "Default module `" << modName <<
1558 "' not added because excluded by loaded module `" <<
1564 LYXERR(Debug::TCLASS, "Default module `" << modName << "' added.");
1565 layoutModules_.push_back(modName);
1572 LayoutFile const * BufferParams::baseClass() const
1574 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1575 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1581 LayoutFileIndex const & BufferParams::baseClassID() const
1583 return pimpl_->baseClass_;
1587 void BufferParams::makeDocumentClass()
1592 doc_class_ = &(DocumentClassBundle::get().newClass(*baseClass()));
1594 // FIXME It might be worth loading the children's modules here,
1595 // just as we load their bibliographies and such, instead of just
1596 // doing a check in InsetInclude.
1597 LayoutModuleList::const_iterator it = layoutModules_.begin();
1598 for (; it != layoutModules_.end(); it++) {
1599 string const modName = *it;
1600 LyXModule * lm = moduleList[modName];
1602 docstring const msg =
1603 bformat(_("The module %1$s has been requested by\n"
1604 "this document but has not been found in the list of\n"
1605 "available modules. If you recently installed it, you\n"
1606 "probably need to reconfigure LyX.\n"), from_utf8(modName));
1607 frontend::Alert::warning(_("Module not available"),
1608 msg + _("Some layouts may not be available."));
1609 LYXERR0("BufferParams::makeDocumentClass(): Module " <<
1610 modName << " requested but not found in module list.");
1613 if (!lm->isAvailable()) {
1614 docstring const msg =
1615 bformat(_("The module %1$s requires a package that is\n"
1616 "not available in your LaTeX installation. LaTeX output\n"
1617 "may not be possible.\n"), from_utf8(modName));
1618 frontend::Alert::warning(_("Package not available"), msg);
1620 FileName layout_file = libFileSearch("layouts", lm->getFilename());
1621 if (!doc_class_->read(layout_file, TextClass::MODULE)) {
1622 docstring const msg =
1623 bformat(_("Error reading module %1$s\n"), from_utf8(modName));
1624 frontend::Alert::warning(_("Read Error"), msg);
1627 if (!local_layout.empty()) {
1628 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1629 docstring const msg = _("Error reading internal layout information");
1630 frontend::Alert::warning(_("Read Error"), msg);
1636 bool BufferParams::addLayoutModule(string const & modName)
1638 LayoutModuleList::const_iterator it = layoutModules_.begin();
1639 LayoutModuleList::const_iterator end = layoutModules_.end();
1640 for (; it != end; it++)
1643 layoutModules_.push_back(modName);
1648 Font const BufferParams::getFont() const
1650 FontInfo f = documentClass().defaultfont();
1651 if (fontsDefaultFamily == "rmdefault")
1652 f.setFamily(ROMAN_FAMILY);
1653 else if (fontsDefaultFamily == "sfdefault")
1654 f.setFamily(SANS_FAMILY);
1655 else if (fontsDefaultFamily == "ttdefault")
1656 f.setFamily(TYPEWRITER_FAMILY);
1657 return Font(f, language);
1661 void BufferParams::readPreamble(Lexer & lex)
1663 if (lex.getString() != "\\begin_preamble")
1664 lyxerr << "Error (BufferParams::readPreamble):"
1665 "consistency check failed." << endl;
1667 preamble = lex.getLongString("\\end_preamble");
1671 void BufferParams::readLocalLayout(Lexer & lex)
1673 if (lex.getString() != "\\begin_local_layout")
1674 lyxerr << "Error (BufferParams::readLocalLayout):"
1675 "consistency check failed." << endl;
1677 local_layout = lex.getLongString("\\end_local_layout");
1681 void BufferParams::readLanguage(Lexer & lex)
1683 if (!lex.next()) return;
1685 string const tmptok = lex.getString();
1687 // check if tmptok is part of tex_babel in tex-defs.h
1688 language = languages.getLanguage(tmptok);
1690 // Language tmptok was not found
1691 language = default_language;
1692 lyxerr << "Warning: Setting language `"
1693 << tmptok << "' to `" << language->lang()
1699 void BufferParams::readGraphicsDriver(Lexer & lex)
1704 string const tmptok = lex.getString();
1705 // check if tmptok is part of tex_graphics in tex_defs.h
1708 string const test = tex_graphics[n++];
1710 if (test == tmptok) {
1711 graphicsDriver = tmptok;
1716 "Warning: graphics driver `$$Token' not recognized!\n"
1717 " Setting graphics driver to `default'.\n");
1718 graphicsDriver = "default";
1725 void BufferParams::readBullets(Lexer & lex)
1730 int const index = lex.getInteger();
1732 int temp_int = lex.getInteger();
1733 user_defined_bullet(index).setFont(temp_int);
1734 temp_bullet(index).setFont(temp_int);
1736 user_defined_bullet(index).setCharacter(temp_int);
1737 temp_bullet(index).setCharacter(temp_int);
1739 user_defined_bullet(index).setSize(temp_int);
1740 temp_bullet(index).setSize(temp_int);
1744 void BufferParams::readBulletsLaTeX(Lexer & lex)
1746 // The bullet class should be able to read this.
1749 int const index = lex.getInteger();
1751 docstring const temp_str = lex.getDocString();
1753 user_defined_bullet(index).setText(temp_str);
1754 temp_bullet(index).setText(temp_str);
1758 void BufferParams::readModules(Lexer & lex)
1760 if (!lex.eatLine()) {
1761 lyxerr << "Error (BufferParams::readModules):"
1762 "Unexpected end of input." << endl;
1766 string mod = lex.getString();
1767 if (mod == "\\end_modules")
1769 addLayoutModule(mod);
1775 void BufferParams::readRemovedModules(Lexer & lex)
1777 if (!lex.eatLine()) {
1778 lyxerr << "Error (BufferParams::readRemovedModules):"
1779 "Unexpected end of input." << endl;
1783 string mod = lex.getString();
1784 if (mod == "\\end_removed_modules")
1786 removedModules_.insert(mod);
1789 // now we want to remove any removed modules that were previously
1790 // added. normally, that will be because default modules were added in
1791 // setBaseClass(), which gets called when \textclass is read at the
1792 // start of the read.
1793 set<string>::const_iterator rit = removedModules_.begin();
1794 set<string>::const_iterator const ren = removedModules_.end();
1795 for (; rit != ren; rit++) {
1796 LayoutModuleList::iterator const mit = layoutModules_.begin();
1797 LayoutModuleList::iterator const men = layoutModules_.end();
1798 LayoutModuleList::iterator found = find(mit, men, *rit);
1801 layoutModules_.erase(found);
1806 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1808 char real_papersize = papersize;
1809 if (real_papersize == PAPER_DEFAULT)
1810 real_papersize = lyxrc.default_papersize;
1812 switch (real_papersize) {
1814 // could be anything, so don't guess
1816 case PAPER_CUSTOM: {
1817 if (purpose == XDVI && !paperwidth.empty() &&
1818 !paperheight.empty()) {
1819 // heightxwidth<unit>
1820 string first = paperwidth;
1821 string second = paperheight;
1822 if (orientation == ORIENTATION_LANDSCAPE)
1825 return first.erase(first.length() - 2)
1837 // dvips and dvipdfm do not know this
1838 if (purpose == DVIPS || purpose == DVIPDFM)
1842 // dvipdfm does not know this
1843 if (purpose == DVIPDFM)
1847 // dvipdfm does not know this
1848 if (purpose == DVIPDFM)
1851 case PAPER_USEXECUTIVE:
1852 // dvipdfm does not know this
1853 if (purpose == DVIPDFM)
1858 case PAPER_USLETTER:
1860 if (purpose == XDVI)
1867 string const BufferParams::dvips_options() const
1872 && papersize == PAPER_CUSTOM
1873 && !lyxrc.print_paper_dimension_flag.empty()
1874 && !paperwidth.empty()
1875 && !paperheight.empty()) {
1876 // using a custom papersize
1877 result = lyxrc.print_paper_dimension_flag;
1878 result += ' ' + paperwidth;
1879 result += ',' + paperheight;
1881 string const paper_option = paperSizeName(DVIPS);
1882 if (!paper_option.empty() && (paper_option != "letter" ||
1883 orientation != ORIENTATION_LANDSCAPE)) {
1884 // dvips won't accept -t letter -t landscape.
1885 // In all other cases, include the paper size
1887 result = lyxrc.print_paper_flag;
1888 result += ' ' + paper_option;
1891 if (orientation == ORIENTATION_LANDSCAPE &&
1892 papersize != PAPER_CUSTOM)
1893 result += ' ' + lyxrc.print_landscape_flag;
1898 void BufferParams::writeEncodingPreamble(odocstream & os,
1899 LaTeXFeatures & features, TexRow & texrow) const
1901 if (inputenc == "auto") {
1902 string const doc_encoding =
1903 language->encoding()->latexName();
1904 Encoding::Package const package =
1905 language->encoding()->package();
1907 // Create a list with all the input encodings used
1909 set<string> encodings =
1910 features.getEncodingSet(doc_encoding);
1912 // If the "japanese" package (i.e. pLaTeX) is used,
1913 // inputenc must be omitted.
1914 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
1915 if (package == Encoding::japanese)
1916 features.require("japanese");
1918 if ((!encodings.empty() || package == Encoding::inputenc)
1919 && !features.isRequired("japanese")) {
1920 os << "\\usepackage[";
1921 set<string>::const_iterator it = encodings.begin();
1922 set<string>::const_iterator const end = encodings.end();
1924 os << from_ascii(*it);
1927 for (; it != end; ++it)
1928 os << ',' << from_ascii(*it);
1929 if (package == Encoding::inputenc) {
1930 if (!encodings.empty())
1932 os << from_ascii(doc_encoding);
1934 os << "]{inputenc}\n";
1937 if (package == Encoding::CJK || features.mustProvide("CJK")) {
1938 os << "\\usepackage{CJK}\n";
1941 } else if (inputenc != "default") {
1942 switch (encoding().package()) {
1943 case Encoding::none:
1944 case Encoding::japanese:
1946 case Encoding::inputenc:
1947 // do not load inputenc if japanese is used
1948 if (features.isRequired("japanese"))
1950 os << "\\usepackage[" << from_ascii(inputenc)
1955 os << "\\usepackage{CJK}\n";
1961 // The encoding "armscii8" (for Armenian) is only available when
1962 // the package "armtex" is loaded.
1963 if (language->encoding()->latexName() == "armscii8"
1964 || inputenc == "armscii8") {
1965 os << "\\usepackage{armtex}\n";
1971 string const BufferParams::loadFonts(string const & rm,
1972 string const & sf, string const & tt,
1973 bool const & sc, bool const & osf,
1974 int const & sfscale, int const & ttscale) const
1976 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1977 several packages have been replaced by others, that might not
1978 be installed on every system. We have to take care for that
1979 (see psnfss.pdf). We try to support all psnfss fonts as well
1980 as the fonts that have become de facto standard in the LaTeX
1981 world (e.g. Latin Modern). We do not support obsolete fonts
1982 (like PSLatex). In general, it should be possible to mix any
1983 rm font with any sf or tt font, respectively. (JSpitzm)
1985 -- separate math fonts.
1988 if (rm == "default" && sf == "default" && tt == "default")
1995 // Computer Modern (must be explicitely selectable -- there might be classes
1996 // that define a different default font!
1998 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1999 // osf for Computer Modern needs eco.sty
2001 os << "\\usepackage{eco}\n";
2003 // Latin Modern Roman
2004 else if (rm == "lmodern")
2005 os << "\\usepackage{lmodern}\n";
2007 else if (rm == "ae") {
2008 // not needed when using OT1 font encoding.
2009 if (lyxrc.fontenc != "default")
2010 os << "\\usepackage{ae,aecompl}\n";
2013 else if (rm == "times") {
2014 // try to load the best available package
2015 if (LaTeXFeatures::isAvailable("mathptmx"))
2016 os << "\\usepackage{mathptmx}\n";
2017 else if (LaTeXFeatures::isAvailable("mathptm"))
2018 os << "\\usepackage{mathptm}\n";
2020 os << "\\usepackage{times}\n";
2023 else if (rm == "palatino") {
2024 // try to load the best available package
2025 if (LaTeXFeatures::isAvailable("mathpazo")) {
2026 os << "\\usepackage";
2032 // "osf" includes "sc"!
2036 os << "{mathpazo}\n";
2038 else if (LaTeXFeatures::isAvailable("mathpple"))
2039 os << "\\usepackage{mathpple}\n";
2041 os << "\\usepackage{palatino}\n";
2044 else if (rm == "utopia") {
2045 // fourier supersedes utopia.sty, but does
2046 // not work with OT1 encoding.
2047 if (LaTeXFeatures::isAvailable("fourier")
2048 && lyxrc.fontenc != "default") {
2049 os << "\\usepackage";
2060 os << "{fourier}\n";
2063 os << "\\usepackage{utopia}\n";
2065 // Bera (complete fontset)
2066 else if (rm == "bera" && sf == "default" && tt == "default")
2067 os << "\\usepackage{bera}\n";
2069 else if (rm != "default")
2070 os << "\\usepackage" << "{" << rm << "}\n";
2073 // Helvetica, Bera Sans
2074 if (sf == "helvet" || sf == "berasans") {
2076 os << "\\usepackage[scaled=" << float(sfscale) / 100
2077 << "]{" << sf << "}\n";
2079 os << "\\usepackage{" << sf << "}\n";
2082 else if (sf == "avant")
2083 os << "\\usepackage{" << sf << "}\n";
2084 // Computer Modern, Latin Modern, CM Bright
2085 else if (sf != "default")
2086 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2088 // monospaced/typewriter
2089 // Courier, LuxiMono
2090 if (tt == "luximono" || tt == "beramono") {
2092 os << "\\usepackage[scaled=" << float(ttscale) / 100
2093 << "]{" << tt << "}\n";
2095 os << "\\usepackage{" << tt << "}\n";
2098 else if (tt == "courier" )
2099 os << "\\usepackage{" << tt << "}\n";
2100 // Computer Modern, Latin Modern, CM Bright
2101 else if (tt != "default")
2102 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2108 Encoding const & BufferParams::encoding() const
2110 if (inputenc == "auto" || inputenc == "default")
2111 return *language->encoding();
2112 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2115 LYXERR0("Unknown inputenc value `" << inputenc
2116 << "'. Using `auto' instead.");
2117 return *language->encoding();
2121 CiteEngine BufferParams::citeEngine() const
2123 // FIXME the class should provide the numerical/
2124 // authoryear choice
2125 if (documentClass().provides("natbib")
2126 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2127 return ENGINE_NATBIB_AUTHORYEAR;
2128 return cite_engine_;
2132 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2134 cite_engine_ = cite_engine;