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 layout file requested by this document,\n"
525 "is not usable. This is probably because a LaTeX\n"
526 "class or style file required by it is not\n"
527 "available. See the Customization documentation\n"
528 "for more information.\n"), from_utf8(classname));
529 frontend::Alert::warning(_("Document class not available"),
530 msg + _("LyX will not be able to produce output."));
532 } else if (token == "\\begin_preamble") {
534 } else if (token == "\\begin_local_layout") {
535 readLocalLayout(lex);
536 } else if (token == "\\begin_modules") {
538 } else if (token == "\\begin_removed_modules") {
539 readRemovedModules(lex);
540 } else if (token == "\\begin_includeonly") {
541 readIncludeonly(lex);
542 } else if (token == "\\maintain_unincluded_children") {
543 lex >> maintain_unincluded_children;
544 } else if (token == "\\options") {
546 options = lex.getString();
547 } else if (token == "\\use_default_options") {
548 lex >> use_default_options;
549 } else if (token == "\\master") {
551 master = lex.getString();
552 } else if (token == "\\suppress_date") {
553 lex >> suppress_date;
554 } else if (token == "\\language") {
556 } else if (token == "\\inputencoding") {
558 } else if (token == "\\graphics") {
559 readGraphicsDriver(lex);
560 } else if (token == "\\default_output_format") {
561 lex >> defaultOutputFormat;
562 } else if (token == "\\bibtex_command") {
564 bibtex_command = lex.getString();
565 } else if (token == "\\index_command") {
567 index_command = lex.getString();
568 } else if (token == "\\fontencoding") {
570 fontenc = lex.getString();
571 } else if (token == "\\font_roman") {
573 fontsRoman = lex.getString();
574 } else if (token == "\\font_sans") {
576 fontsSans = lex.getString();
577 } else if (token == "\\font_typewriter") {
579 fontsTypewriter = lex.getString();
580 } else if (token == "\\font_default_family") {
581 lex >> fontsDefaultFamily;
582 } else if (token == "\\use_xetex") {
584 } else if (token == "\\font_sc") {
586 } else if (token == "\\font_osf") {
588 } else if (token == "\\font_sf_scale") {
589 lex >> fontsSansScale;
590 } else if (token == "\\font_tt_scale") {
591 lex >> fontsTypewriterScale;
592 } else if (token == "\\font_cjk") {
594 } else if (token == "\\paragraph_separation") {
597 paragraph_separation = parseptranslator().find(parsep);
598 } else if (token == "\\paragraph_indentation") {
600 string indentation = lex.getString();
601 pimpl_->indentation = HSpace(indentation);
602 } else if (token == "\\defskip") {
604 string defskip = lex.getString();
605 if (defskip == "defskip")
608 pimpl_->defskip = VSpace(defskip);
609 } else if (token == "\\quotes_language") {
612 quotes_language = quoteslangtranslator().find(quotes_lang);
613 } else if (token == "\\papersize") {
616 papersize = papersizetranslator().find(ppsize);
617 } else if (token == "\\use_geometry") {
619 } else if (token == "\\use_amsmath") {
622 use_amsmath = packagetranslator().find(use_ams);
623 } else if (token == "\\use_esint") {
626 use_esint = packagetranslator().find(useesint);
627 } else if (token == "\\use_mhchem") {
630 use_mhchem = packagetranslator().find(usemhchem);
631 } else if (token == "\\cite_engine") {
634 cite_engine_ = citeenginetranslator().find(engine);
635 } else if (token == "\\use_bibtopic") {
637 } else if (token == "\\use_indices") {
639 } else if (token == "\\tracking_changes") {
641 } else if (token == "\\output_changes") {
642 lex >> outputChanges;
643 } else if (token == "\\branch") {
645 docstring branch = lex.getDocString();
646 branchlist().add(branch);
649 string const tok = lex.getString();
650 if (tok == "\\end_branch")
652 Branch * branch_ptr = branchlist().find(branch);
653 if (tok == "\\selected") {
656 branch_ptr->setSelected(lex.getInteger());
658 if (tok == "\\filename_suffix") {
661 branch_ptr->setFilenameSuffix(lex.getInteger());
663 if (tok == "\\color") {
665 string color = lex.getString();
667 branch_ptr->setColor(color);
668 // Update also the Color table:
670 color = lcolor.getX11Name(Color_background);
672 lcolor.setColor(to_utf8(branch), color);
675 } else if (token == "\\index") {
677 docstring index = lex.getDocString();
679 indiceslist().add(index);
682 string const tok = lex.getString();
683 if (tok == "\\end_index")
685 Index * index_ptr = indiceslist().find(index);
686 if (tok == "\\shortcut") {
688 shortcut = lex.getDocString();
690 index_ptr->setShortcut(shortcut);
692 if (tok == "\\color") {
694 string color = lex.getString();
696 index_ptr->setColor(color);
697 // Update also the Color table:
699 color = lcolor.getX11Name(Color_background);
701 if (!shortcut.empty())
702 lcolor.setColor(to_utf8(shortcut), color);
705 } else if (token == "\\author") {
707 istringstream ss(lex.getString());
710 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
711 } else if (token == "\\paperorientation") {
714 orientation = paperorientationtranslator().find(orient);
715 } else if (token == "\\backgroundcolor") {
717 backgroundcolor = lyx::rgbFromHexName(lex.getString());
718 } else if (token == "\\paperwidth") {
720 } else if (token == "\\paperheight") {
722 } else if (token == "\\leftmargin") {
724 } else if (token == "\\topmargin") {
726 } else if (token == "\\rightmargin") {
728 } else if (token == "\\bottommargin") {
730 } else if (token == "\\headheight") {
732 } else if (token == "\\headsep") {
734 } else if (token == "\\footskip") {
736 } else if (token == "\\columnsep") {
738 } else if (token == "\\paperfontsize") {
740 } else if (token == "\\papercolumns") {
742 } else if (token == "\\listings_params") {
745 listings_params = InsetListingsParams(par).params();
746 } else if (token == "\\papersides") {
749 sides = sidestranslator().find(psides);
750 } else if (token == "\\paperpagestyle") {
752 } else if (token == "\\bullet") {
754 } else if (token == "\\bulletLaTeX") {
755 readBulletsLaTeX(lex);
756 } else if (token == "\\secnumdepth") {
758 } else if (token == "\\tocdepth") {
760 } else if (token == "\\spacing") {
764 if (nspacing == "other") {
767 spacing().set(spacetranslator().find(nspacing), tmp_val);
768 } else if (token == "\\float_placement") {
769 lex >> float_placement;
771 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
772 string toktmp = pdfoptions().readToken(lex, token);
773 if (!toktmp.empty()) {
774 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
778 } else if (token == "\\html_math_output") {
781 html_math_output = static_cast<MathOutput>(temp);
782 } else if (token == "\\html_be_strict") {
783 lex >> html_be_strict;
785 lyxerr << "BufferParams::readToken(): Unknown token: " <<
794 void BufferParams::writeFile(ostream & os) const
796 // The top of the file is written by the buffer.
797 // Prints out the buffer info into the .lyx file given by file
800 os << "\\textclass " << baseClass()->name() << '\n';
803 if (!preamble.empty()) {
804 // remove '\n' from the end of preamble
805 string const tmppreamble = rtrim(preamble, "\n");
806 os << "\\begin_preamble\n"
808 << "\n\\end_preamble\n";
812 if (!options.empty()) {
813 os << "\\options " << options << '\n';
816 // use the class options defined in the layout?
817 os << "\\use_default_options "
818 << convert<string>(use_default_options) << "\n";
820 // the master document
821 if (!master.empty()) {
822 os << "\\master " << master << '\n';
826 if (!removedModules_.empty()) {
827 os << "\\begin_removed_modules" << '\n';
828 list<string>::const_iterator it = removedModules_.begin();
829 list<string>::const_iterator en = removedModules_.end();
830 for (; it != en; it++)
832 os << "\\end_removed_modules" << '\n';
836 if (!layoutModules_.empty()) {
837 os << "\\begin_modules" << '\n';
838 LayoutModuleList::const_iterator it = layoutModules_.begin();
839 LayoutModuleList::const_iterator en = layoutModules_.end();
840 for (; it != en; it++)
842 os << "\\end_modules" << '\n';
846 if (!includedChildren_.empty()) {
847 os << "\\begin_includeonly" << '\n';
848 list<string>::const_iterator it = includedChildren_.begin();
849 list<string>::const_iterator en = includedChildren_.end();
850 for (; it != en; it++)
852 os << "\\end_includeonly" << '\n';
854 os << "\\maintain_unincluded_children "
855 << convert<string>(maintain_unincluded_children) << '\n';
857 // local layout information
858 if (!local_layout.empty()) {
859 // remove '\n' from the end
860 string const tmplocal = rtrim(local_layout, "\n");
861 os << "\\begin_local_layout\n"
863 << "\n\\end_local_layout\n";
866 // then the text parameters
867 if (language != ignore_language)
868 os << "\\language " << language->lang() << '\n';
869 os << "\\inputencoding " << inputenc
870 << "\n\\fontencoding " << fontenc
871 << "\n\\font_roman " << fontsRoman
872 << "\n\\font_sans " << fontsSans
873 << "\n\\font_typewriter " << fontsTypewriter
874 << "\n\\font_default_family " << fontsDefaultFamily
875 << "\n\\use_xetex " << convert<string>(useXetex)
876 << "\n\\font_sc " << convert<string>(fontsSC)
877 << "\n\\font_osf " << convert<string>(fontsOSF)
878 << "\n\\font_sf_scale " << fontsSansScale
879 << "\n\\font_tt_scale " << fontsTypewriterScale
881 if (!fontsCJK.empty()) {
882 os << "\\font_cjk " << fontsCJK << '\n';
884 os << "\n\\graphics " << graphicsDriver << '\n';
885 os << "\\default_output_format " << defaultOutputFormat << '\n';
886 os << "\\bibtex_command " << bibtex_command << '\n';
887 os << "\\index_command " << index_command << '\n';
889 if (!float_placement.empty()) {
890 os << "\\float_placement " << float_placement << '\n';
892 os << "\\paperfontsize " << fontsize << '\n';
894 spacing().writeFile(os);
895 pdfoptions().writeFile(os);
897 os << "\\papersize " << string_papersize[papersize]
898 << "\n\\use_geometry " << convert<string>(use_geometry)
899 << "\n\\use_amsmath " << use_amsmath
900 << "\n\\use_esint " << use_esint
901 << "\n\\use_mhchem " << use_mhchem
902 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
903 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
904 << "\n\\use_indices " << convert<string>(use_indices)
905 << "\n\\paperorientation " << string_orientation[orientation]
906 << "\n\\suppress_date " << convert<string>(suppress_date)
908 if (backgroundcolor != lyx::rgbFromHexName("#ffffff"))
909 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
911 BranchList::const_iterator it = branchlist().begin();
912 BranchList::const_iterator end = branchlist().end();
913 for (; it != end; ++it) {
914 os << "\\branch " << to_utf8(it->branch())
915 << "\n\\selected " << it->isSelected()
916 << "\n\\filename_suffix " << it->hasFilenameSuffix()
917 << "\n\\color " << lyx::X11hexname(it->color())
922 IndicesList::const_iterator iit = indiceslist().begin();
923 IndicesList::const_iterator iend = indiceslist().end();
924 for (; iit != iend; ++iit) {
925 os << "\\index " << to_utf8(iit->index())
926 << "\n\\shortcut " << to_utf8(iit->shortcut())
927 << "\n\\color " << lyx::X11hexname(iit->color())
932 if (!paperwidth.empty())
933 os << "\\paperwidth "
934 << VSpace(paperwidth).asLyXCommand() << '\n';
935 if (!paperheight.empty())
936 os << "\\paperheight "
937 << VSpace(paperheight).asLyXCommand() << '\n';
938 if (!leftmargin.empty())
939 os << "\\leftmargin "
940 << VSpace(leftmargin).asLyXCommand() << '\n';
941 if (!topmargin.empty())
943 << VSpace(topmargin).asLyXCommand() << '\n';
944 if (!rightmargin.empty())
945 os << "\\rightmargin "
946 << VSpace(rightmargin).asLyXCommand() << '\n';
947 if (!bottommargin.empty())
948 os << "\\bottommargin "
949 << VSpace(bottommargin).asLyXCommand() << '\n';
950 if (!headheight.empty())
951 os << "\\headheight "
952 << VSpace(headheight).asLyXCommand() << '\n';
953 if (!headsep.empty())
955 << VSpace(headsep).asLyXCommand() << '\n';
956 if (!footskip.empty())
958 << VSpace(footskip).asLyXCommand() << '\n';
959 if (!columnsep.empty())
961 << VSpace(columnsep).asLyXCommand() << '\n';
962 os << "\\secnumdepth " << secnumdepth
963 << "\n\\tocdepth " << tocdepth
964 << "\n\\paragraph_separation "
965 << string_paragraph_separation[paragraph_separation];
966 if (!paragraph_separation)
967 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
969 os << "\n\\defskip " << getDefSkip().asLyXCommand();
970 os << "\n\\quotes_language "
971 << string_quotes_language[quotes_language]
972 << "\n\\papercolumns " << columns
973 << "\n\\papersides " << sides
974 << "\n\\paperpagestyle " << pagestyle << '\n';
975 if (!listings_params.empty())
976 os << "\\listings_params \"" <<
977 InsetListingsParams(listings_params).encodedString() << "\"\n";
978 for (int i = 0; i < 4; ++i) {
979 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
980 if (user_defined_bullet(i).getFont() != -1) {
981 os << "\\bullet " << i << " "
982 << user_defined_bullet(i).getFont() << " "
983 << user_defined_bullet(i).getCharacter() << " "
984 << user_defined_bullet(i).getSize() << "\n";
988 os << "\\bulletLaTeX " << i << " \""
989 << lyx::to_ascii(user_defined_bullet(i).getText())
995 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n"
996 << "\\output_changes " << convert<string>(outputChanges) << "\n"
997 << "\\html_math_output " << html_math_output << "\n"
998 << "\\html_be_strict " << convert<string>(html_be_strict) << "\n";
1000 os << pimpl_->authorlist;
1004 void BufferParams::validate(LaTeXFeatures & features) const
1006 features.require(documentClass().requires());
1008 if (outputChanges) {
1009 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1010 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1011 LaTeXFeatures::isAvailable("xcolor");
1013 switch (features.runparams().flavor) {
1014 case OutputParams::LATEX:
1016 features.require("ct-dvipost");
1017 features.require("dvipost");
1018 } else if (xcolorulem) {
1019 features.require("ct-xcolor-ulem");
1020 features.require("ulem");
1021 features.require("xcolor");
1023 features.require("ct-none");
1026 case OutputParams::PDFLATEX:
1027 case OutputParams::XETEX:
1029 features.require("ct-xcolor-ulem");
1030 features.require("ulem");
1031 features.require("xcolor");
1032 // improves color handling in PDF output
1033 features.require("pdfcolmk");
1035 features.require("ct-none");
1043 // Floats with 'Here definitely' as default setting.
1044 if (float_placement.find('H') != string::npos)
1045 features.require("float");
1047 // AMS Style is at document level
1048 if (use_amsmath == package_on
1049 || documentClass().provides("amsmath"))
1050 features.require("amsmath");
1051 if (use_esint == package_on)
1052 features.require("esint");
1053 if (use_mhchem == package_on)
1054 features.require("mhchem");
1056 // Document-level line spacing
1057 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1058 features.require("setspace");
1060 // the bullet shapes are buffer level not paragraph level
1061 // so they are tested here
1062 for (int i = 0; i < 4; ++i) {
1063 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1065 int const font = user_defined_bullet(i).getFont();
1067 int const c = user_defined_bullet(i).getCharacter();
1073 features.require("latexsym");
1075 } else if (font == 1) {
1076 features.require("amssymb");
1077 } else if (font >= 2 && font <= 5) {
1078 features.require("pifont");
1082 if (pdfoptions().use_hyperref) {
1083 features.require("hyperref");
1084 // due to interferences with babel and hyperref, the color package has to
1085 // be loaded after hyperref when hyperref is used with the colorlinks
1086 // option, see http://www.lyx.org/trac/ticket/5291
1087 if (pdfoptions().colorlinks)
1088 features.require("color");
1092 features.require("xetex");
1094 if (language->lang() == "vietnamese")
1095 features.require("vietnamese");
1096 else if (language->lang() == "japanese")
1097 features.require("japanese");
1101 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1102 TexRow & texrow, FileName const & filepath) const
1104 os << "\\documentclass";
1106 DocumentClass const & tclass = documentClass();
1108 ostringstream clsoptions; // the document class options.
1110 if (tokenPos(tclass.opt_fontsize(),
1111 '|', fontsize) >= 0) {
1112 // only write if existing in list (and not default)
1113 clsoptions << fontsize << "pt,";
1116 // custom, A3, B3 and B4 paper sizes need geometry
1117 bool nonstandard_papersize = papersize == PAPER_B3
1118 || papersize == PAPER_B4
1119 || papersize == PAPER_A3
1120 || papersize == PAPER_CUSTOM;
1122 if (!use_geometry) {
1123 switch (papersize) {
1125 clsoptions << "a4paper,";
1127 case PAPER_USLETTER:
1128 clsoptions << "letterpaper,";
1131 clsoptions << "a5paper,";
1134 clsoptions << "b5paper,";
1136 case PAPER_USEXECUTIVE:
1137 clsoptions << "executivepaper,";
1140 clsoptions << "legalpaper,";
1152 if (sides != tclass.sides()) {
1155 clsoptions << "oneside,";
1158 clsoptions << "twoside,";
1164 if (columns != tclass.columns()) {
1166 clsoptions << "twocolumn,";
1168 clsoptions << "onecolumn,";
1172 && orientation == ORIENTATION_LANDSCAPE)
1173 clsoptions << "landscape,";
1175 // language should be a parameter to \documentclass
1176 if (language->babel() == "hebrew"
1177 && default_language->babel() != "hebrew")
1178 // This seems necessary
1179 features.useLanguage(default_language);
1181 ostringstream language_options;
1182 bool const use_babel = features.useBabel();
1184 language_options << features.getLanguages();
1185 if (!language->babel().empty()) {
1186 if (!language_options.str().empty())
1187 language_options << ',';
1188 language_options << language->babel();
1190 // if Vietnamese is used, babel must directly be loaded
1191 // with language options, not in the class options, see
1192 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1193 size_t viet = language_options.str().find("vietnam");
1194 // viet = string::npos when not found
1195 // the same is for all other languages that are not directly supported by
1196 // babel, but where LaTeX-packages add babel support.
1197 // this is currently the case for Latvian, Lithuanian, and Mongolian
1198 size_t latvian = language_options.str().find("latvian");
1199 size_t lithu = language_options.str().find("lithuanian");
1200 size_t mongo = language_options.str().find("mongolian");
1201 // if Japanese is used, babel must directly be loaded
1202 // with language options, not in the class options, see
1203 // http://www.lyx.org/trac/ticket/4597#c4
1204 size_t japan = language_options.str().find("japanese");
1205 if (lyxrc.language_global_options && !language_options.str().empty()
1206 && viet == string::npos && japan == string::npos
1207 && latvian == string::npos && lithu == string::npos
1208 && mongo == string::npos)
1209 clsoptions << language_options.str() << ',';
1212 // the predefined options from the layout
1213 if (use_default_options && !tclass.options().empty())
1214 clsoptions << tclass.options() << ',';
1216 // the user-defined options
1217 if (!options.empty()) {
1218 clsoptions << options << ',';
1221 string strOptions(clsoptions.str());
1222 if (!strOptions.empty()) {
1223 strOptions = rtrim(strOptions, ",");
1225 os << '[' << from_utf8(strOptions) << ']';
1228 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1230 // end of \documentclass defs
1233 os << "\\usepackage{fontspec}\n";
1237 // font selection must be done before loading fontenc.sty
1238 string const fonts =
1239 loadFonts(fontsRoman, fontsSans,
1240 fontsTypewriter, fontsSC, fontsOSF,
1241 fontsSansScale, fontsTypewriterScale, useXetex);
1242 if (!fonts.empty()) {
1243 os << from_ascii(fonts);
1246 if (fontsDefaultFamily != "default")
1247 os << "\\renewcommand{\\familydefault}{\\"
1248 << from_ascii(fontsDefaultFamily) << "}\n";
1250 // set font encoding
1251 // for arabic_arabi and farsi we also need to load the LAE and
1253 // XeTeX works without fontenc
1254 if (font_encoding() != "default" && language->lang() != "japanese"
1256 if (language->lang() == "arabic_arabi"
1257 || language->lang() == "farsi") {
1258 os << "\\usepackage[" << from_ascii(font_encoding())
1259 << ",LFE,LAE]{fontenc}\n";
1262 os << "\\usepackage[" << from_ascii(font_encoding())
1268 // handle inputenc etc.
1269 writeEncodingPreamble(os, features, texrow);
1272 if (!features.runparams().includeall && !includedChildren_.empty()) {
1273 os << "\\includeonly{";
1274 list<string>::const_iterator it = includedChildren_.begin();
1276 for (; it != includedChildren_.end() ; ++it) {
1277 string incfile = *it;
1278 FileName inc = makeAbsPath(incfile, filepath.absFilename());
1279 string mangled = DocFileName(changeExtension(inc.absFilename(), ".tex")).
1281 if (!features.runparams().nice)
1283 // \includeonly doesn't want an extension
1284 incfile = changeExtension(incfile, string());
1285 incfile = support::latex_path(incfile);
1286 if (!incfile.empty()) {
1289 os << from_utf8(incfile);
1296 if (!listings_params.empty() || features.isRequired("listings")) {
1297 os << "\\usepackage{listings}\n";
1300 if (!listings_params.empty()) {
1302 // do not test validity because listings_params is
1303 // supposed to be valid
1305 InsetListingsParams(listings_params).separatedParams(true);
1306 // we can't support all packages, but we should load the color package
1307 if (par.find("\\color", 0) != string::npos)
1308 features.require("color");
1309 os << from_utf8(par);
1310 // count the number of newlines
1311 for (size_t i = 0; i < par.size(); ++i)
1317 if (!tclass.provides("geometry")
1318 && (use_geometry || nonstandard_papersize)) {
1319 odocstringstream ods;
1320 if (!getGraphicsDriver("geometry").empty())
1321 ods << getGraphicsDriver("geometry");
1322 if (orientation == ORIENTATION_LANDSCAPE)
1323 ods << ",landscape";
1324 switch (papersize) {
1326 if (!paperwidth.empty())
1327 ods << ",paperwidth="
1328 << from_ascii(paperwidth);
1329 if (!paperheight.empty())
1330 ods << ",paperheight="
1331 << from_ascii(paperheight);
1333 case PAPER_USLETTER:
1334 ods << ",letterpaper";
1337 ods << ",legalpaper";
1339 case PAPER_USEXECUTIVE:
1340 ods << ",executivepaper";
1361 // default papersize ie PAPER_DEFAULT
1362 switch (lyxrc.default_papersize) {
1363 case PAPER_DEFAULT: // keep compiler happy
1364 case PAPER_USLETTER:
1365 ods << ",letterpaper";
1368 ods << ",legalpaper";
1370 case PAPER_USEXECUTIVE:
1371 ods << ",executivepaper";
1391 docstring const g_options = trim(ods.str(), ",");
1392 os << "\\usepackage";
1393 if (!g_options.empty())
1394 os << '[' << g_options << ']';
1395 os << "{geometry}\n";
1397 os << "\\geometry{verbose";
1398 if (!topmargin.empty())
1399 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1400 if (!bottommargin.empty())
1401 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1402 if (!leftmargin.empty())
1403 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1404 if (!rightmargin.empty())
1405 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1406 if (!headheight.empty())
1407 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1408 if (!headsep.empty())
1409 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1410 if (!footskip.empty())
1411 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1412 if (!columnsep.empty())
1413 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1416 } else if (orientation == ORIENTATION_LANDSCAPE) {
1417 features.require("papersize");
1420 if (tokenPos(tclass.opt_pagestyle(),
1421 '|', pagestyle) >= 0) {
1422 if (pagestyle == "fancy") {
1423 os << "\\usepackage{fancyhdr}\n";
1426 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1430 // only output when the background color is not white
1431 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1432 // only require color here, the background color will be defined
1433 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1435 features.require("color");
1436 features.require("pagecolor");
1439 // Only if class has a ToC hierarchy
1440 if (tclass.hasTocLevels()) {
1441 if (secnumdepth != tclass.secnumdepth()) {
1442 os << "\\setcounter{secnumdepth}{"
1447 if (tocdepth != tclass.tocdepth()) {
1448 os << "\\setcounter{tocdepth}{"
1455 if (paragraph_separation) {
1456 // when skip separation
1457 switch (getDefSkip().kind()) {
1458 case VSpace::SMALLSKIP:
1459 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1461 case VSpace::MEDSKIP:
1462 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1464 case VSpace::BIGSKIP:
1465 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1467 case VSpace::LENGTH:
1468 os << "\\setlength{\\parskip}{"
1469 << from_utf8(getDefSkip().length().asLatexString())
1472 default: // should never happen // Then delete it.
1473 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1477 os << "\\setlength{\\parindent}{0pt}\n";
1480 // when separation by indentation
1481 // only output something when a width is given
1482 if (getIndentation().asLyXCommand() != "default") {
1483 os << "\\setlength{\\parindent}{"
1484 << from_utf8(getIndentation().asLatexCommand())
1490 // Now insert the LyX specific LaTeX commands...
1491 docstring lyxpreamble;
1493 // due to interferences with babel and hyperref, the color package has to
1494 // be loaded (when it is not already loaded) before babel when hyperref
1495 // is used with the colorlinks option, see
1496 // http://www.lyx.org/trac/ticket/5291
1497 // we decided therefore to load color always before babel, see
1498 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1499 lyxpreamble += from_ascii(features.getColorOptions());
1501 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1503 && (features.isRequired("jurabib")
1504 || features.isRequired("hyperref")
1505 || features.isRequired("vietnamese")
1506 || features.isRequired("japanese") ) ) {
1508 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1509 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1512 // The optional packages;
1513 lyxpreamble += from_ascii(features.getPackages());
1515 // Additional Indices
1516 if (features.isRequired("splitidx")) {
1517 IndicesList::const_iterator iit = indiceslist().begin();
1518 IndicesList::const_iterator iend = indiceslist().end();
1519 for (; iit != iend; ++iit) {
1520 lyxpreamble += "\\newindex[";
1521 lyxpreamble += iit->index();
1522 lyxpreamble += "]{";
1523 lyxpreamble += iit->shortcut();
1524 lyxpreamble += "}\n";
1529 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1532 // * Hyperref manual: "Make sure it comes last of your loaded
1533 // packages, to give it a fighting chance of not being over-written,
1534 // since its job is to redefine many LaTeX commands."
1535 // * Email from Heiko Oberdiek: "It is usually better to load babel
1536 // before hyperref. Then hyperref has a chance to detect babel.
1537 // * Has to be loaded before the "LyX specific LaTeX commands" to
1538 // avoid errors with algorithm floats.
1539 // use hyperref explicitly if it is required
1540 if (features.isRequired("hyperref")) {
1541 // pass what we have to stream here, since we need
1542 // to access the stream itself in PDFOptions.
1546 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1548 OutputParams tmp_params = features.runparams();
1549 lines += pdfoptions().writeLaTeX(tmp_params, os,
1550 documentClass().provides("hyperref"));
1551 texrow.newlines(lines);
1552 // set back for the rest
1553 lyxpreamble.clear();
1556 // Will be surrounded by \makeatletter and \makeatother when not empty
1557 docstring atlyxpreamble;
1559 // Some macros LyX will need
1560 docstring tmppreamble(features.getMacros());
1562 if (!tmppreamble.empty())
1563 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1564 "LyX specific LaTeX commands.\n"
1565 + tmppreamble + '\n';
1567 // the text class specific preamble
1568 tmppreamble = features.getTClassPreamble();
1569 if (!tmppreamble.empty())
1570 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1571 "Textclass specific LaTeX commands.\n"
1572 + tmppreamble + '\n';
1574 // suppress date if selected
1575 // use \@ifundefined because we cannot be sure that every document class
1576 // has a \date command
1578 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1580 /* the user-defined preamble */
1581 if (!containsOnly(preamble, " \n\t"))
1583 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1584 "User specified LaTeX commands.\n"
1585 + from_utf8(preamble) + '\n';
1587 // subfig loads internally the LaTeX package "caption". As
1588 // caption is a very popular package, users will load it in
1589 // the preamble. Therefore we must load subfig behind the
1590 // user-defined preamble and check if the caption package was
1591 // loaded or not. For the case that caption is loaded before
1592 // subfig, there is the subfig option "caption=false". This
1593 // option also works when a koma-script class is used and
1594 // koma's own caption commands are used instead of caption. We
1595 // use \PassOptionsToPackage here because the user could have
1596 // already loaded subfig in the preamble.
1597 if (features.isRequired("subfig")) {
1598 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1599 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1600 "\\usepackage{subfig}\n";
1603 // Itemize bullet settings need to be last in case the user
1604 // defines their own bullets that use a package included
1605 // in the user-defined preamble -- ARRae
1606 // Actually it has to be done much later than that
1607 // since some packages like frenchb make modifications
1608 // at \begin{document} time -- JMarc
1609 docstring bullets_def;
1610 for (int i = 0; i < 4; ++i) {
1611 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1612 if (bullets_def.empty())
1613 bullets_def += "\\AtBeginDocument{\n";
1614 bullets_def += " \\def\\labelitemi";
1616 // `i' is one less than the item to modify
1623 bullets_def += "ii";
1629 bullets_def += '{' +
1630 user_defined_bullet(i).getText()
1635 if (!bullets_def.empty())
1636 atlyxpreamble += bullets_def + "}\n\n";
1638 if (!atlyxpreamble.empty())
1639 lyxpreamble += "\n\\makeatletter\n"
1640 + atlyxpreamble + "\\makeatother\n\n";
1642 // We try to load babel late, in case it interferes with other packages.
1643 // Jurabib and Hyperref have to be called after babel, though.
1644 if (use_babel && !features.isRequired("jurabib")
1645 && !features.isRequired("hyperref")
1646 && !features.isRequired("vietnamese")
1647 && !features.isRequired("japanese")) {
1649 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1650 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1653 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1654 if (!i18npreamble.empty())
1655 lyxpreamble += i18npreamble + '\n';
1658 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1659 texrow.newlines(nlines);
1663 // these packages (xunicode, for that matter) need to be loaded at least
1664 // after amsmath, amssymb, esint and the other packages that provide
1667 os << "\\usepackage{xunicode}\n";
1669 os << "\\usepackage{xltxtra}\n";
1676 void BufferParams::useClassDefaults()
1678 DocumentClass const & tclass = documentClass();
1680 sides = tclass.sides();
1681 columns = tclass.columns();
1682 pagestyle = tclass.pagestyle();
1683 use_default_options = true;
1684 // Only if class has a ToC hierarchy
1685 if (tclass.hasTocLevels()) {
1686 secnumdepth = tclass.secnumdepth();
1687 tocdepth = tclass.tocdepth();
1692 bool BufferParams::hasClassDefaults() const
1694 DocumentClass const & tclass = documentClass();
1696 return sides == tclass.sides()
1697 && columns == tclass.columns()
1698 && pagestyle == tclass.pagestyle()
1699 && use_default_options
1700 && secnumdepth == tclass.secnumdepth()
1701 && tocdepth == tclass.tocdepth();
1705 DocumentClass const & BufferParams::documentClass() const
1711 DocumentClass const * BufferParams::documentClassPtr() const {
1716 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1717 // evil, but this function is evil
1718 doc_class_ = const_cast<DocumentClass *>(tc);
1722 bool BufferParams::setBaseClass(string const & classname)
1724 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1725 LayoutFileList & bcl = LayoutFileList::get();
1726 if (!bcl.haveClass(classname)) {
1728 bformat(_("The document class %1$s could not be found. "
1729 "A default textclass with default layouts will be used. "
1730 "LyX might not be able to produce output unless a correct "
1731 "textclass is selected from the document settings dialog."),
1732 from_utf8(classname));
1733 frontend::Alert::error(_("Document class not found"), s);
1734 bcl.addEmptyClass(classname);
1737 bool const success = bcl[classname].load();
1740 bformat(_("The document class %1$s could not be loaded."),
1741 from_utf8(classname));
1742 frontend::Alert::error(_("Could not load class"), s);
1746 pimpl_->baseClass_ = classname;
1747 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1752 LayoutFile const * BufferParams::baseClass() const
1754 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1755 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1761 LayoutFileIndex const & BufferParams::baseClassID() const
1763 return pimpl_->baseClass_;
1767 void BufferParams::makeDocumentClass()
1772 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1774 if (!local_layout.empty()) {
1775 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1776 docstring const msg = _("Error reading internal layout information");
1777 frontend::Alert::warning(_("Read Error"), msg);
1782 bool BufferParams::moduleCanBeAdded(string const & modName) const
1784 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1788 bool BufferParams::addLayoutModule(string const & modName)
1790 LayoutModuleList::const_iterator it = layoutModules_.begin();
1791 LayoutModuleList::const_iterator end = layoutModules_.end();
1792 for (; it != end; it++)
1795 layoutModules_.push_back(modName);
1800 Font const BufferParams::getFont() const
1802 FontInfo f = documentClass().defaultfont();
1803 if (fontsDefaultFamily == "rmdefault")
1804 f.setFamily(ROMAN_FAMILY);
1805 else if (fontsDefaultFamily == "sfdefault")
1806 f.setFamily(SANS_FAMILY);
1807 else if (fontsDefaultFamily == "ttdefault")
1808 f.setFamily(TYPEWRITER_FAMILY);
1809 return Font(f, language);
1813 void BufferParams::readPreamble(Lexer & lex)
1815 if (lex.getString() != "\\begin_preamble")
1816 lyxerr << "Error (BufferParams::readPreamble):"
1817 "consistency check failed." << endl;
1819 preamble = lex.getLongString("\\end_preamble");
1823 void BufferParams::readLocalLayout(Lexer & lex)
1825 if (lex.getString() != "\\begin_local_layout")
1826 lyxerr << "Error (BufferParams::readLocalLayout):"
1827 "consistency check failed." << endl;
1829 local_layout = lex.getLongString("\\end_local_layout");
1833 void BufferParams::readLanguage(Lexer & lex)
1835 if (!lex.next()) return;
1837 string const tmptok = lex.getString();
1839 // check if tmptok is part of tex_babel in tex-defs.h
1840 language = languages.getLanguage(tmptok);
1842 // Language tmptok was not found
1843 language = default_language;
1844 lyxerr << "Warning: Setting language `"
1845 << tmptok << "' to `" << language->lang()
1851 void BufferParams::readGraphicsDriver(Lexer & lex)
1856 string const tmptok = lex.getString();
1857 // check if tmptok is part of tex_graphics in tex_defs.h
1860 string const test = tex_graphics[n++];
1862 if (test == tmptok) {
1863 graphicsDriver = tmptok;
1868 "Warning: graphics driver `$$Token' not recognized!\n"
1869 " Setting graphics driver to `default'.\n");
1870 graphicsDriver = "default";
1877 void BufferParams::readBullets(Lexer & lex)
1882 int const index = lex.getInteger();
1884 int temp_int = lex.getInteger();
1885 user_defined_bullet(index).setFont(temp_int);
1886 temp_bullet(index).setFont(temp_int);
1888 user_defined_bullet(index).setCharacter(temp_int);
1889 temp_bullet(index).setCharacter(temp_int);
1891 user_defined_bullet(index).setSize(temp_int);
1892 temp_bullet(index).setSize(temp_int);
1896 void BufferParams::readBulletsLaTeX(Lexer & lex)
1898 // The bullet class should be able to read this.
1901 int const index = lex.getInteger();
1903 docstring const temp_str = lex.getDocString();
1905 user_defined_bullet(index).setText(temp_str);
1906 temp_bullet(index).setText(temp_str);
1910 void BufferParams::readModules(Lexer & lex)
1912 if (!lex.eatLine()) {
1913 lyxerr << "Error (BufferParams::readModules):"
1914 "Unexpected end of input." << endl;
1918 string mod = lex.getString();
1919 if (mod == "\\end_modules")
1921 addLayoutModule(mod);
1927 void BufferParams::readRemovedModules(Lexer & lex)
1929 if (!lex.eatLine()) {
1930 lyxerr << "Error (BufferParams::readRemovedModules):"
1931 "Unexpected end of input." << endl;
1935 string mod = lex.getString();
1936 if (mod == "\\end_removed_modules")
1938 removedModules_.push_back(mod);
1941 // now we want to remove any removed modules that were previously
1942 // added. normally, that will be because default modules were added in
1943 // setBaseClass(), which gets called when \textclass is read at the
1944 // start of the read.
1945 list<string>::const_iterator rit = removedModules_.begin();
1946 list<string>::const_iterator const ren = removedModules_.end();
1947 for (; rit != ren; rit++) {
1948 LayoutModuleList::iterator const mit = layoutModules_.begin();
1949 LayoutModuleList::iterator const men = layoutModules_.end();
1950 LayoutModuleList::iterator found = find(mit, men, *rit);
1953 layoutModules_.erase(found);
1958 void BufferParams::readIncludeonly(Lexer & lex)
1960 if (!lex.eatLine()) {
1961 lyxerr << "Error (BufferParams::readIncludeonly):"
1962 "Unexpected end of input." << endl;
1966 string child = lex.getString();
1967 if (child == "\\end_includeonly")
1969 includedChildren_.push_back(child);
1975 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1977 char real_papersize = papersize;
1978 if (real_papersize == PAPER_DEFAULT)
1979 real_papersize = lyxrc.default_papersize;
1981 switch (real_papersize) {
1983 // could be anything, so don't guess
1985 case PAPER_CUSTOM: {
1986 if (purpose == XDVI && !paperwidth.empty() &&
1987 !paperheight.empty()) {
1988 // heightxwidth<unit>
1989 string first = paperwidth;
1990 string second = paperheight;
1991 if (orientation == ORIENTATION_LANDSCAPE)
1994 return first.erase(first.length() - 2)
2006 // dvips and dvipdfm do not know this
2007 if (purpose == DVIPS || purpose == DVIPDFM)
2011 // dvipdfm does not know this
2012 if (purpose == DVIPDFM)
2016 // dvipdfm does not know this
2017 if (purpose == DVIPDFM)
2020 case PAPER_USEXECUTIVE:
2021 // dvipdfm does not know this
2022 if (purpose == DVIPDFM)
2027 case PAPER_USLETTER:
2029 if (purpose == XDVI)
2036 string const BufferParams::dvips_options() const
2041 && papersize == PAPER_CUSTOM
2042 && !lyxrc.print_paper_dimension_flag.empty()
2043 && !paperwidth.empty()
2044 && !paperheight.empty()) {
2045 // using a custom papersize
2046 result = lyxrc.print_paper_dimension_flag;
2047 result += ' ' + paperwidth;
2048 result += ',' + paperheight;
2050 string const paper_option = paperSizeName(DVIPS);
2051 if (!paper_option.empty() && (paper_option != "letter" ||
2052 orientation != ORIENTATION_LANDSCAPE)) {
2053 // dvips won't accept -t letter -t landscape.
2054 // In all other cases, include the paper size
2056 result = lyxrc.print_paper_flag;
2057 result += ' ' + paper_option;
2060 if (orientation == ORIENTATION_LANDSCAPE &&
2061 papersize != PAPER_CUSTOM)
2062 result += ' ' + lyxrc.print_landscape_flag;
2067 string const BufferParams::font_encoding() const
2069 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2073 string BufferParams::babelCall(string const & lang_opts) const
2075 string lang_pack = lyxrc.language_package;
2076 if (lang_pack != "\\usepackage{babel}")
2078 // suppress the babel call when there is no babel language defined
2079 // for the document language in the lib/languages file and if no
2080 // other languages are used (lang_opts is then empty)
2081 if (lang_opts.empty())
2083 // If Vietnamese is used, babel must directly be loaded with the
2084 // language options, see
2085 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2086 size_t viet = lang_opts.find("vietnam");
2087 // viet = string::npos when not found
2088 // the same is for all other languages that are not directly supported by
2089 // babel, but where LaTeX-packages add babel support.
2090 // this is currently the case for Latvian, Lithuanian, and Mongolian
2091 size_t latvian = lang_opts.find("latvian");
2092 size_t lithu = lang_opts.find("lithuanian");
2093 size_t mongo = lang_opts.find("mongolian");
2094 // If Japanese is used, babel must directly be loaded with the
2095 // language options, see
2096 // http://www.lyx.org/trac/ticket/4597#c4
2097 size_t japan = lang_opts.find("japanese");
2098 if (!lyxrc.language_global_options || viet != string::npos
2099 || japan != string::npos || latvian != string::npos
2100 || lithu != string::npos || mongo != string::npos)
2101 return "\\usepackage[" + lang_opts + "]{babel}";
2106 docstring BufferParams::getGraphicsDriver(string const & package) const
2110 if (package == "geometry") {
2111 if (graphicsDriver == "dvips"
2112 || graphicsDriver == "dvipdfm"
2113 || graphicsDriver == "pdftex"
2114 || graphicsDriver == "vtex")
2115 result = from_ascii(graphicsDriver);
2116 else if (graphicsDriver == "dvipdfmx")
2117 result = from_ascii("dvipdfm");
2124 void BufferParams::writeEncodingPreamble(odocstream & os,
2125 LaTeXFeatures & features, TexRow & texrow) const
2129 if (inputenc == "auto") {
2130 string const doc_encoding =
2131 language->encoding()->latexName();
2132 Encoding::Package const package =
2133 language->encoding()->package();
2135 // Create a list with all the input encodings used
2137 set<string> encodings =
2138 features.getEncodingSet(doc_encoding);
2140 // If the "japanese" package (i.e. pLaTeX) is used,
2141 // inputenc must be omitted.
2142 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2143 if (package == Encoding::japanese)
2144 features.require("japanese");
2146 if ((!encodings.empty() || package == Encoding::inputenc)
2147 && !features.isRequired("japanese")) {
2148 os << "\\usepackage[";
2149 set<string>::const_iterator it = encodings.begin();
2150 set<string>::const_iterator const end = encodings.end();
2152 os << from_ascii(*it);
2155 for (; it != end; ++it)
2156 os << ',' << from_ascii(*it);
2157 if (package == Encoding::inputenc) {
2158 if (!encodings.empty())
2160 os << from_ascii(doc_encoding);
2162 os << "]{inputenc}\n";
2165 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2166 if (language->encoding()->name() == "utf8-cjk"
2167 && LaTeXFeatures::isAvailable("CJKutf8"))
2168 os << "\\usepackage{CJKutf8}\n";
2170 os << "\\usepackage{CJK}\n";
2173 } else if (inputenc != "default") {
2174 switch (encoding().package()) {
2175 case Encoding::none:
2176 case Encoding::japanese:
2178 case Encoding::inputenc:
2179 // do not load inputenc if japanese is used
2180 if (features.isRequired("japanese"))
2182 os << "\\usepackage[" << from_ascii(inputenc)
2187 if (encoding().name() == "utf8-cjk"
2188 && LaTeXFeatures::isAvailable("CJKutf8"))
2189 os << "\\usepackage{CJKutf8}\n";
2191 os << "\\usepackage{CJK}\n";
2197 // The encoding "armscii8" (for Armenian) is only available when
2198 // the package "armtex" is loaded.
2199 if (language->encoding()->latexName() == "armscii8"
2200 || inputenc == "armscii8") {
2201 os << "\\usepackage{armtex}\n";
2207 string const BufferParams::parseFontName(string const & name) const
2209 string mangled = name;
2210 size_t const idx = mangled.find('[');
2211 if (idx == string::npos || idx == 0)
2214 return mangled.substr(0, idx - 1);
2218 string const BufferParams::loadFonts(string const & rm,
2219 string const & sf, string const & tt,
2220 bool const & sc, bool const & osf,
2221 int const & sfscale, int const & ttscale,
2222 bool const & xetex) const
2224 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2225 several packages have been replaced by others, that might not
2226 be installed on every system. We have to take care for that
2227 (see psnfss.pdf). We try to support all psnfss fonts as well
2228 as the fonts that have become de facto standard in the LaTeX
2229 world (e.g. Latin Modern). We do not support obsolete fonts
2230 (like PSLatex). In general, it should be possible to mix any
2231 rm font with any sf or tt font, respectively. (JSpitzm)
2233 -- separate math fonts.
2236 if (rm == "default" && sf == "default" && tt == "default")
2243 if (rm != "default")
2244 os << "\\setmainfont[Mapping=tex-text]{"
2245 << parseFontName(rm) << "}\n";
2246 if (sf != "default") {
2247 string const sans = parseFontName(sf);
2249 os << "\\setsansfont[Scale="
2250 << float(sfscale) / 100
2251 << ",Mapping=tex-text]{"
2254 os << "\\setsansfont[Mapping=tex-text]{"
2257 if (tt != "default") {
2258 string const mono = parseFontName(tt);
2260 os << "\\setmonofont[Scale="
2261 << float(sfscale) / 100
2265 os << "\\setmonofont[Mapping=tex-text]{"
2269 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2274 // Computer Modern (must be explicitly selectable -- there might be classes
2275 // that define a different default font!
2277 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2278 // osf for Computer Modern needs eco.sty
2280 os << "\\usepackage{eco}\n";
2282 // Latin Modern Roman
2283 else if (rm == "lmodern")
2284 os << "\\usepackage{lmodern}\n";
2286 else if (rm == "ae") {
2287 // not needed when using OT1 font encoding.
2288 if (font_encoding() != "default")
2289 os << "\\usepackage{ae,aecompl}\n";
2292 else if (rm == "times") {
2293 // try to load the best available package
2294 if (LaTeXFeatures::isAvailable("mathptmx"))
2295 os << "\\usepackage{mathptmx}\n";
2296 else if (LaTeXFeatures::isAvailable("mathptm"))
2297 os << "\\usepackage{mathptm}\n";
2299 os << "\\usepackage{times}\n";
2302 else if (rm == "palatino") {
2303 // try to load the best available package
2304 if (LaTeXFeatures::isAvailable("mathpazo")) {
2305 os << "\\usepackage";
2311 // "osf" includes "sc"!
2315 os << "{mathpazo}\n";
2317 else if (LaTeXFeatures::isAvailable("mathpple"))
2318 os << "\\usepackage{mathpple}\n";
2320 os << "\\usepackage{palatino}\n";
2323 else if (rm == "utopia") {
2324 // fourier supersedes utopia.sty, but does
2325 // not work with OT1 encoding.
2326 if (LaTeXFeatures::isAvailable("fourier")
2327 && font_encoding() != "default") {
2328 os << "\\usepackage";
2339 os << "{fourier}\n";
2342 os << "\\usepackage{utopia}\n";
2344 // Bera (complete fontset)
2345 else if (rm == "bera" && sf == "default" && tt == "default")
2346 os << "\\usepackage{bera}\n";
2348 else if (rm != "default")
2349 os << "\\usepackage" << "{" << rm << "}\n";
2352 // Helvetica, Bera Sans
2353 if (sf == "helvet" || sf == "berasans") {
2355 os << "\\usepackage[scaled=" << float(sfscale) / 100
2356 << "]{" << sf << "}\n";
2358 os << "\\usepackage{" << sf << "}\n";
2361 else if (sf == "avant")
2362 os << "\\usepackage{" << sf << "}\n";
2363 // Computer Modern, Latin Modern, CM Bright
2364 else if (sf != "default")
2365 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2367 // monospaced/typewriter
2368 // Courier, LuxiMono
2369 if (tt == "luximono" || tt == "beramono") {
2371 os << "\\usepackage[scaled=" << float(ttscale) / 100
2372 << "]{" << tt << "}\n";
2374 os << "\\usepackage{" << tt << "}\n";
2377 else if (tt == "courier" )
2378 os << "\\usepackage{" << tt << "}\n";
2379 // Computer Modern, Latin Modern, CM Bright
2380 else if (tt != "default")
2381 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2387 Encoding const & BufferParams::encoding() const
2390 return *(encodings.fromLaTeXName("utf8-plain"));
2391 if (inputenc == "auto" || inputenc == "default")
2392 return *language->encoding();
2393 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2396 LYXERR0("Unknown inputenc value `" << inputenc
2397 << "'. Using `auto' instead.");
2398 return *language->encoding();
2402 CiteEngine BufferParams::citeEngine() const
2404 // FIXME the class should provide the numerical/
2405 // authoryear choice
2406 if (documentClass().provides("natbib")
2407 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2408 return ENGINE_NATBIB_AUTHORYEAR;
2409 return cite_engine_;
2413 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2415 cite_engine_ = cite_engine;