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 not empty
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.find_first_not_of(" \n\t") != docstring::npos)
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.empty())
1525 lyxpreamble += "\n\\makeatletter\n"
1526 + atlyxpreamble + "\\makeatother\n\n";
1528 // We try to load babel late, in case it interferes with other packages.
1529 // Jurabib and Hyperref have to be called after babel, though.
1530 if (use_babel && !features.isRequired("jurabib")
1531 && !features.isRequired("hyperref")
1532 && !features.isRequired("vietnamese")
1533 && !features.isRequired("japanese")) {
1535 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1536 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1539 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1540 if (!i18npreamble.empty())
1541 lyxpreamble += i18npreamble + '\n';
1544 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1545 for (int j = 0; j != nlines; ++j) {
1551 // these packages (xunicode, for that matter) need to be loaded at least
1552 // after amsmath, amssymb, esint and the other packages that provide
1555 os << "\\usepackage{xunicode}\n";
1557 os << "\\usepackage{xltxtra}\n";
1564 void BufferParams::useClassDefaults()
1566 DocumentClass const & tclass = documentClass();
1568 sides = tclass.sides();
1569 columns = tclass.columns();
1570 pagestyle = tclass.pagestyle();
1571 use_default_options = true;
1572 // Only if class has a ToC hierarchy
1573 if (tclass.hasTocLevels()) {
1574 secnumdepth = tclass.secnumdepth();
1575 tocdepth = tclass.tocdepth();
1580 bool BufferParams::hasClassDefaults() const
1582 DocumentClass const & tclass = documentClass();
1584 return sides == tclass.sides()
1585 && columns == tclass.columns()
1586 && pagestyle == tclass.pagestyle()
1587 && use_default_options
1588 && secnumdepth == tclass.secnumdepth()
1589 && tocdepth == tclass.tocdepth();
1593 DocumentClass const & BufferParams::documentClass() const
1599 DocumentClass const * BufferParams::documentClassPtr() const {
1604 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1605 // evil, but this function is evil
1606 doc_class_ = const_cast<DocumentClass *>(tc);
1610 bool BufferParams::setBaseClass(string const & classname)
1612 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1613 LayoutFileList & bcl = LayoutFileList::get();
1614 if (!bcl.haveClass(classname)) {
1616 bformat(_("The document class %1$s could not be found. "
1617 "A default textclass with default layouts will be used. "
1618 "LyX might not be able to produce output unless a correct "
1619 "textclass is selected from the document settings dialog."),
1620 from_utf8(classname));
1621 frontend::Alert::error(_("Document class not found"), s);
1622 bcl.addEmptyClass(classname);
1625 bool const success = bcl[classname].load();
1628 bformat(_("The document class %1$s could not be loaded."),
1629 from_utf8(classname));
1630 frontend::Alert::error(_("Could not load class"), s);
1634 pimpl_->baseClass_ = classname;
1635 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1640 LayoutFile const * BufferParams::baseClass() const
1642 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1643 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1649 LayoutFileIndex const & BufferParams::baseClassID() const
1651 return pimpl_->baseClass_;
1655 void BufferParams::makeDocumentClass()
1660 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1662 if (!local_layout.empty()) {
1663 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1664 docstring const msg = _("Error reading internal layout information");
1665 frontend::Alert::warning(_("Read Error"), msg);
1670 bool BufferParams::moduleCanBeAdded(string const & modName) const
1672 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1676 bool BufferParams::addLayoutModule(string const & modName)
1678 LayoutModuleList::const_iterator it = layoutModules_.begin();
1679 LayoutModuleList::const_iterator end = layoutModules_.end();
1680 for (; it != end; it++)
1683 layoutModules_.push_back(modName);
1688 Font const BufferParams::getFont() const
1690 FontInfo f = documentClass().defaultfont();
1691 if (fontsDefaultFamily == "rmdefault")
1692 f.setFamily(ROMAN_FAMILY);
1693 else if (fontsDefaultFamily == "sfdefault")
1694 f.setFamily(SANS_FAMILY);
1695 else if (fontsDefaultFamily == "ttdefault")
1696 f.setFamily(TYPEWRITER_FAMILY);
1697 return Font(f, language);
1701 void BufferParams::readPreamble(Lexer & lex)
1703 if (lex.getString() != "\\begin_preamble")
1704 lyxerr << "Error (BufferParams::readPreamble):"
1705 "consistency check failed." << endl;
1707 preamble = lex.getLongString("\\end_preamble");
1711 void BufferParams::readLocalLayout(Lexer & lex)
1713 if (lex.getString() != "\\begin_local_layout")
1714 lyxerr << "Error (BufferParams::readLocalLayout):"
1715 "consistency check failed." << endl;
1717 local_layout = lex.getLongString("\\end_local_layout");
1721 void BufferParams::readLanguage(Lexer & lex)
1723 if (!lex.next()) return;
1725 string const tmptok = lex.getString();
1727 // check if tmptok is part of tex_babel in tex-defs.h
1728 language = languages.getLanguage(tmptok);
1730 // Language tmptok was not found
1731 language = default_language;
1732 lyxerr << "Warning: Setting language `"
1733 << tmptok << "' to `" << language->lang()
1739 void BufferParams::readGraphicsDriver(Lexer & lex)
1744 string const tmptok = lex.getString();
1745 // check if tmptok is part of tex_graphics in tex_defs.h
1748 string const test = tex_graphics[n++];
1750 if (test == tmptok) {
1751 graphicsDriver = tmptok;
1756 "Warning: graphics driver `$$Token' not recognized!\n"
1757 " Setting graphics driver to `default'.\n");
1758 graphicsDriver = "default";
1765 void BufferParams::readBullets(Lexer & lex)
1770 int const index = lex.getInteger();
1772 int temp_int = lex.getInteger();
1773 user_defined_bullet(index).setFont(temp_int);
1774 temp_bullet(index).setFont(temp_int);
1776 user_defined_bullet(index).setCharacter(temp_int);
1777 temp_bullet(index).setCharacter(temp_int);
1779 user_defined_bullet(index).setSize(temp_int);
1780 temp_bullet(index).setSize(temp_int);
1784 void BufferParams::readBulletsLaTeX(Lexer & lex)
1786 // The bullet class should be able to read this.
1789 int const index = lex.getInteger();
1791 docstring const temp_str = lex.getDocString();
1793 user_defined_bullet(index).setText(temp_str);
1794 temp_bullet(index).setText(temp_str);
1798 void BufferParams::readModules(Lexer & lex)
1800 if (!lex.eatLine()) {
1801 lyxerr << "Error (BufferParams::readModules):"
1802 "Unexpected end of input." << endl;
1806 string mod = lex.getString();
1807 if (mod == "\\end_modules")
1809 addLayoutModule(mod);
1815 void BufferParams::readRemovedModules(Lexer & lex)
1817 if (!lex.eatLine()) {
1818 lyxerr << "Error (BufferParams::readRemovedModules):"
1819 "Unexpected end of input." << endl;
1823 string mod = lex.getString();
1824 if (mod == "\\end_removed_modules")
1826 removedModules_.push_back(mod);
1829 // now we want to remove any removed modules that were previously
1830 // added. normally, that will be because default modules were added in
1831 // setBaseClass(), which gets called when \textclass is read at the
1832 // start of the read.
1833 list<string>::const_iterator rit = removedModules_.begin();
1834 list<string>::const_iterator const ren = removedModules_.end();
1835 for (; rit != ren; rit++) {
1836 LayoutModuleList::iterator const mit = layoutModules_.begin();
1837 LayoutModuleList::iterator const men = layoutModules_.end();
1838 LayoutModuleList::iterator found = find(mit, men, *rit);
1841 layoutModules_.erase(found);
1846 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1848 char real_papersize = papersize;
1849 if (real_papersize == PAPER_DEFAULT)
1850 real_papersize = lyxrc.default_papersize;
1852 switch (real_papersize) {
1854 // could be anything, so don't guess
1856 case PAPER_CUSTOM: {
1857 if (purpose == XDVI && !paperwidth.empty() &&
1858 !paperheight.empty()) {
1859 // heightxwidth<unit>
1860 string first = paperwidth;
1861 string second = paperheight;
1862 if (orientation == ORIENTATION_LANDSCAPE)
1865 return first.erase(first.length() - 2)
1877 // dvips and dvipdfm do not know this
1878 if (purpose == DVIPS || purpose == DVIPDFM)
1882 // dvipdfm does not know this
1883 if (purpose == DVIPDFM)
1887 // dvipdfm does not know this
1888 if (purpose == DVIPDFM)
1891 case PAPER_USEXECUTIVE:
1892 // dvipdfm does not know this
1893 if (purpose == DVIPDFM)
1898 case PAPER_USLETTER:
1900 if (purpose == XDVI)
1907 string const BufferParams::dvips_options() const
1912 && papersize == PAPER_CUSTOM
1913 && !lyxrc.print_paper_dimension_flag.empty()
1914 && !paperwidth.empty()
1915 && !paperheight.empty()) {
1916 // using a custom papersize
1917 result = lyxrc.print_paper_dimension_flag;
1918 result += ' ' + paperwidth;
1919 result += ',' + paperheight;
1921 string const paper_option = paperSizeName(DVIPS);
1922 if (!paper_option.empty() && (paper_option != "letter" ||
1923 orientation != ORIENTATION_LANDSCAPE)) {
1924 // dvips won't accept -t letter -t landscape.
1925 // In all other cases, include the paper size
1927 result = lyxrc.print_paper_flag;
1928 result += ' ' + paper_option;
1931 if (orientation == ORIENTATION_LANDSCAPE &&
1932 papersize != PAPER_CUSTOM)
1933 result += ' ' + lyxrc.print_landscape_flag;
1938 string BufferParams::babelCall(string const & lang_opts) const
1940 string lang_pack = lyxrc.language_package;
1941 if (lang_pack != "\\usepackage{babel}")
1943 // suppress the babel call when there is no babel language defined
1944 // for the document language in the lib/languages file and if no
1945 // other languages are used (lang_opts is then empty)
1946 if (lang_opts.empty())
1948 // If Vietnamese is used, babel must directly be loaded with the
1949 // language options, see
1950 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1951 size_t viet = lang_opts.find("vietnam");
1952 // viet = string::npos when not found
1953 // the same is for all other languages that are not directly supported by
1954 // babel, but where LaTeX-packages add babel support.
1955 // this is currently the case for Latvian, Lithuanian, and Mongolian
1956 size_t latvian = lang_opts.find("latvian");
1957 size_t lithu = lang_opts.find("lithuanian");
1958 size_t mongo = lang_opts.find("mongolian");
1959 // If Japanese is used, babel must directly be loaded with the
1960 // language options, see
1961 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1962 size_t japan = lang_opts.find("japanese");
1963 if (!lyxrc.language_global_options || viet != string::npos
1964 || japan != string::npos || latvian != string::npos
1965 || lithu != string::npos || mongo != string::npos)
1966 return "\\usepackage[" + lang_opts + "]{babel}";
1971 docstring BufferParams::getGraphicsDriver(string const & package) const
1975 if (package == "geometry") {
1976 if (graphicsDriver == "dvips"
1977 || graphicsDriver == "dvipdfm"
1978 || graphicsDriver == "pdftex"
1979 || graphicsDriver == "vtex")
1980 result = from_ascii(graphicsDriver);
1981 else if (graphicsDriver == "dvipdfmx")
1982 result = from_ascii("dvipdfm");
1989 void BufferParams::writeEncodingPreamble(odocstream & os,
1990 LaTeXFeatures & features, TexRow & texrow) const
1994 if (inputenc == "auto") {
1995 string const doc_encoding =
1996 language->encoding()->latexName();
1997 Encoding::Package const package =
1998 language->encoding()->package();
2000 // Create a list with all the input encodings used
2002 set<string> encodings =
2003 features.getEncodingSet(doc_encoding);
2005 // If the "japanese" package (i.e. pLaTeX) is used,
2006 // inputenc must be omitted.
2007 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2008 if (package == Encoding::japanese)
2009 features.require("japanese");
2011 if ((!encodings.empty() || package == Encoding::inputenc)
2012 && !features.isRequired("japanese")) {
2013 os << "\\usepackage[";
2014 set<string>::const_iterator it = encodings.begin();
2015 set<string>::const_iterator const end = encodings.end();
2017 os << from_ascii(*it);
2020 for (; it != end; ++it)
2021 os << ',' << from_ascii(*it);
2022 if (package == Encoding::inputenc) {
2023 if (!encodings.empty())
2025 os << from_ascii(doc_encoding);
2027 os << "]{inputenc}\n";
2030 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2031 if (language->encoding()->name() == "utf8-cjk"
2032 && LaTeXFeatures::isAvailable("CJKutf8"))
2033 os << "\\usepackage{CJKutf8}\n";
2035 os << "\\usepackage{CJK}\n";
2038 } else if (inputenc != "default") {
2039 switch (encoding().package()) {
2040 case Encoding::none:
2041 case Encoding::japanese:
2043 case Encoding::inputenc:
2044 // do not load inputenc if japanese is used
2045 if (features.isRequired("japanese"))
2047 os << "\\usepackage[" << from_ascii(inputenc)
2052 if (encoding().name() == "utf8-cjk"
2053 && LaTeXFeatures::isAvailable("CJKutf8"))
2054 os << "\\usepackage{CJKutf8}\n";
2056 os << "\\usepackage{CJK}\n";
2062 // The encoding "armscii8" (for Armenian) is only available when
2063 // the package "armtex" is loaded.
2064 if (language->encoding()->latexName() == "armscii8"
2065 || inputenc == "armscii8") {
2066 os << "\\usepackage{armtex}\n";
2072 string const BufferParams::parseFontName(string const & name) const
2074 string mangled = name;
2075 size_t const idx = mangled.find('[');
2076 if (idx == string::npos || idx == 0)
2079 return mangled.substr(0, idx - 1);
2083 string const BufferParams::loadFonts(string const & rm,
2084 string const & sf, string const & tt,
2085 bool const & sc, bool const & osf,
2086 int const & sfscale, int const & ttscale,
2087 bool const & xetex) const
2089 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2090 several packages have been replaced by others, that might not
2091 be installed on every system. We have to take care for that
2092 (see psnfss.pdf). We try to support all psnfss fonts as well
2093 as the fonts that have become de facto standard in the LaTeX
2094 world (e.g. Latin Modern). We do not support obsolete fonts
2095 (like PSLatex). In general, it should be possible to mix any
2096 rm font with any sf or tt font, respectively. (JSpitzm)
2098 -- separate math fonts.
2101 if (rm == "default" && sf == "default" && tt == "default")
2108 if (rm != "default")
2109 os << "\\setmainfont[Mapping=tex-text]{"
2110 << parseFontName(rm) << "}\n";
2111 if (sf != "default") {
2112 string const sans = parseFontName(sf);
2114 os << "\\setsansfont[Scale="
2115 << float(sfscale) / 100
2116 << ",Mapping=tex-text]{"
2119 os << "\\setsansfont[Mapping=tex-text]{"
2122 if (tt != "default") {
2123 string const mono = parseFontName(tt);
2125 os << "\\setmonofont[Scale="
2126 << float(sfscale) / 100
2130 os << "\\setmonofont[Mapping=tex-text]{"
2134 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2139 // Computer Modern (must be explicitely selectable -- there might be classes
2140 // that define a different default font!
2142 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2143 // osf for Computer Modern needs eco.sty
2145 os << "\\usepackage{eco}\n";
2147 // Latin Modern Roman
2148 else if (rm == "lmodern")
2149 os << "\\usepackage{lmodern}\n";
2151 else if (rm == "ae") {
2152 // not needed when using OT1 font encoding.
2153 if (lyxrc.fontenc != "default")
2154 os << "\\usepackage{ae,aecompl}\n";
2157 else if (rm == "times") {
2158 // try to load the best available package
2159 if (LaTeXFeatures::isAvailable("mathptmx"))
2160 os << "\\usepackage{mathptmx}\n";
2161 else if (LaTeXFeatures::isAvailable("mathptm"))
2162 os << "\\usepackage{mathptm}\n";
2164 os << "\\usepackage{times}\n";
2167 else if (rm == "palatino") {
2168 // try to load the best available package
2169 if (LaTeXFeatures::isAvailable("mathpazo")) {
2170 os << "\\usepackage";
2176 // "osf" includes "sc"!
2180 os << "{mathpazo}\n";
2182 else if (LaTeXFeatures::isAvailable("mathpple"))
2183 os << "\\usepackage{mathpple}\n";
2185 os << "\\usepackage{palatino}\n";
2188 else if (rm == "utopia") {
2189 // fourier supersedes utopia.sty, but does
2190 // not work with OT1 encoding.
2191 if (LaTeXFeatures::isAvailable("fourier")
2192 && lyxrc.fontenc != "default") {
2193 os << "\\usepackage";
2204 os << "{fourier}\n";
2207 os << "\\usepackage{utopia}\n";
2209 // Bera (complete fontset)
2210 else if (rm == "bera" && sf == "default" && tt == "default")
2211 os << "\\usepackage{bera}\n";
2213 else if (rm != "default")
2214 os << "\\usepackage" << "{" << rm << "}\n";
2217 // Helvetica, Bera Sans
2218 if (sf == "helvet" || sf == "berasans") {
2220 os << "\\usepackage[scaled=" << float(sfscale) / 100
2221 << "]{" << sf << "}\n";
2223 os << "\\usepackage{" << sf << "}\n";
2226 else if (sf == "avant")
2227 os << "\\usepackage{" << sf << "}\n";
2228 // Computer Modern, Latin Modern, CM Bright
2229 else if (sf != "default")
2230 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2232 // monospaced/typewriter
2233 // Courier, LuxiMono
2234 if (tt == "luximono" || tt == "beramono") {
2236 os << "\\usepackage[scaled=" << float(ttscale) / 100
2237 << "]{" << tt << "}\n";
2239 os << "\\usepackage{" << tt << "}\n";
2242 else if (tt == "courier" )
2243 os << "\\usepackage{" << tt << "}\n";
2244 // Computer Modern, Latin Modern, CM Bright
2245 else if (tt != "default")
2246 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2252 Encoding const & BufferParams::encoding() const
2255 return *(encodings.fromLaTeXName("utf8-plain"));
2256 if (inputenc == "auto" || inputenc == "default")
2257 return *language->encoding();
2258 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2261 LYXERR0("Unknown inputenc value `" << inputenc
2262 << "'. Using `auto' instead.");
2263 return *language->encoding();
2267 CiteEngine BufferParams::citeEngine() const
2269 // FIXME the class should provide the numerical/
2270 // authoryear choice
2271 if (documentClass().provides("natbib")
2272 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2273 return ENGINE_NATBIB_AUTHORYEAR;
2274 return cite_engine_;
2278 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2280 cite_engine_ = cite_engine;