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]
834 if (backgroundcolor != lyx::rgbFromHexName("#ffffff"))
835 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
837 BranchList::const_iterator it = branchlist().begin();
838 BranchList::const_iterator end = branchlist().end();
839 for (; it != end; ++it) {
840 os << "\\branch " << to_utf8(it->branch())
841 << "\n\\selected " << it->isSelected()
842 << "\n\\color " << lyx::X11hexname(it->color())
847 IndicesList::const_iterator iit = indiceslist().begin();
848 IndicesList::const_iterator iend = indiceslist().end();
849 for (; iit != iend; ++iit) {
850 os << "\\index " << to_utf8(iit->index())
851 << "\n\\shortcut " << to_utf8(iit->shortcut())
852 << "\n\\color " << lyx::X11hexname(iit->color())
857 if (!paperwidth.empty())
858 os << "\\paperwidth "
859 << VSpace(paperwidth).asLyXCommand() << '\n';
860 if (!paperheight.empty())
861 os << "\\paperheight "
862 << VSpace(paperheight).asLyXCommand() << '\n';
863 if (!leftmargin.empty())
864 os << "\\leftmargin "
865 << VSpace(leftmargin).asLyXCommand() << '\n';
866 if (!topmargin.empty())
868 << VSpace(topmargin).asLyXCommand() << '\n';
869 if (!rightmargin.empty())
870 os << "\\rightmargin "
871 << VSpace(rightmargin).asLyXCommand() << '\n';
872 if (!bottommargin.empty())
873 os << "\\bottommargin "
874 << VSpace(bottommargin).asLyXCommand() << '\n';
875 if (!headheight.empty())
876 os << "\\headheight "
877 << VSpace(headheight).asLyXCommand() << '\n';
878 if (!headsep.empty())
880 << VSpace(headsep).asLyXCommand() << '\n';
881 if (!footskip.empty())
883 << VSpace(footskip).asLyXCommand() << '\n';
884 if (!columnsep.empty())
886 << VSpace(columnsep).asLyXCommand() << '\n';
887 os << "\\secnumdepth " << secnumdepth
888 << "\n\\tocdepth " << tocdepth
889 << "\n\\paragraph_separation "
890 << string_paragraph_separation[paragraph_separation]
891 << "\n\\defskip " << getDefSkip().asLyXCommand()
892 << "\n\\quotes_language "
893 << string_quotes_language[quotes_language]
894 << "\n\\papercolumns " << columns
895 << "\n\\papersides " << sides
896 << "\n\\paperpagestyle " << pagestyle << '\n';
897 if (!listings_params.empty())
898 os << "\\listings_params \"" <<
899 InsetListingsParams(listings_params).encodedString() << "\"\n";
900 for (int i = 0; i < 4; ++i) {
901 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
902 if (user_defined_bullet(i).getFont() != -1) {
903 os << "\\bullet " << i << " "
904 << user_defined_bullet(i).getFont() << " "
905 << user_defined_bullet(i).getCharacter() << " "
906 << user_defined_bullet(i).getSize() << "\n";
910 os << "\\bulletLaTeX " << i << " \""
911 << lyx::to_ascii(user_defined_bullet(i).getText())
917 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
918 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
920 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
921 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
922 for (; a_it != a_end; ++a_it) {
923 if (a_it->second.used())
924 os << "\\author " << a_it->second << "\n";
926 os << "\\author " << Author() << "\n";
931 void BufferParams::validate(LaTeXFeatures & features) const
933 features.require(documentClass().requires());
936 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
937 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
938 LaTeXFeatures::isAvailable("xcolor");
940 switch (features.runparams().flavor) {
941 case OutputParams::LATEX:
943 features.require("ct-dvipost");
944 features.require("dvipost");
945 } else if (xcolorulem) {
946 features.require("ct-xcolor-ulem");
947 features.require("ulem");
948 features.require("xcolor");
950 features.require("ct-none");
953 case OutputParams::PDFLATEX:
954 case OutputParams::XETEX:
956 features.require("ct-xcolor-ulem");
957 features.require("ulem");
958 features.require("xcolor");
959 // improves color handling in PDF output
960 features.require("pdfcolmk");
962 features.require("ct-none");
970 // Floats with 'Here definitely' as default setting.
971 if (float_placement.find('H') != string::npos)
972 features.require("float");
974 // AMS Style is at document level
975 if (use_amsmath == package_on
976 || documentClass().provides("amsmath"))
977 features.require("amsmath");
978 if (use_esint == package_on)
979 features.require("esint");
981 // Document-level line spacing
982 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
983 features.require("setspace");
985 // the bullet shapes are buffer level not paragraph level
986 // so they are tested here
987 for (int i = 0; i < 4; ++i) {
988 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
990 int const font = user_defined_bullet(i).getFont();
992 int const c = user_defined_bullet(i).getCharacter();
998 features.require("latexsym");
1000 } else if (font == 1) {
1001 features.require("amssymb");
1002 } else if (font >= 2 && font <= 5) {
1003 features.require("pifont");
1007 if (pdfoptions().use_hyperref) {
1008 features.require("hyperref");
1009 // due to interferences with babel and hyperref, the color package has to
1010 // be loaded after hyperref when hyperref is used with the colorlinks
1011 // option, see http://bugzilla.lyx.org/show_bug.cgi?id=5291
1012 if (pdfoptions().colorlinks)
1013 features.require("color");
1017 features.require("xetex");
1019 if (language->lang() == "vietnamese")
1020 features.require("vietnamese");
1021 else if (language->lang() == "japanese")
1022 features.require("japanese");
1026 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1027 TexRow & texrow) const
1029 os << "\\documentclass";
1031 DocumentClass const & tclass = documentClass();
1033 ostringstream clsoptions; // the document class options.
1035 if (tokenPos(tclass.opt_fontsize(),
1036 '|', fontsize) >= 0) {
1037 // only write if existing in list (and not default)
1038 clsoptions << fontsize << "pt,";
1041 // custom, A3, B3 and B4 paper sizes need geometry
1042 bool nonstandard_papersize = papersize == PAPER_B3
1043 || papersize == PAPER_B4
1044 || papersize == PAPER_A3
1045 || papersize == PAPER_CUSTOM;
1047 if (!use_geometry) {
1048 switch (papersize) {
1050 clsoptions << "a4paper,";
1052 case PAPER_USLETTER:
1053 clsoptions << "letterpaper,";
1056 clsoptions << "a5paper,";
1059 clsoptions << "b5paper,";
1061 case PAPER_USEXECUTIVE:
1062 clsoptions << "executivepaper,";
1065 clsoptions << "legalpaper,";
1077 if (sides != tclass.sides()) {
1080 clsoptions << "oneside,";
1083 clsoptions << "twoside,";
1089 if (columns != tclass.columns()) {
1091 clsoptions << "twocolumn,";
1093 clsoptions << "onecolumn,";
1097 && orientation == ORIENTATION_LANDSCAPE)
1098 clsoptions << "landscape,";
1100 // language should be a parameter to \documentclass
1101 if (language->babel() == "hebrew"
1102 && default_language->babel() != "hebrew")
1103 // This seems necessary
1104 features.useLanguage(default_language);
1106 ostringstream language_options;
1107 bool const use_babel = features.useBabel();
1109 language_options << features.getLanguages();
1110 if (!language->babel().empty()) {
1111 if (!language_options.str().empty())
1112 language_options << ',';
1113 language_options << language->babel();
1115 // if Vietnamese is used, babel must directly be loaded
1116 // with language options, not in the class options, see
1117 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1118 size_t viet = language_options.str().find("vietnam");
1119 // viet = string::npos when not found
1120 // the same is for all other languages that are not directly supported by
1121 // babel, but where LaTeX-packages add babel support.
1122 // this is currently the case for Latvian, Lithuanian, and Mongolian
1123 size_t latvian = language_options.str().find("latvian");
1124 size_t lithu = language_options.str().find("lithuanian");
1125 size_t mongo = language_options.str().find("mongolian");
1126 // if Japanese is used, babel must directly be loaded
1127 // with language options, not in the class options, see
1128 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1129 size_t japan = language_options.str().find("japanese");
1130 if (lyxrc.language_global_options && !language_options.str().empty()
1131 && viet == string::npos && japan == string::npos
1132 && latvian == string::npos && lithu == string::npos
1133 && mongo == string::npos)
1134 clsoptions << language_options.str() << ',';
1137 // the predefined options from the layout
1138 if (use_default_options && !tclass.options().empty())
1139 clsoptions << tclass.options() << ',';
1141 // the user-defined options
1142 if (!options.empty()) {
1143 clsoptions << options << ',';
1146 string strOptions(clsoptions.str());
1147 if (!strOptions.empty()) {
1148 strOptions = rtrim(strOptions, ",");
1150 os << '[' << from_utf8(strOptions) << ']';
1153 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1155 // end of \documentclass defs
1158 os << "\\usepackage{fontspec}\n";
1162 // font selection must be done before loading fontenc.sty
1163 string const fonts =
1164 loadFonts(fontsRoman, fontsSans,
1165 fontsTypewriter, fontsSC, fontsOSF,
1166 fontsSansScale, fontsTypewriterScale, useXetex);
1167 if (!fonts.empty()) {
1168 os << from_ascii(fonts);
1171 if (fontsDefaultFamily != "default")
1172 os << "\\renewcommand{\\familydefault}{\\"
1173 << from_ascii(fontsDefaultFamily) << "}\n";
1175 // set font encoding
1176 // this one is not per buffer
1177 // for arabic_arabi and farsi we also need to load the LAE and
1179 // XeteX works without fontenc
1180 if (lyxrc.fontenc != "default" && language->lang() != "japanese"
1182 if (language->lang() == "arabic_arabi"
1183 || language->lang() == "farsi") {
1184 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1185 << ",LFE,LAE]{fontenc}\n";
1188 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1194 // handle inputenc etc.
1195 writeEncodingPreamble(os, features, texrow);
1197 if (!listings_params.empty() || features.isRequired("listings")) {
1198 os << "\\usepackage{listings}\n";
1201 if (!listings_params.empty()) {
1203 // do not test validity because listings_params is
1204 // supposed to be valid
1206 InsetListingsParams(listings_params).separatedParams(true);
1207 // we can't support all packages, but we should load the color package
1208 if (par.find("\\color", 0) != string::npos)
1209 features.require("color");
1210 os << from_utf8(par);
1211 // count the number of newlines
1212 for (size_t i = 0; i < par.size(); ++i)
1218 if (!tclass.provides("geometry")
1219 && (use_geometry || nonstandard_papersize)) {
1220 odocstringstream ods;
1221 if (!getGraphicsDriver("geometry").empty())
1222 ods << getGraphicsDriver("geometry");
1223 if (orientation == ORIENTATION_LANDSCAPE)
1224 ods << ",landscape";
1225 switch (papersize) {
1227 if (!paperwidth.empty())
1228 ods << ",paperwidth="
1229 << from_ascii(paperwidth);
1230 if (!paperheight.empty())
1231 ods << ",paperheight="
1232 << from_ascii(paperheight);
1234 case PAPER_USLETTER:
1235 ods << ",letterpaper";
1238 ods << ",legalpaper";
1240 case PAPER_USEXECUTIVE:
1241 ods << ",executivepaper";
1262 // default papersize ie PAPER_DEFAULT
1263 switch (lyxrc.default_papersize) {
1264 case PAPER_DEFAULT: // keep compiler happy
1265 case PAPER_USLETTER:
1266 ods << ",letterpaper";
1269 ods << ",legalpaper";
1271 case PAPER_USEXECUTIVE:
1272 ods << ",executivepaper";
1292 docstring const g_options = trim(ods.str(), ",");
1293 os << "\\usepackage";
1294 if (!g_options.empty())
1295 os << '[' << g_options << ']';
1296 os << "{geometry}\n";
1298 os << "\\geometry{verbose";
1299 if (!topmargin.empty())
1300 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1301 if (!bottommargin.empty())
1302 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1303 if (!leftmargin.empty())
1304 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1305 if (!rightmargin.empty())
1306 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1307 if (!headheight.empty())
1308 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1309 if (!headsep.empty())
1310 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1311 if (!footskip.empty())
1312 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1313 if (!columnsep.empty())
1314 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1317 } else if (orientation == ORIENTATION_LANDSCAPE) {
1318 features.require("papersize");
1321 if (tokenPos(tclass.opt_pagestyle(),
1322 '|', pagestyle) >= 0) {
1323 if (pagestyle == "fancy") {
1324 os << "\\usepackage{fancyhdr}\n";
1327 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1331 // only output when the background color is not white
1332 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1333 // only require color here, the background color will be defined
1334 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1336 features.require("color");
1337 features.require("pagecolor");
1340 // Only if class has a ToC hierarchy
1341 if (tclass.hasTocLevels()) {
1342 if (secnumdepth != tclass.secnumdepth()) {
1343 os << "\\setcounter{secnumdepth}{"
1348 if (tocdepth != tclass.tocdepth()) {
1349 os << "\\setcounter{tocdepth}{"
1356 if (paragraph_separation) {
1357 switch (getDefSkip().kind()) {
1358 case VSpace::SMALLSKIP:
1359 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1361 case VSpace::MEDSKIP:
1362 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1364 case VSpace::BIGSKIP:
1365 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1367 case VSpace::LENGTH:
1368 os << "\\setlength{\\parskip}{"
1369 << from_utf8(getDefSkip().length().asLatexString())
1372 default: // should never happen // Then delete it.
1373 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1378 os << "\\setlength{\\parindent}{0pt}\n";
1382 // Now insert the LyX specific LaTeX commands...
1383 docstring lyxpreamble;
1385 // due to interferences with babel and hyperref, the color package has to
1386 // be loaded (when it is not already loaded) before babel when hyperref
1387 // is used with the colorlinks option, see
1388 // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1389 // we decided therefore to load color always before babel, see
1390 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1391 lyxpreamble += from_ascii(features.getColorOptions());
1393 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1395 && (features.isRequired("jurabib")
1396 || features.isRequired("hyperref")
1397 || features.isRequired("vietnamese")
1398 || features.isRequired("japanese") ) ) {
1400 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1401 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1404 // The optional packages;
1405 lyxpreamble += from_ascii(features.getPackages());
1407 // Additional Indices
1408 if (features.isRequired("splitidx")) {
1409 IndicesList::const_iterator iit = indiceslist().begin();
1410 IndicesList::const_iterator iend = indiceslist().end();
1411 for (; iit != iend; ++iit) {
1412 lyxpreamble += "\\newindex[";
1413 lyxpreamble += iit->index();
1414 lyxpreamble += "]{";
1415 lyxpreamble += iit->shortcut();
1416 lyxpreamble += "}\n";
1421 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1424 // * Hyperref manual: "Make sure it comes last of your loaded
1425 // packages, to give it a fighting chance of not being over-written,
1426 // since its job is to redefine many LaTeX commands."
1427 // * Email from Heiko Oberdiek: "It is usually better to load babel
1428 // before hyperref. Then hyperref has a chance to detect babel.
1429 // * Has to be loaded before the "LyX specific LaTeX commands" to
1430 // avoid errors with algorithm floats.
1431 // use hyperref explicitely when it is required
1432 if (features.isRequired("hyperref")) {
1433 odocstringstream oss;
1434 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1435 lyxpreamble += oss.str();
1438 // Will be surrounded by \makeatletter and \makeatother when needed
1439 docstring atlyxpreamble;
1441 // Some macros LyX will need
1442 docstring tmppreamble(from_ascii(features.getMacros()));
1444 if (!tmppreamble.empty())
1445 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1446 "LyX specific LaTeX commands.\n"
1447 + tmppreamble + '\n';
1449 // the text class specific preamble
1450 tmppreamble = features.getTClassPreamble();
1451 if (!tmppreamble.empty())
1452 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1453 "Textclass specific LaTeX commands.\n"
1454 + tmppreamble + '\n';
1456 /* the user-defined preamble */
1457 if (!preamble.empty())
1459 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1460 "User specified LaTeX commands.\n"
1461 + from_utf8(preamble) + '\n';
1463 // subfig loads internally the LaTeX package "caption". As
1464 // caption is a very popular package, users will load it in
1465 // the preamble. Therefore we must load subfig behind the
1466 // user-defined preamble and check if the caption package was
1467 // loaded or not. For the case that caption is loaded before
1468 // subfig, there is the subfig option "caption=false". This
1469 // option also works when a koma-script class is used and
1470 // koma's own caption commands are used instead of caption. We
1471 // use \PassOptionsToPackage here because the user could have
1472 // already loaded subfig in the preamble.
1473 if (features.isRequired("subfig")) {
1474 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1475 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1476 "\\usepackage{subfig}\n";
1479 // Itemize bullet settings need to be last in case the user
1480 // defines their own bullets that use a package included
1481 // in the user-defined preamble -- ARRae
1482 // Actually it has to be done much later than that
1483 // since some packages like frenchb make modifications
1484 // at \begin{document} time -- JMarc
1485 docstring bullets_def;
1486 for (int i = 0; i < 4; ++i) {
1487 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1488 if (bullets_def.empty())
1489 bullets_def += "\\AtBeginDocument{\n";
1490 bullets_def += " \\def\\labelitemi";
1492 // `i' is one less than the item to modify
1499 bullets_def += "ii";
1505 bullets_def += '{' +
1506 user_defined_bullet(i).getText()
1511 if (!bullets_def.empty())
1512 atlyxpreamble += bullets_def + "}\n\n";
1514 if (atlyxpreamble.find(from_ascii("@")) != docstring::npos)
1515 lyxpreamble += "\n\\makeatletter\n"
1516 + atlyxpreamble + "\\makeatother\n\n";
1518 lyxpreamble += '\n' + atlyxpreamble;
1520 // We try to load babel late, in case it interferes with other packages.
1521 // Jurabib and Hyperref have to be called after babel, though.
1522 if (use_babel && !features.isRequired("jurabib")
1523 && !features.isRequired("hyperref")
1524 && !features.isRequired("vietnamese")
1525 && !features.isRequired("japanese")) {
1527 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1528 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1531 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1532 if (!i18npreamble.empty())
1533 lyxpreamble += i18npreamble + '\n';
1536 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1537 for (int j = 0; j != nlines; ++j) {
1543 // these packages (xunicode, for that matter) need to be loaded at least
1544 // after amsmath, amssymb, esint and the other packages that provide
1547 os << "\\usepackage{xunicode}\n";
1549 os << "\\usepackage{xltxtra}\n";
1556 void BufferParams::useClassDefaults()
1558 DocumentClass const & tclass = documentClass();
1560 sides = tclass.sides();
1561 columns = tclass.columns();
1562 pagestyle = tclass.pagestyle();
1563 use_default_options = true;
1564 // Only if class has a ToC hierarchy
1565 if (tclass.hasTocLevels()) {
1566 secnumdepth = tclass.secnumdepth();
1567 tocdepth = tclass.tocdepth();
1572 bool BufferParams::hasClassDefaults() const
1574 DocumentClass const & tclass = documentClass();
1576 return sides == tclass.sides()
1577 && columns == tclass.columns()
1578 && pagestyle == tclass.pagestyle()
1579 && use_default_options
1580 && secnumdepth == tclass.secnumdepth()
1581 && tocdepth == tclass.tocdepth();
1585 DocumentClass const & BufferParams::documentClass() const
1591 DocumentClass const * BufferParams::documentClassPtr() const {
1596 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1597 // evil, but this function is evil
1598 doc_class_ = const_cast<DocumentClass *>(tc);
1602 bool BufferParams::setBaseClass(string const & classname)
1604 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1605 LayoutFileList & bcl = LayoutFileList::get();
1606 if (!bcl.haveClass(classname)) {
1608 bformat(_("The document class %1$s could not be found. "
1609 "A default textclass with default layouts will be used. "
1610 "LyX might not be able to produce output unless a correct "
1611 "textclass is selected from the document settings dialog."),
1612 from_utf8(classname));
1613 frontend::Alert::error(_("Document class not found"), s);
1614 bcl.addEmptyClass(classname);
1617 bool const success = bcl[classname].load();
1620 bformat(_("The document class %1$s could not be loaded."),
1621 from_utf8(classname));
1622 frontend::Alert::error(_("Could not load class"), s);
1626 pimpl_->baseClass_ = classname;
1627 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1632 LayoutFile const * BufferParams::baseClass() const
1634 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1635 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1641 LayoutFileIndex const & BufferParams::baseClassID() const
1643 return pimpl_->baseClass_;
1647 void BufferParams::makeDocumentClass()
1652 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1654 if (!local_layout.empty()) {
1655 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1656 docstring const msg = _("Error reading internal layout information");
1657 frontend::Alert::warning(_("Read Error"), msg);
1662 bool BufferParams::moduleCanBeAdded(string const & modName) const
1664 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1668 bool BufferParams::addLayoutModule(string const & modName)
1670 LayoutModuleList::const_iterator it = layoutModules_.begin();
1671 LayoutModuleList::const_iterator end = layoutModules_.end();
1672 for (; it != end; it++)
1675 layoutModules_.push_back(modName);
1680 Font const BufferParams::getFont() const
1682 FontInfo f = documentClass().defaultfont();
1683 if (fontsDefaultFamily == "rmdefault")
1684 f.setFamily(ROMAN_FAMILY);
1685 else if (fontsDefaultFamily == "sfdefault")
1686 f.setFamily(SANS_FAMILY);
1687 else if (fontsDefaultFamily == "ttdefault")
1688 f.setFamily(TYPEWRITER_FAMILY);
1689 return Font(f, language);
1693 void BufferParams::readPreamble(Lexer & lex)
1695 if (lex.getString() != "\\begin_preamble")
1696 lyxerr << "Error (BufferParams::readPreamble):"
1697 "consistency check failed." << endl;
1699 preamble = lex.getLongString("\\end_preamble");
1703 void BufferParams::readLocalLayout(Lexer & lex)
1705 if (lex.getString() != "\\begin_local_layout")
1706 lyxerr << "Error (BufferParams::readLocalLayout):"
1707 "consistency check failed." << endl;
1709 local_layout = lex.getLongString("\\end_local_layout");
1713 void BufferParams::readLanguage(Lexer & lex)
1715 if (!lex.next()) return;
1717 string const tmptok = lex.getString();
1719 // check if tmptok is part of tex_babel in tex-defs.h
1720 language = languages.getLanguage(tmptok);
1722 // Language tmptok was not found
1723 language = default_language;
1724 lyxerr << "Warning: Setting language `"
1725 << tmptok << "' to `" << language->lang()
1731 void BufferParams::readGraphicsDriver(Lexer & lex)
1736 string const tmptok = lex.getString();
1737 // check if tmptok is part of tex_graphics in tex_defs.h
1740 string const test = tex_graphics[n++];
1742 if (test == tmptok) {
1743 graphicsDriver = tmptok;
1748 "Warning: graphics driver `$$Token' not recognized!\n"
1749 " Setting graphics driver to `default'.\n");
1750 graphicsDriver = "default";
1757 void BufferParams::readBullets(Lexer & lex)
1762 int const index = lex.getInteger();
1764 int temp_int = lex.getInteger();
1765 user_defined_bullet(index).setFont(temp_int);
1766 temp_bullet(index).setFont(temp_int);
1768 user_defined_bullet(index).setCharacter(temp_int);
1769 temp_bullet(index).setCharacter(temp_int);
1771 user_defined_bullet(index).setSize(temp_int);
1772 temp_bullet(index).setSize(temp_int);
1776 void BufferParams::readBulletsLaTeX(Lexer & lex)
1778 // The bullet class should be able to read this.
1781 int const index = lex.getInteger();
1783 docstring const temp_str = lex.getDocString();
1785 user_defined_bullet(index).setText(temp_str);
1786 temp_bullet(index).setText(temp_str);
1790 void BufferParams::readModules(Lexer & lex)
1792 if (!lex.eatLine()) {
1793 lyxerr << "Error (BufferParams::readModules):"
1794 "Unexpected end of input." << endl;
1798 string mod = lex.getString();
1799 if (mod == "\\end_modules")
1801 addLayoutModule(mod);
1807 void BufferParams::readRemovedModules(Lexer & lex)
1809 if (!lex.eatLine()) {
1810 lyxerr << "Error (BufferParams::readRemovedModules):"
1811 "Unexpected end of input." << endl;
1815 string mod = lex.getString();
1816 if (mod == "\\end_removed_modules")
1818 removedModules_.push_back(mod);
1821 // now we want to remove any removed modules that were previously
1822 // added. normally, that will be because default modules were added in
1823 // setBaseClass(), which gets called when \textclass is read at the
1824 // start of the read.
1825 list<string>::const_iterator rit = removedModules_.begin();
1826 list<string>::const_iterator const ren = removedModules_.end();
1827 for (; rit != ren; rit++) {
1828 LayoutModuleList::iterator const mit = layoutModules_.begin();
1829 LayoutModuleList::iterator const men = layoutModules_.end();
1830 LayoutModuleList::iterator found = find(mit, men, *rit);
1833 layoutModules_.erase(found);
1838 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1840 char real_papersize = papersize;
1841 if (real_papersize == PAPER_DEFAULT)
1842 real_papersize = lyxrc.default_papersize;
1844 switch (real_papersize) {
1846 // could be anything, so don't guess
1848 case PAPER_CUSTOM: {
1849 if (purpose == XDVI && !paperwidth.empty() &&
1850 !paperheight.empty()) {
1851 // heightxwidth<unit>
1852 string first = paperwidth;
1853 string second = paperheight;
1854 if (orientation == ORIENTATION_LANDSCAPE)
1857 return first.erase(first.length() - 2)
1869 // dvips and dvipdfm do not know this
1870 if (purpose == DVIPS || purpose == DVIPDFM)
1874 // dvipdfm does not know this
1875 if (purpose == DVIPDFM)
1879 // dvipdfm does not know this
1880 if (purpose == DVIPDFM)
1883 case PAPER_USEXECUTIVE:
1884 // dvipdfm does not know this
1885 if (purpose == DVIPDFM)
1890 case PAPER_USLETTER:
1892 if (purpose == XDVI)
1899 string const BufferParams::dvips_options() const
1904 && papersize == PAPER_CUSTOM
1905 && !lyxrc.print_paper_dimension_flag.empty()
1906 && !paperwidth.empty()
1907 && !paperheight.empty()) {
1908 // using a custom papersize
1909 result = lyxrc.print_paper_dimension_flag;
1910 result += ' ' + paperwidth;
1911 result += ',' + paperheight;
1913 string const paper_option = paperSizeName(DVIPS);
1914 if (!paper_option.empty() && (paper_option != "letter" ||
1915 orientation != ORIENTATION_LANDSCAPE)) {
1916 // dvips won't accept -t letter -t landscape.
1917 // In all other cases, include the paper size
1919 result = lyxrc.print_paper_flag;
1920 result += ' ' + paper_option;
1923 if (orientation == ORIENTATION_LANDSCAPE &&
1924 papersize != PAPER_CUSTOM)
1925 result += ' ' + lyxrc.print_landscape_flag;
1930 string BufferParams::babelCall(string const & lang_opts) const
1932 string lang_pack = lyxrc.language_package;
1933 if (lang_pack != "\\usepackage{babel}")
1935 // suppress the babel call when there is no babel language defined
1936 // for the document language in the lib/languages file and if no
1937 // other languages are used (lang_opts is then empty)
1938 if (lang_opts.empty())
1940 // If Vietnamese is used, babel must directly be loaded with the
1941 // language options, see
1942 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1943 size_t viet = lang_opts.find("vietnam");
1944 // viet = string::npos when not found
1945 // the same is for all other languages that are not directly supported by
1946 // babel, but where LaTeX-packages add babel support.
1947 // this is currently the case for Latvian, Lithuanian, and Mongolian
1948 size_t latvian = lang_opts.find("latvian");
1949 size_t lithu = lang_opts.find("lithuanian");
1950 size_t mongo = lang_opts.find("mongolian");
1951 // If Japanese is used, babel must directly be loaded with the
1952 // language options, see
1953 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1954 size_t japan = lang_opts.find("japanese");
1955 if (!lyxrc.language_global_options || viet != string::npos
1956 || japan != string::npos || latvian != string::npos
1957 || lithu != string::npos || mongo != string::npos)
1958 return "\\usepackage[" + lang_opts + "]{babel}";
1963 docstring BufferParams::getGraphicsDriver(string const & package) const
1967 if (package == "geometry") {
1968 if (graphicsDriver == "dvips"
1969 || graphicsDriver == "dvipdfm"
1970 || graphicsDriver == "pdftex"
1971 || graphicsDriver == "vtex")
1972 result = from_ascii(graphicsDriver);
1973 else if (graphicsDriver == "dvipdfmx")
1974 result = from_ascii("dvipdfm");
1981 void BufferParams::writeEncodingPreamble(odocstream & os,
1982 LaTeXFeatures & features, TexRow & texrow) const
1986 if (inputenc == "auto") {
1987 string const doc_encoding =
1988 language->encoding()->latexName();
1989 Encoding::Package const package =
1990 language->encoding()->package();
1992 // Create a list with all the input encodings used
1994 set<string> encodings =
1995 features.getEncodingSet(doc_encoding);
1997 // If the "japanese" package (i.e. pLaTeX) is used,
1998 // inputenc must be omitted.
1999 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2000 if (package == Encoding::japanese)
2001 features.require("japanese");
2003 if ((!encodings.empty() || package == Encoding::inputenc)
2004 && !features.isRequired("japanese")) {
2005 os << "\\usepackage[";
2006 set<string>::const_iterator it = encodings.begin();
2007 set<string>::const_iterator const end = encodings.end();
2009 os << from_ascii(*it);
2012 for (; it != end; ++it)
2013 os << ',' << from_ascii(*it);
2014 if (package == Encoding::inputenc) {
2015 if (!encodings.empty())
2017 os << from_ascii(doc_encoding);
2019 os << "]{inputenc}\n";
2022 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2023 if (language->encoding()->name() == "utf8-cjk"
2024 && LaTeXFeatures::isAvailable("CJKutf8"))
2025 os << "\\usepackage{CJKutf8}\n";
2027 os << "\\usepackage{CJK}\n";
2030 } else if (inputenc != "default") {
2031 switch (encoding().package()) {
2032 case Encoding::none:
2033 case Encoding::japanese:
2035 case Encoding::inputenc:
2036 // do not load inputenc if japanese is used
2037 if (features.isRequired("japanese"))
2039 os << "\\usepackage[" << from_ascii(inputenc)
2044 if (encoding().name() == "utf8-cjk"
2045 && LaTeXFeatures::isAvailable("CJKutf8"))
2046 os << "\\usepackage{CJKutf8}\n";
2048 os << "\\usepackage{CJK}\n";
2054 // The encoding "armscii8" (for Armenian) is only available when
2055 // the package "armtex" is loaded.
2056 if (language->encoding()->latexName() == "armscii8"
2057 || inputenc == "armscii8") {
2058 os << "\\usepackage{armtex}\n";
2064 string const BufferParams::parseFontName(string const & name) const
2066 string mangled = name;
2067 size_t const idx = mangled.find('[');
2068 if (idx == string::npos || idx == 0)
2071 return mangled.substr(0, idx - 1);
2075 string const BufferParams::loadFonts(string const & rm,
2076 string const & sf, string const & tt,
2077 bool const & sc, bool const & osf,
2078 int const & sfscale, int const & ttscale,
2079 bool const & xetex) const
2081 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2082 several packages have been replaced by others, that might not
2083 be installed on every system. We have to take care for that
2084 (see psnfss.pdf). We try to support all psnfss fonts as well
2085 as the fonts that have become de facto standard in the LaTeX
2086 world (e.g. Latin Modern). We do not support obsolete fonts
2087 (like PSLatex). In general, it should be possible to mix any
2088 rm font with any sf or tt font, respectively. (JSpitzm)
2090 -- separate math fonts.
2093 if (rm == "default" && sf == "default" && tt == "default")
2100 if (rm != "default")
2101 os << "\\setmainfont[Mapping=tex-text]{"
2102 << parseFontName(rm) << "}\n";
2103 if (sf != "default") {
2104 string const sans = parseFontName(sf);
2106 os << "\\setsansfont[Scale="
2107 << float(sfscale) / 100
2108 << ",Mapping=tex-text]{"
2111 os << "\\setsansfont[Mapping=tex-text]{"
2114 if (tt != "default") {
2115 string const mono = parseFontName(tt);
2117 os << "\\setmonofont[Scale="
2118 << float(sfscale) / 100
2122 os << "\\setmonofont[Mapping=tex-text]{"
2126 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2131 // Computer Modern (must be explicitely selectable -- there might be classes
2132 // that define a different default font!
2134 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2135 // osf for Computer Modern needs eco.sty
2137 os << "\\usepackage{eco}\n";
2139 // Latin Modern Roman
2140 else if (rm == "lmodern")
2141 os << "\\usepackage{lmodern}\n";
2143 else if (rm == "ae") {
2144 // not needed when using OT1 font encoding.
2145 if (lyxrc.fontenc != "default")
2146 os << "\\usepackage{ae,aecompl}\n";
2149 else if (rm == "times") {
2150 // try to load the best available package
2151 if (LaTeXFeatures::isAvailable("mathptmx"))
2152 os << "\\usepackage{mathptmx}\n";
2153 else if (LaTeXFeatures::isAvailable("mathptm"))
2154 os << "\\usepackage{mathptm}\n";
2156 os << "\\usepackage{times}\n";
2159 else if (rm == "palatino") {
2160 // try to load the best available package
2161 if (LaTeXFeatures::isAvailable("mathpazo")) {
2162 os << "\\usepackage";
2168 // "osf" includes "sc"!
2172 os << "{mathpazo}\n";
2174 else if (LaTeXFeatures::isAvailable("mathpple"))
2175 os << "\\usepackage{mathpple}\n";
2177 os << "\\usepackage{palatino}\n";
2180 else if (rm == "utopia") {
2181 // fourier supersedes utopia.sty, but does
2182 // not work with OT1 encoding.
2183 if (LaTeXFeatures::isAvailable("fourier")
2184 && lyxrc.fontenc != "default") {
2185 os << "\\usepackage";
2196 os << "{fourier}\n";
2199 os << "\\usepackage{utopia}\n";
2201 // Bera (complete fontset)
2202 else if (rm == "bera" && sf == "default" && tt == "default")
2203 os << "\\usepackage{bera}\n";
2205 else if (rm != "default")
2206 os << "\\usepackage" << "{" << rm << "}\n";
2209 // Helvetica, Bera Sans
2210 if (sf == "helvet" || sf == "berasans") {
2212 os << "\\usepackage[scaled=" << float(sfscale) / 100
2213 << "]{" << sf << "}\n";
2215 os << "\\usepackage{" << sf << "}\n";
2218 else if (sf == "avant")
2219 os << "\\usepackage{" << sf << "}\n";
2220 // Computer Modern, Latin Modern, CM Bright
2221 else if (sf != "default")
2222 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2224 // monospaced/typewriter
2225 // Courier, LuxiMono
2226 if (tt == "luximono" || tt == "beramono") {
2228 os << "\\usepackage[scaled=" << float(ttscale) / 100
2229 << "]{" << tt << "}\n";
2231 os << "\\usepackage{" << tt << "}\n";
2234 else if (tt == "courier" )
2235 os << "\\usepackage{" << tt << "}\n";
2236 // Computer Modern, Latin Modern, CM Bright
2237 else if (tt != "default")
2238 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2244 Encoding const & BufferParams::encoding() const
2247 return *(encodings.fromLaTeXName("utf8-plain"));
2248 if (inputenc == "auto" || inputenc == "default")
2249 return *language->encoding();
2250 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2253 LYXERR0("Unknown inputenc value `" << inputenc
2254 << "'. Using `auto' instead.");
2255 return *language->encoding();
2259 CiteEngine BufferParams::citeEngine() const
2261 // FIXME the class should provide the numerical/
2262 // authoryear choice
2263 if (documentClass().provides("natbib")
2264 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2265 return ENGINE_NATBIB_AUTHORYEAR;
2266 return cite_engine_;
2270 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2272 cite_engine_ = cite_engine;