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"
29 #include "LaTeXFeatures.h"
30 #include "ModuleList.h"
34 #include "OutputParams.h"
38 #include "PDFOptions.h"
40 #include "frontends/alert.h"
42 #include "insets/InsetListingsParams.h"
44 #include "support/convert.h"
45 #include "support/debug.h"
46 #include "support/docstream.h"
47 #include "support/FileName.h"
48 #include "support/filetools.h"
49 #include "support/gettext.h"
50 #include "support/Messages.h"
51 #include "support/Translator.h"
52 #include "support/lstrings.h"
58 using namespace lyx::support;
61 static char const * const string_paragraph_separation[] = {
66 static char const * const string_quotes_language[] = {
67 "english", "swedish", "german", "polish", "french", "danish", ""
71 static char const * const string_papersize[] = {
72 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
73 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
77 static char const * const string_orientation[] = {
78 "portrait", "landscape", ""
82 static char const * const string_footnotekinds[] = {
83 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
87 static char const * const tex_graphics[] = {
88 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
89 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
90 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
91 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
102 // Paragraph separation
103 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
106 ParSepTranslator const init_parseptranslator()
108 ParSepTranslator translator
109 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
110 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
115 ParSepTranslator const & parseptranslator()
117 static ParSepTranslator translator = init_parseptranslator();
123 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
126 QuotesLangTranslator const init_quoteslangtranslator()
128 QuotesLangTranslator translator
129 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
130 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
131 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
132 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
133 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
134 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
139 QuotesLangTranslator const & quoteslangtranslator()
141 static QuotesLangTranslator translator = init_quoteslangtranslator();
147 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
150 static PaperSizeTranslator initPaperSizeTranslator()
152 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
153 translator.addPair(string_papersize[1], PAPER_CUSTOM);
154 translator.addPair(string_papersize[2], PAPER_USLETTER);
155 translator.addPair(string_papersize[3], PAPER_USLEGAL);
156 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
157 translator.addPair(string_papersize[5], PAPER_A3);
158 translator.addPair(string_papersize[6], PAPER_A4);
159 translator.addPair(string_papersize[7], PAPER_A5);
160 translator.addPair(string_papersize[8], PAPER_B3);
161 translator.addPair(string_papersize[9], PAPER_B4);
162 translator.addPair(string_papersize[10], PAPER_B5);
167 PaperSizeTranslator const & papersizetranslator()
169 static PaperSizeTranslator translator = initPaperSizeTranslator();
175 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
178 PaperOrientationTranslator const init_paperorientationtranslator()
180 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
181 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
186 PaperOrientationTranslator const & paperorientationtranslator()
188 static PaperOrientationTranslator translator = init_paperorientationtranslator();
194 typedef Translator<int, PageSides> SidesTranslator;
197 SidesTranslator const init_sidestranslator()
199 SidesTranslator translator(1, OneSide);
200 translator.addPair(2, TwoSides);
205 SidesTranslator const & sidestranslator()
207 static SidesTranslator translator = init_sidestranslator();
213 typedef Translator<int, BufferParams::Package> PackageTranslator;
216 PackageTranslator const init_packagetranslator()
218 PackageTranslator translator(0, BufferParams::package_off);
219 translator.addPair(1, BufferParams::package_auto);
220 translator.addPair(2, BufferParams::package_on);
225 PackageTranslator const & packagetranslator()
227 static PackageTranslator translator = init_packagetranslator();
233 typedef Translator<string, CiteEngine> CiteEngineTranslator;
236 CiteEngineTranslator const init_citeenginetranslator()
238 CiteEngineTranslator translator("basic", ENGINE_BASIC);
239 translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
240 translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
241 translator.addPair("jurabib", ENGINE_JURABIB);
246 CiteEngineTranslator const & citeenginetranslator()
248 static CiteEngineTranslator translator = init_citeenginetranslator();
254 typedef Translator<string, Spacing::Space> SpaceTranslator;
257 SpaceTranslator const init_spacetranslator()
259 SpaceTranslator translator("default", Spacing::Default);
260 translator.addPair("single", Spacing::Single);
261 translator.addPair("onehalf", Spacing::Onehalf);
262 translator.addPair("double", Spacing::Double);
263 translator.addPair("other", Spacing::Other);
268 SpaceTranslator const & spacetranslator()
270 static SpaceTranslator translator = init_spacetranslator();
277 class BufferParams::Impl
282 AuthorList authorlist;
283 BranchList branchlist;
284 Bullet temp_bullets[4];
285 Bullet user_defined_bullets[4];
287 /** This is the amount of space used for paragraph_separation "skip",
288 * and for detached paragraphs in "indented" documents.
291 PDFOptions pdfoptions;
292 LayoutFileIndex baseClass_;
296 BufferParams::Impl::Impl()
297 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
299 // set initial author
301 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
306 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
310 return new BufferParams::Impl(*ptr);
314 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
320 BufferParams::BufferParams()
323 setBaseClass(defaultBaseclass());
325 paragraph_separation = ParagraphIndentSeparation;
326 quotes_language = InsetQuotes::EnglishQuotes;
327 fontsize = "default";
330 papersize = PAPER_DEFAULT;
331 orientation = ORIENTATION_PORTRAIT;
332 use_geometry = false;
333 use_amsmath = package_auto;
334 use_esint = package_auto;
335 cite_engine_ = ENGINE_BASIC;
336 use_bibtopic = false;
337 trackChanges = false;
338 outputChanges = false;
339 use_default_options = true;
342 language = default_language;
343 fontsRoman = "default";
344 fontsSans = "default";
345 fontsTypewriter = "default";
346 fontsDefaultFamily = "default";
350 fontsSansScale = 100;
351 fontsTypewriterScale = 100;
353 graphicsDriver = "default";
354 defaultOutputFormat = "default";
357 listings_params = string();
358 pagestyle = "default";
360 for (int iter = 0; iter < 4; ++iter) {
361 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
362 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
367 docstring BufferParams::B_(string const & l10n) const
369 LASSERT(language, /**/);
370 return getMessages(language->code()).get(l10n);
374 AuthorList & BufferParams::authors()
376 return pimpl_->authorlist;
380 AuthorList const & BufferParams::authors() const
382 return pimpl_->authorlist;
386 BranchList & BufferParams::branchlist()
388 return pimpl_->branchlist;
392 BranchList const & BufferParams::branchlist() const
394 return pimpl_->branchlist;
398 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
400 LASSERT(index < 4, /**/);
401 return pimpl_->temp_bullets[index];
405 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
407 LASSERT(index < 4, /**/);
408 return pimpl_->temp_bullets[index];
412 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
414 LASSERT(index < 4, /**/);
415 return pimpl_->user_defined_bullets[index];
419 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
421 LASSERT(index < 4, /**/);
422 return pimpl_->user_defined_bullets[index];
426 Spacing & BufferParams::spacing()
428 return pimpl_->spacing;
432 Spacing const & BufferParams::spacing() const
434 return pimpl_->spacing;
438 PDFOptions & BufferParams::pdfoptions()
440 return pimpl_->pdfoptions;
444 PDFOptions const & BufferParams::pdfoptions() const
446 return pimpl_->pdfoptions;
450 VSpace const & BufferParams::getDefSkip() const
452 return pimpl_->defskip;
456 void BufferParams::setDefSkip(VSpace const & vs)
458 pimpl_->defskip = vs;
462 string BufferParams::readToken(Lexer & lex, string const & token,
463 FileName const & filepath)
465 if (token == "\\textclass") {
467 string const classname = lex.getString();
468 // if there exists a local layout file, ignore the system one
469 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
471 LayoutFileList & bcl = LayoutFileList::get();
472 if (tcp.empty() && !filepath.empty())
473 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
477 setBaseClass(classname);
478 // We assume that a tex class exists for local or unknown layouts so this warning
479 // will only be given for system layouts.
480 if (!baseClass()->isTeXClassAvailable()) {
481 docstring const msg =
482 bformat(_("The layout file requested by this document,\n"
484 "is not usable. This is probably because a LaTeX\n"
485 "class or style file required by it is not\n"
486 "available. See the Customization documentation\n"
487 "for more information.\n"), from_utf8(classname));
488 frontend::Alert::warning(_("Document class not available"),
489 msg + _("LyX will not be able to produce output."));
491 } else if (token == "\\begin_preamble") {
493 } else if (token == "\\begin_local_layout") {
494 readLocalLayout(lex);
495 } else if (token == "\\begin_modules") {
497 } else if (token == "\\begin_removed_modules") {
498 readRemovedModules(lex);
499 } else if (token == "\\options") {
501 options = lex.getString();
502 } else if (token == "\\use_default_options") {
503 lex >> use_default_options;
504 } else if (token == "\\master") {
506 master = lex.getString();
507 } else if (token == "\\language") {
509 } else if (token == "\\inputencoding") {
511 } else if (token == "\\graphics") {
512 readGraphicsDriver(lex);
513 } else if (token == "\\default_output_format") {
514 lex >> defaultOutputFormat;
515 } else if (token == "\\font_roman") {
517 fontsRoman = lex.getString();
518 } else if (token == "\\font_sans") {
520 fontsSans = lex.getString();
521 } else if (token == "\\font_typewriter") {
523 fontsTypewriter = lex.getString();
524 } else if (token == "\\font_default_family") {
525 lex >> fontsDefaultFamily;
526 } else if (token == "\\use_xetex") {
528 } else if (token == "\\font_sc") {
530 } else if (token == "\\font_osf") {
532 } else if (token == "\\font_sf_scale") {
533 lex >> fontsSansScale;
534 } else if (token == "\\font_tt_scale") {
535 lex >> fontsTypewriterScale;
536 } else if (token == "\\font_cjk") {
538 } else if (token == "\\paragraph_separation") {
541 paragraph_separation = parseptranslator().find(parsep);
542 } else if (token == "\\defskip") {
544 string defskip = lex.getString();
545 if (defskip == "defskip")
548 pimpl_->defskip = VSpace(defskip);
549 } else if (token == "\\quotes_language") {
552 quotes_language = quoteslangtranslator().find(quotes_lang);
553 } else if (token == "\\papersize") {
556 papersize = papersizetranslator().find(ppsize);
557 } else if (token == "\\use_geometry") {
559 } else if (token == "\\use_amsmath") {
562 use_amsmath = packagetranslator().find(use_ams);
563 } else if (token == "\\use_esint") {
566 use_esint = packagetranslator().find(useesint);
567 } else if (token == "\\cite_engine") {
570 cite_engine_ = citeenginetranslator().find(engine);
571 } else if (token == "\\use_bibtopic") {
573 } else if (token == "\\tracking_changes") {
575 } else if (token == "\\output_changes") {
576 lex >> outputChanges;
577 } else if (token == "\\branch") {
579 docstring branch = lex.getDocString();
580 branchlist().add(branch);
583 string const tok = lex.getString();
584 if (tok == "\\end_branch")
586 Branch * branch_ptr = branchlist().find(branch);
587 if (tok == "\\selected") {
590 branch_ptr->setSelected(lex.getInteger());
592 // not yet operational
593 if (tok == "\\color") {
595 string color = lex.getString();
597 branch_ptr->setColor(color);
598 // Update also the Color table:
600 color = lcolor.getX11Name(Color_background);
602 lcolor.setColor(to_utf8(branch), color);
606 } else if (token == "\\author") {
608 istringstream ss(lex.getString());
611 author_map.push_back(pimpl_->authorlist.record(a));
612 } else if (token == "\\paperorientation") {
615 orientation = paperorientationtranslator().find(orient);
616 } else if (token == "\\paperwidth") {
618 } else if (token == "\\paperheight") {
620 } else if (token == "\\leftmargin") {
622 } else if (token == "\\topmargin") {
624 } else if (token == "\\rightmargin") {
626 } else if (token == "\\bottommargin") {
628 } else if (token == "\\headheight") {
630 } else if (token == "\\headsep") {
632 } else if (token == "\\footskip") {
634 } else if (token == "\\columnsep") {
636 } else if (token == "\\paperfontsize") {
638 } else if (token == "\\papercolumns") {
640 } else if (token == "\\listings_params") {
643 listings_params = InsetListingsParams(par).params();
644 } else if (token == "\\papersides") {
647 sides = sidestranslator().find(psides);
648 } else if (token == "\\paperpagestyle") {
650 } else if (token == "\\bullet") {
652 } else if (token == "\\bulletLaTeX") {
653 readBulletsLaTeX(lex);
654 } else if (token == "\\secnumdepth") {
656 } else if (token == "\\tocdepth") {
658 } else if (token == "\\spacing") {
662 if (nspacing == "other") {
665 spacing().set(spacetranslator().find(nspacing), tmp_val);
666 } else if (token == "\\float_placement") {
667 lex >> float_placement;
669 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
670 string toktmp = pdfoptions().readToken(lex, token);
671 if (!toktmp.empty()) {
672 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
677 lyxerr << "BufferParams::readToken(): Unknown token: " <<
686 void BufferParams::writeFile(ostream & os) const
688 // The top of the file is written by the buffer.
689 // Prints out the buffer info into the .lyx file given by file
692 os << "\\textclass " << baseClass()->name() << '\n';
695 if (!preamble.empty()) {
696 // remove '\n' from the end of preamble
697 string const tmppreamble = rtrim(preamble, "\n");
698 os << "\\begin_preamble\n"
700 << "\n\\end_preamble\n";
704 if (!options.empty()) {
705 os << "\\options " << options << '\n';
708 // use the class options defined in the layout?
709 os << "\\use_default_options "
710 << convert<string>(use_default_options) << "\n";
712 // the master document
713 if (!master.empty()) {
714 os << "\\master " << master << '\n';
718 if (!removedModules_.empty()) {
719 os << "\\begin_removed_modules" << '\n';
720 list<string>::const_iterator it = removedModules_.begin();
721 list<string>::const_iterator en = removedModules_.end();
722 for (; it != en; it++)
724 os << "\\end_removed_modules" << '\n';
728 if (!layoutModules_.empty()) {
729 os << "\\begin_modules" << '\n';
730 LayoutModuleList::const_iterator it = layoutModules_.begin();
731 LayoutModuleList::const_iterator en = layoutModules_.end();
732 for (; it != en; it++)
734 os << "\\end_modules" << '\n';
737 // local layout information
738 if (!local_layout.empty()) {
739 // remove '\n' from the end
740 string const tmplocal = rtrim(local_layout, "\n");
741 os << "\\begin_local_layout\n"
743 << "\n\\end_local_layout\n";
746 // then the text parameters
747 if (language != ignore_language)
748 os << "\\language " << language->lang() << '\n';
749 os << "\\inputencoding " << inputenc
750 << "\n\\font_roman " << fontsRoman
751 << "\n\\font_sans " << fontsSans
752 << "\n\\font_typewriter " << fontsTypewriter
753 << "\n\\font_default_family " << fontsDefaultFamily
754 << "\n\\use_xetex " << convert<string>(useXetex)
755 << "\n\\font_sc " << convert<string>(fontsSC)
756 << "\n\\font_osf " << convert<string>(fontsOSF)
757 << "\n\\font_sf_scale " << fontsSansScale
758 << "\n\\font_tt_scale " << fontsTypewriterScale
760 if (!fontsCJK.empty()) {
761 os << "\\font_cjk " << fontsCJK << '\n';
763 os << "\n\\graphics " << graphicsDriver << '\n';
764 os << "\\default_output_format " << defaultOutputFormat << '\n';
766 if (!float_placement.empty()) {
767 os << "\\float_placement " << float_placement << '\n';
769 os << "\\paperfontsize " << fontsize << '\n';
771 spacing().writeFile(os);
772 pdfoptions().writeFile(os);
774 os << "\\papersize " << string_papersize[papersize]
775 << "\n\\use_geometry " << convert<string>(use_geometry)
776 << "\n\\use_amsmath " << use_amsmath
777 << "\n\\use_esint " << use_esint
778 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
779 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
780 << "\n\\paperorientation " << string_orientation[orientation]
783 BranchList::const_iterator it = branchlist().begin();
784 BranchList::const_iterator end = branchlist().end();
785 for (; it != end; ++it) {
786 os << "\\branch " << to_utf8(it->branch())
787 << "\n\\selected " << it->isSelected()
788 << "\n\\color " << lyx::X11hexname(it->color())
793 if (!paperwidth.empty())
794 os << "\\paperwidth "
795 << VSpace(paperwidth).asLyXCommand() << '\n';
796 if (!paperheight.empty())
797 os << "\\paperheight "
798 << VSpace(paperheight).asLyXCommand() << '\n';
799 if (!leftmargin.empty())
800 os << "\\leftmargin "
801 << VSpace(leftmargin).asLyXCommand() << '\n';
802 if (!topmargin.empty())
804 << VSpace(topmargin).asLyXCommand() << '\n';
805 if (!rightmargin.empty())
806 os << "\\rightmargin "
807 << VSpace(rightmargin).asLyXCommand() << '\n';
808 if (!bottommargin.empty())
809 os << "\\bottommargin "
810 << VSpace(bottommargin).asLyXCommand() << '\n';
811 if (!headheight.empty())
812 os << "\\headheight "
813 << VSpace(headheight).asLyXCommand() << '\n';
814 if (!headsep.empty())
816 << VSpace(headsep).asLyXCommand() << '\n';
817 if (!footskip.empty())
819 << VSpace(footskip).asLyXCommand() << '\n';
820 if (!columnsep.empty())
822 << VSpace(columnsep).asLyXCommand() << '\n';
823 os << "\\secnumdepth " << secnumdepth
824 << "\n\\tocdepth " << tocdepth
825 << "\n\\paragraph_separation "
826 << string_paragraph_separation[paragraph_separation]
827 << "\n\\defskip " << getDefSkip().asLyXCommand()
828 << "\n\\quotes_language "
829 << string_quotes_language[quotes_language]
830 << "\n\\papercolumns " << columns
831 << "\n\\papersides " << sides
832 << "\n\\paperpagestyle " << pagestyle << '\n';
833 if (!listings_params.empty())
834 os << "\\listings_params \"" <<
835 InsetListingsParams(listings_params).encodedString() << "\"\n";
836 for (int i = 0; i < 4; ++i) {
837 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
838 if (user_defined_bullet(i).getFont() != -1) {
839 os << "\\bullet " << i << " "
840 << user_defined_bullet(i).getFont() << " "
841 << user_defined_bullet(i).getCharacter() << " "
842 << user_defined_bullet(i).getSize() << "\n";
846 os << "\\bulletLaTeX " << i << " \""
847 << lyx::to_ascii(user_defined_bullet(i).getText())
853 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
854 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
856 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
857 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
858 for (; a_it != a_end; ++a_it) {
859 if (a_it->second.used())
860 os << "\\author " << a_it->second << "\n";
862 os << "\\author " << Author() << "\n";
867 void BufferParams::validate(LaTeXFeatures & features) const
869 features.require(documentClass().requires());
872 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
873 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
874 LaTeXFeatures::isAvailable("xcolor");
876 switch (features.runparams().flavor) {
877 case OutputParams::LATEX:
879 features.require("ct-dvipost");
880 features.require("dvipost");
881 } else if (xcolorulem) {
882 features.require("ct-xcolor-ulem");
883 features.require("ulem");
884 features.require("xcolor");
886 features.require("ct-none");
889 case OutputParams::PDFLATEX:
890 case OutputParams::XETEX:
892 features.require("ct-xcolor-ulem");
893 features.require("ulem");
894 features.require("xcolor");
895 // improves color handling in PDF output
896 features.require("pdfcolmk");
898 features.require("ct-none");
906 // Floats with 'Here definitely' as default setting.
907 if (float_placement.find('H') != string::npos)
908 features.require("float");
910 // AMS Style is at document level
911 if (use_amsmath == package_on
912 || documentClass().provides("amsmath"))
913 features.require("amsmath");
914 if (use_esint == package_on)
915 features.require("esint");
917 // Document-level line spacing
918 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
919 features.require("setspace");
921 // the bullet shapes are buffer level not paragraph level
922 // so they are tested here
923 for (int i = 0; i < 4; ++i) {
924 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
926 int const font = user_defined_bullet(i).getFont();
928 int const c = user_defined_bullet(i).getCharacter();
934 features.require("latexsym");
936 } else if (font == 1) {
937 features.require("amssymb");
938 } else if (font >= 2 && font <= 5) {
939 features.require("pifont");
943 if (pdfoptions().use_hyperref) {
944 features.require("hyperref");
945 // due to interferences with babel and hyperref, the color package has to
946 // be loaded after hyperref when hyperref is used with the colorlinks
947 // option, see http://bugzilla.lyx.org/show_bug.cgi?id=5291
948 if (pdfoptions().colorlinks)
949 features.require("color");
953 features.require("xetex");
955 if (language->lang() == "vietnamese")
956 features.require("vietnamese");
957 else if (language->lang() == "japanese")
958 features.require("japanese");
962 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
963 TexRow & texrow) const
965 os << "\\documentclass";
967 DocumentClass const & tclass = documentClass();
969 ostringstream clsoptions; // the document class options.
971 if (tokenPos(tclass.opt_fontsize(),
972 '|', fontsize) >= 0) {
973 // only write if existing in list (and not default)
974 clsoptions << fontsize << "pt,";
977 // custom, A3, B3 and B4 paper sizes need geometry
978 bool nonstandard_papersize = papersize == PAPER_B3
979 || papersize == PAPER_B4
980 || papersize == PAPER_A3
981 || papersize == PAPER_CUSTOM;
986 clsoptions << "a4paper,";
989 clsoptions << "letterpaper,";
992 clsoptions << "a5paper,";
995 clsoptions << "b5paper,";
997 case PAPER_USEXECUTIVE:
998 clsoptions << "executivepaper,";
1001 clsoptions << "legalpaper,";
1013 if (sides != tclass.sides()) {
1016 clsoptions << "oneside,";
1019 clsoptions << "twoside,";
1025 if (columns != tclass.columns()) {
1027 clsoptions << "twocolumn,";
1029 clsoptions << "onecolumn,";
1033 && orientation == ORIENTATION_LANDSCAPE)
1034 clsoptions << "landscape,";
1036 // language should be a parameter to \documentclass
1037 if (language->babel() == "hebrew"
1038 && default_language->babel() != "hebrew")
1039 // This seems necessary
1040 features.useLanguage(default_language);
1042 ostringstream language_options;
1043 bool const use_babel = features.useBabel();
1045 language_options << features.getLanguages();
1046 if (!language->babel().empty()) {
1047 if (!language_options.str().empty())
1048 language_options << ',';
1049 language_options << language->babel();
1051 // if Vietnamese is used, babel must directly be loaded
1052 // with language options, not in the class options, see
1053 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1054 size_t viet = language_options.str().find("vietnam");
1055 // viet = string::npos when not found
1056 // the same is for all other languages that are not directly supported by
1057 // babel, but where LaTeX-packages add babel support.
1058 // this is currently the case for Latvian, Lithuanian, and Mongolian
1059 size_t latvian = language_options.str().find("latvian");
1060 size_t lithu = language_options.str().find("lithuanian");
1061 size_t mongo = language_options.str().find("mongolian");
1062 // if Japanese is used, babel must directly be loaded
1063 // with language options, not in the class options, see
1064 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1065 size_t japan = language_options.str().find("japanese");
1066 if (lyxrc.language_global_options && !language_options.str().empty()
1067 && viet == string::npos && japan == string::npos
1068 && latvian == string::npos && lithu == string::npos
1069 && mongo == string::npos)
1070 clsoptions << language_options.str() << ',';
1073 // the predefined options from the layout
1074 if (use_default_options && !tclass.options().empty())
1075 clsoptions << tclass.options() << ',';
1077 // the user-defined options
1078 if (!options.empty()) {
1079 clsoptions << options << ',';
1082 string strOptions(clsoptions.str());
1083 if (!strOptions.empty()) {
1084 strOptions = rtrim(strOptions, ",");
1086 os << '[' << from_utf8(strOptions) << ']';
1089 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1091 // end of \documentclass defs
1094 os << "\\usepackage{fontspec}\n";
1098 // font selection must be done before loading fontenc.sty
1099 string const fonts =
1100 loadFonts(fontsRoman, fontsSans,
1101 fontsTypewriter, fontsSC, fontsOSF,
1102 fontsSansScale, fontsTypewriterScale, useXetex);
1103 if (!fonts.empty()) {
1104 os << from_ascii(fonts);
1107 if (fontsDefaultFamily != "default")
1108 os << "\\renewcommand{\\familydefault}{\\"
1109 << from_ascii(fontsDefaultFamily) << "}\n";
1111 // set font encoding
1112 // this one is not per buffer
1113 // for arabic_arabi and farsi we also need to load the LAE and
1115 // XeteX works without fontenc
1116 if (lyxrc.fontenc != "default" && language->lang() != "japanese"
1118 if (language->lang() == "arabic_arabi"
1119 || language->lang() == "farsi") {
1120 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1121 << ",LFE,LAE]{fontenc}\n";
1124 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1130 // handle inputenc etc.
1131 writeEncodingPreamble(os, features, texrow);
1133 if (!listings_params.empty() || features.isRequired("listings")) {
1134 os << "\\usepackage{listings}\n";
1137 if (!listings_params.empty()) {
1139 // do not test validity because listings_params is
1140 // supposed to be valid
1142 InsetListingsParams(listings_params).separatedParams(true);
1143 // we can't support all packages, but we should load the color package
1144 if (par.find("\\color", 0) != string::npos)
1145 features.require("color");
1146 os << from_utf8(par);
1147 // count the number of newlines
1148 for (size_t i = 0; i < par.size(); ++i)
1154 if (!tclass.provides("geometry")
1155 && (use_geometry || nonstandard_papersize)) {
1156 odocstringstream ods;
1157 if (!getGraphicsDriver("geometry").empty())
1158 ods << getGraphicsDriver("geometry");
1159 if (orientation == ORIENTATION_LANDSCAPE)
1160 ods << ",landscape";
1161 switch (papersize) {
1163 if (!paperwidth.empty())
1164 ods << ",paperwidth="
1165 << from_ascii(paperwidth);
1166 if (!paperheight.empty())
1167 ods << ",paperheight="
1168 << from_ascii(paperheight);
1170 case PAPER_USLETTER:
1171 ods << ",letterpaper";
1174 ods << ",legalpaper";
1176 case PAPER_USEXECUTIVE:
1177 ods << ",executivepaper";
1198 // default papersize ie PAPER_DEFAULT
1199 switch (lyxrc.default_papersize) {
1200 case PAPER_DEFAULT: // keep compiler happy
1201 case PAPER_USLETTER:
1202 ods << ",letterpaper";
1205 ods << ",legalpaper";
1207 case PAPER_USEXECUTIVE:
1208 ods << ",executivepaper";
1228 docstring const g_options = trim(ods.str(), ",");
1229 os << "\\usepackage";
1230 if (!g_options.empty())
1231 os << '[' << g_options << ']';
1232 os << "{geometry}\n";
1234 os << "\\geometry{verbose";
1235 if (!topmargin.empty())
1236 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1237 if (!bottommargin.empty())
1238 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1239 if (!leftmargin.empty())
1240 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1241 if (!rightmargin.empty())
1242 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1243 if (!headheight.empty())
1244 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1245 if (!headsep.empty())
1246 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1247 if (!footskip.empty())
1248 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1249 if (!columnsep.empty())
1250 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1253 } else if (orientation == ORIENTATION_LANDSCAPE) {
1254 features.require("papersize");
1257 if (tokenPos(tclass.opt_pagestyle(),
1258 '|', pagestyle) >= 0) {
1259 if (pagestyle == "fancy") {
1260 os << "\\usepackage{fancyhdr}\n";
1263 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1267 // Only if class has a ToC hierarchy
1268 if (tclass.hasTocLevels()) {
1269 if (secnumdepth != tclass.secnumdepth()) {
1270 os << "\\setcounter{secnumdepth}{"
1275 if (tocdepth != tclass.tocdepth()) {
1276 os << "\\setcounter{tocdepth}{"
1283 if (paragraph_separation) {
1284 switch (getDefSkip().kind()) {
1285 case VSpace::SMALLSKIP:
1286 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1288 case VSpace::MEDSKIP:
1289 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1291 case VSpace::BIGSKIP:
1292 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1294 case VSpace::LENGTH:
1295 os << "\\setlength{\\parskip}{"
1296 << from_utf8(getDefSkip().length().asLatexString())
1299 default: // should never happen // Then delete it.
1300 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1305 os << "\\setlength{\\parindent}{0pt}\n";
1309 // Now insert the LyX specific LaTeX commands...
1310 docstring lyxpreamble;
1312 // due to interferences with babel and hyperref, the color package has to
1313 // be loaded (when it is not already loaded) before babel when hyperref
1314 // is used with the colorlinks option, see
1315 // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1316 // we decided therefore to load color always before babel, see
1317 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1318 lyxpreamble += from_ascii(features.getColorOptions());
1320 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1322 && (features.isRequired("jurabib")
1323 || features.isRequired("hyperref")
1324 || features.isRequired("vietnamese")
1325 || features.isRequired("japanese") ) ) {
1327 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1328 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1331 // The optional packages;
1332 lyxpreamble += from_ascii(features.getPackages());
1335 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1338 // * Hyperref manual: "Make sure it comes last of your loaded
1339 // packages, to give it a fighting chance of not being over-written,
1340 // since its job is to redefine many LaTeX commands."
1341 // * Email from Heiko Oberdiek: "It is usually better to load babel
1342 // before hyperref. Then hyperref has a chance to detect babel.
1343 // * Has to be loaded before the "LyX specific LaTeX commands" to
1344 // avoid errors with algorithm floats.
1345 // use hyperref explicitely when it is required
1346 if (features.isRequired("hyperref")) {
1347 odocstringstream oss;
1348 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1349 lyxpreamble += oss.str();
1352 // Will be surrounded by \makeatletter and \makeatother when needed
1353 docstring atlyxpreamble;
1355 // Some macros LyX will need
1356 docstring tmppreamble(from_ascii(features.getMacros()));
1358 if (!tmppreamble.empty())
1359 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1360 "LyX specific LaTeX commands.\n"
1361 + tmppreamble + '\n';
1363 // the text class specific preamble
1364 tmppreamble = features.getTClassPreamble();
1365 if (!tmppreamble.empty())
1366 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1367 "Textclass specific LaTeX commands.\n"
1368 + tmppreamble + '\n';
1370 /* the user-defined preamble */
1371 if (!preamble.empty())
1373 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1374 "User specified LaTeX commands.\n"
1375 + from_utf8(preamble) + '\n';
1377 // subfig loads internally the LaTeX package "caption". As
1378 // caption is a very popular package, users will load it in
1379 // the preamble. Therefore we must load subfig behind the
1380 // user-defined preamble and check if the caption package was
1381 // loaded or not. For the case that caption is loaded before
1382 // subfig, there is the subfig option "caption=false". This
1383 // option also works when a koma-script class is used and
1384 // koma's own caption commands are used instead of caption. We
1385 // use \PassOptionsToPackage here because the user could have
1386 // already loaded subfig in the preamble.
1387 if (features.isRequired("subfig")) {
1388 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1389 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1390 "\\usepackage{subfig}\n";
1393 // Itemize bullet settings need to be last in case the user
1394 // defines their own bullets that use a package included
1395 // in the user-defined preamble -- ARRae
1396 // Actually it has to be done much later than that
1397 // since some packages like frenchb make modifications
1398 // at \begin{document} time -- JMarc
1399 docstring bullets_def;
1400 for (int i = 0; i < 4; ++i) {
1401 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1402 if (bullets_def.empty())
1403 bullets_def += "\\AtBeginDocument{\n";
1404 bullets_def += " \\def\\labelitemi";
1406 // `i' is one less than the item to modify
1413 bullets_def += "ii";
1419 bullets_def += '{' +
1420 user_defined_bullet(i).getText()
1425 if (!bullets_def.empty())
1426 atlyxpreamble += bullets_def + "}\n\n";
1428 if (atlyxpreamble.find(from_ascii("@")) != docstring::npos)
1429 lyxpreamble += "\n\\makeatletter\n"
1430 + atlyxpreamble + "\\makeatother\n\n";
1432 lyxpreamble += '\n' + atlyxpreamble;
1434 // We try to load babel late, in case it interferes with other packages.
1435 // Jurabib and Hyperref have to be called after babel, though.
1436 if (use_babel && !features.isRequired("jurabib")
1437 && !features.isRequired("hyperref")
1438 && !features.isRequired("vietnamese")
1439 && !features.isRequired("japanese")) {
1441 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1442 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1445 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1446 if (!i18npreamble.empty())
1447 lyxpreamble += i18npreamble + '\n';
1450 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1451 for (int j = 0; j != nlines; ++j) {
1457 // these packages (xunicode, for that matter) need to be loaded at least
1458 // after amsmath, amssymb, esint and the other packages that provide
1461 os << "\\usepackage{xunicode}\n";
1463 os << "\\usepackage{xltxtra}\n";
1470 void BufferParams::useClassDefaults()
1472 DocumentClass const & tclass = documentClass();
1474 sides = tclass.sides();
1475 columns = tclass.columns();
1476 pagestyle = tclass.pagestyle();
1477 use_default_options = true;
1478 // Only if class has a ToC hierarchy
1479 if (tclass.hasTocLevels()) {
1480 secnumdepth = tclass.secnumdepth();
1481 tocdepth = tclass.tocdepth();
1486 bool BufferParams::hasClassDefaults() const
1488 DocumentClass const & tclass = documentClass();
1490 return sides == tclass.sides()
1491 && columns == tclass.columns()
1492 && pagestyle == tclass.pagestyle()
1493 && use_default_options
1494 && secnumdepth == tclass.secnumdepth()
1495 && tocdepth == tclass.tocdepth();
1499 DocumentClass const & BufferParams::documentClass() const
1505 DocumentClass const * BufferParams::documentClassPtr() const {
1510 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1511 // evil, but this function is evil
1512 doc_class_ = const_cast<DocumentClass *>(tc);
1516 bool BufferParams::setBaseClass(string const & classname)
1518 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1519 LayoutFileList & bcl = LayoutFileList::get();
1520 if (!bcl.haveClass(classname)) {
1522 bformat(_("The document class %1$s could not be found. "
1523 "A default textclass with default layouts will be used. "
1524 "LyX might not be able to produce output unless a correct "
1525 "textclass is selected from the document settings dialog."),
1526 from_utf8(classname));
1527 frontend::Alert::error(_("Document class not found"), s);
1528 bcl.addEmptyClass(classname);
1531 bool const success = bcl[classname].load();
1534 bformat(_("The document class %1$s could not be loaded."),
1535 from_utf8(classname));
1536 frontend::Alert::error(_("Could not load class"), s);
1540 pimpl_->baseClass_ = classname;
1541 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1546 LayoutFile const * BufferParams::baseClass() const
1548 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1549 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1555 LayoutFileIndex const & BufferParams::baseClassID() const
1557 return pimpl_->baseClass_;
1561 void BufferParams::makeDocumentClass()
1566 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1568 if (!local_layout.empty()) {
1569 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1570 docstring const msg = _("Error reading internal layout information");
1571 frontend::Alert::warning(_("Read Error"), msg);
1576 bool BufferParams::moduleCanBeAdded(string const & modName) const
1578 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1582 bool BufferParams::addLayoutModule(string const & modName)
1584 LayoutModuleList::const_iterator it = layoutModules_.begin();
1585 LayoutModuleList::const_iterator end = layoutModules_.end();
1586 for (; it != end; it++)
1589 layoutModules_.push_back(modName);
1594 Font const BufferParams::getFont() const
1596 FontInfo f = documentClass().defaultfont();
1597 if (fontsDefaultFamily == "rmdefault")
1598 f.setFamily(ROMAN_FAMILY);
1599 else if (fontsDefaultFamily == "sfdefault")
1600 f.setFamily(SANS_FAMILY);
1601 else if (fontsDefaultFamily == "ttdefault")
1602 f.setFamily(TYPEWRITER_FAMILY);
1603 return Font(f, language);
1607 void BufferParams::readPreamble(Lexer & lex)
1609 if (lex.getString() != "\\begin_preamble")
1610 lyxerr << "Error (BufferParams::readPreamble):"
1611 "consistency check failed." << endl;
1613 preamble = lex.getLongString("\\end_preamble");
1617 void BufferParams::readLocalLayout(Lexer & lex)
1619 if (lex.getString() != "\\begin_local_layout")
1620 lyxerr << "Error (BufferParams::readLocalLayout):"
1621 "consistency check failed." << endl;
1623 local_layout = lex.getLongString("\\end_local_layout");
1627 void BufferParams::readLanguage(Lexer & lex)
1629 if (!lex.next()) return;
1631 string const tmptok = lex.getString();
1633 // check if tmptok is part of tex_babel in tex-defs.h
1634 language = languages.getLanguage(tmptok);
1636 // Language tmptok was not found
1637 language = default_language;
1638 lyxerr << "Warning: Setting language `"
1639 << tmptok << "' to `" << language->lang()
1645 void BufferParams::readGraphicsDriver(Lexer & lex)
1650 string const tmptok = lex.getString();
1651 // check if tmptok is part of tex_graphics in tex_defs.h
1654 string const test = tex_graphics[n++];
1656 if (test == tmptok) {
1657 graphicsDriver = tmptok;
1662 "Warning: graphics driver `$$Token' not recognized!\n"
1663 " Setting graphics driver to `default'.\n");
1664 graphicsDriver = "default";
1671 void BufferParams::readBullets(Lexer & lex)
1676 int const index = lex.getInteger();
1678 int temp_int = lex.getInteger();
1679 user_defined_bullet(index).setFont(temp_int);
1680 temp_bullet(index).setFont(temp_int);
1682 user_defined_bullet(index).setCharacter(temp_int);
1683 temp_bullet(index).setCharacter(temp_int);
1685 user_defined_bullet(index).setSize(temp_int);
1686 temp_bullet(index).setSize(temp_int);
1690 void BufferParams::readBulletsLaTeX(Lexer & lex)
1692 // The bullet class should be able to read this.
1695 int const index = lex.getInteger();
1697 docstring const temp_str = lex.getDocString();
1699 user_defined_bullet(index).setText(temp_str);
1700 temp_bullet(index).setText(temp_str);
1704 void BufferParams::readModules(Lexer & lex)
1706 if (!lex.eatLine()) {
1707 lyxerr << "Error (BufferParams::readModules):"
1708 "Unexpected end of input." << endl;
1712 string mod = lex.getString();
1713 if (mod == "\\end_modules")
1715 addLayoutModule(mod);
1721 void BufferParams::readRemovedModules(Lexer & lex)
1723 if (!lex.eatLine()) {
1724 lyxerr << "Error (BufferParams::readRemovedModules):"
1725 "Unexpected end of input." << endl;
1729 string mod = lex.getString();
1730 if (mod == "\\end_removed_modules")
1732 removedModules_.push_back(mod);
1735 // now we want to remove any removed modules that were previously
1736 // added. normally, that will be because default modules were added in
1737 // setBaseClass(), which gets called when \textclass is read at the
1738 // start of the read.
1739 list<string>::const_iterator rit = removedModules_.begin();
1740 list<string>::const_iterator const ren = removedModules_.end();
1741 for (; rit != ren; rit++) {
1742 LayoutModuleList::iterator const mit = layoutModules_.begin();
1743 LayoutModuleList::iterator const men = layoutModules_.end();
1744 LayoutModuleList::iterator found = find(mit, men, *rit);
1747 layoutModules_.erase(found);
1752 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1754 char real_papersize = papersize;
1755 if (real_papersize == PAPER_DEFAULT)
1756 real_papersize = lyxrc.default_papersize;
1758 switch (real_papersize) {
1760 // could be anything, so don't guess
1762 case PAPER_CUSTOM: {
1763 if (purpose == XDVI && !paperwidth.empty() &&
1764 !paperheight.empty()) {
1765 // heightxwidth<unit>
1766 string first = paperwidth;
1767 string second = paperheight;
1768 if (orientation == ORIENTATION_LANDSCAPE)
1771 return first.erase(first.length() - 2)
1783 // dvips and dvipdfm do not know this
1784 if (purpose == DVIPS || purpose == DVIPDFM)
1788 // dvipdfm does not know this
1789 if (purpose == DVIPDFM)
1793 // dvipdfm does not know this
1794 if (purpose == DVIPDFM)
1797 case PAPER_USEXECUTIVE:
1798 // dvipdfm does not know this
1799 if (purpose == DVIPDFM)
1804 case PAPER_USLETTER:
1806 if (purpose == XDVI)
1813 string const BufferParams::dvips_options() const
1818 && papersize == PAPER_CUSTOM
1819 && !lyxrc.print_paper_dimension_flag.empty()
1820 && !paperwidth.empty()
1821 && !paperheight.empty()) {
1822 // using a custom papersize
1823 result = lyxrc.print_paper_dimension_flag;
1824 result += ' ' + paperwidth;
1825 result += ',' + paperheight;
1827 string const paper_option = paperSizeName(DVIPS);
1828 if (!paper_option.empty() && (paper_option != "letter" ||
1829 orientation != ORIENTATION_LANDSCAPE)) {
1830 // dvips won't accept -t letter -t landscape.
1831 // In all other cases, include the paper size
1833 result = lyxrc.print_paper_flag;
1834 result += ' ' + paper_option;
1837 if (orientation == ORIENTATION_LANDSCAPE &&
1838 papersize != PAPER_CUSTOM)
1839 result += ' ' + lyxrc.print_landscape_flag;
1844 string BufferParams::babelCall(string const & lang_opts) const
1846 string lang_pack = lyxrc.language_package;
1847 if (lang_pack != "\\usepackage{babel}")
1849 // suppress the babel call when there is no babel language defined
1850 // for the document language in the lib/languages file and if no
1851 // other languages are used (lang_opts is then empty)
1852 if (lang_opts.empty())
1854 // If Vietnamese is used, babel must directly be loaded with the
1855 // language options, see
1856 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1857 size_t viet = lang_opts.find("vietnam");
1858 // viet = string::npos when not found
1859 // the same is for all other languages that are not directly supported by
1860 // babel, but where LaTeX-packages add babel support.
1861 // this is currently the case for Latvian, Lithuanian, and Mongolian
1862 size_t latvian = lang_opts.find("latvian");
1863 size_t lithu = lang_opts.find("lithuanian");
1864 size_t mongo = lang_opts.find("mongolian");
1865 // If Japanese is used, babel must directly be loaded with the
1866 // language options, see
1867 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1868 size_t japan = lang_opts.find("japanese");
1869 if (!lyxrc.language_global_options || viet != string::npos
1870 || japan != string::npos || latvian != string::npos
1871 || lithu != string::npos || mongo != string::npos)
1872 return "\\usepackage[" + lang_opts + "]{babel}";
1877 docstring BufferParams::getGraphicsDriver(string const & package) const
1881 if (package == "geometry") {
1882 if (graphicsDriver == "dvips"
1883 || graphicsDriver == "dvipdfm"
1884 || graphicsDriver == "pdftex"
1885 || graphicsDriver == "vtex")
1886 result = from_ascii(graphicsDriver);
1887 else if (graphicsDriver == "dvipdfmx")
1888 result = from_ascii("dvipdfm");
1895 void BufferParams::writeEncodingPreamble(odocstream & os,
1896 LaTeXFeatures & features, TexRow & texrow) const
1900 if (inputenc == "auto") {
1901 string const doc_encoding =
1902 language->encoding()->latexName();
1903 Encoding::Package const package =
1904 language->encoding()->package();
1906 // Create a list with all the input encodings used
1908 set<string> encodings =
1909 features.getEncodingSet(doc_encoding);
1911 // If the "japanese" package (i.e. pLaTeX) is used,
1912 // inputenc must be omitted.
1913 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
1914 if (package == Encoding::japanese)
1915 features.require("japanese");
1917 if ((!encodings.empty() || package == Encoding::inputenc)
1918 && !features.isRequired("japanese")) {
1919 os << "\\usepackage[";
1920 set<string>::const_iterator it = encodings.begin();
1921 set<string>::const_iterator const end = encodings.end();
1923 os << from_ascii(*it);
1926 for (; it != end; ++it)
1927 os << ',' << from_ascii(*it);
1928 if (package == Encoding::inputenc) {
1929 if (!encodings.empty())
1931 os << from_ascii(doc_encoding);
1933 os << "]{inputenc}\n";
1936 if (package == Encoding::CJK || features.mustProvide("CJK")) {
1937 if (language->encoding()->name() == "utf8-cjk"
1938 && LaTeXFeatures::isAvailable("CJKutf8"))
1939 os << "\\usepackage{CJKutf8}\n";
1941 os << "\\usepackage{CJK}\n";
1944 } else if (inputenc != "default") {
1945 switch (encoding().package()) {
1946 case Encoding::none:
1947 case Encoding::japanese:
1949 case Encoding::inputenc:
1950 // do not load inputenc if japanese is used
1951 if (features.isRequired("japanese"))
1953 os << "\\usepackage[" << from_ascii(inputenc)
1958 if (encoding().name() == "utf8-cjk"
1959 && LaTeXFeatures::isAvailable("CJKutf8"))
1960 os << "\\usepackage{CJKutf8}\n";
1962 os << "\\usepackage{CJK}\n";
1968 // The encoding "armscii8" (for Armenian) is only available when
1969 // the package "armtex" is loaded.
1970 if (language->encoding()->latexName() == "armscii8"
1971 || inputenc == "armscii8") {
1972 os << "\\usepackage{armtex}\n";
1978 string const BufferParams::parseFontName(string const & name) const
1980 string mangled = name;
1981 size_t const idx = mangled.find('[');
1982 if (idx == string::npos || idx == 0)
1985 return mangled.substr(0, idx - 1);
1989 string const BufferParams::loadFonts(string const & rm,
1990 string const & sf, string const & tt,
1991 bool const & sc, bool const & osf,
1992 int const & sfscale, int const & ttscale,
1993 bool const & xetex) const
1995 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1996 several packages have been replaced by others, that might not
1997 be installed on every system. We have to take care for that
1998 (see psnfss.pdf). We try to support all psnfss fonts as well
1999 as the fonts that have become de facto standard in the LaTeX
2000 world (e.g. Latin Modern). We do not support obsolete fonts
2001 (like PSLatex). In general, it should be possible to mix any
2002 rm font with any sf or tt font, respectively. (JSpitzm)
2004 -- separate math fonts.
2007 if (rm == "default" && sf == "default" && tt == "default")
2014 if (rm != "default")
2015 os << "\\setmainfont[Mapping=tex-text]{"
2016 << parseFontName(rm) << "}\n";
2017 if (sf != "default") {
2018 string const sans = parseFontName(sf);
2020 os << "\\setsansfont[Scale="
2021 << float(sfscale) / 100
2022 << ",Mapping=tex-text]{"
2025 os << "\\setsansfont[Mapping=tex-text]{"
2028 if (tt != "default") {
2029 string const mono = parseFontName(tt);
2031 os << "\\setmonofont[Scale="
2032 << float(sfscale) / 100
2036 os << "\\setmonofont[Mapping=tex-text]{"
2040 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2045 // Computer Modern (must be explicitely selectable -- there might be classes
2046 // that define a different default font!
2048 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2049 // osf for Computer Modern needs eco.sty
2051 os << "\\usepackage{eco}\n";
2053 // Latin Modern Roman
2054 else if (rm == "lmodern")
2055 os << "\\usepackage{lmodern}\n";
2057 else if (rm == "ae") {
2058 // not needed when using OT1 font encoding.
2059 if (lyxrc.fontenc != "default")
2060 os << "\\usepackage{ae,aecompl}\n";
2063 else if (rm == "times") {
2064 // try to load the best available package
2065 if (LaTeXFeatures::isAvailable("mathptmx"))
2066 os << "\\usepackage{mathptmx}\n";
2067 else if (LaTeXFeatures::isAvailable("mathptm"))
2068 os << "\\usepackage{mathptm}\n";
2070 os << "\\usepackage{times}\n";
2073 else if (rm == "palatino") {
2074 // try to load the best available package
2075 if (LaTeXFeatures::isAvailable("mathpazo")) {
2076 os << "\\usepackage";
2082 // "osf" includes "sc"!
2086 os << "{mathpazo}\n";
2088 else if (LaTeXFeatures::isAvailable("mathpple"))
2089 os << "\\usepackage{mathpple}\n";
2091 os << "\\usepackage{palatino}\n";
2094 else if (rm == "utopia") {
2095 // fourier supersedes utopia.sty, but does
2096 // not work with OT1 encoding.
2097 if (LaTeXFeatures::isAvailable("fourier")
2098 && lyxrc.fontenc != "default") {
2099 os << "\\usepackage";
2110 os << "{fourier}\n";
2113 os << "\\usepackage{utopia}\n";
2115 // Bera (complete fontset)
2116 else if (rm == "bera" && sf == "default" && tt == "default")
2117 os << "\\usepackage{bera}\n";
2119 else if (rm != "default")
2120 os << "\\usepackage" << "{" << rm << "}\n";
2123 // Helvetica, Bera Sans
2124 if (sf == "helvet" || sf == "berasans") {
2126 os << "\\usepackage[scaled=" << float(sfscale) / 100
2127 << "]{" << sf << "}\n";
2129 os << "\\usepackage{" << sf << "}\n";
2132 else if (sf == "avant")
2133 os << "\\usepackage{" << sf << "}\n";
2134 // Computer Modern, Latin Modern, CM Bright
2135 else if (sf != "default")
2136 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2138 // monospaced/typewriter
2139 // Courier, LuxiMono
2140 if (tt == "luximono" || tt == "beramono") {
2142 os << "\\usepackage[scaled=" << float(ttscale) / 100
2143 << "]{" << tt << "}\n";
2145 os << "\\usepackage{" << tt << "}\n";
2148 else if (tt == "courier" )
2149 os << "\\usepackage{" << tt << "}\n";
2150 // Computer Modern, Latin Modern, CM Bright
2151 else if (tt != "default")
2152 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2158 Encoding const & BufferParams::encoding() const
2161 return *(encodings.fromLaTeXName("utf8-plain"));
2162 if (inputenc == "auto" || inputenc == "default")
2163 return *language->encoding();
2164 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2167 LYXERR0("Unknown inputenc value `" << inputenc
2168 << "'. Using `auto' instead.");
2169 return *language->encoding();
2173 CiteEngine BufferParams::citeEngine() const
2175 // FIXME the class should provide the numerical/
2176 // authoryear choice
2177 if (documentClass().provides("natbib")
2178 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2179 return ENGINE_NATBIB_AUTHORYEAR;
2180 return cite_engine_;
2184 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2186 cite_engine_ = cite_engine;