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"
29 #include "IndicesList.h"
31 #include "LaTeXFeatures.h"
32 #include "ModuleList.h"
36 #include "OutputParams.h"
40 #include "PDFOptions.h"
42 #include "frontends/alert.h"
44 #include "insets/InsetListingsParams.h"
46 #include "support/convert.h"
47 #include "support/debug.h"
48 #include "support/docstream.h"
49 #include "support/FileName.h"
50 #include "support/filetools.h"
51 #include "support/gettext.h"
52 #include "support/Messages.h"
53 #include "support/Translator.h"
54 #include "support/lstrings.h"
60 using namespace lyx::support;
63 static char const * const string_paragraph_separation[] = {
68 static char const * const string_quotes_language[] = {
69 "english", "swedish", "german", "polish", "french", "danish", ""
73 static char const * const string_papersize[] = {
74 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
75 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
79 static char const * const string_orientation[] = {
80 "portrait", "landscape", ""
84 static char const * const string_footnotekinds[] = {
85 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
89 static char const * const tex_graphics[] = {
90 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
91 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
92 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
93 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
104 // Paragraph separation
105 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
108 ParSepTranslator const init_parseptranslator()
110 ParSepTranslator translator
111 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
112 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
117 ParSepTranslator const & parseptranslator()
119 static ParSepTranslator translator = init_parseptranslator();
125 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
128 QuotesLangTranslator const init_quoteslangtranslator()
130 QuotesLangTranslator translator
131 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
132 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
133 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
134 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
135 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
136 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
141 QuotesLangTranslator const & quoteslangtranslator()
143 static QuotesLangTranslator translator = init_quoteslangtranslator();
149 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
152 static PaperSizeTranslator initPaperSizeTranslator()
154 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
155 translator.addPair(string_papersize[1], PAPER_CUSTOM);
156 translator.addPair(string_papersize[2], PAPER_USLETTER);
157 translator.addPair(string_papersize[3], PAPER_USLEGAL);
158 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
159 translator.addPair(string_papersize[5], PAPER_A3);
160 translator.addPair(string_papersize[6], PAPER_A4);
161 translator.addPair(string_papersize[7], PAPER_A5);
162 translator.addPair(string_papersize[8], PAPER_B3);
163 translator.addPair(string_papersize[9], PAPER_B4);
164 translator.addPair(string_papersize[10], PAPER_B5);
169 PaperSizeTranslator const & papersizetranslator()
171 static PaperSizeTranslator translator = initPaperSizeTranslator();
177 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
180 PaperOrientationTranslator const init_paperorientationtranslator()
182 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
183 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
188 PaperOrientationTranslator const & paperorientationtranslator()
190 static PaperOrientationTranslator translator = init_paperorientationtranslator();
196 typedef Translator<int, PageSides> SidesTranslator;
199 SidesTranslator const init_sidestranslator()
201 SidesTranslator translator(1, OneSide);
202 translator.addPair(2, TwoSides);
207 SidesTranslator const & sidestranslator()
209 static SidesTranslator translator = init_sidestranslator();
215 typedef Translator<int, BufferParams::Package> PackageTranslator;
218 PackageTranslator const init_packagetranslator()
220 PackageTranslator translator(0, BufferParams::package_off);
221 translator.addPair(1, BufferParams::package_auto);
222 translator.addPair(2, BufferParams::package_on);
227 PackageTranslator const & packagetranslator()
229 static PackageTranslator translator = init_packagetranslator();
235 typedef Translator<string, CiteEngine> CiteEngineTranslator;
238 CiteEngineTranslator const init_citeenginetranslator()
240 CiteEngineTranslator translator("basic", ENGINE_BASIC);
241 translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
242 translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
243 translator.addPair("jurabib", ENGINE_JURABIB);
248 CiteEngineTranslator const & citeenginetranslator()
250 static CiteEngineTranslator translator = init_citeenginetranslator();
256 typedef Translator<string, Spacing::Space> SpaceTranslator;
259 SpaceTranslator const init_spacetranslator()
261 SpaceTranslator translator("default", Spacing::Default);
262 translator.addPair("single", Spacing::Single);
263 translator.addPair("onehalf", Spacing::Onehalf);
264 translator.addPair("double", Spacing::Double);
265 translator.addPair("other", Spacing::Other);
270 SpaceTranslator const & spacetranslator()
272 static SpaceTranslator translator = init_spacetranslator();
279 class BufferParams::Impl
284 AuthorList authorlist;
285 BranchList branchlist;
286 Bullet temp_bullets[4];
287 Bullet user_defined_bullets[4];
288 IndicesList indiceslist;
290 /** This is the amount of space used for paragraph_separation "skip",
291 * and for detached paragraphs in "indented" documents.
295 PDFOptions pdfoptions;
296 LayoutFileIndex baseClass_;
300 BufferParams::Impl::Impl()
301 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
303 // set initial author
305 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
310 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
314 return new BufferParams::Impl(*ptr);
318 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
324 BufferParams::BufferParams()
327 setBaseClass(defaultBaseclass());
329 paragraph_separation = ParagraphIndentSeparation;
330 quotes_language = InsetQuotes::EnglishQuotes;
331 fontsize = "default";
334 papersize = PAPER_DEFAULT;
335 orientation = ORIENTATION_PORTRAIT;
336 use_geometry = false;
337 use_amsmath = package_auto;
338 use_esint = package_auto;
339 use_mhchem = package_auto;
340 cite_engine_ = ENGINE_BASIC;
341 use_bibtopic = false;
343 trackChanges = false;
344 outputChanges = false;
345 use_default_options = true;
346 maintain_unincluded_children = false;
349 language = default_language;
351 fontsRoman = "default";
352 fontsSans = "default";
353 fontsTypewriter = "default";
354 fontsDefaultFamily = "default";
358 fontsSansScale = 100;
359 fontsTypewriterScale = 100;
361 graphicsDriver = "default";
362 defaultOutputFormat = "default";
363 bibtex_command = "default";
364 index_command = "default";
367 listings_params = string();
368 pagestyle = "default";
369 suppress_date = false;
370 // white is equal to no background color
371 backgroundcolor = lyx::rgbFromHexName("#ffffff");
373 for (int iter = 0; iter < 4; ++iter) {
374 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
375 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
378 indiceslist().addDefault(B_("Index"));
379 html_be_strict = true;
380 html_math_output = MathML;
384 docstring BufferParams::B_(string const & l10n) const
386 LASSERT(language, /**/);
387 return getMessages(language->code()).get(l10n);
391 AuthorList & BufferParams::authors()
393 return pimpl_->authorlist;
397 AuthorList const & BufferParams::authors() const
399 return pimpl_->authorlist;
403 BranchList & BufferParams::branchlist()
405 return pimpl_->branchlist;
409 BranchList const & BufferParams::branchlist() const
411 return pimpl_->branchlist;
415 IndicesList & BufferParams::indiceslist()
417 return pimpl_->indiceslist;
421 IndicesList const & BufferParams::indiceslist() const
423 return pimpl_->indiceslist;
427 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
429 LASSERT(index < 4, /**/);
430 return pimpl_->temp_bullets[index];
434 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
436 LASSERT(index < 4, /**/);
437 return pimpl_->temp_bullets[index];
441 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
443 LASSERT(index < 4, /**/);
444 return pimpl_->user_defined_bullets[index];
448 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
450 LASSERT(index < 4, /**/);
451 return pimpl_->user_defined_bullets[index];
455 Spacing & BufferParams::spacing()
457 return pimpl_->spacing;
461 Spacing const & BufferParams::spacing() const
463 return pimpl_->spacing;
467 PDFOptions & BufferParams::pdfoptions()
469 return pimpl_->pdfoptions;
473 PDFOptions const & BufferParams::pdfoptions() const
475 return pimpl_->pdfoptions;
479 HSpace const & BufferParams::getIndentation() const
481 return pimpl_->indentation;
485 void BufferParams::setIndentation(HSpace const & indent)
487 pimpl_->indentation = indent;
491 VSpace const & BufferParams::getDefSkip() const
493 return pimpl_->defskip;
497 void BufferParams::setDefSkip(VSpace const & vs)
499 pimpl_->defskip = vs;
503 string BufferParams::readToken(Lexer & lex, string const & token,
504 FileName const & filepath)
506 if (token == "\\textclass") {
508 string const classname = lex.getString();
509 // if there exists a local layout file, ignore the system one
510 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
512 LayoutFileList & bcl = LayoutFileList::get();
513 if (tcp.empty() && !filepath.empty())
514 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
518 setBaseClass(classname);
519 // We assume that a tex class exists for local or unknown layouts so this warning
520 // will only be given for system layouts.
521 if (!baseClass()->isTeXClassAvailable()) {
522 docstring const msg =
523 bformat(_("The document class requested\n"
525 "requires external files that are not available.\n"
526 "The document class can still be used, but LyX\n"
527 "will not be able to produce output until the\n"
528 "following prerequisites are installed:\n"
530 "See section 3.1.2.2 of the User's Guide"
531 "for more information."),
532 from_utf8(classname), from_utf8(baseClass()->prerequisites()));
533 frontend::Alert::warning(_("Document class not available"),
536 } else if (token == "\\begin_preamble") {
538 } else if (token == "\\begin_local_layout") {
539 readLocalLayout(lex);
540 } else if (token == "\\begin_modules") {
542 } else if (token == "\\begin_removed_modules") {
543 readRemovedModules(lex);
544 } else if (token == "\\begin_includeonly") {
545 readIncludeonly(lex);
546 } else if (token == "\\maintain_unincluded_children") {
547 lex >> maintain_unincluded_children;
548 } else if (token == "\\options") {
550 options = lex.getString();
551 } else if (token == "\\use_default_options") {
552 lex >> use_default_options;
553 } else if (token == "\\master") {
555 master = lex.getString();
556 } else if (token == "\\suppress_date") {
557 lex >> suppress_date;
558 } else if (token == "\\language") {
560 } else if (token == "\\inputencoding") {
562 } else if (token == "\\graphics") {
563 readGraphicsDriver(lex);
564 } else if (token == "\\default_output_format") {
565 lex >> defaultOutputFormat;
566 } else if (token == "\\bibtex_command") {
568 bibtex_command = lex.getString();
569 } else if (token == "\\index_command") {
571 index_command = lex.getString();
572 } else if (token == "\\fontencoding") {
574 fontenc = lex.getString();
575 } else if (token == "\\font_roman") {
577 fontsRoman = lex.getString();
578 } else if (token == "\\font_sans") {
580 fontsSans = lex.getString();
581 } else if (token == "\\font_typewriter") {
583 fontsTypewriter = lex.getString();
584 } else if (token == "\\font_default_family") {
585 lex >> fontsDefaultFamily;
586 } else if (token == "\\use_xetex") {
588 } else if (token == "\\font_sc") {
590 } else if (token == "\\font_osf") {
592 } else if (token == "\\font_sf_scale") {
593 lex >> fontsSansScale;
594 } else if (token == "\\font_tt_scale") {
595 lex >> fontsTypewriterScale;
596 } else if (token == "\\font_cjk") {
598 } else if (token == "\\paragraph_separation") {
601 paragraph_separation = parseptranslator().find(parsep);
602 } else if (token == "\\paragraph_indentation") {
604 string indentation = lex.getString();
605 pimpl_->indentation = HSpace(indentation);
606 } else if (token == "\\defskip") {
608 string defskip = lex.getString();
609 if (defskip == "defskip")
612 pimpl_->defskip = VSpace(defskip);
613 } else if (token == "\\quotes_language") {
616 quotes_language = quoteslangtranslator().find(quotes_lang);
617 } else if (token == "\\papersize") {
620 papersize = papersizetranslator().find(ppsize);
621 } else if (token == "\\use_geometry") {
623 } else if (token == "\\use_amsmath") {
626 use_amsmath = packagetranslator().find(use_ams);
627 } else if (token == "\\use_esint") {
630 use_esint = packagetranslator().find(useesint);
631 } else if (token == "\\use_mhchem") {
634 use_mhchem = packagetranslator().find(usemhchem);
635 } else if (token == "\\cite_engine") {
638 cite_engine_ = citeenginetranslator().find(engine);
639 } else if (token == "\\use_bibtopic") {
641 } else if (token == "\\use_indices") {
643 } else if (token == "\\tracking_changes") {
645 } else if (token == "\\output_changes") {
646 lex >> outputChanges;
647 } else if (token == "\\branch") {
649 docstring branch = lex.getDocString();
650 branchlist().add(branch);
653 string const tok = lex.getString();
654 if (tok == "\\end_branch")
656 Branch * branch_ptr = branchlist().find(branch);
657 if (tok == "\\selected") {
660 branch_ptr->setSelected(lex.getInteger());
662 if (tok == "\\filename_suffix") {
665 branch_ptr->setFilenameSuffix(lex.getInteger());
667 if (tok == "\\color") {
669 string color = lex.getString();
671 branch_ptr->setColor(color);
672 // Update also the Color table:
674 color = lcolor.getX11Name(Color_background);
676 lcolor.setColor(to_utf8(branch), color);
679 } else if (token == "\\index") {
681 docstring index = lex.getDocString();
683 indiceslist().add(index);
686 string const tok = lex.getString();
687 if (tok == "\\end_index")
689 Index * index_ptr = indiceslist().find(index);
690 if (tok == "\\shortcut") {
692 shortcut = lex.getDocString();
694 index_ptr->setShortcut(shortcut);
696 if (tok == "\\color") {
698 string color = lex.getString();
700 index_ptr->setColor(color);
701 // Update also the Color table:
703 color = lcolor.getX11Name(Color_background);
705 if (!shortcut.empty())
706 lcolor.setColor(to_utf8(shortcut), color);
709 } else if (token == "\\author") {
711 istringstream ss(lex.getString());
714 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
715 } else if (token == "\\paperorientation") {
718 orientation = paperorientationtranslator().find(orient);
719 } else if (token == "\\backgroundcolor") {
721 backgroundcolor = lyx::rgbFromHexName(lex.getString());
722 } else if (token == "\\paperwidth") {
724 } else if (token == "\\paperheight") {
726 } else if (token == "\\leftmargin") {
728 } else if (token == "\\topmargin") {
730 } else if (token == "\\rightmargin") {
732 } else if (token == "\\bottommargin") {
734 } else if (token == "\\headheight") {
736 } else if (token == "\\headsep") {
738 } else if (token == "\\footskip") {
740 } else if (token == "\\columnsep") {
742 } else if (token == "\\paperfontsize") {
744 } else if (token == "\\papercolumns") {
746 } else if (token == "\\listings_params") {
749 listings_params = InsetListingsParams(par).params();
750 } else if (token == "\\papersides") {
753 sides = sidestranslator().find(psides);
754 } else if (token == "\\paperpagestyle") {
756 } else if (token == "\\bullet") {
758 } else if (token == "\\bulletLaTeX") {
759 readBulletsLaTeX(lex);
760 } else if (token == "\\secnumdepth") {
762 } else if (token == "\\tocdepth") {
764 } else if (token == "\\spacing") {
768 if (nspacing == "other") {
771 spacing().set(spacetranslator().find(nspacing), tmp_val);
772 } else if (token == "\\float_placement") {
773 lex >> float_placement;
775 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
776 string toktmp = pdfoptions().readToken(lex, token);
777 if (!toktmp.empty()) {
778 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
782 } else if (token == "\\html_math_output") {
785 html_math_output = static_cast<MathOutput>(temp);
786 } else if (token == "\\html_be_strict") {
787 lex >> html_be_strict;
789 lyxerr << "BufferParams::readToken(): Unknown token: " <<
798 void BufferParams::writeFile(ostream & os) const
800 // The top of the file is written by the buffer.
801 // Prints out the buffer info into the .lyx file given by file
804 os << "\\textclass " << baseClass()->name() << '\n';
807 if (!preamble.empty()) {
808 // remove '\n' from the end of preamble
809 string const tmppreamble = rtrim(preamble, "\n");
810 os << "\\begin_preamble\n"
812 << "\n\\end_preamble\n";
816 if (!options.empty()) {
817 os << "\\options " << options << '\n';
820 // use the class options defined in the layout?
821 os << "\\use_default_options "
822 << convert<string>(use_default_options) << "\n";
824 // the master document
825 if (!master.empty()) {
826 os << "\\master " << master << '\n';
830 if (!removedModules_.empty()) {
831 os << "\\begin_removed_modules" << '\n';
832 list<string>::const_iterator it = removedModules_.begin();
833 list<string>::const_iterator en = removedModules_.end();
834 for (; it != en; it++)
836 os << "\\end_removed_modules" << '\n';
840 if (!layoutModules_.empty()) {
841 os << "\\begin_modules" << '\n';
842 LayoutModuleList::const_iterator it = layoutModules_.begin();
843 LayoutModuleList::const_iterator en = layoutModules_.end();
844 for (; it != en; it++)
846 os << "\\end_modules" << '\n';
850 if (!includedChildren_.empty()) {
851 os << "\\begin_includeonly" << '\n';
852 list<string>::const_iterator it = includedChildren_.begin();
853 list<string>::const_iterator en = includedChildren_.end();
854 for (; it != en; it++)
856 os << "\\end_includeonly" << '\n';
858 os << "\\maintain_unincluded_children "
859 << convert<string>(maintain_unincluded_children) << '\n';
861 // local layout information
862 if (!local_layout.empty()) {
863 // remove '\n' from the end
864 string const tmplocal = rtrim(local_layout, "\n");
865 os << "\\begin_local_layout\n"
867 << "\n\\end_local_layout\n";
870 // then the text parameters
871 if (language != ignore_language)
872 os << "\\language " << language->lang() << '\n';
873 os << "\\inputencoding " << inputenc
874 << "\n\\fontencoding " << fontenc
875 << "\n\\font_roman " << fontsRoman
876 << "\n\\font_sans " << fontsSans
877 << "\n\\font_typewriter " << fontsTypewriter
878 << "\n\\font_default_family " << fontsDefaultFamily
879 << "\n\\use_xetex " << convert<string>(useXetex)
880 << "\n\\font_sc " << convert<string>(fontsSC)
881 << "\n\\font_osf " << convert<string>(fontsOSF)
882 << "\n\\font_sf_scale " << fontsSansScale
883 << "\n\\font_tt_scale " << fontsTypewriterScale
885 if (!fontsCJK.empty()) {
886 os << "\\font_cjk " << fontsCJK << '\n';
888 os << "\n\\graphics " << graphicsDriver << '\n';
889 os << "\\default_output_format " << defaultOutputFormat << '\n';
890 os << "\\bibtex_command " << bibtex_command << '\n';
891 os << "\\index_command " << index_command << '\n';
893 if (!float_placement.empty()) {
894 os << "\\float_placement " << float_placement << '\n';
896 os << "\\paperfontsize " << fontsize << '\n';
898 spacing().writeFile(os);
899 pdfoptions().writeFile(os);
901 os << "\\papersize " << string_papersize[papersize]
902 << "\n\\use_geometry " << convert<string>(use_geometry)
903 << "\n\\use_amsmath " << use_amsmath
904 << "\n\\use_esint " << use_esint
905 << "\n\\use_mhchem " << use_mhchem
906 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
907 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
908 << "\n\\use_indices " << convert<string>(use_indices)
909 << "\n\\paperorientation " << string_orientation[orientation]
910 << "\n\\suppress_date " << convert<string>(suppress_date)
912 if (backgroundcolor != lyx::rgbFromHexName("#ffffff"))
913 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
915 BranchList::const_iterator it = branchlist().begin();
916 BranchList::const_iterator end = branchlist().end();
917 for (; it != end; ++it) {
918 os << "\\branch " << to_utf8(it->branch())
919 << "\n\\selected " << it->isSelected()
920 << "\n\\filename_suffix " << it->hasFilenameSuffix()
921 << "\n\\color " << lyx::X11hexname(it->color())
926 IndicesList::const_iterator iit = indiceslist().begin();
927 IndicesList::const_iterator iend = indiceslist().end();
928 for (; iit != iend; ++iit) {
929 os << "\\index " << to_utf8(iit->index())
930 << "\n\\shortcut " << to_utf8(iit->shortcut())
931 << "\n\\color " << lyx::X11hexname(iit->color())
936 if (!paperwidth.empty())
937 os << "\\paperwidth "
938 << VSpace(paperwidth).asLyXCommand() << '\n';
939 if (!paperheight.empty())
940 os << "\\paperheight "
941 << VSpace(paperheight).asLyXCommand() << '\n';
942 if (!leftmargin.empty())
943 os << "\\leftmargin "
944 << VSpace(leftmargin).asLyXCommand() << '\n';
945 if (!topmargin.empty())
947 << VSpace(topmargin).asLyXCommand() << '\n';
948 if (!rightmargin.empty())
949 os << "\\rightmargin "
950 << VSpace(rightmargin).asLyXCommand() << '\n';
951 if (!bottommargin.empty())
952 os << "\\bottommargin "
953 << VSpace(bottommargin).asLyXCommand() << '\n';
954 if (!headheight.empty())
955 os << "\\headheight "
956 << VSpace(headheight).asLyXCommand() << '\n';
957 if (!headsep.empty())
959 << VSpace(headsep).asLyXCommand() << '\n';
960 if (!footskip.empty())
962 << VSpace(footskip).asLyXCommand() << '\n';
963 if (!columnsep.empty())
965 << VSpace(columnsep).asLyXCommand() << '\n';
966 os << "\\secnumdepth " << secnumdepth
967 << "\n\\tocdepth " << tocdepth
968 << "\n\\paragraph_separation "
969 << string_paragraph_separation[paragraph_separation];
970 if (!paragraph_separation)
971 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
973 os << "\n\\defskip " << getDefSkip().asLyXCommand();
974 os << "\n\\quotes_language "
975 << string_quotes_language[quotes_language]
976 << "\n\\papercolumns " << columns
977 << "\n\\papersides " << sides
978 << "\n\\paperpagestyle " << pagestyle << '\n';
979 if (!listings_params.empty())
980 os << "\\listings_params \"" <<
981 InsetListingsParams(listings_params).encodedString() << "\"\n";
982 for (int i = 0; i < 4; ++i) {
983 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
984 if (user_defined_bullet(i).getFont() != -1) {
985 os << "\\bullet " << i << " "
986 << user_defined_bullet(i).getFont() << " "
987 << user_defined_bullet(i).getCharacter() << " "
988 << user_defined_bullet(i).getSize() << "\n";
992 os << "\\bulletLaTeX " << i << " \""
993 << lyx::to_ascii(user_defined_bullet(i).getText())
999 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n"
1000 << "\\output_changes " << convert<string>(outputChanges) << "\n"
1001 << "\\html_math_output " << html_math_output << "\n"
1002 << "\\html_be_strict " << convert<string>(html_be_strict) << "\n";
1004 os << pimpl_->authorlist;
1008 void BufferParams::validate(LaTeXFeatures & features) const
1010 features.require(documentClass().requires());
1012 if (outputChanges) {
1013 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1014 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1015 LaTeXFeatures::isAvailable("xcolor");
1017 switch (features.runparams().flavor) {
1018 case OutputParams::LATEX:
1020 features.require("ct-dvipost");
1021 features.require("dvipost");
1022 } else if (xcolorulem) {
1023 features.require("ct-xcolor-ulem");
1024 features.require("ulem");
1025 features.require("xcolor");
1027 features.require("ct-none");
1030 case OutputParams::PDFLATEX:
1031 case OutputParams::XETEX:
1033 features.require("ct-xcolor-ulem");
1034 features.require("ulem");
1035 features.require("xcolor");
1036 // improves color handling in PDF output
1037 features.require("pdfcolmk");
1039 features.require("ct-none");
1047 // Floats with 'Here definitely' as default setting.
1048 if (float_placement.find('H') != string::npos)
1049 features.require("float");
1051 // AMS Style is at document level
1052 if (use_amsmath == package_on
1053 || documentClass().provides("amsmath"))
1054 features.require("amsmath");
1055 if (use_esint == package_on)
1056 features.require("esint");
1057 if (use_mhchem == package_on)
1058 features.require("mhchem");
1060 // Document-level line spacing
1061 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1062 features.require("setspace");
1064 // the bullet shapes are buffer level not paragraph level
1065 // so they are tested here
1066 for (int i = 0; i < 4; ++i) {
1067 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1069 int const font = user_defined_bullet(i).getFont();
1071 int const c = user_defined_bullet(i).getCharacter();
1077 features.require("latexsym");
1079 } else if (font == 1) {
1080 features.require("amssymb");
1081 } else if (font >= 2 && font <= 5) {
1082 features.require("pifont");
1086 if (pdfoptions().use_hyperref) {
1087 features.require("hyperref");
1088 // due to interferences with babel and hyperref, the color package has to
1089 // be loaded after hyperref when hyperref is used with the colorlinks
1090 // option, see http://www.lyx.org/trac/ticket/5291
1091 if (pdfoptions().colorlinks)
1092 features.require("color");
1096 features.require("xetex");
1098 if (language->lang() == "vietnamese")
1099 features.require("vietnamese");
1100 else if (language->lang() == "japanese")
1101 features.require("japanese");
1105 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1106 TexRow & texrow, FileName const & filepath) const
1108 os << "\\documentclass";
1110 DocumentClass const & tclass = documentClass();
1112 ostringstream clsoptions; // the document class options.
1114 if (tokenPos(tclass.opt_fontsize(),
1115 '|', fontsize) >= 0) {
1116 // only write if existing in list (and not default)
1117 clsoptions << fontsize << "pt,";
1120 // custom, A3, B3 and B4 paper sizes need geometry
1121 bool nonstandard_papersize = papersize == PAPER_B3
1122 || papersize == PAPER_B4
1123 || papersize == PAPER_A3
1124 || papersize == PAPER_CUSTOM;
1126 if (!use_geometry) {
1127 switch (papersize) {
1129 clsoptions << "a4paper,";
1131 case PAPER_USLETTER:
1132 clsoptions << "letterpaper,";
1135 clsoptions << "a5paper,";
1138 clsoptions << "b5paper,";
1140 case PAPER_USEXECUTIVE:
1141 clsoptions << "executivepaper,";
1144 clsoptions << "legalpaper,";
1156 if (sides != tclass.sides()) {
1159 clsoptions << "oneside,";
1162 clsoptions << "twoside,";
1168 if (columns != tclass.columns()) {
1170 clsoptions << "twocolumn,";
1172 clsoptions << "onecolumn,";
1176 && orientation == ORIENTATION_LANDSCAPE)
1177 clsoptions << "landscape,";
1179 // language should be a parameter to \documentclass
1180 if (language->babel() == "hebrew"
1181 && default_language->babel() != "hebrew")
1182 // This seems necessary
1183 features.useLanguage(default_language);
1185 ostringstream language_options;
1186 bool const use_babel = features.useBabel();
1188 language_options << features.getLanguages();
1189 if (!language->babel().empty()) {
1190 if (!language_options.str().empty())
1191 language_options << ',';
1192 language_options << language->babel();
1194 // if Vietnamese is used, babel must directly be loaded
1195 // with language options, not in the class options, see
1196 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1197 size_t viet = language_options.str().find("vietnam");
1198 // viet = string::npos when not found
1199 // the same is for all other languages that are not directly supported by
1200 // babel, but where LaTeX-packages add babel support.
1201 // this is currently the case for Latvian, Lithuanian, and Mongolian
1202 size_t latvian = language_options.str().find("latvian");
1203 size_t lithu = language_options.str().find("lithuanian");
1204 size_t mongo = language_options.str().find("mongolian");
1205 // if Japanese is used, babel must directly be loaded
1206 // with language options, not in the class options, see
1207 // http://www.lyx.org/trac/ticket/4597#c4
1208 size_t japan = language_options.str().find("japanese");
1209 if (lyxrc.language_global_options && !language_options.str().empty()
1210 && viet == string::npos && japan == string::npos
1211 && latvian == string::npos && lithu == string::npos
1212 && mongo == string::npos)
1213 clsoptions << language_options.str() << ',';
1216 // the predefined options from the layout
1217 if (use_default_options && !tclass.options().empty())
1218 clsoptions << tclass.options() << ',';
1220 // the user-defined options
1221 if (!options.empty()) {
1222 clsoptions << options << ',';
1225 string strOptions(clsoptions.str());
1226 if (!strOptions.empty()) {
1227 strOptions = rtrim(strOptions, ",");
1229 os << '[' << from_utf8(strOptions) << ']';
1232 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1234 // end of \documentclass defs
1237 os << "\\usepackage{fontspec}\n";
1241 // font selection must be done before loading fontenc.sty
1242 string const fonts =
1243 loadFonts(fontsRoman, fontsSans,
1244 fontsTypewriter, fontsSC, fontsOSF,
1245 fontsSansScale, fontsTypewriterScale, useXetex);
1246 if (!fonts.empty()) {
1247 os << from_ascii(fonts);
1250 if (fontsDefaultFamily != "default")
1251 os << "\\renewcommand{\\familydefault}{\\"
1252 << from_ascii(fontsDefaultFamily) << "}\n";
1254 // set font encoding
1255 // for arabic_arabi and farsi we also need to load the LAE and
1257 // XeTeX works without fontenc
1258 if (font_encoding() != "default" && language->lang() != "japanese"
1260 if (language->lang() == "arabic_arabi"
1261 || language->lang() == "farsi") {
1262 os << "\\usepackage[" << from_ascii(font_encoding())
1263 << ",LFE,LAE]{fontenc}\n";
1266 os << "\\usepackage[" << from_ascii(font_encoding())
1272 // handle inputenc etc.
1273 writeEncodingPreamble(os, features, texrow);
1276 if (!features.runparams().includeall && !includedChildren_.empty()) {
1277 os << "\\includeonly{";
1278 list<string>::const_iterator it = includedChildren_.begin();
1280 for (; it != includedChildren_.end() ; ++it) {
1281 string incfile = *it;
1282 FileName inc = makeAbsPath(incfile, filepath.absFilename());
1283 string mangled = DocFileName(changeExtension(inc.absFilename(), ".tex")).
1285 if (!features.runparams().nice)
1287 // \includeonly doesn't want an extension
1288 incfile = changeExtension(incfile, string());
1289 incfile = support::latex_path(incfile);
1290 if (!incfile.empty()) {
1293 os << from_utf8(incfile);
1300 if (!listings_params.empty() || features.isRequired("listings")) {
1301 os << "\\usepackage{listings}\n";
1304 if (!listings_params.empty()) {
1306 // do not test validity because listings_params is
1307 // supposed to be valid
1309 InsetListingsParams(listings_params).separatedParams(true);
1310 // we can't support all packages, but we should load the color package
1311 if (par.find("\\color", 0) != string::npos)
1312 features.require("color");
1313 os << from_utf8(par);
1314 // count the number of newlines
1315 for (size_t i = 0; i < par.size(); ++i)
1321 if (!tclass.provides("geometry")
1322 && (use_geometry || nonstandard_papersize)) {
1323 odocstringstream ods;
1324 if (!getGraphicsDriver("geometry").empty())
1325 ods << getGraphicsDriver("geometry");
1326 if (orientation == ORIENTATION_LANDSCAPE)
1327 ods << ",landscape";
1328 switch (papersize) {
1330 if (!paperwidth.empty())
1331 ods << ",paperwidth="
1332 << from_ascii(paperwidth);
1333 if (!paperheight.empty())
1334 ods << ",paperheight="
1335 << from_ascii(paperheight);
1337 case PAPER_USLETTER:
1338 ods << ",letterpaper";
1341 ods << ",legalpaper";
1343 case PAPER_USEXECUTIVE:
1344 ods << ",executivepaper";
1365 // default papersize ie PAPER_DEFAULT
1366 switch (lyxrc.default_papersize) {
1367 case PAPER_DEFAULT: // keep compiler happy
1368 case PAPER_USLETTER:
1369 ods << ",letterpaper";
1372 ods << ",legalpaper";
1374 case PAPER_USEXECUTIVE:
1375 ods << ",executivepaper";
1395 docstring const g_options = trim(ods.str(), ",");
1396 os << "\\usepackage";
1397 if (!g_options.empty())
1398 os << '[' << g_options << ']';
1399 os << "{geometry}\n";
1401 os << "\\geometry{verbose";
1402 if (!topmargin.empty())
1403 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1404 if (!bottommargin.empty())
1405 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1406 if (!leftmargin.empty())
1407 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1408 if (!rightmargin.empty())
1409 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1410 if (!headheight.empty())
1411 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1412 if (!headsep.empty())
1413 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1414 if (!footskip.empty())
1415 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1416 if (!columnsep.empty())
1417 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1420 } else if (orientation == ORIENTATION_LANDSCAPE) {
1421 features.require("papersize");
1424 if (tokenPos(tclass.opt_pagestyle(),
1425 '|', pagestyle) >= 0) {
1426 if (pagestyle == "fancy") {
1427 os << "\\usepackage{fancyhdr}\n";
1430 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1434 // only output when the background color is not white
1435 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1436 // only require color here, the background color will be defined
1437 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1439 features.require("color");
1440 features.require("pagecolor");
1443 // Only if class has a ToC hierarchy
1444 if (tclass.hasTocLevels()) {
1445 if (secnumdepth != tclass.secnumdepth()) {
1446 os << "\\setcounter{secnumdepth}{"
1451 if (tocdepth != tclass.tocdepth()) {
1452 os << "\\setcounter{tocdepth}{"
1459 if (paragraph_separation) {
1460 // when skip separation
1461 switch (getDefSkip().kind()) {
1462 case VSpace::SMALLSKIP:
1463 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1465 case VSpace::MEDSKIP:
1466 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1468 case VSpace::BIGSKIP:
1469 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1471 case VSpace::LENGTH:
1472 os << "\\setlength{\\parskip}{"
1473 << from_utf8(getDefSkip().length().asLatexString())
1476 default: // should never happen // Then delete it.
1477 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1481 os << "\\setlength{\\parindent}{0pt}\n";
1484 // when separation by indentation
1485 // only output something when a width is given
1486 if (getIndentation().asLyXCommand() != "default") {
1487 os << "\\setlength{\\parindent}{"
1488 << from_utf8(getIndentation().asLatexCommand())
1494 // Now insert the LyX specific LaTeX commands...
1495 docstring lyxpreamble;
1497 // due to interferences with babel and hyperref, the color package has to
1498 // be loaded (when it is not already loaded) before babel when hyperref
1499 // is used with the colorlinks option, see
1500 // http://www.lyx.org/trac/ticket/5291
1501 // we decided therefore to load color always before babel, see
1502 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1503 lyxpreamble += from_ascii(features.getColorOptions());
1505 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1507 && (features.isRequired("jurabib")
1508 || features.isRequired("hyperref")
1509 || features.isRequired("vietnamese")
1510 || features.isRequired("japanese") ) ) {
1512 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1513 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1516 // The optional packages;
1517 lyxpreamble += from_ascii(features.getPackages());
1519 // Additional Indices
1520 if (features.isRequired("splitidx")) {
1521 IndicesList::const_iterator iit = indiceslist().begin();
1522 IndicesList::const_iterator iend = indiceslist().end();
1523 for (; iit != iend; ++iit) {
1524 lyxpreamble += "\\newindex[";
1525 lyxpreamble += iit->index();
1526 lyxpreamble += "]{";
1527 lyxpreamble += iit->shortcut();
1528 lyxpreamble += "}\n";
1533 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1536 // * Hyperref manual: "Make sure it comes last of your loaded
1537 // packages, to give it a fighting chance of not being over-written,
1538 // since its job is to redefine many LaTeX commands."
1539 // * Email from Heiko Oberdiek: "It is usually better to load babel
1540 // before hyperref. Then hyperref has a chance to detect babel.
1541 // * Has to be loaded before the "LyX specific LaTeX commands" to
1542 // avoid errors with algorithm floats.
1543 // use hyperref explicitly if it is required
1544 if (features.isRequired("hyperref")) {
1545 // pass what we have to stream here, since we need
1546 // to access the stream itself in PDFOptions.
1550 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1552 OutputParams tmp_params = features.runparams();
1553 lines += pdfoptions().writeLaTeX(tmp_params, os,
1554 documentClass().provides("hyperref"));
1555 texrow.newlines(lines);
1556 // set back for the rest
1557 lyxpreamble.clear();
1560 // Will be surrounded by \makeatletter and \makeatother when not empty
1561 docstring atlyxpreamble;
1563 // Some macros LyX will need
1564 docstring tmppreamble(features.getMacros());
1566 if (!tmppreamble.empty())
1567 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1568 "LyX specific LaTeX commands.\n"
1569 + tmppreamble + '\n';
1571 // the text class specific preamble
1572 tmppreamble = features.getTClassPreamble();
1573 if (!tmppreamble.empty())
1574 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1575 "Textclass specific LaTeX commands.\n"
1576 + tmppreamble + '\n';
1578 // suppress date if selected
1579 // use \@ifundefined because we cannot be sure that every document class
1580 // has a \date command
1582 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1584 /* the user-defined preamble */
1585 if (!containsOnly(preamble, " \n\t"))
1587 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1588 "User specified LaTeX commands.\n"
1589 + from_utf8(preamble) + '\n';
1591 // subfig loads internally the LaTeX package "caption". As
1592 // caption is a very popular package, users will load it in
1593 // the preamble. Therefore we must load subfig behind the
1594 // user-defined preamble and check if the caption package was
1595 // loaded or not. For the case that caption is loaded before
1596 // subfig, there is the subfig option "caption=false". This
1597 // option also works when a koma-script class is used and
1598 // koma's own caption commands are used instead of caption. We
1599 // use \PassOptionsToPackage here because the user could have
1600 // already loaded subfig in the preamble.
1601 if (features.isRequired("subfig")) {
1602 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1603 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1604 "\\usepackage{subfig}\n";
1607 // Itemize bullet settings need to be last in case the user
1608 // defines their own bullets that use a package included
1609 // in the user-defined preamble -- ARRae
1610 // Actually it has to be done much later than that
1611 // since some packages like frenchb make modifications
1612 // at \begin{document} time -- JMarc
1613 docstring bullets_def;
1614 for (int i = 0; i < 4; ++i) {
1615 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1616 if (bullets_def.empty())
1617 bullets_def += "\\AtBeginDocument{\n";
1618 bullets_def += " \\def\\labelitemi";
1620 // `i' is one less than the item to modify
1627 bullets_def += "ii";
1633 bullets_def += '{' +
1634 user_defined_bullet(i).getText()
1639 if (!bullets_def.empty())
1640 atlyxpreamble += bullets_def + "}\n\n";
1642 if (!atlyxpreamble.empty())
1643 lyxpreamble += "\n\\makeatletter\n"
1644 + atlyxpreamble + "\\makeatother\n\n";
1646 // We try to load babel late, in case it interferes with other packages.
1647 // Jurabib and Hyperref have to be called after babel, though.
1648 if (use_babel && !features.isRequired("jurabib")
1649 && !features.isRequired("hyperref")
1650 && !features.isRequired("vietnamese")
1651 && !features.isRequired("japanese")) {
1653 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1654 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1657 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1658 if (!i18npreamble.empty())
1659 lyxpreamble += i18npreamble + '\n';
1662 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1663 texrow.newlines(nlines);
1667 // these packages (xunicode, for that matter) need to be loaded at least
1668 // after amsmath, amssymb, esint and the other packages that provide
1671 os << "\\usepackage{xunicode}\n";
1673 os << "\\usepackage{xltxtra}\n";
1680 void BufferParams::useClassDefaults()
1682 DocumentClass const & tclass = documentClass();
1684 sides = tclass.sides();
1685 columns = tclass.columns();
1686 pagestyle = tclass.pagestyle();
1687 use_default_options = true;
1688 // Only if class has a ToC hierarchy
1689 if (tclass.hasTocLevels()) {
1690 secnumdepth = tclass.secnumdepth();
1691 tocdepth = tclass.tocdepth();
1696 bool BufferParams::hasClassDefaults() const
1698 DocumentClass const & tclass = documentClass();
1700 return sides == tclass.sides()
1701 && columns == tclass.columns()
1702 && pagestyle == tclass.pagestyle()
1703 && use_default_options
1704 && secnumdepth == tclass.secnumdepth()
1705 && tocdepth == tclass.tocdepth();
1709 DocumentClass const & BufferParams::documentClass() const
1715 DocumentClass const * BufferParams::documentClassPtr() const {
1720 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1721 // evil, but this function is evil
1722 doc_class_ = const_cast<DocumentClass *>(tc);
1726 bool BufferParams::setBaseClass(string const & classname)
1728 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1729 LayoutFileList & bcl = LayoutFileList::get();
1730 if (!bcl.haveClass(classname)) {
1732 bformat(_("The document class %1$s could not be found. "
1733 "A default textclass with default layouts will be used. "
1734 "LyX might not be able to produce output unless a correct "
1735 "textclass is selected from the document settings dialog."),
1736 from_utf8(classname));
1737 frontend::Alert::error(_("Document class not found"), s);
1738 bcl.addEmptyClass(classname);
1741 bool const success = bcl[classname].load();
1744 bformat(_("The document class %1$s could not be loaded."),
1745 from_utf8(classname));
1746 frontend::Alert::error(_("Could not load class"), s);
1750 pimpl_->baseClass_ = classname;
1751 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1756 LayoutFile const * BufferParams::baseClass() const
1758 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1759 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1765 LayoutFileIndex const & BufferParams::baseClassID() const
1767 return pimpl_->baseClass_;
1771 void BufferParams::makeDocumentClass()
1776 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1778 if (!local_layout.empty()) {
1779 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1780 docstring const msg = _("Error reading internal layout information");
1781 frontend::Alert::warning(_("Read Error"), msg);
1786 bool BufferParams::moduleCanBeAdded(string const & modName) const
1788 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1792 bool BufferParams::addLayoutModule(string const & modName)
1794 LayoutModuleList::const_iterator it = layoutModules_.begin();
1795 LayoutModuleList::const_iterator end = layoutModules_.end();
1796 for (; it != end; it++)
1799 layoutModules_.push_back(modName);
1804 Font const BufferParams::getFont() const
1806 FontInfo f = documentClass().defaultfont();
1807 if (fontsDefaultFamily == "rmdefault")
1808 f.setFamily(ROMAN_FAMILY);
1809 else if (fontsDefaultFamily == "sfdefault")
1810 f.setFamily(SANS_FAMILY);
1811 else if (fontsDefaultFamily == "ttdefault")
1812 f.setFamily(TYPEWRITER_FAMILY);
1813 return Font(f, language);
1817 void BufferParams::readPreamble(Lexer & lex)
1819 if (lex.getString() != "\\begin_preamble")
1820 lyxerr << "Error (BufferParams::readPreamble):"
1821 "consistency check failed." << endl;
1823 preamble = lex.getLongString("\\end_preamble");
1827 void BufferParams::readLocalLayout(Lexer & lex)
1829 if (lex.getString() != "\\begin_local_layout")
1830 lyxerr << "Error (BufferParams::readLocalLayout):"
1831 "consistency check failed." << endl;
1833 local_layout = lex.getLongString("\\end_local_layout");
1837 void BufferParams::readLanguage(Lexer & lex)
1839 if (!lex.next()) return;
1841 string const tmptok = lex.getString();
1843 // check if tmptok is part of tex_babel in tex-defs.h
1844 language = languages.getLanguage(tmptok);
1846 // Language tmptok was not found
1847 language = default_language;
1848 lyxerr << "Warning: Setting language `"
1849 << tmptok << "' to `" << language->lang()
1855 void BufferParams::readGraphicsDriver(Lexer & lex)
1860 string const tmptok = lex.getString();
1861 // check if tmptok is part of tex_graphics in tex_defs.h
1864 string const test = tex_graphics[n++];
1866 if (test == tmptok) {
1867 graphicsDriver = tmptok;
1872 "Warning: graphics driver `$$Token' not recognized!\n"
1873 " Setting graphics driver to `default'.\n");
1874 graphicsDriver = "default";
1881 void BufferParams::readBullets(Lexer & lex)
1886 int const index = lex.getInteger();
1888 int temp_int = lex.getInteger();
1889 user_defined_bullet(index).setFont(temp_int);
1890 temp_bullet(index).setFont(temp_int);
1892 user_defined_bullet(index).setCharacter(temp_int);
1893 temp_bullet(index).setCharacter(temp_int);
1895 user_defined_bullet(index).setSize(temp_int);
1896 temp_bullet(index).setSize(temp_int);
1900 void BufferParams::readBulletsLaTeX(Lexer & lex)
1902 // The bullet class should be able to read this.
1905 int const index = lex.getInteger();
1907 docstring const temp_str = lex.getDocString();
1909 user_defined_bullet(index).setText(temp_str);
1910 temp_bullet(index).setText(temp_str);
1914 void BufferParams::readModules(Lexer & lex)
1916 if (!lex.eatLine()) {
1917 lyxerr << "Error (BufferParams::readModules):"
1918 "Unexpected end of input." << endl;
1922 string mod = lex.getString();
1923 if (mod == "\\end_modules")
1925 addLayoutModule(mod);
1931 void BufferParams::readRemovedModules(Lexer & lex)
1933 if (!lex.eatLine()) {
1934 lyxerr << "Error (BufferParams::readRemovedModules):"
1935 "Unexpected end of input." << endl;
1939 string mod = lex.getString();
1940 if (mod == "\\end_removed_modules")
1942 removedModules_.push_back(mod);
1945 // now we want to remove any removed modules that were previously
1946 // added. normally, that will be because default modules were added in
1947 // setBaseClass(), which gets called when \textclass is read at the
1948 // start of the read.
1949 list<string>::const_iterator rit = removedModules_.begin();
1950 list<string>::const_iterator const ren = removedModules_.end();
1951 for (; rit != ren; rit++) {
1952 LayoutModuleList::iterator const mit = layoutModules_.begin();
1953 LayoutModuleList::iterator const men = layoutModules_.end();
1954 LayoutModuleList::iterator found = find(mit, men, *rit);
1957 layoutModules_.erase(found);
1962 void BufferParams::readIncludeonly(Lexer & lex)
1964 if (!lex.eatLine()) {
1965 lyxerr << "Error (BufferParams::readIncludeonly):"
1966 "Unexpected end of input." << endl;
1970 string child = lex.getString();
1971 if (child == "\\end_includeonly")
1973 includedChildren_.push_back(child);
1979 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1981 char real_papersize = papersize;
1982 if (real_papersize == PAPER_DEFAULT)
1983 real_papersize = lyxrc.default_papersize;
1985 switch (real_papersize) {
1987 // could be anything, so don't guess
1989 case PAPER_CUSTOM: {
1990 if (purpose == XDVI && !paperwidth.empty() &&
1991 !paperheight.empty()) {
1992 // heightxwidth<unit>
1993 string first = paperwidth;
1994 string second = paperheight;
1995 if (orientation == ORIENTATION_LANDSCAPE)
1998 return first.erase(first.length() - 2)
2010 // dvips and dvipdfm do not know this
2011 if (purpose == DVIPS || purpose == DVIPDFM)
2015 // dvipdfm does not know this
2016 if (purpose == DVIPDFM)
2020 // dvipdfm does not know this
2021 if (purpose == DVIPDFM)
2024 case PAPER_USEXECUTIVE:
2025 // dvipdfm does not know this
2026 if (purpose == DVIPDFM)
2031 case PAPER_USLETTER:
2033 if (purpose == XDVI)
2040 string const BufferParams::dvips_options() const
2045 && papersize == PAPER_CUSTOM
2046 && !lyxrc.print_paper_dimension_flag.empty()
2047 && !paperwidth.empty()
2048 && !paperheight.empty()) {
2049 // using a custom papersize
2050 result = lyxrc.print_paper_dimension_flag;
2051 result += ' ' + paperwidth;
2052 result += ',' + paperheight;
2054 string const paper_option = paperSizeName(DVIPS);
2055 if (!paper_option.empty() && (paper_option != "letter" ||
2056 orientation != ORIENTATION_LANDSCAPE)) {
2057 // dvips won't accept -t letter -t landscape.
2058 // In all other cases, include the paper size
2060 result = lyxrc.print_paper_flag;
2061 result += ' ' + paper_option;
2064 if (orientation == ORIENTATION_LANDSCAPE &&
2065 papersize != PAPER_CUSTOM)
2066 result += ' ' + lyxrc.print_landscape_flag;
2071 string const BufferParams::font_encoding() const
2073 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2077 string BufferParams::babelCall(string const & lang_opts) const
2079 string lang_pack = lyxrc.language_package;
2080 if (lang_pack != "\\usepackage{babel}")
2082 // suppress the babel call when there is no babel language defined
2083 // for the document language in the lib/languages file and if no
2084 // other languages are used (lang_opts is then empty)
2085 if (lang_opts.empty())
2087 // If Vietnamese is used, babel must directly be loaded with the
2088 // language options, see
2089 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2090 size_t viet = lang_opts.find("vietnam");
2091 // viet = string::npos when not found
2092 // the same is for all other languages that are not directly supported by
2093 // babel, but where LaTeX-packages add babel support.
2094 // this is currently the case for Latvian, Lithuanian, and Mongolian
2095 size_t latvian = lang_opts.find("latvian");
2096 size_t lithu = lang_opts.find("lithuanian");
2097 size_t mongo = lang_opts.find("mongolian");
2098 // If Japanese is used, babel must directly be loaded with the
2099 // language options, see
2100 // http://www.lyx.org/trac/ticket/4597#c4
2101 size_t japan = lang_opts.find("japanese");
2102 if (!lyxrc.language_global_options || viet != string::npos
2103 || japan != string::npos || latvian != string::npos
2104 || lithu != string::npos || mongo != string::npos)
2105 return "\\usepackage[" + lang_opts + "]{babel}";
2110 docstring BufferParams::getGraphicsDriver(string const & package) const
2114 if (package == "geometry") {
2115 if (graphicsDriver == "dvips"
2116 || graphicsDriver == "dvipdfm"
2117 || graphicsDriver == "pdftex"
2118 || graphicsDriver == "vtex")
2119 result = from_ascii(graphicsDriver);
2120 else if (graphicsDriver == "dvipdfmx")
2121 result = from_ascii("dvipdfm");
2128 void BufferParams::writeEncodingPreamble(odocstream & os,
2129 LaTeXFeatures & features, TexRow & texrow) const
2133 if (inputenc == "auto") {
2134 string const doc_encoding =
2135 language->encoding()->latexName();
2136 Encoding::Package const package =
2137 language->encoding()->package();
2139 // Create a list with all the input encodings used
2141 set<string> encodings =
2142 features.getEncodingSet(doc_encoding);
2144 // If the "japanese" package (i.e. pLaTeX) is used,
2145 // inputenc must be omitted.
2146 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2147 if (package == Encoding::japanese)
2148 features.require("japanese");
2150 if ((!encodings.empty() || package == Encoding::inputenc)
2151 && !features.isRequired("japanese")) {
2152 os << "\\usepackage[";
2153 set<string>::const_iterator it = encodings.begin();
2154 set<string>::const_iterator const end = encodings.end();
2156 os << from_ascii(*it);
2159 for (; it != end; ++it)
2160 os << ',' << from_ascii(*it);
2161 if (package == Encoding::inputenc) {
2162 if (!encodings.empty())
2164 os << from_ascii(doc_encoding);
2166 os << "]{inputenc}\n";
2169 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2170 if (language->encoding()->name() == "utf8-cjk"
2171 && LaTeXFeatures::isAvailable("CJKutf8"))
2172 os << "\\usepackage{CJKutf8}\n";
2174 os << "\\usepackage{CJK}\n";
2177 } else if (inputenc != "default") {
2178 switch (encoding().package()) {
2179 case Encoding::none:
2180 case Encoding::japanese:
2182 case Encoding::inputenc:
2183 // do not load inputenc if japanese is used
2184 if (features.isRequired("japanese"))
2186 os << "\\usepackage[" << from_ascii(inputenc)
2191 if (encoding().name() == "utf8-cjk"
2192 && LaTeXFeatures::isAvailable("CJKutf8"))
2193 os << "\\usepackage{CJKutf8}\n";
2195 os << "\\usepackage{CJK}\n";
2201 // The encoding "armscii8" (for Armenian) is only available when
2202 // the package "armtex" is loaded.
2203 if (language->encoding()->latexName() == "armscii8"
2204 || inputenc == "armscii8") {
2205 os << "\\usepackage{armtex}\n";
2211 string const BufferParams::parseFontName(string const & name) const
2213 string mangled = name;
2214 size_t const idx = mangled.find('[');
2215 if (idx == string::npos || idx == 0)
2218 return mangled.substr(0, idx - 1);
2222 string const BufferParams::loadFonts(string const & rm,
2223 string const & sf, string const & tt,
2224 bool const & sc, bool const & osf,
2225 int const & sfscale, int const & ttscale,
2226 bool const & xetex) const
2228 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2229 several packages have been replaced by others, that might not
2230 be installed on every system. We have to take care for that
2231 (see psnfss.pdf). We try to support all psnfss fonts as well
2232 as the fonts that have become de facto standard in the LaTeX
2233 world (e.g. Latin Modern). We do not support obsolete fonts
2234 (like PSLatex). In general, it should be possible to mix any
2235 rm font with any sf or tt font, respectively. (JSpitzm)
2237 -- separate math fonts.
2240 if (rm == "default" && sf == "default" && tt == "default")
2247 if (rm != "default")
2248 os << "\\setmainfont[Mapping=tex-text]{"
2249 << parseFontName(rm) << "}\n";
2250 if (sf != "default") {
2251 string const sans = parseFontName(sf);
2253 os << "\\setsansfont[Scale="
2254 << float(sfscale) / 100
2255 << ",Mapping=tex-text]{"
2258 os << "\\setsansfont[Mapping=tex-text]{"
2261 if (tt != "default") {
2262 string const mono = parseFontName(tt);
2264 os << "\\setmonofont[Scale="
2265 << float(sfscale) / 100
2269 os << "\\setmonofont[Mapping=tex-text]{"
2273 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2278 // Computer Modern (must be explicitly selectable -- there might be classes
2279 // that define a different default font!
2281 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2282 // osf for Computer Modern needs eco.sty
2284 os << "\\usepackage{eco}\n";
2286 // Latin Modern Roman
2287 else if (rm == "lmodern")
2288 os << "\\usepackage{lmodern}\n";
2290 else if (rm == "ae") {
2291 // not needed when using OT1 font encoding.
2292 if (font_encoding() != "default")
2293 os << "\\usepackage{ae,aecompl}\n";
2296 else if (rm == "times") {
2297 // try to load the best available package
2298 if (LaTeXFeatures::isAvailable("mathptmx"))
2299 os << "\\usepackage{mathptmx}\n";
2300 else if (LaTeXFeatures::isAvailable("mathptm"))
2301 os << "\\usepackage{mathptm}\n";
2303 os << "\\usepackage{times}\n";
2306 else if (rm == "palatino") {
2307 // try to load the best available package
2308 if (LaTeXFeatures::isAvailable("mathpazo")) {
2309 os << "\\usepackage";
2315 // "osf" includes "sc"!
2319 os << "{mathpazo}\n";
2321 else if (LaTeXFeatures::isAvailable("mathpple"))
2322 os << "\\usepackage{mathpple}\n";
2324 os << "\\usepackage{palatino}\n";
2327 else if (rm == "utopia") {
2328 // fourier supersedes utopia.sty, but does
2329 // not work with OT1 encoding.
2330 if (LaTeXFeatures::isAvailable("fourier")
2331 && font_encoding() != "default") {
2332 os << "\\usepackage";
2343 os << "{fourier}\n";
2346 os << "\\usepackage{utopia}\n";
2348 // Bera (complete fontset)
2349 else if (rm == "bera" && sf == "default" && tt == "default")
2350 os << "\\usepackage{bera}\n";
2352 else if (rm != "default")
2353 os << "\\usepackage" << "{" << rm << "}\n";
2356 // Helvetica, Bera Sans
2357 if (sf == "helvet" || sf == "berasans") {
2359 os << "\\usepackage[scaled=" << float(sfscale) / 100
2360 << "]{" << sf << "}\n";
2362 os << "\\usepackage{" << sf << "}\n";
2365 else if (sf == "avant")
2366 os << "\\usepackage{" << sf << "}\n";
2367 // Computer Modern, Latin Modern, CM Bright
2368 else if (sf != "default")
2369 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2371 // monospaced/typewriter
2372 // Courier, LuxiMono
2373 if (tt == "luximono" || tt == "beramono") {
2375 os << "\\usepackage[scaled=" << float(ttscale) / 100
2376 << "]{" << tt << "}\n";
2378 os << "\\usepackage{" << tt << "}\n";
2381 else if (tt == "courier" )
2382 os << "\\usepackage{" << tt << "}\n";
2383 // Computer Modern, Latin Modern, CM Bright
2384 else if (tt != "default")
2385 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2391 Encoding const & BufferParams::encoding() const
2394 return *(encodings.fromLaTeXName("utf8-plain"));
2395 if (inputenc == "auto" || inputenc == "default")
2396 return *language->encoding();
2397 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2400 LYXERR0("Unknown inputenc value `" << inputenc
2401 << "'. Using `auto' instead.");
2402 return *language->encoding();
2406 CiteEngine BufferParams::citeEngine() const
2408 // FIXME the class should provide the numerical/
2409 // authoryear choice
2410 if (documentClass().provides("natbib")
2411 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2412 return ENGINE_NATBIB_AUTHORYEAR;
2413 return cite_engine_;
2417 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2419 cite_engine_ = cite_engine;