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";
358 bibtex_command = "default";
359 index_command = "default";
362 listings_params = string();
363 pagestyle = "default";
364 // white is equal to no background color
365 backgroundcolor = lyx::rgbFromHexName("#ffffff");
367 for (int iter = 0; iter < 4; ++iter) {
368 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
369 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
372 indiceslist().addDefault(B_("Index"));
376 docstring BufferParams::B_(string const & l10n) const
378 LASSERT(language, /**/);
379 return getMessages(language->code()).get(l10n);
383 AuthorList & BufferParams::authors()
385 return pimpl_->authorlist;
389 AuthorList const & BufferParams::authors() const
391 return pimpl_->authorlist;
395 BranchList & BufferParams::branchlist()
397 return pimpl_->branchlist;
401 BranchList const & BufferParams::branchlist() const
403 return pimpl_->branchlist;
407 IndicesList & BufferParams::indiceslist()
409 return pimpl_->indiceslist;
413 IndicesList const & BufferParams::indiceslist() const
415 return pimpl_->indiceslist;
419 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
421 LASSERT(index < 4, /**/);
422 return pimpl_->temp_bullets[index];
426 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
428 LASSERT(index < 4, /**/);
429 return pimpl_->temp_bullets[index];
433 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
435 LASSERT(index < 4, /**/);
436 return pimpl_->user_defined_bullets[index];
440 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
442 LASSERT(index < 4, /**/);
443 return pimpl_->user_defined_bullets[index];
447 Spacing & BufferParams::spacing()
449 return pimpl_->spacing;
453 Spacing const & BufferParams::spacing() const
455 return pimpl_->spacing;
459 PDFOptions & BufferParams::pdfoptions()
461 return pimpl_->pdfoptions;
465 PDFOptions const & BufferParams::pdfoptions() const
467 return pimpl_->pdfoptions;
471 VSpace const & BufferParams::getDefSkip() const
473 return pimpl_->defskip;
477 void BufferParams::setDefSkip(VSpace const & vs)
479 pimpl_->defskip = vs;
483 string BufferParams::readToken(Lexer & lex, string const & token,
484 FileName const & filepath)
486 if (token == "\\textclass") {
488 string const classname = lex.getString();
489 // if there exists a local layout file, ignore the system one
490 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
492 LayoutFileList & bcl = LayoutFileList::get();
493 if (tcp.empty() && !filepath.empty())
494 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
498 setBaseClass(classname);
499 // We assume that a tex class exists for local or unknown layouts so this warning
500 // will only be given for system layouts.
501 if (!baseClass()->isTeXClassAvailable()) {
502 docstring const msg =
503 bformat(_("The layout file requested by this document,\n"
505 "is not usable. This is probably because a LaTeX\n"
506 "class or style file required by it is not\n"
507 "available. See the Customization documentation\n"
508 "for more information.\n"), from_utf8(classname));
509 frontend::Alert::warning(_("Document class not available"),
510 msg + _("LyX will not be able to produce output."));
512 } else if (token == "\\begin_preamble") {
514 } else if (token == "\\begin_local_layout") {
515 readLocalLayout(lex);
516 } else if (token == "\\begin_modules") {
518 } else if (token == "\\begin_removed_modules") {
519 readRemovedModules(lex);
520 } else if (token == "\\options") {
522 options = lex.getString();
523 } else if (token == "\\use_default_options") {
524 lex >> use_default_options;
525 } else if (token == "\\master") {
527 master = lex.getString();
528 } else if (token == "\\language") {
530 } else if (token == "\\inputencoding") {
532 } else if (token == "\\graphics") {
533 readGraphicsDriver(lex);
534 } else if (token == "\\default_output_format") {
535 lex >> defaultOutputFormat;
536 } else if (token == "\\bibtex_command") {
538 bibtex_command = lex.getString();
539 } else if (token == "\\index_command") {
541 index_command = lex.getString();
542 } else if (token == "\\font_roman") {
544 fontsRoman = lex.getString();
545 } else if (token == "\\font_sans") {
547 fontsSans = lex.getString();
548 } else if (token == "\\font_typewriter") {
550 fontsTypewriter = lex.getString();
551 } else if (token == "\\font_default_family") {
552 lex >> fontsDefaultFamily;
553 } else if (token == "\\use_xetex") {
555 } else if (token == "\\font_sc") {
557 } else if (token == "\\font_osf") {
559 } else if (token == "\\font_sf_scale") {
560 lex >> fontsSansScale;
561 } else if (token == "\\font_tt_scale") {
562 lex >> fontsTypewriterScale;
563 } else if (token == "\\font_cjk") {
565 } else if (token == "\\paragraph_separation") {
568 paragraph_separation = parseptranslator().find(parsep);
569 } else if (token == "\\defskip") {
571 string defskip = lex.getString();
572 if (defskip == "defskip")
575 pimpl_->defskip = VSpace(defskip);
576 } else if (token == "\\quotes_language") {
579 quotes_language = quoteslangtranslator().find(quotes_lang);
580 } else if (token == "\\papersize") {
583 papersize = papersizetranslator().find(ppsize);
584 } else if (token == "\\use_geometry") {
586 } else if (token == "\\use_amsmath") {
589 use_amsmath = packagetranslator().find(use_ams);
590 } else if (token == "\\use_esint") {
593 use_esint = packagetranslator().find(useesint);
594 } else if (token == "\\cite_engine") {
597 cite_engine_ = citeenginetranslator().find(engine);
598 } else if (token == "\\use_bibtopic") {
600 } else if (token == "\\use_indices") {
602 } else if (token == "\\tracking_changes") {
604 } else if (token == "\\output_changes") {
605 lex >> outputChanges;
606 } else if (token == "\\branch") {
608 docstring branch = lex.getDocString();
609 branchlist().add(branch);
612 string const tok = lex.getString();
613 if (tok == "\\end_branch")
615 Branch * branch_ptr = branchlist().find(branch);
616 if (tok == "\\selected") {
619 branch_ptr->setSelected(lex.getInteger());
621 // not yet operational
622 if (tok == "\\color") {
624 string color = lex.getString();
626 branch_ptr->setColor(color);
627 // Update also the Color table:
629 color = lcolor.getX11Name(Color_background);
631 lcolor.setColor(to_utf8(branch), color);
634 } else if (token == "\\index") {
636 docstring index = lex.getDocString();
637 indiceslist().add(index);
640 string const tok = lex.getString();
641 if (tok == "\\end_index")
643 Index * index_ptr = indiceslist().find(index);
644 if (tok == "\\shortcut") {
647 index_ptr->setShortcut(lex.getDocString());
649 // not yet operational
650 if (tok == "\\color") {
652 string color = lex.getString();
654 index_ptr->setColor(color);
655 // Update also the Color table:
657 color = lcolor.getX11Name(Color_background);
659 lcolor.setColor(to_utf8(index), color);
662 } else if (token == "\\author") {
664 istringstream ss(lex.getString());
667 author_map.push_back(pimpl_->authorlist.record(a));
668 } else if (token == "\\paperorientation") {
671 orientation = paperorientationtranslator().find(orient);
672 } else if (token == "\\backgroundcolor") {
674 backgroundcolor = lyx::rgbFromHexName(lex.getString());
675 } else if (token == "\\paperwidth") {
677 } else if (token == "\\paperheight") {
679 } else if (token == "\\leftmargin") {
681 } else if (token == "\\topmargin") {
683 } else if (token == "\\rightmargin") {
685 } else if (token == "\\bottommargin") {
687 } else if (token == "\\headheight") {
689 } else if (token == "\\headsep") {
691 } else if (token == "\\footskip") {
693 } else if (token == "\\columnsep") {
695 } else if (token == "\\paperfontsize") {
697 } else if (token == "\\papercolumns") {
699 } else if (token == "\\listings_params") {
702 listings_params = InsetListingsParams(par).params();
703 } else if (token == "\\papersides") {
706 sides = sidestranslator().find(psides);
707 } else if (token == "\\paperpagestyle") {
709 } else if (token == "\\bullet") {
711 } else if (token == "\\bulletLaTeX") {
712 readBulletsLaTeX(lex);
713 } else if (token == "\\secnumdepth") {
715 } else if (token == "\\tocdepth") {
717 } else if (token == "\\spacing") {
721 if (nspacing == "other") {
724 spacing().set(spacetranslator().find(nspacing), tmp_val);
725 } else if (token == "\\float_placement") {
726 lex >> float_placement;
728 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
729 string toktmp = pdfoptions().readToken(lex, token);
730 if (!toktmp.empty()) {
731 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
736 lyxerr << "BufferParams::readToken(): Unknown token: " <<
745 void BufferParams::writeFile(ostream & os) const
747 // The top of the file is written by the buffer.
748 // Prints out the buffer info into the .lyx file given by file
751 os << "\\textclass " << baseClass()->name() << '\n';
754 if (!preamble.empty()) {
755 // remove '\n' from the end of preamble
756 string const tmppreamble = rtrim(preamble, "\n");
757 os << "\\begin_preamble\n"
759 << "\n\\end_preamble\n";
763 if (!options.empty()) {
764 os << "\\options " << options << '\n';
767 // use the class options defined in the layout?
768 os << "\\use_default_options "
769 << convert<string>(use_default_options) << "\n";
771 // the master document
772 if (!master.empty()) {
773 os << "\\master " << master << '\n';
777 if (!removedModules_.empty()) {
778 os << "\\begin_removed_modules" << '\n';
779 list<string>::const_iterator it = removedModules_.begin();
780 list<string>::const_iterator en = removedModules_.end();
781 for (; it != en; it++)
783 os << "\\end_removed_modules" << '\n';
787 if (!layoutModules_.empty()) {
788 os << "\\begin_modules" << '\n';
789 LayoutModuleList::const_iterator it = layoutModules_.begin();
790 LayoutModuleList::const_iterator en = layoutModules_.end();
791 for (; it != en; it++)
793 os << "\\end_modules" << '\n';
796 // local layout information
797 if (!local_layout.empty()) {
798 // remove '\n' from the end
799 string const tmplocal = rtrim(local_layout, "\n");
800 os << "\\begin_local_layout\n"
802 << "\n\\end_local_layout\n";
805 // then the text parameters
806 if (language != ignore_language)
807 os << "\\language " << language->lang() << '\n';
808 os << "\\inputencoding " << inputenc
809 << "\n\\font_roman " << fontsRoman
810 << "\n\\font_sans " << fontsSans
811 << "\n\\font_typewriter " << fontsTypewriter
812 << "\n\\font_default_family " << fontsDefaultFamily
813 << "\n\\use_xetex " << convert<string>(useXetex)
814 << "\n\\font_sc " << convert<string>(fontsSC)
815 << "\n\\font_osf " << convert<string>(fontsOSF)
816 << "\n\\font_sf_scale " << fontsSansScale
817 << "\n\\font_tt_scale " << fontsTypewriterScale
819 if (!fontsCJK.empty()) {
820 os << "\\font_cjk " << fontsCJK << '\n';
822 os << "\n\\graphics " << graphicsDriver << '\n';
823 os << "\\default_output_format " << defaultOutputFormat << '\n';
824 os << "\\bibtex_command " << bibtex_command << '\n';
825 os << "\\index_command " << index_command << '\n';
827 if (!float_placement.empty()) {
828 os << "\\float_placement " << float_placement << '\n';
830 os << "\\paperfontsize " << fontsize << '\n';
832 spacing().writeFile(os);
833 pdfoptions().writeFile(os);
835 os << "\\papersize " << string_papersize[papersize]
836 << "\n\\use_geometry " << convert<string>(use_geometry)
837 << "\n\\use_amsmath " << use_amsmath
838 << "\n\\use_esint " << use_esint
839 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
840 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
841 << "\n\\use_indices " << convert<string>(use_indices)
842 << "\n\\paperorientation " << string_orientation[orientation]
844 if (backgroundcolor != lyx::rgbFromHexName("#ffffff"))
845 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
847 BranchList::const_iterator it = branchlist().begin();
848 BranchList::const_iterator end = branchlist().end();
849 for (; it != end; ++it) {
850 os << "\\branch " << to_utf8(it->branch())
851 << "\n\\selected " << it->isSelected()
852 << "\n\\color " << lyx::X11hexname(it->color())
857 IndicesList::const_iterator iit = indiceslist().begin();
858 IndicesList::const_iterator iend = indiceslist().end();
859 for (; iit != iend; ++iit) {
860 os << "\\index " << to_utf8(iit->index())
861 << "\n\\shortcut " << to_utf8(iit->shortcut())
862 << "\n\\color " << lyx::X11hexname(iit->color())
867 if (!paperwidth.empty())
868 os << "\\paperwidth "
869 << VSpace(paperwidth).asLyXCommand() << '\n';
870 if (!paperheight.empty())
871 os << "\\paperheight "
872 << VSpace(paperheight).asLyXCommand() << '\n';
873 if (!leftmargin.empty())
874 os << "\\leftmargin "
875 << VSpace(leftmargin).asLyXCommand() << '\n';
876 if (!topmargin.empty())
878 << VSpace(topmargin).asLyXCommand() << '\n';
879 if (!rightmargin.empty())
880 os << "\\rightmargin "
881 << VSpace(rightmargin).asLyXCommand() << '\n';
882 if (!bottommargin.empty())
883 os << "\\bottommargin "
884 << VSpace(bottommargin).asLyXCommand() << '\n';
885 if (!headheight.empty())
886 os << "\\headheight "
887 << VSpace(headheight).asLyXCommand() << '\n';
888 if (!headsep.empty())
890 << VSpace(headsep).asLyXCommand() << '\n';
891 if (!footskip.empty())
893 << VSpace(footskip).asLyXCommand() << '\n';
894 if (!columnsep.empty())
896 << VSpace(columnsep).asLyXCommand() << '\n';
897 os << "\\secnumdepth " << secnumdepth
898 << "\n\\tocdepth " << tocdepth
899 << "\n\\paragraph_separation "
900 << string_paragraph_separation[paragraph_separation]
901 << "\n\\defskip " << getDefSkip().asLyXCommand()
902 << "\n\\quotes_language "
903 << string_quotes_language[quotes_language]
904 << "\n\\papercolumns " << columns
905 << "\n\\papersides " << sides
906 << "\n\\paperpagestyle " << pagestyle << '\n';
907 if (!listings_params.empty())
908 os << "\\listings_params \"" <<
909 InsetListingsParams(listings_params).encodedString() << "\"\n";
910 for (int i = 0; i < 4; ++i) {
911 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
912 if (user_defined_bullet(i).getFont() != -1) {
913 os << "\\bullet " << i << " "
914 << user_defined_bullet(i).getFont() << " "
915 << user_defined_bullet(i).getCharacter() << " "
916 << user_defined_bullet(i).getSize() << "\n";
920 os << "\\bulletLaTeX " << i << " \""
921 << lyx::to_ascii(user_defined_bullet(i).getText())
927 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
928 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
930 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
931 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
932 for (; a_it != a_end; ++a_it) {
933 if (a_it->second.used())
934 os << "\\author " << a_it->second << "\n";
936 os << "\\author " << Author() << "\n";
941 void BufferParams::validate(LaTeXFeatures & features) const
943 features.require(documentClass().requires());
946 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
947 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
948 LaTeXFeatures::isAvailable("xcolor");
950 switch (features.runparams().flavor) {
951 case OutputParams::LATEX:
953 features.require("ct-dvipost");
954 features.require("dvipost");
955 } else if (xcolorulem) {
956 features.require("ct-xcolor-ulem");
957 features.require("ulem");
958 features.require("xcolor");
960 features.require("ct-none");
963 case OutputParams::PDFLATEX:
964 case OutputParams::XETEX:
966 features.require("ct-xcolor-ulem");
967 features.require("ulem");
968 features.require("xcolor");
969 // improves color handling in PDF output
970 features.require("pdfcolmk");
972 features.require("ct-none");
980 // Floats with 'Here definitely' as default setting.
981 if (float_placement.find('H') != string::npos)
982 features.require("float");
984 // AMS Style is at document level
985 if (use_amsmath == package_on
986 || documentClass().provides("amsmath"))
987 features.require("amsmath");
988 if (use_esint == package_on)
989 features.require("esint");
991 // Document-level line spacing
992 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
993 features.require("setspace");
995 // the bullet shapes are buffer level not paragraph level
996 // so they are tested here
997 for (int i = 0; i < 4; ++i) {
998 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1000 int const font = user_defined_bullet(i).getFont();
1002 int const c = user_defined_bullet(i).getCharacter();
1008 features.require("latexsym");
1010 } else if (font == 1) {
1011 features.require("amssymb");
1012 } else if (font >= 2 && font <= 5) {
1013 features.require("pifont");
1017 if (pdfoptions().use_hyperref) {
1018 features.require("hyperref");
1019 // due to interferences with babel and hyperref, the color package has to
1020 // be loaded after hyperref when hyperref is used with the colorlinks
1021 // option, see http://bugzilla.lyx.org/show_bug.cgi?id=5291
1022 if (pdfoptions().colorlinks)
1023 features.require("color");
1027 features.require("xetex");
1029 if (language->lang() == "vietnamese")
1030 features.require("vietnamese");
1031 else if (language->lang() == "japanese")
1032 features.require("japanese");
1036 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1037 TexRow & texrow) const
1039 os << "\\documentclass";
1041 DocumentClass const & tclass = documentClass();
1043 ostringstream clsoptions; // the document class options.
1045 if (tokenPos(tclass.opt_fontsize(),
1046 '|', fontsize) >= 0) {
1047 // only write if existing in list (and not default)
1048 clsoptions << fontsize << "pt,";
1051 // custom, A3, B3 and B4 paper sizes need geometry
1052 bool nonstandard_papersize = papersize == PAPER_B3
1053 || papersize == PAPER_B4
1054 || papersize == PAPER_A3
1055 || papersize == PAPER_CUSTOM;
1057 if (!use_geometry) {
1058 switch (papersize) {
1060 clsoptions << "a4paper,";
1062 case PAPER_USLETTER:
1063 clsoptions << "letterpaper,";
1066 clsoptions << "a5paper,";
1069 clsoptions << "b5paper,";
1071 case PAPER_USEXECUTIVE:
1072 clsoptions << "executivepaper,";
1075 clsoptions << "legalpaper,";
1087 if (sides != tclass.sides()) {
1090 clsoptions << "oneside,";
1093 clsoptions << "twoside,";
1099 if (columns != tclass.columns()) {
1101 clsoptions << "twocolumn,";
1103 clsoptions << "onecolumn,";
1107 && orientation == ORIENTATION_LANDSCAPE)
1108 clsoptions << "landscape,";
1110 // language should be a parameter to \documentclass
1111 if (language->babel() == "hebrew"
1112 && default_language->babel() != "hebrew")
1113 // This seems necessary
1114 features.useLanguage(default_language);
1116 ostringstream language_options;
1117 bool const use_babel = features.useBabel();
1119 language_options << features.getLanguages();
1120 if (!language->babel().empty()) {
1121 if (!language_options.str().empty())
1122 language_options << ',';
1123 language_options << language->babel();
1125 // if Vietnamese is used, babel must directly be loaded
1126 // with language options, not in the class options, see
1127 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1128 size_t viet = language_options.str().find("vietnam");
1129 // viet = string::npos when not found
1130 // the same is for all other languages that are not directly supported by
1131 // babel, but where LaTeX-packages add babel support.
1132 // this is currently the case for Latvian, Lithuanian, and Mongolian
1133 size_t latvian = language_options.str().find("latvian");
1134 size_t lithu = language_options.str().find("lithuanian");
1135 size_t mongo = language_options.str().find("mongolian");
1136 // if Japanese is used, babel must directly be loaded
1137 // with language options, not in the class options, see
1138 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1139 size_t japan = language_options.str().find("japanese");
1140 if (lyxrc.language_global_options && !language_options.str().empty()
1141 && viet == string::npos && japan == string::npos
1142 && latvian == string::npos && lithu == string::npos
1143 && mongo == string::npos)
1144 clsoptions << language_options.str() << ',';
1147 // the predefined options from the layout
1148 if (use_default_options && !tclass.options().empty())
1149 clsoptions << tclass.options() << ',';
1151 // the user-defined options
1152 if (!options.empty()) {
1153 clsoptions << options << ',';
1156 string strOptions(clsoptions.str());
1157 if (!strOptions.empty()) {
1158 strOptions = rtrim(strOptions, ",");
1160 os << '[' << from_utf8(strOptions) << ']';
1163 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1165 // end of \documentclass defs
1168 os << "\\usepackage{fontspec}\n";
1172 // font selection must be done before loading fontenc.sty
1173 string const fonts =
1174 loadFonts(fontsRoman, fontsSans,
1175 fontsTypewriter, fontsSC, fontsOSF,
1176 fontsSansScale, fontsTypewriterScale, useXetex);
1177 if (!fonts.empty()) {
1178 os << from_ascii(fonts);
1181 if (fontsDefaultFamily != "default")
1182 os << "\\renewcommand{\\familydefault}{\\"
1183 << from_ascii(fontsDefaultFamily) << "}\n";
1185 // set font encoding
1186 // this one is not per buffer
1187 // for arabic_arabi and farsi we also need to load the LAE and
1189 // XeTeX works without fontenc
1190 if (lyxrc.fontenc != "default" && language->lang() != "japanese"
1192 if (language->lang() == "arabic_arabi"
1193 || language->lang() == "farsi") {
1194 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1195 << ",LFE,LAE]{fontenc}\n";
1198 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1204 // handle inputenc etc.
1205 writeEncodingPreamble(os, features, texrow);
1207 if (!listings_params.empty() || features.isRequired("listings")) {
1208 os << "\\usepackage{listings}\n";
1211 if (!listings_params.empty()) {
1213 // do not test validity because listings_params is
1214 // supposed to be valid
1216 InsetListingsParams(listings_params).separatedParams(true);
1217 // we can't support all packages, but we should load the color package
1218 if (par.find("\\color", 0) != string::npos)
1219 features.require("color");
1220 os << from_utf8(par);
1221 // count the number of newlines
1222 for (size_t i = 0; i < par.size(); ++i)
1228 if (!tclass.provides("geometry")
1229 && (use_geometry || nonstandard_papersize)) {
1230 odocstringstream ods;
1231 if (!getGraphicsDriver("geometry").empty())
1232 ods << getGraphicsDriver("geometry");
1233 if (orientation == ORIENTATION_LANDSCAPE)
1234 ods << ",landscape";
1235 switch (papersize) {
1237 if (!paperwidth.empty())
1238 ods << ",paperwidth="
1239 << from_ascii(paperwidth);
1240 if (!paperheight.empty())
1241 ods << ",paperheight="
1242 << from_ascii(paperheight);
1244 case PAPER_USLETTER:
1245 ods << ",letterpaper";
1248 ods << ",legalpaper";
1250 case PAPER_USEXECUTIVE:
1251 ods << ",executivepaper";
1272 // default papersize ie PAPER_DEFAULT
1273 switch (lyxrc.default_papersize) {
1274 case PAPER_DEFAULT: // keep compiler happy
1275 case PAPER_USLETTER:
1276 ods << ",letterpaper";
1279 ods << ",legalpaper";
1281 case PAPER_USEXECUTIVE:
1282 ods << ",executivepaper";
1302 docstring const g_options = trim(ods.str(), ",");
1303 os << "\\usepackage";
1304 if (!g_options.empty())
1305 os << '[' << g_options << ']';
1306 os << "{geometry}\n";
1308 os << "\\geometry{verbose";
1309 if (!topmargin.empty())
1310 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1311 if (!bottommargin.empty())
1312 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1313 if (!leftmargin.empty())
1314 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1315 if (!rightmargin.empty())
1316 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1317 if (!headheight.empty())
1318 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1319 if (!headsep.empty())
1320 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1321 if (!footskip.empty())
1322 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1323 if (!columnsep.empty())
1324 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1327 } else if (orientation == ORIENTATION_LANDSCAPE) {
1328 features.require("papersize");
1331 if (tokenPos(tclass.opt_pagestyle(),
1332 '|', pagestyle) >= 0) {
1333 if (pagestyle == "fancy") {
1334 os << "\\usepackage{fancyhdr}\n";
1337 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1341 // only output when the background color is not white
1342 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1343 // only require color here, the background color will be defined
1344 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1346 features.require("color");
1347 features.require("pagecolor");
1350 // Only if class has a ToC hierarchy
1351 if (tclass.hasTocLevels()) {
1352 if (secnumdepth != tclass.secnumdepth()) {
1353 os << "\\setcounter{secnumdepth}{"
1358 if (tocdepth != tclass.tocdepth()) {
1359 os << "\\setcounter{tocdepth}{"
1366 if (paragraph_separation) {
1367 switch (getDefSkip().kind()) {
1368 case VSpace::SMALLSKIP:
1369 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1371 case VSpace::MEDSKIP:
1372 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1374 case VSpace::BIGSKIP:
1375 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1377 case VSpace::LENGTH:
1378 os << "\\setlength{\\parskip}{"
1379 << from_utf8(getDefSkip().length().asLatexString())
1382 default: // should never happen // Then delete it.
1383 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1388 os << "\\setlength{\\parindent}{0pt}\n";
1392 // Now insert the LyX specific LaTeX commands...
1393 docstring lyxpreamble;
1395 // due to interferences with babel and hyperref, the color package has to
1396 // be loaded (when it is not already loaded) before babel when hyperref
1397 // is used with the colorlinks option, see
1398 // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1399 // we decided therefore to load color always before babel, see
1400 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1401 lyxpreamble += from_ascii(features.getColorOptions());
1403 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1405 && (features.isRequired("jurabib")
1406 || features.isRequired("hyperref")
1407 || features.isRequired("vietnamese")
1408 || features.isRequired("japanese") ) ) {
1410 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1411 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1414 // The optional packages;
1415 lyxpreamble += from_ascii(features.getPackages());
1417 // Additional Indices
1418 if (features.isRequired("splitidx")) {
1419 IndicesList::const_iterator iit = indiceslist().begin();
1420 IndicesList::const_iterator iend = indiceslist().end();
1421 for (; iit != iend; ++iit) {
1422 lyxpreamble += "\\newindex[";
1423 lyxpreamble += iit->index();
1424 lyxpreamble += "]{";
1425 lyxpreamble += iit->shortcut();
1426 lyxpreamble += "}\n";
1431 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1434 // * Hyperref manual: "Make sure it comes last of your loaded
1435 // packages, to give it a fighting chance of not being over-written,
1436 // since its job is to redefine many LaTeX commands."
1437 // * Email from Heiko Oberdiek: "It is usually better to load babel
1438 // before hyperref. Then hyperref has a chance to detect babel.
1439 // * Has to be loaded before the "LyX specific LaTeX commands" to
1440 // avoid errors with algorithm floats.
1441 // use hyperref explicitely when it is required
1442 if (features.isRequired("hyperref")) {
1443 odocstringstream oss;
1444 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1445 lyxpreamble += oss.str();
1448 // Will be surrounded by \makeatletter and \makeatother when needed
1449 docstring atlyxpreamble;
1451 // Some macros LyX will need
1452 docstring tmppreamble(from_ascii(features.getMacros()));
1454 if (!tmppreamble.empty())
1455 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1456 "LyX specific LaTeX commands.\n"
1457 + tmppreamble + '\n';
1459 // the text class specific preamble
1460 tmppreamble = features.getTClassPreamble();
1461 if (!tmppreamble.empty())
1462 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1463 "Textclass specific LaTeX commands.\n"
1464 + tmppreamble + '\n';
1466 /* the user-defined preamble */
1467 if (!preamble.empty())
1469 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1470 "User specified LaTeX commands.\n"
1471 + from_utf8(preamble) + '\n';
1473 // subfig loads internally the LaTeX package "caption". As
1474 // caption is a very popular package, users will load it in
1475 // the preamble. Therefore we must load subfig behind the
1476 // user-defined preamble and check if the caption package was
1477 // loaded or not. For the case that caption is loaded before
1478 // subfig, there is the subfig option "caption=false". This
1479 // option also works when a koma-script class is used and
1480 // koma's own caption commands are used instead of caption. We
1481 // use \PassOptionsToPackage here because the user could have
1482 // already loaded subfig in the preamble.
1483 if (features.isRequired("subfig")) {
1484 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1485 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1486 "\\usepackage{subfig}\n";
1489 // Itemize bullet settings need to be last in case the user
1490 // defines their own bullets that use a package included
1491 // in the user-defined preamble -- ARRae
1492 // Actually it has to be done much later than that
1493 // since some packages like frenchb make modifications
1494 // at \begin{document} time -- JMarc
1495 docstring bullets_def;
1496 for (int i = 0; i < 4; ++i) {
1497 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1498 if (bullets_def.empty())
1499 bullets_def += "\\AtBeginDocument{\n";
1500 bullets_def += " \\def\\labelitemi";
1502 // `i' is one less than the item to modify
1509 bullets_def += "ii";
1515 bullets_def += '{' +
1516 user_defined_bullet(i).getText()
1521 if (!bullets_def.empty())
1522 atlyxpreamble += bullets_def + "}\n\n";
1524 if (atlyxpreamble.find(from_ascii("@")) != docstring::npos)
1525 lyxpreamble += "\n\\makeatletter\n"
1526 + atlyxpreamble + "\\makeatother\n\n";
1528 lyxpreamble += '\n' + atlyxpreamble;
1530 // We try to load babel late, in case it interferes with other packages.
1531 // Jurabib and Hyperref have to be called after babel, though.
1532 if (use_babel && !features.isRequired("jurabib")
1533 && !features.isRequired("hyperref")
1534 && !features.isRequired("vietnamese")
1535 && !features.isRequired("japanese")) {
1537 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1538 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1541 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1542 if (!i18npreamble.empty())
1543 lyxpreamble += i18npreamble + '\n';
1546 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1547 for (int j = 0; j != nlines; ++j) {
1553 // these packages (xunicode, for that matter) need to be loaded at least
1554 // after amsmath, amssymb, esint and the other packages that provide
1557 os << "\\usepackage{xunicode}\n";
1559 os << "\\usepackage{xltxtra}\n";
1566 void BufferParams::useClassDefaults()
1568 DocumentClass const & tclass = documentClass();
1570 sides = tclass.sides();
1571 columns = tclass.columns();
1572 pagestyle = tclass.pagestyle();
1573 use_default_options = true;
1574 // Only if class has a ToC hierarchy
1575 if (tclass.hasTocLevels()) {
1576 secnumdepth = tclass.secnumdepth();
1577 tocdepth = tclass.tocdepth();
1582 bool BufferParams::hasClassDefaults() const
1584 DocumentClass const & tclass = documentClass();
1586 return sides == tclass.sides()
1587 && columns == tclass.columns()
1588 && pagestyle == tclass.pagestyle()
1589 && use_default_options
1590 && secnumdepth == tclass.secnumdepth()
1591 && tocdepth == tclass.tocdepth();
1595 DocumentClass const & BufferParams::documentClass() const
1601 DocumentClass const * BufferParams::documentClassPtr() const {
1606 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1607 // evil, but this function is evil
1608 doc_class_ = const_cast<DocumentClass *>(tc);
1612 bool BufferParams::setBaseClass(string const & classname)
1614 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1615 LayoutFileList & bcl = LayoutFileList::get();
1616 if (!bcl.haveClass(classname)) {
1618 bformat(_("The document class %1$s could not be found. "
1619 "A default textclass with default layouts will be used. "
1620 "LyX might not be able to produce output unless a correct "
1621 "textclass is selected from the document settings dialog."),
1622 from_utf8(classname));
1623 frontend::Alert::error(_("Document class not found"), s);
1624 bcl.addEmptyClass(classname);
1627 bool const success = bcl[classname].load();
1630 bformat(_("The document class %1$s could not be loaded."),
1631 from_utf8(classname));
1632 frontend::Alert::error(_("Could not load class"), s);
1636 pimpl_->baseClass_ = classname;
1637 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1642 LayoutFile const * BufferParams::baseClass() const
1644 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1645 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1651 LayoutFileIndex const & BufferParams::baseClassID() const
1653 return pimpl_->baseClass_;
1657 void BufferParams::makeDocumentClass()
1662 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1664 if (!local_layout.empty()) {
1665 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1666 docstring const msg = _("Error reading internal layout information");
1667 frontend::Alert::warning(_("Read Error"), msg);
1672 bool BufferParams::moduleCanBeAdded(string const & modName) const
1674 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1678 bool BufferParams::addLayoutModule(string const & modName)
1680 LayoutModuleList::const_iterator it = layoutModules_.begin();
1681 LayoutModuleList::const_iterator end = layoutModules_.end();
1682 for (; it != end; it++)
1685 layoutModules_.push_back(modName);
1690 Font const BufferParams::getFont() const
1692 FontInfo f = documentClass().defaultfont();
1693 if (fontsDefaultFamily == "rmdefault")
1694 f.setFamily(ROMAN_FAMILY);
1695 else if (fontsDefaultFamily == "sfdefault")
1696 f.setFamily(SANS_FAMILY);
1697 else if (fontsDefaultFamily == "ttdefault")
1698 f.setFamily(TYPEWRITER_FAMILY);
1699 return Font(f, language);
1703 void BufferParams::readPreamble(Lexer & lex)
1705 if (lex.getString() != "\\begin_preamble")
1706 lyxerr << "Error (BufferParams::readPreamble):"
1707 "consistency check failed." << endl;
1709 preamble = lex.getLongString("\\end_preamble");
1713 void BufferParams::readLocalLayout(Lexer & lex)
1715 if (lex.getString() != "\\begin_local_layout")
1716 lyxerr << "Error (BufferParams::readLocalLayout):"
1717 "consistency check failed." << endl;
1719 local_layout = lex.getLongString("\\end_local_layout");
1723 void BufferParams::readLanguage(Lexer & lex)
1725 if (!lex.next()) return;
1727 string const tmptok = lex.getString();
1729 // check if tmptok is part of tex_babel in tex-defs.h
1730 language = languages.getLanguage(tmptok);
1732 // Language tmptok was not found
1733 language = default_language;
1734 lyxerr << "Warning: Setting language `"
1735 << tmptok << "' to `" << language->lang()
1741 void BufferParams::readGraphicsDriver(Lexer & lex)
1746 string const tmptok = lex.getString();
1747 // check if tmptok is part of tex_graphics in tex_defs.h
1750 string const test = tex_graphics[n++];
1752 if (test == tmptok) {
1753 graphicsDriver = tmptok;
1758 "Warning: graphics driver `$$Token' not recognized!\n"
1759 " Setting graphics driver to `default'.\n");
1760 graphicsDriver = "default";
1767 void BufferParams::readBullets(Lexer & lex)
1772 int const index = lex.getInteger();
1774 int temp_int = lex.getInteger();
1775 user_defined_bullet(index).setFont(temp_int);
1776 temp_bullet(index).setFont(temp_int);
1778 user_defined_bullet(index).setCharacter(temp_int);
1779 temp_bullet(index).setCharacter(temp_int);
1781 user_defined_bullet(index).setSize(temp_int);
1782 temp_bullet(index).setSize(temp_int);
1786 void BufferParams::readBulletsLaTeX(Lexer & lex)
1788 // The bullet class should be able to read this.
1791 int const index = lex.getInteger();
1793 docstring const temp_str = lex.getDocString();
1795 user_defined_bullet(index).setText(temp_str);
1796 temp_bullet(index).setText(temp_str);
1800 void BufferParams::readModules(Lexer & lex)
1802 if (!lex.eatLine()) {
1803 lyxerr << "Error (BufferParams::readModules):"
1804 "Unexpected end of input." << endl;
1808 string mod = lex.getString();
1809 if (mod == "\\end_modules")
1811 addLayoutModule(mod);
1817 void BufferParams::readRemovedModules(Lexer & lex)
1819 if (!lex.eatLine()) {
1820 lyxerr << "Error (BufferParams::readRemovedModules):"
1821 "Unexpected end of input." << endl;
1825 string mod = lex.getString();
1826 if (mod == "\\end_removed_modules")
1828 removedModules_.push_back(mod);
1831 // now we want to remove any removed modules that were previously
1832 // added. normally, that will be because default modules were added in
1833 // setBaseClass(), which gets called when \textclass is read at the
1834 // start of the read.
1835 list<string>::const_iterator rit = removedModules_.begin();
1836 list<string>::const_iterator const ren = removedModules_.end();
1837 for (; rit != ren; rit++) {
1838 LayoutModuleList::iterator const mit = layoutModules_.begin();
1839 LayoutModuleList::iterator const men = layoutModules_.end();
1840 LayoutModuleList::iterator found = find(mit, men, *rit);
1843 layoutModules_.erase(found);
1848 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1850 char real_papersize = papersize;
1851 if (real_papersize == PAPER_DEFAULT)
1852 real_papersize = lyxrc.default_papersize;
1854 switch (real_papersize) {
1856 // could be anything, so don't guess
1858 case PAPER_CUSTOM: {
1859 if (purpose == XDVI && !paperwidth.empty() &&
1860 !paperheight.empty()) {
1861 // heightxwidth<unit>
1862 string first = paperwidth;
1863 string second = paperheight;
1864 if (orientation == ORIENTATION_LANDSCAPE)
1867 return first.erase(first.length() - 2)
1879 // dvips and dvipdfm do not know this
1880 if (purpose == DVIPS || purpose == DVIPDFM)
1884 // dvipdfm does not know this
1885 if (purpose == DVIPDFM)
1889 // dvipdfm does not know this
1890 if (purpose == DVIPDFM)
1893 case PAPER_USEXECUTIVE:
1894 // dvipdfm does not know this
1895 if (purpose == DVIPDFM)
1900 case PAPER_USLETTER:
1902 if (purpose == XDVI)
1909 string const BufferParams::dvips_options() const
1914 && papersize == PAPER_CUSTOM
1915 && !lyxrc.print_paper_dimension_flag.empty()
1916 && !paperwidth.empty()
1917 && !paperheight.empty()) {
1918 // using a custom papersize
1919 result = lyxrc.print_paper_dimension_flag;
1920 result += ' ' + paperwidth;
1921 result += ',' + paperheight;
1923 string const paper_option = paperSizeName(DVIPS);
1924 if (!paper_option.empty() && (paper_option != "letter" ||
1925 orientation != ORIENTATION_LANDSCAPE)) {
1926 // dvips won't accept -t letter -t landscape.
1927 // In all other cases, include the paper size
1929 result = lyxrc.print_paper_flag;
1930 result += ' ' + paper_option;
1933 if (orientation == ORIENTATION_LANDSCAPE &&
1934 papersize != PAPER_CUSTOM)
1935 result += ' ' + lyxrc.print_landscape_flag;
1940 string BufferParams::babelCall(string const & lang_opts) const
1942 string lang_pack = lyxrc.language_package;
1943 if (lang_pack != "\\usepackage{babel}")
1945 // suppress the babel call when there is no babel language defined
1946 // for the document language in the lib/languages file and if no
1947 // other languages are used (lang_opts is then empty)
1948 if (lang_opts.empty())
1950 // If Vietnamese is used, babel must directly be loaded with the
1951 // language options, see
1952 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1953 size_t viet = lang_opts.find("vietnam");
1954 // viet = string::npos when not found
1955 // the same is for all other languages that are not directly supported by
1956 // babel, but where LaTeX-packages add babel support.
1957 // this is currently the case for Latvian, Lithuanian, and Mongolian
1958 size_t latvian = lang_opts.find("latvian");
1959 size_t lithu = lang_opts.find("lithuanian");
1960 size_t mongo = lang_opts.find("mongolian");
1961 // If Japanese is used, babel must directly be loaded with the
1962 // language options, see
1963 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1964 size_t japan = lang_opts.find("japanese");
1965 if (!lyxrc.language_global_options || viet != string::npos
1966 || japan != string::npos || latvian != string::npos
1967 || lithu != string::npos || mongo != string::npos)
1968 return "\\usepackage[" + lang_opts + "]{babel}";
1973 docstring BufferParams::getGraphicsDriver(string const & package) const
1977 if (package == "geometry") {
1978 if (graphicsDriver == "dvips"
1979 || graphicsDriver == "dvipdfm"
1980 || graphicsDriver == "pdftex"
1981 || graphicsDriver == "vtex")
1982 result = from_ascii(graphicsDriver);
1983 else if (graphicsDriver == "dvipdfmx")
1984 result = from_ascii("dvipdfm");
1991 void BufferParams::writeEncodingPreamble(odocstream & os,
1992 LaTeXFeatures & features, TexRow & texrow) const
1996 if (inputenc == "auto") {
1997 string const doc_encoding =
1998 language->encoding()->latexName();
1999 Encoding::Package const package =
2000 language->encoding()->package();
2002 // Create a list with all the input encodings used
2004 set<string> encodings =
2005 features.getEncodingSet(doc_encoding);
2007 // If the "japanese" package (i.e. pLaTeX) is used,
2008 // inputenc must be omitted.
2009 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2010 if (package == Encoding::japanese)
2011 features.require("japanese");
2013 if ((!encodings.empty() || package == Encoding::inputenc)
2014 && !features.isRequired("japanese")) {
2015 os << "\\usepackage[";
2016 set<string>::const_iterator it = encodings.begin();
2017 set<string>::const_iterator const end = encodings.end();
2019 os << from_ascii(*it);
2022 for (; it != end; ++it)
2023 os << ',' << from_ascii(*it);
2024 if (package == Encoding::inputenc) {
2025 if (!encodings.empty())
2027 os << from_ascii(doc_encoding);
2029 os << "]{inputenc}\n";
2032 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2033 if (language->encoding()->name() == "utf8-cjk"
2034 && LaTeXFeatures::isAvailable("CJKutf8"))
2035 os << "\\usepackage{CJKutf8}\n";
2037 os << "\\usepackage{CJK}\n";
2040 } else if (inputenc != "default") {
2041 switch (encoding().package()) {
2042 case Encoding::none:
2043 case Encoding::japanese:
2045 case Encoding::inputenc:
2046 // do not load inputenc if japanese is used
2047 if (features.isRequired("japanese"))
2049 os << "\\usepackage[" << from_ascii(inputenc)
2054 if (encoding().name() == "utf8-cjk"
2055 && LaTeXFeatures::isAvailable("CJKutf8"))
2056 os << "\\usepackage{CJKutf8}\n";
2058 os << "\\usepackage{CJK}\n";
2064 // The encoding "armscii8" (for Armenian) is only available when
2065 // the package "armtex" is loaded.
2066 if (language->encoding()->latexName() == "armscii8"
2067 || inputenc == "armscii8") {
2068 os << "\\usepackage{armtex}\n";
2074 string const BufferParams::parseFontName(string const & name) const
2076 string mangled = name;
2077 size_t const idx = mangled.find('[');
2078 if (idx == string::npos || idx == 0)
2081 return mangled.substr(0, idx - 1);
2085 string const BufferParams::loadFonts(string const & rm,
2086 string const & sf, string const & tt,
2087 bool const & sc, bool const & osf,
2088 int const & sfscale, int const & ttscale,
2089 bool const & xetex) const
2091 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2092 several packages have been replaced by others, that might not
2093 be installed on every system. We have to take care for that
2094 (see psnfss.pdf). We try to support all psnfss fonts as well
2095 as the fonts that have become de facto standard in the LaTeX
2096 world (e.g. Latin Modern). We do not support obsolete fonts
2097 (like PSLatex). In general, it should be possible to mix any
2098 rm font with any sf or tt font, respectively. (JSpitzm)
2100 -- separate math fonts.
2103 if (rm == "default" && sf == "default" && tt == "default")
2110 if (rm != "default")
2111 os << "\\setmainfont[Mapping=tex-text]{"
2112 << parseFontName(rm) << "}\n";
2113 if (sf != "default") {
2114 string const sans = parseFontName(sf);
2116 os << "\\setsansfont[Scale="
2117 << float(sfscale) / 100
2118 << ",Mapping=tex-text]{"
2121 os << "\\setsansfont[Mapping=tex-text]{"
2124 if (tt != "default") {
2125 string const mono = parseFontName(tt);
2127 os << "\\setmonofont[Scale="
2128 << float(sfscale) / 100
2132 os << "\\setmonofont[Mapping=tex-text]{"
2136 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2141 // Computer Modern (must be explicitely selectable -- there might be classes
2142 // that define a different default font!
2144 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2145 // osf for Computer Modern needs eco.sty
2147 os << "\\usepackage{eco}\n";
2149 // Latin Modern Roman
2150 else if (rm == "lmodern")
2151 os << "\\usepackage{lmodern}\n";
2153 else if (rm == "ae") {
2154 // not needed when using OT1 font encoding.
2155 if (lyxrc.fontenc != "default")
2156 os << "\\usepackage{ae,aecompl}\n";
2159 else if (rm == "times") {
2160 // try to load the best available package
2161 if (LaTeXFeatures::isAvailable("mathptmx"))
2162 os << "\\usepackage{mathptmx}\n";
2163 else if (LaTeXFeatures::isAvailable("mathptm"))
2164 os << "\\usepackage{mathptm}\n";
2166 os << "\\usepackage{times}\n";
2169 else if (rm == "palatino") {
2170 // try to load the best available package
2171 if (LaTeXFeatures::isAvailable("mathpazo")) {
2172 os << "\\usepackage";
2178 // "osf" includes "sc"!
2182 os << "{mathpazo}\n";
2184 else if (LaTeXFeatures::isAvailable("mathpple"))
2185 os << "\\usepackage{mathpple}\n";
2187 os << "\\usepackage{palatino}\n";
2190 else if (rm == "utopia") {
2191 // fourier supersedes utopia.sty, but does
2192 // not work with OT1 encoding.
2193 if (LaTeXFeatures::isAvailable("fourier")
2194 && lyxrc.fontenc != "default") {
2195 os << "\\usepackage";
2206 os << "{fourier}\n";
2209 os << "\\usepackage{utopia}\n";
2211 // Bera (complete fontset)
2212 else if (rm == "bera" && sf == "default" && tt == "default")
2213 os << "\\usepackage{bera}\n";
2215 else if (rm != "default")
2216 os << "\\usepackage" << "{" << rm << "}\n";
2219 // Helvetica, Bera Sans
2220 if (sf == "helvet" || sf == "berasans") {
2222 os << "\\usepackage[scaled=" << float(sfscale) / 100
2223 << "]{" << sf << "}\n";
2225 os << "\\usepackage{" << sf << "}\n";
2228 else if (sf == "avant")
2229 os << "\\usepackage{" << sf << "}\n";
2230 // Computer Modern, Latin Modern, CM Bright
2231 else if (sf != "default")
2232 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2234 // monospaced/typewriter
2235 // Courier, LuxiMono
2236 if (tt == "luximono" || tt == "beramono") {
2238 os << "\\usepackage[scaled=" << float(ttscale) / 100
2239 << "]{" << tt << "}\n";
2241 os << "\\usepackage{" << tt << "}\n";
2244 else if (tt == "courier" )
2245 os << "\\usepackage{" << tt << "}\n";
2246 // Computer Modern, Latin Modern, CM Bright
2247 else if (tt != "default")
2248 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2254 Encoding const & BufferParams::encoding() const
2257 return *(encodings.fromLaTeXName("utf8-plain"));
2258 if (inputenc == "auto" || inputenc == "default")
2259 return *language->encoding();
2260 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2263 LYXERR0("Unknown inputenc value `" << inputenc
2264 << "'. Using `auto' instead.");
2265 return *language->encoding();
2269 CiteEngine BufferParams::citeEngine() const
2271 // FIXME the class should provide the numerical/
2272 // authoryear choice
2273 if (documentClass().provides("natbib")
2274 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2275 return ENGINE_NATBIB_AUTHORYEAR;
2276 return cite_engine_;
2280 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2282 cite_engine_ = cite_engine;