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 if (tok == "\\filename_suffix") {
624 branch_ptr->setFilenameSuffix(lex.getInteger());
626 // not yet operational
627 if (tok == "\\color") {
629 string color = lex.getString();
631 branch_ptr->setColor(color);
632 // Update also the Color table:
634 color = lcolor.getX11Name(Color_background);
636 lcolor.setColor(to_utf8(branch), color);
639 } else if (token == "\\index") {
641 docstring index = lex.getDocString();
642 indiceslist().add(index);
645 string const tok = lex.getString();
646 if (tok == "\\end_index")
648 Index * index_ptr = indiceslist().find(index);
649 if (tok == "\\shortcut") {
652 index_ptr->setShortcut(lex.getDocString());
654 // not yet operational
655 if (tok == "\\color") {
657 string color = lex.getString();
659 index_ptr->setColor(color);
660 // Update also the Color table:
662 color = lcolor.getX11Name(Color_background);
664 lcolor.setColor(to_utf8(index), color);
667 } else if (token == "\\author") {
669 istringstream ss(lex.getString());
672 author_map.push_back(pimpl_->authorlist.record(a));
673 } else if (token == "\\paperorientation") {
676 orientation = paperorientationtranslator().find(orient);
677 } else if (token == "\\backgroundcolor") {
679 backgroundcolor = lyx::rgbFromHexName(lex.getString());
680 } else if (token == "\\paperwidth") {
682 } else if (token == "\\paperheight") {
684 } else if (token == "\\leftmargin") {
686 } else if (token == "\\topmargin") {
688 } else if (token == "\\rightmargin") {
690 } else if (token == "\\bottommargin") {
692 } else if (token == "\\headheight") {
694 } else if (token == "\\headsep") {
696 } else if (token == "\\footskip") {
698 } else if (token == "\\columnsep") {
700 } else if (token == "\\paperfontsize") {
702 } else if (token == "\\papercolumns") {
704 } else if (token == "\\listings_params") {
707 listings_params = InsetListingsParams(par).params();
708 } else if (token == "\\papersides") {
711 sides = sidestranslator().find(psides);
712 } else if (token == "\\paperpagestyle") {
714 } else if (token == "\\bullet") {
716 } else if (token == "\\bulletLaTeX") {
717 readBulletsLaTeX(lex);
718 } else if (token == "\\secnumdepth") {
720 } else if (token == "\\tocdepth") {
722 } else if (token == "\\spacing") {
726 if (nspacing == "other") {
729 spacing().set(spacetranslator().find(nspacing), tmp_val);
730 } else if (token == "\\float_placement") {
731 lex >> float_placement;
733 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
734 string toktmp = pdfoptions().readToken(lex, token);
735 if (!toktmp.empty()) {
736 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
741 lyxerr << "BufferParams::readToken(): Unknown token: " <<
750 void BufferParams::writeFile(ostream & os) const
752 // The top of the file is written by the buffer.
753 // Prints out the buffer info into the .lyx file given by file
756 os << "\\textclass " << baseClass()->name() << '\n';
759 if (!preamble.empty()) {
760 // remove '\n' from the end of preamble
761 string const tmppreamble = rtrim(preamble, "\n");
762 os << "\\begin_preamble\n"
764 << "\n\\end_preamble\n";
768 if (!options.empty()) {
769 os << "\\options " << options << '\n';
772 // use the class options defined in the layout?
773 os << "\\use_default_options "
774 << convert<string>(use_default_options) << "\n";
776 // the master document
777 if (!master.empty()) {
778 os << "\\master " << master << '\n';
782 if (!removedModules_.empty()) {
783 os << "\\begin_removed_modules" << '\n';
784 list<string>::const_iterator it = removedModules_.begin();
785 list<string>::const_iterator en = removedModules_.end();
786 for (; it != en; it++)
788 os << "\\end_removed_modules" << '\n';
792 if (!layoutModules_.empty()) {
793 os << "\\begin_modules" << '\n';
794 LayoutModuleList::const_iterator it = layoutModules_.begin();
795 LayoutModuleList::const_iterator en = layoutModules_.end();
796 for (; it != en; it++)
798 os << "\\end_modules" << '\n';
801 // local layout information
802 if (!local_layout.empty()) {
803 // remove '\n' from the end
804 string const tmplocal = rtrim(local_layout, "\n");
805 os << "\\begin_local_layout\n"
807 << "\n\\end_local_layout\n";
810 // then the text parameters
811 if (language != ignore_language)
812 os << "\\language " << language->lang() << '\n';
813 os << "\\inputencoding " << inputenc
814 << "\n\\font_roman " << fontsRoman
815 << "\n\\font_sans " << fontsSans
816 << "\n\\font_typewriter " << fontsTypewriter
817 << "\n\\font_default_family " << fontsDefaultFamily
818 << "\n\\use_xetex " << convert<string>(useXetex)
819 << "\n\\font_sc " << convert<string>(fontsSC)
820 << "\n\\font_osf " << convert<string>(fontsOSF)
821 << "\n\\font_sf_scale " << fontsSansScale
822 << "\n\\font_tt_scale " << fontsTypewriterScale
824 if (!fontsCJK.empty()) {
825 os << "\\font_cjk " << fontsCJK << '\n';
827 os << "\n\\graphics " << graphicsDriver << '\n';
828 os << "\\default_output_format " << defaultOutputFormat << '\n';
829 os << "\\bibtex_command " << bibtex_command << '\n';
830 os << "\\index_command " << index_command << '\n';
832 if (!float_placement.empty()) {
833 os << "\\float_placement " << float_placement << '\n';
835 os << "\\paperfontsize " << fontsize << '\n';
837 spacing().writeFile(os);
838 pdfoptions().writeFile(os);
840 os << "\\papersize " << string_papersize[papersize]
841 << "\n\\use_geometry " << convert<string>(use_geometry)
842 << "\n\\use_amsmath " << use_amsmath
843 << "\n\\use_esint " << use_esint
844 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
845 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
846 << "\n\\use_indices " << convert<string>(use_indices)
847 << "\n\\paperorientation " << string_orientation[orientation]
849 if (backgroundcolor != lyx::rgbFromHexName("#ffffff"))
850 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
852 BranchList::const_iterator it = branchlist().begin();
853 BranchList::const_iterator end = branchlist().end();
854 for (; it != end; ++it) {
855 os << "\\branch " << to_utf8(it->branch())
856 << "\n\\selected " << it->isSelected()
857 << "\n\\filename_suffix " << it->hasFilenameSuffix()
858 << "\n\\color " << lyx::X11hexname(it->color())
863 IndicesList::const_iterator iit = indiceslist().begin();
864 IndicesList::const_iterator iend = indiceslist().end();
865 for (; iit != iend; ++iit) {
866 os << "\\index " << to_utf8(iit->index())
867 << "\n\\shortcut " << to_utf8(iit->shortcut())
868 << "\n\\color " << lyx::X11hexname(iit->color())
873 if (!paperwidth.empty())
874 os << "\\paperwidth "
875 << VSpace(paperwidth).asLyXCommand() << '\n';
876 if (!paperheight.empty())
877 os << "\\paperheight "
878 << VSpace(paperheight).asLyXCommand() << '\n';
879 if (!leftmargin.empty())
880 os << "\\leftmargin "
881 << VSpace(leftmargin).asLyXCommand() << '\n';
882 if (!topmargin.empty())
884 << VSpace(topmargin).asLyXCommand() << '\n';
885 if (!rightmargin.empty())
886 os << "\\rightmargin "
887 << VSpace(rightmargin).asLyXCommand() << '\n';
888 if (!bottommargin.empty())
889 os << "\\bottommargin "
890 << VSpace(bottommargin).asLyXCommand() << '\n';
891 if (!headheight.empty())
892 os << "\\headheight "
893 << VSpace(headheight).asLyXCommand() << '\n';
894 if (!headsep.empty())
896 << VSpace(headsep).asLyXCommand() << '\n';
897 if (!footskip.empty())
899 << VSpace(footskip).asLyXCommand() << '\n';
900 if (!columnsep.empty())
902 << VSpace(columnsep).asLyXCommand() << '\n';
903 os << "\\secnumdepth " << secnumdepth
904 << "\n\\tocdepth " << tocdepth
905 << "\n\\paragraph_separation "
906 << string_paragraph_separation[paragraph_separation]
907 << "\n\\defskip " << getDefSkip().asLyXCommand()
908 << "\n\\quotes_language "
909 << string_quotes_language[quotes_language]
910 << "\n\\papercolumns " << columns
911 << "\n\\papersides " << sides
912 << "\n\\paperpagestyle " << pagestyle << '\n';
913 if (!listings_params.empty())
914 os << "\\listings_params \"" <<
915 InsetListingsParams(listings_params).encodedString() << "\"\n";
916 for (int i = 0; i < 4; ++i) {
917 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
918 if (user_defined_bullet(i).getFont() != -1) {
919 os << "\\bullet " << i << " "
920 << user_defined_bullet(i).getFont() << " "
921 << user_defined_bullet(i).getCharacter() << " "
922 << user_defined_bullet(i).getSize() << "\n";
926 os << "\\bulletLaTeX " << i << " \""
927 << lyx::to_ascii(user_defined_bullet(i).getText())
933 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
934 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
936 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
937 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
938 for (; a_it != a_end; ++a_it) {
939 if (a_it->second.used())
940 os << "\\author " << a_it->second << "\n";
942 os << "\\author " << Author() << "\n";
947 void BufferParams::validate(LaTeXFeatures & features) const
949 features.require(documentClass().requires());
952 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
953 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
954 LaTeXFeatures::isAvailable("xcolor");
956 switch (features.runparams().flavor) {
957 case OutputParams::LATEX:
959 features.require("ct-dvipost");
960 features.require("dvipost");
961 } else if (xcolorulem) {
962 features.require("ct-xcolor-ulem");
963 features.require("ulem");
964 features.require("xcolor");
966 features.require("ct-none");
969 case OutputParams::PDFLATEX:
970 case OutputParams::XETEX:
972 features.require("ct-xcolor-ulem");
973 features.require("ulem");
974 features.require("xcolor");
975 // improves color handling in PDF output
976 features.require("pdfcolmk");
978 features.require("ct-none");
986 // Floats with 'Here definitely' as default setting.
987 if (float_placement.find('H') != string::npos)
988 features.require("float");
990 // AMS Style is at document level
991 if (use_amsmath == package_on
992 || documentClass().provides("amsmath"))
993 features.require("amsmath");
994 if (use_esint == package_on)
995 features.require("esint");
997 // Document-level line spacing
998 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
999 features.require("setspace");
1001 // the bullet shapes are buffer level not paragraph level
1002 // so they are tested here
1003 for (int i = 0; i < 4; ++i) {
1004 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1006 int const font = user_defined_bullet(i).getFont();
1008 int const c = user_defined_bullet(i).getCharacter();
1014 features.require("latexsym");
1016 } else if (font == 1) {
1017 features.require("amssymb");
1018 } else if (font >= 2 && font <= 5) {
1019 features.require("pifont");
1023 if (pdfoptions().use_hyperref) {
1024 features.require("hyperref");
1025 // due to interferences with babel and hyperref, the color package has to
1026 // be loaded after hyperref when hyperref is used with the colorlinks
1027 // option, see http://bugzilla.lyx.org/show_bug.cgi?id=5291
1028 if (pdfoptions().colorlinks)
1029 features.require("color");
1033 features.require("xetex");
1035 if (language->lang() == "vietnamese")
1036 features.require("vietnamese");
1037 else if (language->lang() == "japanese")
1038 features.require("japanese");
1042 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1043 TexRow & texrow) const
1045 os << "\\documentclass";
1047 DocumentClass const & tclass = documentClass();
1049 ostringstream clsoptions; // the document class options.
1051 if (tokenPos(tclass.opt_fontsize(),
1052 '|', fontsize) >= 0) {
1053 // only write if existing in list (and not default)
1054 clsoptions << fontsize << "pt,";
1057 // custom, A3, B3 and B4 paper sizes need geometry
1058 bool nonstandard_papersize = papersize == PAPER_B3
1059 || papersize == PAPER_B4
1060 || papersize == PAPER_A3
1061 || papersize == PAPER_CUSTOM;
1063 if (!use_geometry) {
1064 switch (papersize) {
1066 clsoptions << "a4paper,";
1068 case PAPER_USLETTER:
1069 clsoptions << "letterpaper,";
1072 clsoptions << "a5paper,";
1075 clsoptions << "b5paper,";
1077 case PAPER_USEXECUTIVE:
1078 clsoptions << "executivepaper,";
1081 clsoptions << "legalpaper,";
1093 if (sides != tclass.sides()) {
1096 clsoptions << "oneside,";
1099 clsoptions << "twoside,";
1105 if (columns != tclass.columns()) {
1107 clsoptions << "twocolumn,";
1109 clsoptions << "onecolumn,";
1113 && orientation == ORIENTATION_LANDSCAPE)
1114 clsoptions << "landscape,";
1116 // language should be a parameter to \documentclass
1117 if (language->babel() == "hebrew"
1118 && default_language->babel() != "hebrew")
1119 // This seems necessary
1120 features.useLanguage(default_language);
1122 ostringstream language_options;
1123 bool const use_babel = features.useBabel();
1125 language_options << features.getLanguages();
1126 if (!language->babel().empty()) {
1127 if (!language_options.str().empty())
1128 language_options << ',';
1129 language_options << language->babel();
1131 // if Vietnamese is used, babel must directly be loaded
1132 // with language options, not in the class options, see
1133 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1134 size_t viet = language_options.str().find("vietnam");
1135 // viet = string::npos when not found
1136 // the same is for all other languages that are not directly supported by
1137 // babel, but where LaTeX-packages add babel support.
1138 // this is currently the case for Latvian, Lithuanian, and Mongolian
1139 size_t latvian = language_options.str().find("latvian");
1140 size_t lithu = language_options.str().find("lithuanian");
1141 size_t mongo = language_options.str().find("mongolian");
1142 // if Japanese is used, babel must directly be loaded
1143 // with language options, not in the class options, see
1144 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1145 size_t japan = language_options.str().find("japanese");
1146 if (lyxrc.language_global_options && !language_options.str().empty()
1147 && viet == string::npos && japan == string::npos
1148 && latvian == string::npos && lithu == string::npos
1149 && mongo == string::npos)
1150 clsoptions << language_options.str() << ',';
1153 // the predefined options from the layout
1154 if (use_default_options && !tclass.options().empty())
1155 clsoptions << tclass.options() << ',';
1157 // the user-defined options
1158 if (!options.empty()) {
1159 clsoptions << options << ',';
1162 string strOptions(clsoptions.str());
1163 if (!strOptions.empty()) {
1164 strOptions = rtrim(strOptions, ",");
1166 os << '[' << from_utf8(strOptions) << ']';
1169 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1171 // end of \documentclass defs
1174 os << "\\usepackage{fontspec}\n";
1178 // font selection must be done before loading fontenc.sty
1179 string const fonts =
1180 loadFonts(fontsRoman, fontsSans,
1181 fontsTypewriter, fontsSC, fontsOSF,
1182 fontsSansScale, fontsTypewriterScale, useXetex);
1183 if (!fonts.empty()) {
1184 os << from_ascii(fonts);
1187 if (fontsDefaultFamily != "default")
1188 os << "\\renewcommand{\\familydefault}{\\"
1189 << from_ascii(fontsDefaultFamily) << "}\n";
1191 // set font encoding
1192 // this one is not per buffer
1193 // for arabic_arabi and farsi we also need to load the LAE and
1195 // XeTeX works without fontenc
1196 if (lyxrc.fontenc != "default" && language->lang() != "japanese"
1198 if (language->lang() == "arabic_arabi"
1199 || language->lang() == "farsi") {
1200 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1201 << ",LFE,LAE]{fontenc}\n";
1204 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1210 // handle inputenc etc.
1211 writeEncodingPreamble(os, features, texrow);
1213 if (!listings_params.empty() || features.isRequired("listings")) {
1214 os << "\\usepackage{listings}\n";
1217 if (!listings_params.empty()) {
1219 // do not test validity because listings_params is
1220 // supposed to be valid
1222 InsetListingsParams(listings_params).separatedParams(true);
1223 // we can't support all packages, but we should load the color package
1224 if (par.find("\\color", 0) != string::npos)
1225 features.require("color");
1226 os << from_utf8(par);
1227 // count the number of newlines
1228 for (size_t i = 0; i < par.size(); ++i)
1234 if (!tclass.provides("geometry")
1235 && (use_geometry || nonstandard_papersize)) {
1236 odocstringstream ods;
1237 if (!getGraphicsDriver("geometry").empty())
1238 ods << getGraphicsDriver("geometry");
1239 if (orientation == ORIENTATION_LANDSCAPE)
1240 ods << ",landscape";
1241 switch (papersize) {
1243 if (!paperwidth.empty())
1244 ods << ",paperwidth="
1245 << from_ascii(paperwidth);
1246 if (!paperheight.empty())
1247 ods << ",paperheight="
1248 << from_ascii(paperheight);
1250 case PAPER_USLETTER:
1251 ods << ",letterpaper";
1254 ods << ",legalpaper";
1256 case PAPER_USEXECUTIVE:
1257 ods << ",executivepaper";
1278 // default papersize ie PAPER_DEFAULT
1279 switch (lyxrc.default_papersize) {
1280 case PAPER_DEFAULT: // keep compiler happy
1281 case PAPER_USLETTER:
1282 ods << ",letterpaper";
1285 ods << ",legalpaper";
1287 case PAPER_USEXECUTIVE:
1288 ods << ",executivepaper";
1308 docstring const g_options = trim(ods.str(), ",");
1309 os << "\\usepackage";
1310 if (!g_options.empty())
1311 os << '[' << g_options << ']';
1312 os << "{geometry}\n";
1314 os << "\\geometry{verbose";
1315 if (!topmargin.empty())
1316 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1317 if (!bottommargin.empty())
1318 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1319 if (!leftmargin.empty())
1320 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1321 if (!rightmargin.empty())
1322 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1323 if (!headheight.empty())
1324 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1325 if (!headsep.empty())
1326 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1327 if (!footskip.empty())
1328 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1329 if (!columnsep.empty())
1330 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1333 } else if (orientation == ORIENTATION_LANDSCAPE) {
1334 features.require("papersize");
1337 if (tokenPos(tclass.opt_pagestyle(),
1338 '|', pagestyle) >= 0) {
1339 if (pagestyle == "fancy") {
1340 os << "\\usepackage{fancyhdr}\n";
1343 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1347 // only output when the background color is not white
1348 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1349 // only require color here, the background color will be defined
1350 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1352 features.require("color");
1353 features.require("pagecolor");
1356 // Only if class has a ToC hierarchy
1357 if (tclass.hasTocLevels()) {
1358 if (secnumdepth != tclass.secnumdepth()) {
1359 os << "\\setcounter{secnumdepth}{"
1364 if (tocdepth != tclass.tocdepth()) {
1365 os << "\\setcounter{tocdepth}{"
1372 if (paragraph_separation) {
1373 switch (getDefSkip().kind()) {
1374 case VSpace::SMALLSKIP:
1375 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1377 case VSpace::MEDSKIP:
1378 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1380 case VSpace::BIGSKIP:
1381 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1383 case VSpace::LENGTH:
1384 os << "\\setlength{\\parskip}{"
1385 << from_utf8(getDefSkip().length().asLatexString())
1388 default: // should never happen // Then delete it.
1389 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1394 os << "\\setlength{\\parindent}{0pt}\n";
1398 // Now insert the LyX specific LaTeX commands...
1399 docstring lyxpreamble;
1401 // due to interferences with babel and hyperref, the color package has to
1402 // be loaded (when it is not already loaded) before babel when hyperref
1403 // is used with the colorlinks option, see
1404 // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1405 // we decided therefore to load color always before babel, see
1406 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1407 lyxpreamble += from_ascii(features.getColorOptions());
1409 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1411 && (features.isRequired("jurabib")
1412 || features.isRequired("hyperref")
1413 || features.isRequired("vietnamese")
1414 || features.isRequired("japanese") ) ) {
1416 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1417 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1420 // The optional packages;
1421 lyxpreamble += from_ascii(features.getPackages());
1423 // Additional Indices
1424 if (features.isRequired("splitidx")) {
1425 IndicesList::const_iterator iit = indiceslist().begin();
1426 IndicesList::const_iterator iend = indiceslist().end();
1427 for (; iit != iend; ++iit) {
1428 lyxpreamble += "\\newindex[";
1429 lyxpreamble += iit->index();
1430 lyxpreamble += "]{";
1431 lyxpreamble += iit->shortcut();
1432 lyxpreamble += "}\n";
1437 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1440 // * Hyperref manual: "Make sure it comes last of your loaded
1441 // packages, to give it a fighting chance of not being over-written,
1442 // since its job is to redefine many LaTeX commands."
1443 // * Email from Heiko Oberdiek: "It is usually better to load babel
1444 // before hyperref. Then hyperref has a chance to detect babel.
1445 // * Has to be loaded before the "LyX specific LaTeX commands" to
1446 // avoid errors with algorithm floats.
1447 // use hyperref explicitely when it is required
1448 if (features.isRequired("hyperref")) {
1449 odocstringstream oss;
1450 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1451 lyxpreamble += oss.str();
1454 // Will be surrounded by \makeatletter and \makeatother when not empty
1455 docstring atlyxpreamble;
1457 // Some macros LyX will need
1458 docstring tmppreamble(features.getMacros());
1460 if (!tmppreamble.empty())
1461 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1462 "LyX specific LaTeX commands.\n"
1463 + tmppreamble + '\n';
1465 // the text class specific preamble
1466 tmppreamble = features.getTClassPreamble();
1467 if (!tmppreamble.empty())
1468 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1469 "Textclass specific LaTeX commands.\n"
1470 + tmppreamble + '\n';
1472 /* the user-defined preamble */
1473 if (!containsOnly(preamble, " \n\t"))
1475 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1476 "User specified LaTeX commands.\n"
1477 + from_utf8(preamble) + '\n';
1479 // subfig loads internally the LaTeX package "caption". As
1480 // caption is a very popular package, users will load it in
1481 // the preamble. Therefore we must load subfig behind the
1482 // user-defined preamble and check if the caption package was
1483 // loaded or not. For the case that caption is loaded before
1484 // subfig, there is the subfig option "caption=false". This
1485 // option also works when a koma-script class is used and
1486 // koma's own caption commands are used instead of caption. We
1487 // use \PassOptionsToPackage here because the user could have
1488 // already loaded subfig in the preamble.
1489 if (features.isRequired("subfig")) {
1490 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1491 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1492 "\\usepackage{subfig}\n";
1495 // Itemize bullet settings need to be last in case the user
1496 // defines their own bullets that use a package included
1497 // in the user-defined preamble -- ARRae
1498 // Actually it has to be done much later than that
1499 // since some packages like frenchb make modifications
1500 // at \begin{document} time -- JMarc
1501 docstring bullets_def;
1502 for (int i = 0; i < 4; ++i) {
1503 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1504 if (bullets_def.empty())
1505 bullets_def += "\\AtBeginDocument{\n";
1506 bullets_def += " \\def\\labelitemi";
1508 // `i' is one less than the item to modify
1515 bullets_def += "ii";
1521 bullets_def += '{' +
1522 user_defined_bullet(i).getText()
1527 if (!bullets_def.empty())
1528 atlyxpreamble += bullets_def + "}\n\n";
1530 if (!atlyxpreamble.empty())
1531 lyxpreamble += "\n\\makeatletter\n"
1532 + atlyxpreamble + "\\makeatother\n\n";
1534 // We try to load babel late, in case it interferes with other packages.
1535 // Jurabib and Hyperref have to be called after babel, though.
1536 if (use_babel && !features.isRequired("jurabib")
1537 && !features.isRequired("hyperref")
1538 && !features.isRequired("vietnamese")
1539 && !features.isRequired("japanese")) {
1541 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1542 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1545 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1546 if (!i18npreamble.empty())
1547 lyxpreamble += i18npreamble + '\n';
1550 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1551 for (int j = 0; j != nlines; ++j) {
1557 // these packages (xunicode, for that matter) need to be loaded at least
1558 // after amsmath, amssymb, esint and the other packages that provide
1561 os << "\\usepackage{xunicode}\n";
1563 os << "\\usepackage{xltxtra}\n";
1570 void BufferParams::useClassDefaults()
1572 DocumentClass const & tclass = documentClass();
1574 sides = tclass.sides();
1575 columns = tclass.columns();
1576 pagestyle = tclass.pagestyle();
1577 use_default_options = true;
1578 // Only if class has a ToC hierarchy
1579 if (tclass.hasTocLevels()) {
1580 secnumdepth = tclass.secnumdepth();
1581 tocdepth = tclass.tocdepth();
1586 bool BufferParams::hasClassDefaults() const
1588 DocumentClass const & tclass = documentClass();
1590 return sides == tclass.sides()
1591 && columns == tclass.columns()
1592 && pagestyle == tclass.pagestyle()
1593 && use_default_options
1594 && secnumdepth == tclass.secnumdepth()
1595 && tocdepth == tclass.tocdepth();
1599 DocumentClass const & BufferParams::documentClass() const
1605 DocumentClass const * BufferParams::documentClassPtr() const {
1610 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1611 // evil, but this function is evil
1612 doc_class_ = const_cast<DocumentClass *>(tc);
1616 bool BufferParams::setBaseClass(string const & classname)
1618 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1619 LayoutFileList & bcl = LayoutFileList::get();
1620 if (!bcl.haveClass(classname)) {
1622 bformat(_("The document class %1$s could not be found. "
1623 "A default textclass with default layouts will be used. "
1624 "LyX might not be able to produce output unless a correct "
1625 "textclass is selected from the document settings dialog."),
1626 from_utf8(classname));
1627 frontend::Alert::error(_("Document class not found"), s);
1628 bcl.addEmptyClass(classname);
1631 bool const success = bcl[classname].load();
1634 bformat(_("The document class %1$s could not be loaded."),
1635 from_utf8(classname));
1636 frontend::Alert::error(_("Could not load class"), s);
1640 pimpl_->baseClass_ = classname;
1641 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1646 LayoutFile const * BufferParams::baseClass() const
1648 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1649 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1655 LayoutFileIndex const & BufferParams::baseClassID() const
1657 return pimpl_->baseClass_;
1661 void BufferParams::makeDocumentClass()
1666 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1668 if (!local_layout.empty()) {
1669 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1670 docstring const msg = _("Error reading internal layout information");
1671 frontend::Alert::warning(_("Read Error"), msg);
1676 bool BufferParams::moduleCanBeAdded(string const & modName) const
1678 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1682 bool BufferParams::addLayoutModule(string const & modName)
1684 LayoutModuleList::const_iterator it = layoutModules_.begin();
1685 LayoutModuleList::const_iterator end = layoutModules_.end();
1686 for (; it != end; it++)
1689 layoutModules_.push_back(modName);
1694 Font const BufferParams::getFont() const
1696 FontInfo f = documentClass().defaultfont();
1697 if (fontsDefaultFamily == "rmdefault")
1698 f.setFamily(ROMAN_FAMILY);
1699 else if (fontsDefaultFamily == "sfdefault")
1700 f.setFamily(SANS_FAMILY);
1701 else if (fontsDefaultFamily == "ttdefault")
1702 f.setFamily(TYPEWRITER_FAMILY);
1703 return Font(f, language);
1707 void BufferParams::readPreamble(Lexer & lex)
1709 if (lex.getString() != "\\begin_preamble")
1710 lyxerr << "Error (BufferParams::readPreamble):"
1711 "consistency check failed." << endl;
1713 preamble = lex.getLongString("\\end_preamble");
1717 void BufferParams::readLocalLayout(Lexer & lex)
1719 if (lex.getString() != "\\begin_local_layout")
1720 lyxerr << "Error (BufferParams::readLocalLayout):"
1721 "consistency check failed." << endl;
1723 local_layout = lex.getLongString("\\end_local_layout");
1727 void BufferParams::readLanguage(Lexer & lex)
1729 if (!lex.next()) return;
1731 string const tmptok = lex.getString();
1733 // check if tmptok is part of tex_babel in tex-defs.h
1734 language = languages.getLanguage(tmptok);
1736 // Language tmptok was not found
1737 language = default_language;
1738 lyxerr << "Warning: Setting language `"
1739 << tmptok << "' to `" << language->lang()
1745 void BufferParams::readGraphicsDriver(Lexer & lex)
1750 string const tmptok = lex.getString();
1751 // check if tmptok is part of tex_graphics in tex_defs.h
1754 string const test = tex_graphics[n++];
1756 if (test == tmptok) {
1757 graphicsDriver = tmptok;
1762 "Warning: graphics driver `$$Token' not recognized!\n"
1763 " Setting graphics driver to `default'.\n");
1764 graphicsDriver = "default";
1771 void BufferParams::readBullets(Lexer & lex)
1776 int const index = lex.getInteger();
1778 int temp_int = lex.getInteger();
1779 user_defined_bullet(index).setFont(temp_int);
1780 temp_bullet(index).setFont(temp_int);
1782 user_defined_bullet(index).setCharacter(temp_int);
1783 temp_bullet(index).setCharacter(temp_int);
1785 user_defined_bullet(index).setSize(temp_int);
1786 temp_bullet(index).setSize(temp_int);
1790 void BufferParams::readBulletsLaTeX(Lexer & lex)
1792 // The bullet class should be able to read this.
1795 int const index = lex.getInteger();
1797 docstring const temp_str = lex.getDocString();
1799 user_defined_bullet(index).setText(temp_str);
1800 temp_bullet(index).setText(temp_str);
1804 void BufferParams::readModules(Lexer & lex)
1806 if (!lex.eatLine()) {
1807 lyxerr << "Error (BufferParams::readModules):"
1808 "Unexpected end of input." << endl;
1812 string mod = lex.getString();
1813 if (mod == "\\end_modules")
1815 addLayoutModule(mod);
1821 void BufferParams::readRemovedModules(Lexer & lex)
1823 if (!lex.eatLine()) {
1824 lyxerr << "Error (BufferParams::readRemovedModules):"
1825 "Unexpected end of input." << endl;
1829 string mod = lex.getString();
1830 if (mod == "\\end_removed_modules")
1832 removedModules_.push_back(mod);
1835 // now we want to remove any removed modules that were previously
1836 // added. normally, that will be because default modules were added in
1837 // setBaseClass(), which gets called when \textclass is read at the
1838 // start of the read.
1839 list<string>::const_iterator rit = removedModules_.begin();
1840 list<string>::const_iterator const ren = removedModules_.end();
1841 for (; rit != ren; rit++) {
1842 LayoutModuleList::iterator const mit = layoutModules_.begin();
1843 LayoutModuleList::iterator const men = layoutModules_.end();
1844 LayoutModuleList::iterator found = find(mit, men, *rit);
1847 layoutModules_.erase(found);
1852 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1854 char real_papersize = papersize;
1855 if (real_papersize == PAPER_DEFAULT)
1856 real_papersize = lyxrc.default_papersize;
1858 switch (real_papersize) {
1860 // could be anything, so don't guess
1862 case PAPER_CUSTOM: {
1863 if (purpose == XDVI && !paperwidth.empty() &&
1864 !paperheight.empty()) {
1865 // heightxwidth<unit>
1866 string first = paperwidth;
1867 string second = paperheight;
1868 if (orientation == ORIENTATION_LANDSCAPE)
1871 return first.erase(first.length() - 2)
1883 // dvips and dvipdfm do not know this
1884 if (purpose == DVIPS || purpose == DVIPDFM)
1888 // dvipdfm does not know this
1889 if (purpose == DVIPDFM)
1893 // dvipdfm does not know this
1894 if (purpose == DVIPDFM)
1897 case PAPER_USEXECUTIVE:
1898 // dvipdfm does not know this
1899 if (purpose == DVIPDFM)
1904 case PAPER_USLETTER:
1906 if (purpose == XDVI)
1913 string const BufferParams::dvips_options() const
1918 && papersize == PAPER_CUSTOM
1919 && !lyxrc.print_paper_dimension_flag.empty()
1920 && !paperwidth.empty()
1921 && !paperheight.empty()) {
1922 // using a custom papersize
1923 result = lyxrc.print_paper_dimension_flag;
1924 result += ' ' + paperwidth;
1925 result += ',' + paperheight;
1927 string const paper_option = paperSizeName(DVIPS);
1928 if (!paper_option.empty() && (paper_option != "letter" ||
1929 orientation != ORIENTATION_LANDSCAPE)) {
1930 // dvips won't accept -t letter -t landscape.
1931 // In all other cases, include the paper size
1933 result = lyxrc.print_paper_flag;
1934 result += ' ' + paper_option;
1937 if (orientation == ORIENTATION_LANDSCAPE &&
1938 papersize != PAPER_CUSTOM)
1939 result += ' ' + lyxrc.print_landscape_flag;
1944 string BufferParams::babelCall(string const & lang_opts) const
1946 string lang_pack = lyxrc.language_package;
1947 if (lang_pack != "\\usepackage{babel}")
1949 // suppress the babel call when there is no babel language defined
1950 // for the document language in the lib/languages file and if no
1951 // other languages are used (lang_opts is then empty)
1952 if (lang_opts.empty())
1954 // If Vietnamese is used, babel must directly be loaded with the
1955 // language options, see
1956 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1957 size_t viet = lang_opts.find("vietnam");
1958 // viet = string::npos when not found
1959 // the same is for all other languages that are not directly supported by
1960 // babel, but where LaTeX-packages add babel support.
1961 // this is currently the case for Latvian, Lithuanian, and Mongolian
1962 size_t latvian = lang_opts.find("latvian");
1963 size_t lithu = lang_opts.find("lithuanian");
1964 size_t mongo = lang_opts.find("mongolian");
1965 // If Japanese is used, babel must directly be loaded with the
1966 // language options, see
1967 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1968 size_t japan = lang_opts.find("japanese");
1969 if (!lyxrc.language_global_options || viet != string::npos
1970 || japan != string::npos || latvian != string::npos
1971 || lithu != string::npos || mongo != string::npos)
1972 return "\\usepackage[" + lang_opts + "]{babel}";
1977 docstring BufferParams::getGraphicsDriver(string const & package) const
1981 if (package == "geometry") {
1982 if (graphicsDriver == "dvips"
1983 || graphicsDriver == "dvipdfm"
1984 || graphicsDriver == "pdftex"
1985 || graphicsDriver == "vtex")
1986 result = from_ascii(graphicsDriver);
1987 else if (graphicsDriver == "dvipdfmx")
1988 result = from_ascii("dvipdfm");
1995 void BufferParams::writeEncodingPreamble(odocstream & os,
1996 LaTeXFeatures & features, TexRow & texrow) const
2000 if (inputenc == "auto") {
2001 string const doc_encoding =
2002 language->encoding()->latexName();
2003 Encoding::Package const package =
2004 language->encoding()->package();
2006 // Create a list with all the input encodings used
2008 set<string> encodings =
2009 features.getEncodingSet(doc_encoding);
2011 // If the "japanese" package (i.e. pLaTeX) is used,
2012 // inputenc must be omitted.
2013 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2014 if (package == Encoding::japanese)
2015 features.require("japanese");
2017 if ((!encodings.empty() || package == Encoding::inputenc)
2018 && !features.isRequired("japanese")) {
2019 os << "\\usepackage[";
2020 set<string>::const_iterator it = encodings.begin();
2021 set<string>::const_iterator const end = encodings.end();
2023 os << from_ascii(*it);
2026 for (; it != end; ++it)
2027 os << ',' << from_ascii(*it);
2028 if (package == Encoding::inputenc) {
2029 if (!encodings.empty())
2031 os << from_ascii(doc_encoding);
2033 os << "]{inputenc}\n";
2036 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2037 if (language->encoding()->name() == "utf8-cjk"
2038 && LaTeXFeatures::isAvailable("CJKutf8"))
2039 os << "\\usepackage{CJKutf8}\n";
2041 os << "\\usepackage{CJK}\n";
2044 } else if (inputenc != "default") {
2045 switch (encoding().package()) {
2046 case Encoding::none:
2047 case Encoding::japanese:
2049 case Encoding::inputenc:
2050 // do not load inputenc if japanese is used
2051 if (features.isRequired("japanese"))
2053 os << "\\usepackage[" << from_ascii(inputenc)
2058 if (encoding().name() == "utf8-cjk"
2059 && LaTeXFeatures::isAvailable("CJKutf8"))
2060 os << "\\usepackage{CJKutf8}\n";
2062 os << "\\usepackage{CJK}\n";
2068 // The encoding "armscii8" (for Armenian) is only available when
2069 // the package "armtex" is loaded.
2070 if (language->encoding()->latexName() == "armscii8"
2071 || inputenc == "armscii8") {
2072 os << "\\usepackage{armtex}\n";
2078 string const BufferParams::parseFontName(string const & name) const
2080 string mangled = name;
2081 size_t const idx = mangled.find('[');
2082 if (idx == string::npos || idx == 0)
2085 return mangled.substr(0, idx - 1);
2089 string const BufferParams::loadFonts(string const & rm,
2090 string const & sf, string const & tt,
2091 bool const & sc, bool const & osf,
2092 int const & sfscale, int const & ttscale,
2093 bool const & xetex) const
2095 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2096 several packages have been replaced by others, that might not
2097 be installed on every system. We have to take care for that
2098 (see psnfss.pdf). We try to support all psnfss fonts as well
2099 as the fonts that have become de facto standard in the LaTeX
2100 world (e.g. Latin Modern). We do not support obsolete fonts
2101 (like PSLatex). In general, it should be possible to mix any
2102 rm font with any sf or tt font, respectively. (JSpitzm)
2104 -- separate math fonts.
2107 if (rm == "default" && sf == "default" && tt == "default")
2114 if (rm != "default")
2115 os << "\\setmainfont[Mapping=tex-text]{"
2116 << parseFontName(rm) << "}\n";
2117 if (sf != "default") {
2118 string const sans = parseFontName(sf);
2120 os << "\\setsansfont[Scale="
2121 << float(sfscale) / 100
2122 << ",Mapping=tex-text]{"
2125 os << "\\setsansfont[Mapping=tex-text]{"
2128 if (tt != "default") {
2129 string const mono = parseFontName(tt);
2131 os << "\\setmonofont[Scale="
2132 << float(sfscale) / 100
2136 os << "\\setmonofont[Mapping=tex-text]{"
2140 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2145 // Computer Modern (must be explicitely selectable -- there might be classes
2146 // that define a different default font!
2148 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2149 // osf for Computer Modern needs eco.sty
2151 os << "\\usepackage{eco}\n";
2153 // Latin Modern Roman
2154 else if (rm == "lmodern")
2155 os << "\\usepackage{lmodern}\n";
2157 else if (rm == "ae") {
2158 // not needed when using OT1 font encoding.
2159 if (lyxrc.fontenc != "default")
2160 os << "\\usepackage{ae,aecompl}\n";
2163 else if (rm == "times") {
2164 // try to load the best available package
2165 if (LaTeXFeatures::isAvailable("mathptmx"))
2166 os << "\\usepackage{mathptmx}\n";
2167 else if (LaTeXFeatures::isAvailable("mathptm"))
2168 os << "\\usepackage{mathptm}\n";
2170 os << "\\usepackage{times}\n";
2173 else if (rm == "palatino") {
2174 // try to load the best available package
2175 if (LaTeXFeatures::isAvailable("mathpazo")) {
2176 os << "\\usepackage";
2182 // "osf" includes "sc"!
2186 os << "{mathpazo}\n";
2188 else if (LaTeXFeatures::isAvailable("mathpple"))
2189 os << "\\usepackage{mathpple}\n";
2191 os << "\\usepackage{palatino}\n";
2194 else if (rm == "utopia") {
2195 // fourier supersedes utopia.sty, but does
2196 // not work with OT1 encoding.
2197 if (LaTeXFeatures::isAvailable("fourier")
2198 && lyxrc.fontenc != "default") {
2199 os << "\\usepackage";
2210 os << "{fourier}\n";
2213 os << "\\usepackage{utopia}\n";
2215 // Bera (complete fontset)
2216 else if (rm == "bera" && sf == "default" && tt == "default")
2217 os << "\\usepackage{bera}\n";
2219 else if (rm != "default")
2220 os << "\\usepackage" << "{" << rm << "}\n";
2223 // Helvetica, Bera Sans
2224 if (sf == "helvet" || sf == "berasans") {
2226 os << "\\usepackage[scaled=" << float(sfscale) / 100
2227 << "]{" << sf << "}\n";
2229 os << "\\usepackage{" << sf << "}\n";
2232 else if (sf == "avant")
2233 os << "\\usepackage{" << sf << "}\n";
2234 // Computer Modern, Latin Modern, CM Bright
2235 else if (sf != "default")
2236 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2238 // monospaced/typewriter
2239 // Courier, LuxiMono
2240 if (tt == "luximono" || tt == "beramono") {
2242 os << "\\usepackage[scaled=" << float(ttscale) / 100
2243 << "]{" << tt << "}\n";
2245 os << "\\usepackage{" << tt << "}\n";
2248 else if (tt == "courier" )
2249 os << "\\usepackage{" << tt << "}\n";
2250 // Computer Modern, Latin Modern, CM Bright
2251 else if (tt != "default")
2252 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2258 Encoding const & BufferParams::encoding() const
2261 return *(encodings.fromLaTeXName("utf8-plain"));
2262 if (inputenc == "auto" || inputenc == "default")
2263 return *language->encoding();
2264 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2267 LYXERR0("Unknown inputenc value `" << inputenc
2268 << "'. Using `auto' instead.");
2269 return *language->encoding();
2273 CiteEngine BufferParams::citeEngine() const
2275 // FIXME the class should provide the numerical/
2276 // authoryear choice
2277 if (documentClass().provides("natbib")
2278 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2279 return ENGINE_NATBIB_AUTHORYEAR;
2280 return cite_engine_;
2284 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2286 cite_engine_ = cite_engine;