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 "IndicesList.h"
30 #include "LaTeXFeatures.h"
31 #include "ModuleList.h"
35 #include "OutputParams.h"
39 #include "PDFOptions.h"
41 #include "frontends/alert.h"
43 #include "insets/InsetListingsParams.h"
45 #include "support/convert.h"
46 #include "support/debug.h"
47 #include "support/docstream.h"
48 #include "support/FileName.h"
49 #include "support/filetools.h"
50 #include "support/gettext.h"
51 #include "support/Messages.h"
52 #include "support/Translator.h"
53 #include "support/lstrings.h"
59 using namespace lyx::support;
62 static char const * const string_paragraph_separation[] = {
67 static char const * const string_quotes_language[] = {
68 "english", "swedish", "german", "polish", "french", "danish", ""
72 static char const * const string_papersize[] = {
73 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
74 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
78 static char const * const string_orientation[] = {
79 "portrait", "landscape", ""
83 static char const * const string_footnotekinds[] = {
84 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
88 static char const * const tex_graphics[] = {
89 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
90 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
91 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
92 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
103 // Paragraph separation
104 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
107 ParSepTranslator const init_parseptranslator()
109 ParSepTranslator translator
110 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
111 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
116 ParSepTranslator const & parseptranslator()
118 static ParSepTranslator translator = init_parseptranslator();
124 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
127 QuotesLangTranslator const init_quoteslangtranslator()
129 QuotesLangTranslator translator
130 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
131 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
132 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
133 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
134 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
135 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
140 QuotesLangTranslator const & quoteslangtranslator()
142 static QuotesLangTranslator translator = init_quoteslangtranslator();
148 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
151 static PaperSizeTranslator initPaperSizeTranslator()
153 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
154 translator.addPair(string_papersize[1], PAPER_CUSTOM);
155 translator.addPair(string_papersize[2], PAPER_USLETTER);
156 translator.addPair(string_papersize[3], PAPER_USLEGAL);
157 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
158 translator.addPair(string_papersize[5], PAPER_A3);
159 translator.addPair(string_papersize[6], PAPER_A4);
160 translator.addPair(string_papersize[7], PAPER_A5);
161 translator.addPair(string_papersize[8], PAPER_B3);
162 translator.addPair(string_papersize[9], PAPER_B4);
163 translator.addPair(string_papersize[10], PAPER_B5);
168 PaperSizeTranslator const & papersizetranslator()
170 static PaperSizeTranslator translator = initPaperSizeTranslator();
176 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
179 PaperOrientationTranslator const init_paperorientationtranslator()
181 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
182 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
187 PaperOrientationTranslator const & paperorientationtranslator()
189 static PaperOrientationTranslator translator = init_paperorientationtranslator();
195 typedef Translator<int, PageSides> SidesTranslator;
198 SidesTranslator const init_sidestranslator()
200 SidesTranslator translator(1, OneSide);
201 translator.addPair(2, TwoSides);
206 SidesTranslator const & sidestranslator()
208 static SidesTranslator translator = init_sidestranslator();
214 typedef Translator<int, BufferParams::Package> PackageTranslator;
217 PackageTranslator const init_packagetranslator()
219 PackageTranslator translator(0, BufferParams::package_off);
220 translator.addPair(1, BufferParams::package_auto);
221 translator.addPair(2, BufferParams::package_on);
226 PackageTranslator const & packagetranslator()
228 static PackageTranslator translator = init_packagetranslator();
234 typedef Translator<string, CiteEngine> CiteEngineTranslator;
237 CiteEngineTranslator const init_citeenginetranslator()
239 CiteEngineTranslator translator("basic", ENGINE_BASIC);
240 translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
241 translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
242 translator.addPair("jurabib", ENGINE_JURABIB);
247 CiteEngineTranslator const & citeenginetranslator()
249 static CiteEngineTranslator translator = init_citeenginetranslator();
255 typedef Translator<string, Spacing::Space> SpaceTranslator;
258 SpaceTranslator const init_spacetranslator()
260 SpaceTranslator translator("default", Spacing::Default);
261 translator.addPair("single", Spacing::Single);
262 translator.addPair("onehalf", Spacing::Onehalf);
263 translator.addPair("double", Spacing::Double);
264 translator.addPair("other", Spacing::Other);
269 SpaceTranslator const & spacetranslator()
271 static SpaceTranslator translator = init_spacetranslator();
278 class BufferParams::Impl
283 AuthorList authorlist;
284 BranchList branchlist;
285 Bullet temp_bullets[4];
286 Bullet user_defined_bullets[4];
287 IndicesList indiceslist;
289 /** This is the amount of space used for paragraph_separation "skip",
290 * and for detached paragraphs in "indented" documents.
293 PDFOptions pdfoptions;
294 LayoutFileIndex baseClass_;
298 BufferParams::Impl::Impl()
299 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
301 // set initial author
303 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
308 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
312 return new BufferParams::Impl(*ptr);
316 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
322 BufferParams::BufferParams()
325 setBaseClass(defaultBaseclass());
327 paragraph_separation = ParagraphIndentSeparation;
328 quotes_language = InsetQuotes::EnglishQuotes;
329 fontsize = "default";
332 papersize = PAPER_DEFAULT;
333 orientation = ORIENTATION_PORTRAIT;
334 use_geometry = false;
335 use_amsmath = package_auto;
336 use_esint = package_auto;
337 cite_engine_ = ENGINE_BASIC;
338 use_bibtopic = false;
340 trackChanges = false;
341 outputChanges = false;
342 use_default_options = true;
345 language = default_language;
346 fontsRoman = "default";
347 fontsSans = "default";
348 fontsTypewriter = "default";
349 fontsDefaultFamily = "default";
353 fontsSansScale = 100;
354 fontsTypewriterScale = 100;
356 graphicsDriver = "default";
357 defaultOutputFormat = "default";
360 listings_params = string();
361 pagestyle = "default";
362 // white is equal to no background color
363 backgroundcolor = lyx::rgbFromHexName("#ffffff");
365 for (int iter = 0; iter < 4; ++iter) {
366 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
367 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
370 indiceslist().addDefault(B_("Index"));
374 docstring BufferParams::B_(string const & l10n) const
376 LASSERT(language, /**/);
377 return getMessages(language->code()).get(l10n);
381 AuthorList & BufferParams::authors()
383 return pimpl_->authorlist;
387 AuthorList const & BufferParams::authors() const
389 return pimpl_->authorlist;
393 BranchList & BufferParams::branchlist()
395 return pimpl_->branchlist;
399 BranchList const & BufferParams::branchlist() const
401 return pimpl_->branchlist;
405 IndicesList & BufferParams::indiceslist()
407 return pimpl_->indiceslist;
411 IndicesList const & BufferParams::indiceslist() const
413 return pimpl_->indiceslist;
417 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
419 LASSERT(index < 4, /**/);
420 return pimpl_->temp_bullets[index];
424 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
426 LASSERT(index < 4, /**/);
427 return pimpl_->temp_bullets[index];
431 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
433 LASSERT(index < 4, /**/);
434 return pimpl_->user_defined_bullets[index];
438 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
440 LASSERT(index < 4, /**/);
441 return pimpl_->user_defined_bullets[index];
445 Spacing & BufferParams::spacing()
447 return pimpl_->spacing;
451 Spacing const & BufferParams::spacing() const
453 return pimpl_->spacing;
457 PDFOptions & BufferParams::pdfoptions()
459 return pimpl_->pdfoptions;
463 PDFOptions const & BufferParams::pdfoptions() const
465 return pimpl_->pdfoptions;
469 VSpace const & BufferParams::getDefSkip() const
471 return pimpl_->defskip;
475 void BufferParams::setDefSkip(VSpace const & vs)
477 pimpl_->defskip = vs;
481 string BufferParams::readToken(Lexer & lex, string const & token,
482 FileName const & filepath)
484 if (token == "\\textclass") {
486 string const classname = lex.getString();
487 // if there exists a local layout file, ignore the system one
488 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
490 LayoutFileList & bcl = LayoutFileList::get();
491 if (tcp.empty() && !filepath.empty())
492 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
496 setBaseClass(classname);
497 // We assume that a tex class exists for local or unknown layouts so this warning
498 // will only be given for system layouts.
499 if (!baseClass()->isTeXClassAvailable()) {
500 docstring const msg =
501 bformat(_("The layout file requested by this document,\n"
503 "is not usable. This is probably because a LaTeX\n"
504 "class or style file required by it is not\n"
505 "available. See the Customization documentation\n"
506 "for more information.\n"), from_utf8(classname));
507 frontend::Alert::warning(_("Document class not available"),
508 msg + _("LyX will not be able to produce output."));
510 } else if (token == "\\begin_preamble") {
512 } else if (token == "\\begin_local_layout") {
513 readLocalLayout(lex);
514 } else if (token == "\\begin_modules") {
516 } else if (token == "\\begin_removed_modules") {
517 readRemovedModules(lex);
518 } else if (token == "\\options") {
520 options = lex.getString();
521 } else if (token == "\\use_default_options") {
522 lex >> use_default_options;
523 } else if (token == "\\master") {
525 master = lex.getString();
526 } else if (token == "\\language") {
528 } else if (token == "\\inputencoding") {
530 } else if (token == "\\graphics") {
531 readGraphicsDriver(lex);
532 } else if (token == "\\default_output_format") {
533 lex >> defaultOutputFormat;
534 } else if (token == "\\font_roman") {
536 fontsRoman = lex.getString();
537 } else if (token == "\\font_sans") {
539 fontsSans = lex.getString();
540 } else if (token == "\\font_typewriter") {
542 fontsTypewriter = lex.getString();
543 } else if (token == "\\font_default_family") {
544 lex >> fontsDefaultFamily;
545 } else if (token == "\\use_xetex") {
547 } else if (token == "\\font_sc") {
549 } else if (token == "\\font_osf") {
551 } else if (token == "\\font_sf_scale") {
552 lex >> fontsSansScale;
553 } else if (token == "\\font_tt_scale") {
554 lex >> fontsTypewriterScale;
555 } else if (token == "\\font_cjk") {
557 } else if (token == "\\paragraph_separation") {
560 paragraph_separation = parseptranslator().find(parsep);
561 } else if (token == "\\defskip") {
563 string defskip = lex.getString();
564 if (defskip == "defskip")
567 pimpl_->defskip = VSpace(defskip);
568 } else if (token == "\\quotes_language") {
571 quotes_language = quoteslangtranslator().find(quotes_lang);
572 } else if (token == "\\papersize") {
575 papersize = papersizetranslator().find(ppsize);
576 } else if (token == "\\use_geometry") {
578 } else if (token == "\\use_amsmath") {
581 use_amsmath = packagetranslator().find(use_ams);
582 } else if (token == "\\use_esint") {
585 use_esint = packagetranslator().find(useesint);
586 } else if (token == "\\cite_engine") {
589 cite_engine_ = citeenginetranslator().find(engine);
590 } else if (token == "\\use_bibtopic") {
592 } else if (token == "\\use_indices") {
594 } else if (token == "\\tracking_changes") {
596 } else if (token == "\\output_changes") {
597 lex >> outputChanges;
598 } else if (token == "\\branch") {
600 docstring branch = lex.getDocString();
601 branchlist().add(branch);
604 string const tok = lex.getString();
605 if (tok == "\\end_branch")
607 Branch * branch_ptr = branchlist().find(branch);
608 if (tok == "\\selected") {
611 branch_ptr->setSelected(lex.getInteger());
613 // not yet operational
614 if (tok == "\\color") {
616 string color = lex.getString();
618 branch_ptr->setColor(color);
619 // Update also the Color table:
621 color = lcolor.getX11Name(Color_background);
623 lcolor.setColor(to_utf8(branch), color);
626 } else if (token == "\\index") {
628 docstring index = lex.getDocString();
629 indiceslist().add(index);
632 string const tok = lex.getString();
633 if (tok == "\\end_index")
635 Index * index_ptr = indiceslist().find(index);
636 if (tok == "\\shortcut") {
639 index_ptr->setShortcut(lex.getDocString());
641 // not yet operational
642 if (tok == "\\color") {
644 string color = lex.getString();
646 index_ptr->setColor(color);
647 // Update also the Color table:
649 color = lcolor.getX11Name(Color_background);
651 lcolor.setColor(to_utf8(index), color);
654 } else if (token == "\\author") {
656 istringstream ss(lex.getString());
659 author_map.push_back(pimpl_->authorlist.record(a));
660 } else if (token == "\\paperorientation") {
663 orientation = paperorientationtranslator().find(orient);
664 } else if (token == "\\backgroundcolor") {
666 backgroundcolor = lyx::rgbFromHexName(lex.getString());
667 } else if (token == "\\paperwidth") {
669 } else if (token == "\\paperheight") {
671 } else if (token == "\\leftmargin") {
673 } else if (token == "\\topmargin") {
675 } else if (token == "\\rightmargin") {
677 } else if (token == "\\bottommargin") {
679 } else if (token == "\\headheight") {
681 } else if (token == "\\headsep") {
683 } else if (token == "\\footskip") {
685 } else if (token == "\\columnsep") {
687 } else if (token == "\\paperfontsize") {
689 } else if (token == "\\papercolumns") {
691 } else if (token == "\\listings_params") {
694 listings_params = InsetListingsParams(par).params();
695 } else if (token == "\\papersides") {
698 sides = sidestranslator().find(psides);
699 } else if (token == "\\paperpagestyle") {
701 } else if (token == "\\bullet") {
703 } else if (token == "\\bulletLaTeX") {
704 readBulletsLaTeX(lex);
705 } else if (token == "\\secnumdepth") {
707 } else if (token == "\\tocdepth") {
709 } else if (token == "\\spacing") {
713 if (nspacing == "other") {
716 spacing().set(spacetranslator().find(nspacing), tmp_val);
717 } else if (token == "\\float_placement") {
718 lex >> float_placement;
720 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
721 string toktmp = pdfoptions().readToken(lex, token);
722 if (!toktmp.empty()) {
723 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
728 lyxerr << "BufferParams::readToken(): Unknown token: " <<
737 void BufferParams::writeFile(ostream & os) const
739 // The top of the file is written by the buffer.
740 // Prints out the buffer info into the .lyx file given by file
743 os << "\\textclass " << baseClass()->name() << '\n';
746 if (!preamble.empty()) {
747 // remove '\n' from the end of preamble
748 string const tmppreamble = rtrim(preamble, "\n");
749 os << "\\begin_preamble\n"
751 << "\n\\end_preamble\n";
755 if (!options.empty()) {
756 os << "\\options " << options << '\n';
759 // use the class options defined in the layout?
760 os << "\\use_default_options "
761 << convert<string>(use_default_options) << "\n";
763 // the master document
764 if (!master.empty()) {
765 os << "\\master " << master << '\n';
769 if (!removedModules_.empty()) {
770 os << "\\begin_removed_modules" << '\n';
771 list<string>::const_iterator it = removedModules_.begin();
772 list<string>::const_iterator en = removedModules_.end();
773 for (; it != en; it++)
775 os << "\\end_removed_modules" << '\n';
779 if (!layoutModules_.empty()) {
780 os << "\\begin_modules" << '\n';
781 LayoutModuleList::const_iterator it = layoutModules_.begin();
782 LayoutModuleList::const_iterator en = layoutModules_.end();
783 for (; it != en; it++)
785 os << "\\end_modules" << '\n';
788 // local layout information
789 if (!local_layout.empty()) {
790 // remove '\n' from the end
791 string const tmplocal = rtrim(local_layout, "\n");
792 os << "\\begin_local_layout\n"
794 << "\n\\end_local_layout\n";
797 // then the text parameters
798 if (language != ignore_language)
799 os << "\\language " << language->lang() << '\n';
800 os << "\\inputencoding " << inputenc
801 << "\n\\font_roman " << fontsRoman
802 << "\n\\font_sans " << fontsSans
803 << "\n\\font_typewriter " << fontsTypewriter
804 << "\n\\font_default_family " << fontsDefaultFamily
805 << "\n\\use_xetex " << convert<string>(useXetex)
806 << "\n\\font_sc " << convert<string>(fontsSC)
807 << "\n\\font_osf " << convert<string>(fontsOSF)
808 << "\n\\font_sf_scale " << fontsSansScale
809 << "\n\\font_tt_scale " << fontsTypewriterScale
811 if (!fontsCJK.empty()) {
812 os << "\\font_cjk " << fontsCJK << '\n';
814 os << "\n\\graphics " << graphicsDriver << '\n';
815 os << "\\default_output_format " << defaultOutputFormat << '\n';
817 if (!float_placement.empty()) {
818 os << "\\float_placement " << float_placement << '\n';
820 os << "\\paperfontsize " << fontsize << '\n';
822 spacing().writeFile(os);
823 pdfoptions().writeFile(os);
825 os << "\\papersize " << string_papersize[papersize]
826 << "\n\\use_geometry " << convert<string>(use_geometry)
827 << "\n\\use_amsmath " << use_amsmath
828 << "\n\\use_esint " << use_esint
829 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
830 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
831 << "\n\\use_indices " << convert<string>(use_indices)
832 << "\n\\paperorientation " << string_orientation[orientation]
833 << "\n\\backgroundcolor " << lyx::X11hexname(backgroundcolor)
836 BranchList::const_iterator it = branchlist().begin();
837 BranchList::const_iterator end = branchlist().end();
838 for (; it != end; ++it) {
839 os << "\\branch " << to_utf8(it->branch())
840 << "\n\\selected " << it->isSelected()
841 << "\n\\color " << lyx::X11hexname(it->color())
846 IndicesList::const_iterator iit = indiceslist().begin();
847 IndicesList::const_iterator iend = indiceslist().end();
848 for (; iit != iend; ++iit) {
849 os << "\\index " << to_utf8(iit->index())
850 << "\n\\shortcut " << to_utf8(iit->shortcut())
851 << "\n\\color " << lyx::X11hexname(iit->color())
856 if (!paperwidth.empty())
857 os << "\\paperwidth "
858 << VSpace(paperwidth).asLyXCommand() << '\n';
859 if (!paperheight.empty())
860 os << "\\paperheight "
861 << VSpace(paperheight).asLyXCommand() << '\n';
862 if (!leftmargin.empty())
863 os << "\\leftmargin "
864 << VSpace(leftmargin).asLyXCommand() << '\n';
865 if (!topmargin.empty())
867 << VSpace(topmargin).asLyXCommand() << '\n';
868 if (!rightmargin.empty())
869 os << "\\rightmargin "
870 << VSpace(rightmargin).asLyXCommand() << '\n';
871 if (!bottommargin.empty())
872 os << "\\bottommargin "
873 << VSpace(bottommargin).asLyXCommand() << '\n';
874 if (!headheight.empty())
875 os << "\\headheight "
876 << VSpace(headheight).asLyXCommand() << '\n';
877 if (!headsep.empty())
879 << VSpace(headsep).asLyXCommand() << '\n';
880 if (!footskip.empty())
882 << VSpace(footskip).asLyXCommand() << '\n';
883 if (!columnsep.empty())
885 << VSpace(columnsep).asLyXCommand() << '\n';
886 os << "\\secnumdepth " << secnumdepth
887 << "\n\\tocdepth " << tocdepth
888 << "\n\\paragraph_separation "
889 << string_paragraph_separation[paragraph_separation]
890 << "\n\\defskip " << getDefSkip().asLyXCommand()
891 << "\n\\quotes_language "
892 << string_quotes_language[quotes_language]
893 << "\n\\papercolumns " << columns
894 << "\n\\papersides " << sides
895 << "\n\\paperpagestyle " << pagestyle << '\n';
896 if (!listings_params.empty())
897 os << "\\listings_params \"" <<
898 InsetListingsParams(listings_params).encodedString() << "\"\n";
899 for (int i = 0; i < 4; ++i) {
900 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
901 if (user_defined_bullet(i).getFont() != -1) {
902 os << "\\bullet " << i << " "
903 << user_defined_bullet(i).getFont() << " "
904 << user_defined_bullet(i).getCharacter() << " "
905 << user_defined_bullet(i).getSize() << "\n";
909 os << "\\bulletLaTeX " << i << " \""
910 << lyx::to_ascii(user_defined_bullet(i).getText())
916 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
917 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
919 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
920 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
921 for (; a_it != a_end; ++a_it) {
922 if (a_it->second.used())
923 os << "\\author " << a_it->second << "\n";
925 os << "\\author " << Author() << "\n";
930 void BufferParams::validate(LaTeXFeatures & features) const
932 features.require(documentClass().requires());
935 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
936 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
937 LaTeXFeatures::isAvailable("xcolor");
939 switch (features.runparams().flavor) {
940 case OutputParams::LATEX:
942 features.require("ct-dvipost");
943 features.require("dvipost");
944 } else if (xcolorulem) {
945 features.require("ct-xcolor-ulem");
946 features.require("ulem");
947 features.require("xcolor");
949 features.require("ct-none");
952 case OutputParams::PDFLATEX:
953 case OutputParams::XETEX:
955 features.require("ct-xcolor-ulem");
956 features.require("ulem");
957 features.require("xcolor");
958 // improves color handling in PDF output
959 features.require("pdfcolmk");
961 features.require("ct-none");
969 // Floats with 'Here definitely' as default setting.
970 if (float_placement.find('H') != string::npos)
971 features.require("float");
973 // AMS Style is at document level
974 if (use_amsmath == package_on
975 || documentClass().provides("amsmath"))
976 features.require("amsmath");
977 if (use_esint == package_on)
978 features.require("esint");
980 // Document-level line spacing
981 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
982 features.require("setspace");
984 // the bullet shapes are buffer level not paragraph level
985 // so they are tested here
986 for (int i = 0; i < 4; ++i) {
987 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
989 int const font = user_defined_bullet(i).getFont();
991 int const c = user_defined_bullet(i).getCharacter();
997 features.require("latexsym");
999 } else if (font == 1) {
1000 features.require("amssymb");
1001 } else if (font >= 2 && font <= 5) {
1002 features.require("pifont");
1006 if (pdfoptions().use_hyperref) {
1007 features.require("hyperref");
1008 // due to interferences with babel and hyperref, the color package has to
1009 // be loaded after hyperref when hyperref is used with the colorlinks
1010 // option, see http://bugzilla.lyx.org/show_bug.cgi?id=5291
1011 if (pdfoptions().colorlinks)
1012 features.require("color");
1016 features.require("xetex");
1018 if (language->lang() == "vietnamese")
1019 features.require("vietnamese");
1020 else if (language->lang() == "japanese")
1021 features.require("japanese");
1025 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1026 TexRow & texrow) const
1028 os << "\\documentclass";
1030 DocumentClass const & tclass = documentClass();
1032 ostringstream clsoptions; // the document class options.
1034 if (tokenPos(tclass.opt_fontsize(),
1035 '|', fontsize) >= 0) {
1036 // only write if existing in list (and not default)
1037 clsoptions << fontsize << "pt,";
1040 // custom, A3, B3 and B4 paper sizes need geometry
1041 bool nonstandard_papersize = papersize == PAPER_B3
1042 || papersize == PAPER_B4
1043 || papersize == PAPER_A3
1044 || papersize == PAPER_CUSTOM;
1046 if (!use_geometry) {
1047 switch (papersize) {
1049 clsoptions << "a4paper,";
1051 case PAPER_USLETTER:
1052 clsoptions << "letterpaper,";
1055 clsoptions << "a5paper,";
1058 clsoptions << "b5paper,";
1060 case PAPER_USEXECUTIVE:
1061 clsoptions << "executivepaper,";
1064 clsoptions << "legalpaper,";
1076 if (sides != tclass.sides()) {
1079 clsoptions << "oneside,";
1082 clsoptions << "twoside,";
1088 if (columns != tclass.columns()) {
1090 clsoptions << "twocolumn,";
1092 clsoptions << "onecolumn,";
1096 && orientation == ORIENTATION_LANDSCAPE)
1097 clsoptions << "landscape,";
1099 // language should be a parameter to \documentclass
1100 if (language->babel() == "hebrew"
1101 && default_language->babel() != "hebrew")
1102 // This seems necessary
1103 features.useLanguage(default_language);
1105 ostringstream language_options;
1106 bool const use_babel = features.useBabel();
1108 language_options << features.getLanguages();
1109 if (!language->babel().empty()) {
1110 if (!language_options.str().empty())
1111 language_options << ',';
1112 language_options << language->babel();
1114 // if Vietnamese is used, babel must directly be loaded
1115 // with language options, not in the class options, see
1116 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1117 size_t viet = language_options.str().find("vietnam");
1118 // viet = string::npos when not found
1119 // the same is for all other languages that are not directly supported by
1120 // babel, but where LaTeX-packages add babel support.
1121 // this is currently the case for Latvian, Lithuanian, and Mongolian
1122 size_t latvian = language_options.str().find("latvian");
1123 size_t lithu = language_options.str().find("lithuanian");
1124 size_t mongo = language_options.str().find("mongolian");
1125 // if Japanese is used, babel must directly be loaded
1126 // with language options, not in the class options, see
1127 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1128 size_t japan = language_options.str().find("japanese");
1129 if (lyxrc.language_global_options && !language_options.str().empty()
1130 && viet == string::npos && japan == string::npos
1131 && latvian == string::npos && lithu == string::npos
1132 && mongo == string::npos)
1133 clsoptions << language_options.str() << ',';
1136 // the predefined options from the layout
1137 if (use_default_options && !tclass.options().empty())
1138 clsoptions << tclass.options() << ',';
1140 // the user-defined options
1141 if (!options.empty()) {
1142 clsoptions << options << ',';
1145 string strOptions(clsoptions.str());
1146 if (!strOptions.empty()) {
1147 strOptions = rtrim(strOptions, ",");
1149 os << '[' << from_utf8(strOptions) << ']';
1152 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1154 // end of \documentclass defs
1157 os << "\\usepackage{fontspec}\n";
1161 // font selection must be done before loading fontenc.sty
1162 string const fonts =
1163 loadFonts(fontsRoman, fontsSans,
1164 fontsTypewriter, fontsSC, fontsOSF,
1165 fontsSansScale, fontsTypewriterScale, useXetex);
1166 if (!fonts.empty()) {
1167 os << from_ascii(fonts);
1170 if (fontsDefaultFamily != "default")
1171 os << "\\renewcommand{\\familydefault}{\\"
1172 << from_ascii(fontsDefaultFamily) << "}\n";
1174 // set font encoding
1175 // this one is not per buffer
1176 // for arabic_arabi and farsi we also need to load the LAE and
1178 // XeteX works without fontenc
1179 if (lyxrc.fontenc != "default" && language->lang() != "japanese"
1181 if (language->lang() == "arabic_arabi"
1182 || language->lang() == "farsi") {
1183 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1184 << ",LFE,LAE]{fontenc}\n";
1187 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1193 // handle inputenc etc.
1194 writeEncodingPreamble(os, features, texrow);
1196 if (!listings_params.empty() || features.isRequired("listings")) {
1197 os << "\\usepackage{listings}\n";
1200 if (!listings_params.empty()) {
1202 // do not test validity because listings_params is
1203 // supposed to be valid
1205 InsetListingsParams(listings_params).separatedParams(true);
1206 // we can't support all packages, but we should load the color package
1207 if (par.find("\\color", 0) != string::npos)
1208 features.require("color");
1209 os << from_utf8(par);
1210 // count the number of newlines
1211 for (size_t i = 0; i < par.size(); ++i)
1217 if (!tclass.provides("geometry")
1218 && (use_geometry || nonstandard_papersize)) {
1219 odocstringstream ods;
1220 if (!getGraphicsDriver("geometry").empty())
1221 ods << getGraphicsDriver("geometry");
1222 if (orientation == ORIENTATION_LANDSCAPE)
1223 ods << ",landscape";
1224 switch (papersize) {
1226 if (!paperwidth.empty())
1227 ods << ",paperwidth="
1228 << from_ascii(paperwidth);
1229 if (!paperheight.empty())
1230 ods << ",paperheight="
1231 << from_ascii(paperheight);
1233 case PAPER_USLETTER:
1234 ods << ",letterpaper";
1237 ods << ",legalpaper";
1239 case PAPER_USEXECUTIVE:
1240 ods << ",executivepaper";
1261 // default papersize ie PAPER_DEFAULT
1262 switch (lyxrc.default_papersize) {
1263 case PAPER_DEFAULT: // keep compiler happy
1264 case PAPER_USLETTER:
1265 ods << ",letterpaper";
1268 ods << ",legalpaper";
1270 case PAPER_USEXECUTIVE:
1271 ods << ",executivepaper";
1291 docstring const g_options = trim(ods.str(), ",");
1292 os << "\\usepackage";
1293 if (!g_options.empty())
1294 os << '[' << g_options << ']';
1295 os << "{geometry}\n";
1297 os << "\\geometry{verbose";
1298 if (!topmargin.empty())
1299 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1300 if (!bottommargin.empty())
1301 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1302 if (!leftmargin.empty())
1303 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1304 if (!rightmargin.empty())
1305 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1306 if (!headheight.empty())
1307 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1308 if (!headsep.empty())
1309 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1310 if (!footskip.empty())
1311 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1312 if (!columnsep.empty())
1313 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1316 } else if (orientation == ORIENTATION_LANDSCAPE) {
1317 features.require("papersize");
1320 if (tokenPos(tclass.opt_pagestyle(),
1321 '|', pagestyle) >= 0) {
1322 if (pagestyle == "fancy") {
1323 os << "\\usepackage{fancyhdr}\n";
1326 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1330 // only output when the background color is not white
1331 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1332 // only require color here, the background color will be defined
1333 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1335 features.require("color");
1336 features.require("pagecolor");
1339 // Only if class has a ToC hierarchy
1340 if (tclass.hasTocLevels()) {
1341 if (secnumdepth != tclass.secnumdepth()) {
1342 os << "\\setcounter{secnumdepth}{"
1347 if (tocdepth != tclass.tocdepth()) {
1348 os << "\\setcounter{tocdepth}{"
1355 if (paragraph_separation) {
1356 switch (getDefSkip().kind()) {
1357 case VSpace::SMALLSKIP:
1358 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1360 case VSpace::MEDSKIP:
1361 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1363 case VSpace::BIGSKIP:
1364 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1366 case VSpace::LENGTH:
1367 os << "\\setlength{\\parskip}{"
1368 << from_utf8(getDefSkip().length().asLatexString())
1371 default: // should never happen // Then delete it.
1372 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1377 os << "\\setlength{\\parindent}{0pt}\n";
1381 // Now insert the LyX specific LaTeX commands...
1382 docstring lyxpreamble;
1384 // due to interferences with babel and hyperref, the color package has to
1385 // be loaded (when it is not already loaded) before babel when hyperref
1386 // is used with the colorlinks option, see
1387 // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1388 // we decided therefore to load color always before babel, see
1389 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1390 lyxpreamble += from_ascii(features.getColorOptions());
1392 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1394 && (features.isRequired("jurabib")
1395 || features.isRequired("hyperref")
1396 || features.isRequired("vietnamese")
1397 || features.isRequired("japanese") ) ) {
1399 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1400 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1403 // The optional packages;
1404 lyxpreamble += from_ascii(features.getPackages());
1406 // Additional Indices
1407 if (features.isRequired("splitidx")) {
1408 IndicesList::const_iterator iit = indiceslist().begin();
1409 IndicesList::const_iterator iend = indiceslist().end();
1410 for (; iit != iend; ++iit) {
1411 lyxpreamble += "\\newindex[";
1412 lyxpreamble += iit->index();
1413 lyxpreamble += "]{";
1414 lyxpreamble += iit->shortcut();
1415 lyxpreamble += "}\n";
1420 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1423 // * Hyperref manual: "Make sure it comes last of your loaded
1424 // packages, to give it a fighting chance of not being over-written,
1425 // since its job is to redefine many LaTeX commands."
1426 // * Email from Heiko Oberdiek: "It is usually better to load babel
1427 // before hyperref. Then hyperref has a chance to detect babel.
1428 // * Has to be loaded before the "LyX specific LaTeX commands" to
1429 // avoid errors with algorithm floats.
1430 // use hyperref explicitely when it is required
1431 if (features.isRequired("hyperref")) {
1432 odocstringstream oss;
1433 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1434 lyxpreamble += oss.str();
1437 // Will be surrounded by \makeatletter and \makeatother when needed
1438 docstring atlyxpreamble;
1440 // Some macros LyX will need
1441 docstring tmppreamble(from_ascii(features.getMacros()));
1443 if (!tmppreamble.empty())
1444 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1445 "LyX specific LaTeX commands.\n"
1446 + tmppreamble + '\n';
1448 // the text class specific preamble
1449 tmppreamble = features.getTClassPreamble();
1450 if (!tmppreamble.empty())
1451 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1452 "Textclass specific LaTeX commands.\n"
1453 + tmppreamble + '\n';
1455 /* the user-defined preamble */
1456 if (!preamble.empty())
1458 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1459 "User specified LaTeX commands.\n"
1460 + from_utf8(preamble) + '\n';
1462 // subfig loads internally the LaTeX package "caption". As
1463 // caption is a very popular package, users will load it in
1464 // the preamble. Therefore we must load subfig behind the
1465 // user-defined preamble and check if the caption package was
1466 // loaded or not. For the case that caption is loaded before
1467 // subfig, there is the subfig option "caption=false". This
1468 // option also works when a koma-script class is used and
1469 // koma's own caption commands are used instead of caption. We
1470 // use \PassOptionsToPackage here because the user could have
1471 // already loaded subfig in the preamble.
1472 if (features.isRequired("subfig")) {
1473 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1474 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1475 "\\usepackage{subfig}\n";
1478 // Itemize bullet settings need to be last in case the user
1479 // defines their own bullets that use a package included
1480 // in the user-defined preamble -- ARRae
1481 // Actually it has to be done much later than that
1482 // since some packages like frenchb make modifications
1483 // at \begin{document} time -- JMarc
1484 docstring bullets_def;
1485 for (int i = 0; i < 4; ++i) {
1486 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1487 if (bullets_def.empty())
1488 bullets_def += "\\AtBeginDocument{\n";
1489 bullets_def += " \\def\\labelitemi";
1491 // `i' is one less than the item to modify
1498 bullets_def += "ii";
1504 bullets_def += '{' +
1505 user_defined_bullet(i).getText()
1510 if (!bullets_def.empty())
1511 atlyxpreamble += bullets_def + "}\n\n";
1513 if (atlyxpreamble.find(from_ascii("@")) != docstring::npos)
1514 lyxpreamble += "\n\\makeatletter\n"
1515 + atlyxpreamble + "\\makeatother\n\n";
1517 lyxpreamble += '\n' + atlyxpreamble;
1519 // We try to load babel late, in case it interferes with other packages.
1520 // Jurabib and Hyperref have to be called after babel, though.
1521 if (use_babel && !features.isRequired("jurabib")
1522 && !features.isRequired("hyperref")
1523 && !features.isRequired("vietnamese")
1524 && !features.isRequired("japanese")) {
1526 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1527 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1530 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1531 if (!i18npreamble.empty())
1532 lyxpreamble += i18npreamble + '\n';
1535 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1536 for (int j = 0; j != nlines; ++j) {
1542 // these packages (xunicode, for that matter) need to be loaded at least
1543 // after amsmath, amssymb, esint and the other packages that provide
1546 os << "\\usepackage{xunicode}\n";
1548 os << "\\usepackage{xltxtra}\n";
1555 void BufferParams::useClassDefaults()
1557 DocumentClass const & tclass = documentClass();
1559 sides = tclass.sides();
1560 columns = tclass.columns();
1561 pagestyle = tclass.pagestyle();
1562 use_default_options = true;
1563 // Only if class has a ToC hierarchy
1564 if (tclass.hasTocLevels()) {
1565 secnumdepth = tclass.secnumdepth();
1566 tocdepth = tclass.tocdepth();
1571 bool BufferParams::hasClassDefaults() const
1573 DocumentClass const & tclass = documentClass();
1575 return sides == tclass.sides()
1576 && columns == tclass.columns()
1577 && pagestyle == tclass.pagestyle()
1578 && use_default_options
1579 && secnumdepth == tclass.secnumdepth()
1580 && tocdepth == tclass.tocdepth();
1584 DocumentClass const & BufferParams::documentClass() const
1590 DocumentClass const * BufferParams::documentClassPtr() const {
1595 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1596 // evil, but this function is evil
1597 doc_class_ = const_cast<DocumentClass *>(tc);
1601 bool BufferParams::setBaseClass(string const & classname)
1603 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1604 LayoutFileList & bcl = LayoutFileList::get();
1605 if (!bcl.haveClass(classname)) {
1607 bformat(_("The document class %1$s could not be found. "
1608 "A default textclass with default layouts will be used. "
1609 "LyX might not be able to produce output unless a correct "
1610 "textclass is selected from the document settings dialog."),
1611 from_utf8(classname));
1612 frontend::Alert::error(_("Document class not found"), s);
1613 bcl.addEmptyClass(classname);
1616 bool const success = bcl[classname].load();
1619 bformat(_("The document class %1$s could not be loaded."),
1620 from_utf8(classname));
1621 frontend::Alert::error(_("Could not load class"), s);
1625 pimpl_->baseClass_ = classname;
1626 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1631 LayoutFile const * BufferParams::baseClass() const
1633 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1634 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1640 LayoutFileIndex const & BufferParams::baseClassID() const
1642 return pimpl_->baseClass_;
1646 void BufferParams::makeDocumentClass()
1651 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1653 if (!local_layout.empty()) {
1654 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1655 docstring const msg = _("Error reading internal layout information");
1656 frontend::Alert::warning(_("Read Error"), msg);
1661 bool BufferParams::moduleCanBeAdded(string const & modName) const
1663 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1667 bool BufferParams::addLayoutModule(string const & modName)
1669 LayoutModuleList::const_iterator it = layoutModules_.begin();
1670 LayoutModuleList::const_iterator end = layoutModules_.end();
1671 for (; it != end; it++)
1674 layoutModules_.push_back(modName);
1679 Font const BufferParams::getFont() const
1681 FontInfo f = documentClass().defaultfont();
1682 if (fontsDefaultFamily == "rmdefault")
1683 f.setFamily(ROMAN_FAMILY);
1684 else if (fontsDefaultFamily == "sfdefault")
1685 f.setFamily(SANS_FAMILY);
1686 else if (fontsDefaultFamily == "ttdefault")
1687 f.setFamily(TYPEWRITER_FAMILY);
1688 return Font(f, language);
1692 void BufferParams::readPreamble(Lexer & lex)
1694 if (lex.getString() != "\\begin_preamble")
1695 lyxerr << "Error (BufferParams::readPreamble):"
1696 "consistency check failed." << endl;
1698 preamble = lex.getLongString("\\end_preamble");
1702 void BufferParams::readLocalLayout(Lexer & lex)
1704 if (lex.getString() != "\\begin_local_layout")
1705 lyxerr << "Error (BufferParams::readLocalLayout):"
1706 "consistency check failed." << endl;
1708 local_layout = lex.getLongString("\\end_local_layout");
1712 void BufferParams::readLanguage(Lexer & lex)
1714 if (!lex.next()) return;
1716 string const tmptok = lex.getString();
1718 // check if tmptok is part of tex_babel in tex-defs.h
1719 language = languages.getLanguage(tmptok);
1721 // Language tmptok was not found
1722 language = default_language;
1723 lyxerr << "Warning: Setting language `"
1724 << tmptok << "' to `" << language->lang()
1730 void BufferParams::readGraphicsDriver(Lexer & lex)
1735 string const tmptok = lex.getString();
1736 // check if tmptok is part of tex_graphics in tex_defs.h
1739 string const test = tex_graphics[n++];
1741 if (test == tmptok) {
1742 graphicsDriver = tmptok;
1747 "Warning: graphics driver `$$Token' not recognized!\n"
1748 " Setting graphics driver to `default'.\n");
1749 graphicsDriver = "default";
1756 void BufferParams::readBullets(Lexer & lex)
1761 int const index = lex.getInteger();
1763 int temp_int = lex.getInteger();
1764 user_defined_bullet(index).setFont(temp_int);
1765 temp_bullet(index).setFont(temp_int);
1767 user_defined_bullet(index).setCharacter(temp_int);
1768 temp_bullet(index).setCharacter(temp_int);
1770 user_defined_bullet(index).setSize(temp_int);
1771 temp_bullet(index).setSize(temp_int);
1775 void BufferParams::readBulletsLaTeX(Lexer & lex)
1777 // The bullet class should be able to read this.
1780 int const index = lex.getInteger();
1782 docstring const temp_str = lex.getDocString();
1784 user_defined_bullet(index).setText(temp_str);
1785 temp_bullet(index).setText(temp_str);
1789 void BufferParams::readModules(Lexer & lex)
1791 if (!lex.eatLine()) {
1792 lyxerr << "Error (BufferParams::readModules):"
1793 "Unexpected end of input." << endl;
1797 string mod = lex.getString();
1798 if (mod == "\\end_modules")
1800 addLayoutModule(mod);
1806 void BufferParams::readRemovedModules(Lexer & lex)
1808 if (!lex.eatLine()) {
1809 lyxerr << "Error (BufferParams::readRemovedModules):"
1810 "Unexpected end of input." << endl;
1814 string mod = lex.getString();
1815 if (mod == "\\end_removed_modules")
1817 removedModules_.push_back(mod);
1820 // now we want to remove any removed modules that were previously
1821 // added. normally, that will be because default modules were added in
1822 // setBaseClass(), which gets called when \textclass is read at the
1823 // start of the read.
1824 list<string>::const_iterator rit = removedModules_.begin();
1825 list<string>::const_iterator const ren = removedModules_.end();
1826 for (; rit != ren; rit++) {
1827 LayoutModuleList::iterator const mit = layoutModules_.begin();
1828 LayoutModuleList::iterator const men = layoutModules_.end();
1829 LayoutModuleList::iterator found = find(mit, men, *rit);
1832 layoutModules_.erase(found);
1837 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1839 char real_papersize = papersize;
1840 if (real_papersize == PAPER_DEFAULT)
1841 real_papersize = lyxrc.default_papersize;
1843 switch (real_papersize) {
1845 // could be anything, so don't guess
1847 case PAPER_CUSTOM: {
1848 if (purpose == XDVI && !paperwidth.empty() &&
1849 !paperheight.empty()) {
1850 // heightxwidth<unit>
1851 string first = paperwidth;
1852 string second = paperheight;
1853 if (orientation == ORIENTATION_LANDSCAPE)
1856 return first.erase(first.length() - 2)
1868 // dvips and dvipdfm do not know this
1869 if (purpose == DVIPS || purpose == DVIPDFM)
1873 // dvipdfm does not know this
1874 if (purpose == DVIPDFM)
1878 // dvipdfm does not know this
1879 if (purpose == DVIPDFM)
1882 case PAPER_USEXECUTIVE:
1883 // dvipdfm does not know this
1884 if (purpose == DVIPDFM)
1889 case PAPER_USLETTER:
1891 if (purpose == XDVI)
1898 string const BufferParams::dvips_options() const
1903 && papersize == PAPER_CUSTOM
1904 && !lyxrc.print_paper_dimension_flag.empty()
1905 && !paperwidth.empty()
1906 && !paperheight.empty()) {
1907 // using a custom papersize
1908 result = lyxrc.print_paper_dimension_flag;
1909 result += ' ' + paperwidth;
1910 result += ',' + paperheight;
1912 string const paper_option = paperSizeName(DVIPS);
1913 if (!paper_option.empty() && (paper_option != "letter" ||
1914 orientation != ORIENTATION_LANDSCAPE)) {
1915 // dvips won't accept -t letter -t landscape.
1916 // In all other cases, include the paper size
1918 result = lyxrc.print_paper_flag;
1919 result += ' ' + paper_option;
1922 if (orientation == ORIENTATION_LANDSCAPE &&
1923 papersize != PAPER_CUSTOM)
1924 result += ' ' + lyxrc.print_landscape_flag;
1929 string BufferParams::babelCall(string const & lang_opts) const
1931 string lang_pack = lyxrc.language_package;
1932 if (lang_pack != "\\usepackage{babel}")
1934 // suppress the babel call when there is no babel language defined
1935 // for the document language in the lib/languages file and if no
1936 // other languages are used (lang_opts is then empty)
1937 if (lang_opts.empty())
1939 // If Vietnamese is used, babel must directly be loaded with the
1940 // language options, see
1941 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1942 size_t viet = lang_opts.find("vietnam");
1943 // viet = string::npos when not found
1944 // the same is for all other languages that are not directly supported by
1945 // babel, but where LaTeX-packages add babel support.
1946 // this is currently the case for Latvian, Lithuanian, and Mongolian
1947 size_t latvian = lang_opts.find("latvian");
1948 size_t lithu = lang_opts.find("lithuanian");
1949 size_t mongo = lang_opts.find("mongolian");
1950 // If Japanese is used, babel must directly be loaded with the
1951 // language options, see
1952 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1953 size_t japan = lang_opts.find("japanese");
1954 if (!lyxrc.language_global_options || viet != string::npos
1955 || japan != string::npos || latvian != string::npos
1956 || lithu != string::npos || mongo != string::npos)
1957 return "\\usepackage[" + lang_opts + "]{babel}";
1962 docstring BufferParams::getGraphicsDriver(string const & package) const
1966 if (package == "geometry") {
1967 if (graphicsDriver == "dvips"
1968 || graphicsDriver == "dvipdfm"
1969 || graphicsDriver == "pdftex"
1970 || graphicsDriver == "vtex")
1971 result = from_ascii(graphicsDriver);
1972 else if (graphicsDriver == "dvipdfmx")
1973 result = from_ascii("dvipdfm");
1980 void BufferParams::writeEncodingPreamble(odocstream & os,
1981 LaTeXFeatures & features, TexRow & texrow) const
1985 if (inputenc == "auto") {
1986 string const doc_encoding =
1987 language->encoding()->latexName();
1988 Encoding::Package const package =
1989 language->encoding()->package();
1991 // Create a list with all the input encodings used
1993 set<string> encodings =
1994 features.getEncodingSet(doc_encoding);
1996 // If the "japanese" package (i.e. pLaTeX) is used,
1997 // inputenc must be omitted.
1998 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
1999 if (package == Encoding::japanese)
2000 features.require("japanese");
2002 if ((!encodings.empty() || package == Encoding::inputenc)
2003 && !features.isRequired("japanese")) {
2004 os << "\\usepackage[";
2005 set<string>::const_iterator it = encodings.begin();
2006 set<string>::const_iterator const end = encodings.end();
2008 os << from_ascii(*it);
2011 for (; it != end; ++it)
2012 os << ',' << from_ascii(*it);
2013 if (package == Encoding::inputenc) {
2014 if (!encodings.empty())
2016 os << from_ascii(doc_encoding);
2018 os << "]{inputenc}\n";
2021 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2022 if (language->encoding()->name() == "utf8-cjk"
2023 && LaTeXFeatures::isAvailable("CJKutf8"))
2024 os << "\\usepackage{CJKutf8}\n";
2026 os << "\\usepackage{CJK}\n";
2029 } else if (inputenc != "default") {
2030 switch (encoding().package()) {
2031 case Encoding::none:
2032 case Encoding::japanese:
2034 case Encoding::inputenc:
2035 // do not load inputenc if japanese is used
2036 if (features.isRequired("japanese"))
2038 os << "\\usepackage[" << from_ascii(inputenc)
2043 if (encoding().name() == "utf8-cjk"
2044 && LaTeXFeatures::isAvailable("CJKutf8"))
2045 os << "\\usepackage{CJKutf8}\n";
2047 os << "\\usepackage{CJK}\n";
2053 // The encoding "armscii8" (for Armenian) is only available when
2054 // the package "armtex" is loaded.
2055 if (language->encoding()->latexName() == "armscii8"
2056 || inputenc == "armscii8") {
2057 os << "\\usepackage{armtex}\n";
2063 string const BufferParams::parseFontName(string const & name) const
2065 string mangled = name;
2066 size_t const idx = mangled.find('[');
2067 if (idx == string::npos || idx == 0)
2070 return mangled.substr(0, idx - 1);
2074 string const BufferParams::loadFonts(string const & rm,
2075 string const & sf, string const & tt,
2076 bool const & sc, bool const & osf,
2077 int const & sfscale, int const & ttscale,
2078 bool const & xetex) const
2080 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2081 several packages have been replaced by others, that might not
2082 be installed on every system. We have to take care for that
2083 (see psnfss.pdf). We try to support all psnfss fonts as well
2084 as the fonts that have become de facto standard in the LaTeX
2085 world (e.g. Latin Modern). We do not support obsolete fonts
2086 (like PSLatex). In general, it should be possible to mix any
2087 rm font with any sf or tt font, respectively. (JSpitzm)
2089 -- separate math fonts.
2092 if (rm == "default" && sf == "default" && tt == "default")
2099 if (rm != "default")
2100 os << "\\setmainfont[Mapping=tex-text]{"
2101 << parseFontName(rm) << "}\n";
2102 if (sf != "default") {
2103 string const sans = parseFontName(sf);
2105 os << "\\setsansfont[Scale="
2106 << float(sfscale) / 100
2107 << ",Mapping=tex-text]{"
2110 os << "\\setsansfont[Mapping=tex-text]{"
2113 if (tt != "default") {
2114 string const mono = parseFontName(tt);
2116 os << "\\setmonofont[Scale="
2117 << float(sfscale) / 100
2121 os << "\\setmonofont[Mapping=tex-text]{"
2125 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2130 // Computer Modern (must be explicitely selectable -- there might be classes
2131 // that define a different default font!
2133 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2134 // osf for Computer Modern needs eco.sty
2136 os << "\\usepackage{eco}\n";
2138 // Latin Modern Roman
2139 else if (rm == "lmodern")
2140 os << "\\usepackage{lmodern}\n";
2142 else if (rm == "ae") {
2143 // not needed when using OT1 font encoding.
2144 if (lyxrc.fontenc != "default")
2145 os << "\\usepackage{ae,aecompl}\n";
2148 else if (rm == "times") {
2149 // try to load the best available package
2150 if (LaTeXFeatures::isAvailable("mathptmx"))
2151 os << "\\usepackage{mathptmx}\n";
2152 else if (LaTeXFeatures::isAvailable("mathptm"))
2153 os << "\\usepackage{mathptm}\n";
2155 os << "\\usepackage{times}\n";
2158 else if (rm == "palatino") {
2159 // try to load the best available package
2160 if (LaTeXFeatures::isAvailable("mathpazo")) {
2161 os << "\\usepackage";
2167 // "osf" includes "sc"!
2171 os << "{mathpazo}\n";
2173 else if (LaTeXFeatures::isAvailable("mathpple"))
2174 os << "\\usepackage{mathpple}\n";
2176 os << "\\usepackage{palatino}\n";
2179 else if (rm == "utopia") {
2180 // fourier supersedes utopia.sty, but does
2181 // not work with OT1 encoding.
2182 if (LaTeXFeatures::isAvailable("fourier")
2183 && lyxrc.fontenc != "default") {
2184 os << "\\usepackage";
2195 os << "{fourier}\n";
2198 os << "\\usepackage{utopia}\n";
2200 // Bera (complete fontset)
2201 else if (rm == "bera" && sf == "default" && tt == "default")
2202 os << "\\usepackage{bera}\n";
2204 else if (rm != "default")
2205 os << "\\usepackage" << "{" << rm << "}\n";
2208 // Helvetica, Bera Sans
2209 if (sf == "helvet" || sf == "berasans") {
2211 os << "\\usepackage[scaled=" << float(sfscale) / 100
2212 << "]{" << sf << "}\n";
2214 os << "\\usepackage{" << sf << "}\n";
2217 else if (sf == "avant")
2218 os << "\\usepackage{" << sf << "}\n";
2219 // Computer Modern, Latin Modern, CM Bright
2220 else if (sf != "default")
2221 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2223 // monospaced/typewriter
2224 // Courier, LuxiMono
2225 if (tt == "luximono" || tt == "beramono") {
2227 os << "\\usepackage[scaled=" << float(ttscale) / 100
2228 << "]{" << tt << "}\n";
2230 os << "\\usepackage{" << tt << "}\n";
2233 else if (tt == "courier" )
2234 os << "\\usepackage{" << tt << "}\n";
2235 // Computer Modern, Latin Modern, CM Bright
2236 else if (tt != "default")
2237 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2243 Encoding const & BufferParams::encoding() const
2246 return *(encodings.fromLaTeXName("utf8-plain"));
2247 if (inputenc == "auto" || inputenc == "default")
2248 return *language->encoding();
2249 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2252 LYXERR0("Unknown inputenc value `" << inputenc
2253 << "'. Using `auto' instead.");
2254 return *language->encoding();
2258 CiteEngine BufferParams::citeEngine() const
2260 // FIXME the class should provide the numerical/
2261 // authoryear choice
2262 if (documentClass().provides("natbib")
2263 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2264 return ENGINE_NATBIB_AUTHORYEAR;
2265 return cite_engine_;
2269 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2271 cite_engine_ = cite_engine;