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_use_mathml = true;
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_use_mathml") {
779 lex >> html_use_mathml;
780 } else if (token == "\\html_be_strict") {
781 lex >> html_be_strict;
783 lyxerr << "BufferParams::readToken(): Unknown token: " <<
792 void BufferParams::writeFile(ostream & os) const
794 // The top of the file is written by the buffer.
795 // Prints out the buffer info into the .lyx file given by file
798 os << "\\textclass " << baseClass()->name() << '\n';
801 if (!preamble.empty()) {
802 // remove '\n' from the end of preamble
803 string const tmppreamble = rtrim(preamble, "\n");
804 os << "\\begin_preamble\n"
806 << "\n\\end_preamble\n";
810 if (!options.empty()) {
811 os << "\\options " << options << '\n';
814 // use the class options defined in the layout?
815 os << "\\use_default_options "
816 << convert<string>(use_default_options) << "\n";
818 // the master document
819 if (!master.empty()) {
820 os << "\\master " << master << '\n';
824 if (!removedModules_.empty()) {
825 os << "\\begin_removed_modules" << '\n';
826 list<string>::const_iterator it = removedModules_.begin();
827 list<string>::const_iterator en = removedModules_.end();
828 for (; it != en; it++)
830 os << "\\end_removed_modules" << '\n';
834 if (!layoutModules_.empty()) {
835 os << "\\begin_modules" << '\n';
836 LayoutModuleList::const_iterator it = layoutModules_.begin();
837 LayoutModuleList::const_iterator en = layoutModules_.end();
838 for (; it != en; it++)
840 os << "\\end_modules" << '\n';
844 if (!includedChildren_.empty()) {
845 os << "\\begin_includeonly" << '\n';
846 list<string>::const_iterator it = includedChildren_.begin();
847 list<string>::const_iterator en = includedChildren_.end();
848 for (; it != en; it++)
850 os << "\\end_includeonly" << '\n';
852 os << "\\maintain_unincluded_children "
853 << convert<string>(maintain_unincluded_children) << '\n';
855 // local layout information
856 if (!local_layout.empty()) {
857 // remove '\n' from the end
858 string const tmplocal = rtrim(local_layout, "\n");
859 os << "\\begin_local_layout\n"
861 << "\n\\end_local_layout\n";
864 // then the text parameters
865 if (language != ignore_language)
866 os << "\\language " << language->lang() << '\n';
867 os << "\\inputencoding " << inputenc
868 << "\n\\fontencoding " << fontenc
869 << "\n\\font_roman " << fontsRoman
870 << "\n\\font_sans " << fontsSans
871 << "\n\\font_typewriter " << fontsTypewriter
872 << "\n\\font_default_family " << fontsDefaultFamily
873 << "\n\\use_xetex " << convert<string>(useXetex)
874 << "\n\\font_sc " << convert<string>(fontsSC)
875 << "\n\\font_osf " << convert<string>(fontsOSF)
876 << "\n\\font_sf_scale " << fontsSansScale
877 << "\n\\font_tt_scale " << fontsTypewriterScale
879 if (!fontsCJK.empty()) {
880 os << "\\font_cjk " << fontsCJK << '\n';
882 os << "\n\\graphics " << graphicsDriver << '\n';
883 os << "\\default_output_format " << defaultOutputFormat << '\n';
884 os << "\\bibtex_command " << bibtex_command << '\n';
885 os << "\\index_command " << index_command << '\n';
887 if (!float_placement.empty()) {
888 os << "\\float_placement " << float_placement << '\n';
890 os << "\\paperfontsize " << fontsize << '\n';
892 spacing().writeFile(os);
893 pdfoptions().writeFile(os);
895 os << "\\papersize " << string_papersize[papersize]
896 << "\n\\use_geometry " << convert<string>(use_geometry)
897 << "\n\\use_amsmath " << use_amsmath
898 << "\n\\use_esint " << use_esint
899 << "\n\\use_mhchem " << use_mhchem
900 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
901 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
902 << "\n\\use_indices " << convert<string>(use_indices)
903 << "\n\\paperorientation " << string_orientation[orientation]
904 << "\n\\suppress_date " << convert<string>(suppress_date)
906 if (backgroundcolor != lyx::rgbFromHexName("#ffffff"))
907 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
909 BranchList::const_iterator it = branchlist().begin();
910 BranchList::const_iterator end = branchlist().end();
911 for (; it != end; ++it) {
912 os << "\\branch " << to_utf8(it->branch())
913 << "\n\\selected " << it->isSelected()
914 << "\n\\filename_suffix " << it->hasFilenameSuffix()
915 << "\n\\color " << lyx::X11hexname(it->color())
920 IndicesList::const_iterator iit = indiceslist().begin();
921 IndicesList::const_iterator iend = indiceslist().end();
922 for (; iit != iend; ++iit) {
923 os << "\\index " << to_utf8(iit->index())
924 << "\n\\shortcut " << to_utf8(iit->shortcut())
925 << "\n\\color " << lyx::X11hexname(iit->color())
930 if (!paperwidth.empty())
931 os << "\\paperwidth "
932 << VSpace(paperwidth).asLyXCommand() << '\n';
933 if (!paperheight.empty())
934 os << "\\paperheight "
935 << VSpace(paperheight).asLyXCommand() << '\n';
936 if (!leftmargin.empty())
937 os << "\\leftmargin "
938 << VSpace(leftmargin).asLyXCommand() << '\n';
939 if (!topmargin.empty())
941 << VSpace(topmargin).asLyXCommand() << '\n';
942 if (!rightmargin.empty())
943 os << "\\rightmargin "
944 << VSpace(rightmargin).asLyXCommand() << '\n';
945 if (!bottommargin.empty())
946 os << "\\bottommargin "
947 << VSpace(bottommargin).asLyXCommand() << '\n';
948 if (!headheight.empty())
949 os << "\\headheight "
950 << VSpace(headheight).asLyXCommand() << '\n';
951 if (!headsep.empty())
953 << VSpace(headsep).asLyXCommand() << '\n';
954 if (!footskip.empty())
956 << VSpace(footskip).asLyXCommand() << '\n';
957 if (!columnsep.empty())
959 << VSpace(columnsep).asLyXCommand() << '\n';
960 os << "\\secnumdepth " << secnumdepth
961 << "\n\\tocdepth " << tocdepth
962 << "\n\\paragraph_separation "
963 << string_paragraph_separation[paragraph_separation];
964 if (!paragraph_separation)
965 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
967 os << "\n\\defskip " << getDefSkip().asLyXCommand();
968 os << "\n\\quotes_language "
969 << string_quotes_language[quotes_language]
970 << "\n\\papercolumns " << columns
971 << "\n\\papersides " << sides
972 << "\n\\paperpagestyle " << pagestyle << '\n';
973 if (!listings_params.empty())
974 os << "\\listings_params \"" <<
975 InsetListingsParams(listings_params).encodedString() << "\"\n";
976 for (int i = 0; i < 4; ++i) {
977 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
978 if (user_defined_bullet(i).getFont() != -1) {
979 os << "\\bullet " << i << " "
980 << user_defined_bullet(i).getFont() << " "
981 << user_defined_bullet(i).getCharacter() << " "
982 << user_defined_bullet(i).getSize() << "\n";
986 os << "\\bulletLaTeX " << i << " \""
987 << lyx::to_ascii(user_defined_bullet(i).getText())
993 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n"
994 << "\\output_changes " << convert<string>(outputChanges) << "\n"
995 << "\\html_use_mathml " << convert<string>(html_use_mathml) << "\n"
996 << "\\html_be_strict " << convert<string>(html_be_strict) << "\n";
998 os << pimpl_->authorlist;
1002 void BufferParams::validate(LaTeXFeatures & features) const
1004 features.require(documentClass().requires());
1006 if (outputChanges) {
1007 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1008 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1009 LaTeXFeatures::isAvailable("xcolor");
1011 switch (features.runparams().flavor) {
1012 case OutputParams::LATEX:
1014 features.require("ct-dvipost");
1015 features.require("dvipost");
1016 } else if (xcolorulem) {
1017 features.require("ct-xcolor-ulem");
1018 features.require("ulem");
1019 features.require("xcolor");
1021 features.require("ct-none");
1024 case OutputParams::PDFLATEX:
1025 case OutputParams::XETEX:
1027 features.require("ct-xcolor-ulem");
1028 features.require("ulem");
1029 features.require("xcolor");
1030 // improves color handling in PDF output
1031 features.require("pdfcolmk");
1033 features.require("ct-none");
1041 // Floats with 'Here definitely' as default setting.
1042 if (float_placement.find('H') != string::npos)
1043 features.require("float");
1045 // AMS Style is at document level
1046 if (use_amsmath == package_on
1047 || documentClass().provides("amsmath"))
1048 features.require("amsmath");
1049 if (use_esint == package_on)
1050 features.require("esint");
1051 if (use_mhchem == package_on)
1052 features.require("mhchem");
1054 // Document-level line spacing
1055 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1056 features.require("setspace");
1058 // the bullet shapes are buffer level not paragraph level
1059 // so they are tested here
1060 for (int i = 0; i < 4; ++i) {
1061 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1063 int const font = user_defined_bullet(i).getFont();
1065 int const c = user_defined_bullet(i).getCharacter();
1071 features.require("latexsym");
1073 } else if (font == 1) {
1074 features.require("amssymb");
1075 } else if (font >= 2 && font <= 5) {
1076 features.require("pifont");
1080 if (pdfoptions().use_hyperref) {
1081 features.require("hyperref");
1082 // due to interferences with babel and hyperref, the color package has to
1083 // be loaded after hyperref when hyperref is used with the colorlinks
1084 // option, see http://www.lyx.org/trac/ticket/5291
1085 if (pdfoptions().colorlinks)
1086 features.require("color");
1090 features.require("xetex");
1092 if (language->lang() == "vietnamese")
1093 features.require("vietnamese");
1094 else if (language->lang() == "japanese")
1095 features.require("japanese");
1099 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1100 TexRow & texrow, FileName const & filepath) const
1102 os << "\\documentclass";
1104 DocumentClass const & tclass = documentClass();
1106 ostringstream clsoptions; // the document class options.
1108 if (tokenPos(tclass.opt_fontsize(),
1109 '|', fontsize) >= 0) {
1110 // only write if existing in list (and not default)
1111 clsoptions << fontsize << "pt,";
1114 // custom, A3, B3 and B4 paper sizes need geometry
1115 bool nonstandard_papersize = papersize == PAPER_B3
1116 || papersize == PAPER_B4
1117 || papersize == PAPER_A3
1118 || papersize == PAPER_CUSTOM;
1120 if (!use_geometry) {
1121 switch (papersize) {
1123 clsoptions << "a4paper,";
1125 case PAPER_USLETTER:
1126 clsoptions << "letterpaper,";
1129 clsoptions << "a5paper,";
1132 clsoptions << "b5paper,";
1134 case PAPER_USEXECUTIVE:
1135 clsoptions << "executivepaper,";
1138 clsoptions << "legalpaper,";
1150 if (sides != tclass.sides()) {
1153 clsoptions << "oneside,";
1156 clsoptions << "twoside,";
1162 if (columns != tclass.columns()) {
1164 clsoptions << "twocolumn,";
1166 clsoptions << "onecolumn,";
1170 && orientation == ORIENTATION_LANDSCAPE)
1171 clsoptions << "landscape,";
1173 // language should be a parameter to \documentclass
1174 if (language->babel() == "hebrew"
1175 && default_language->babel() != "hebrew")
1176 // This seems necessary
1177 features.useLanguage(default_language);
1179 ostringstream language_options;
1180 bool const use_babel = features.useBabel();
1182 language_options << features.getLanguages();
1183 if (!language->babel().empty()) {
1184 if (!language_options.str().empty())
1185 language_options << ',';
1186 language_options << language->babel();
1188 // if Vietnamese is used, babel must directly be loaded
1189 // with language options, not in the class options, see
1190 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1191 size_t viet = language_options.str().find("vietnam");
1192 // viet = string::npos when not found
1193 // the same is for all other languages that are not directly supported by
1194 // babel, but where LaTeX-packages add babel support.
1195 // this is currently the case for Latvian, Lithuanian, and Mongolian
1196 size_t latvian = language_options.str().find("latvian");
1197 size_t lithu = language_options.str().find("lithuanian");
1198 size_t mongo = language_options.str().find("mongolian");
1199 // if Japanese is used, babel must directly be loaded
1200 // with language options, not in the class options, see
1201 // http://www.lyx.org/trac/ticket/4597#c4
1202 size_t japan = language_options.str().find("japanese");
1203 if (lyxrc.language_global_options && !language_options.str().empty()
1204 && viet == string::npos && japan == string::npos
1205 && latvian == string::npos && lithu == string::npos
1206 && mongo == string::npos)
1207 clsoptions << language_options.str() << ',';
1210 // the predefined options from the layout
1211 if (use_default_options && !tclass.options().empty())
1212 clsoptions << tclass.options() << ',';
1214 // the user-defined options
1215 if (!options.empty()) {
1216 clsoptions << options << ',';
1219 string strOptions(clsoptions.str());
1220 if (!strOptions.empty()) {
1221 strOptions = rtrim(strOptions, ",");
1223 os << '[' << from_utf8(strOptions) << ']';
1226 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1228 // end of \documentclass defs
1231 os << "\\usepackage{fontspec}\n";
1235 // font selection must be done before loading fontenc.sty
1236 string const fonts =
1237 loadFonts(fontsRoman, fontsSans,
1238 fontsTypewriter, fontsSC, fontsOSF,
1239 fontsSansScale, fontsTypewriterScale, useXetex);
1240 if (!fonts.empty()) {
1241 os << from_ascii(fonts);
1244 if (fontsDefaultFamily != "default")
1245 os << "\\renewcommand{\\familydefault}{\\"
1246 << from_ascii(fontsDefaultFamily) << "}\n";
1248 // set font encoding
1249 // for arabic_arabi and farsi we also need to load the LAE and
1251 // XeTeX works without fontenc
1252 if (font_encoding() != "default" && language->lang() != "japanese"
1254 if (language->lang() == "arabic_arabi"
1255 || language->lang() == "farsi") {
1256 os << "\\usepackage[" << from_ascii(font_encoding())
1257 << ",LFE,LAE]{fontenc}\n";
1260 os << "\\usepackage[" << from_ascii(font_encoding())
1266 // handle inputenc etc.
1267 writeEncodingPreamble(os, features, texrow);
1270 if (!features.runparams().includeall && !includedChildren_.empty()) {
1271 os << "\\includeonly{";
1272 list<string>::const_iterator it = includedChildren_.begin();
1274 for (; it != includedChildren_.end() ; ++it) {
1275 string incfile = *it;
1276 FileName inc = makeAbsPath(incfile, filepath.absFilename());
1277 string mangled = DocFileName(changeExtension(inc.absFilename(), ".tex")).
1279 if (!features.runparams().nice)
1281 // \includeonly doesn't want an extension
1282 incfile = changeExtension(incfile, string());
1283 incfile = support::latex_path(incfile);
1284 if (!incfile.empty()) {
1287 os << from_utf8(incfile);
1294 if (!listings_params.empty() || features.isRequired("listings")) {
1295 os << "\\usepackage{listings}\n";
1298 if (!listings_params.empty()) {
1300 // do not test validity because listings_params is
1301 // supposed to be valid
1303 InsetListingsParams(listings_params).separatedParams(true);
1304 // we can't support all packages, but we should load the color package
1305 if (par.find("\\color", 0) != string::npos)
1306 features.require("color");
1307 os << from_utf8(par);
1308 // count the number of newlines
1309 for (size_t i = 0; i < par.size(); ++i)
1315 if (!tclass.provides("geometry")
1316 && (use_geometry || nonstandard_papersize)) {
1317 odocstringstream ods;
1318 if (!getGraphicsDriver("geometry").empty())
1319 ods << getGraphicsDriver("geometry");
1320 if (orientation == ORIENTATION_LANDSCAPE)
1321 ods << ",landscape";
1322 switch (papersize) {
1324 if (!paperwidth.empty())
1325 ods << ",paperwidth="
1326 << from_ascii(paperwidth);
1327 if (!paperheight.empty())
1328 ods << ",paperheight="
1329 << from_ascii(paperheight);
1331 case PAPER_USLETTER:
1332 ods << ",letterpaper";
1335 ods << ",legalpaper";
1337 case PAPER_USEXECUTIVE:
1338 ods << ",executivepaper";
1359 // default papersize ie PAPER_DEFAULT
1360 switch (lyxrc.default_papersize) {
1361 case PAPER_DEFAULT: // keep compiler happy
1362 case PAPER_USLETTER:
1363 ods << ",letterpaper";
1366 ods << ",legalpaper";
1368 case PAPER_USEXECUTIVE:
1369 ods << ",executivepaper";
1389 docstring const g_options = trim(ods.str(), ",");
1390 os << "\\usepackage";
1391 if (!g_options.empty())
1392 os << '[' << g_options << ']';
1393 os << "{geometry}\n";
1395 os << "\\geometry{verbose";
1396 if (!topmargin.empty())
1397 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1398 if (!bottommargin.empty())
1399 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1400 if (!leftmargin.empty())
1401 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1402 if (!rightmargin.empty())
1403 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1404 if (!headheight.empty())
1405 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1406 if (!headsep.empty())
1407 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1408 if (!footskip.empty())
1409 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1410 if (!columnsep.empty())
1411 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1414 } else if (orientation == ORIENTATION_LANDSCAPE) {
1415 features.require("papersize");
1418 if (tokenPos(tclass.opt_pagestyle(),
1419 '|', pagestyle) >= 0) {
1420 if (pagestyle == "fancy") {
1421 os << "\\usepackage{fancyhdr}\n";
1424 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1428 // only output when the background color is not white
1429 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1430 // only require color here, the background color will be defined
1431 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1433 features.require("color");
1434 features.require("pagecolor");
1437 // Only if class has a ToC hierarchy
1438 if (tclass.hasTocLevels()) {
1439 if (secnumdepth != tclass.secnumdepth()) {
1440 os << "\\setcounter{secnumdepth}{"
1445 if (tocdepth != tclass.tocdepth()) {
1446 os << "\\setcounter{tocdepth}{"
1453 if (paragraph_separation) {
1454 // when skip separation
1455 switch (getDefSkip().kind()) {
1456 case VSpace::SMALLSKIP:
1457 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1459 case VSpace::MEDSKIP:
1460 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1462 case VSpace::BIGSKIP:
1463 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1465 case VSpace::LENGTH:
1466 os << "\\setlength{\\parskip}{"
1467 << from_utf8(getDefSkip().length().asLatexString())
1470 default: // should never happen // Then delete it.
1471 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1475 os << "\\setlength{\\parindent}{0pt}\n";
1478 // when separation by indentation
1479 // only output something when a width is given
1480 if (getIndentation().asLyXCommand() != "default") {
1481 os << "\\setlength{\\parindent}{"
1482 << from_utf8(getIndentation().asLatexCommand())
1488 // Now insert the LyX specific LaTeX commands...
1489 docstring lyxpreamble;
1491 // due to interferences with babel and hyperref, the color package has to
1492 // be loaded (when it is not already loaded) before babel when hyperref
1493 // is used with the colorlinks option, see
1494 // http://www.lyx.org/trac/ticket/5291
1495 // we decided therefore to load color always before babel, see
1496 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1497 lyxpreamble += from_ascii(features.getColorOptions());
1499 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1501 && (features.isRequired("jurabib")
1502 || features.isRequired("hyperref")
1503 || features.isRequired("vietnamese")
1504 || features.isRequired("japanese") ) ) {
1506 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1507 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1510 // The optional packages;
1511 lyxpreamble += from_ascii(features.getPackages());
1513 // Additional Indices
1514 if (features.isRequired("splitidx")) {
1515 IndicesList::const_iterator iit = indiceslist().begin();
1516 IndicesList::const_iterator iend = indiceslist().end();
1517 for (; iit != iend; ++iit) {
1518 lyxpreamble += "\\newindex[";
1519 lyxpreamble += iit->index();
1520 lyxpreamble += "]{";
1521 lyxpreamble += iit->shortcut();
1522 lyxpreamble += "}\n";
1527 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1530 // * Hyperref manual: "Make sure it comes last of your loaded
1531 // packages, to give it a fighting chance of not being over-written,
1532 // since its job is to redefine many LaTeX commands."
1533 // * Email from Heiko Oberdiek: "It is usually better to load babel
1534 // before hyperref. Then hyperref has a chance to detect babel.
1535 // * Has to be loaded before the "LyX specific LaTeX commands" to
1536 // avoid errors with algorithm floats.
1537 // use hyperref explicitly if it is required
1538 if (features.isRequired("hyperref")) {
1539 // pass what we have to stream here, since we need
1540 // to access the stream itself in PDFOptions.
1544 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1546 OutputParams tmp_params = features.runparams();
1547 lines += pdfoptions().writeLaTeX(tmp_params, os,
1548 documentClass().provides("hyperref"));
1549 texrow.newlines(lines);
1550 // set back for the rest
1551 lyxpreamble.clear();
1554 // Will be surrounded by \makeatletter and \makeatother when not empty
1555 docstring atlyxpreamble;
1557 // Some macros LyX will need
1558 docstring tmppreamble(features.getMacros());
1560 if (!tmppreamble.empty())
1561 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1562 "LyX specific LaTeX commands.\n"
1563 + tmppreamble + '\n';
1565 // the text class specific preamble
1566 tmppreamble = features.getTClassPreamble();
1567 if (!tmppreamble.empty())
1568 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1569 "Textclass specific LaTeX commands.\n"
1570 + tmppreamble + '\n';
1572 // suppress date if selected
1573 // use \@ifundefined because we cannot be sure that every document class
1574 // has a \date command
1576 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1578 /* the user-defined preamble */
1579 if (!containsOnly(preamble, " \n\t"))
1581 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1582 "User specified LaTeX commands.\n"
1583 + from_utf8(preamble) + '\n';
1585 // subfig loads internally the LaTeX package "caption". As
1586 // caption is a very popular package, users will load it in
1587 // the preamble. Therefore we must load subfig behind the
1588 // user-defined preamble and check if the caption package was
1589 // loaded or not. For the case that caption is loaded before
1590 // subfig, there is the subfig option "caption=false". This
1591 // option also works when a koma-script class is used and
1592 // koma's own caption commands are used instead of caption. We
1593 // use \PassOptionsToPackage here because the user could have
1594 // already loaded subfig in the preamble.
1595 if (features.isRequired("subfig")) {
1596 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1597 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1598 "\\usepackage{subfig}\n";
1601 // Itemize bullet settings need to be last in case the user
1602 // defines their own bullets that use a package included
1603 // in the user-defined preamble -- ARRae
1604 // Actually it has to be done much later than that
1605 // since some packages like frenchb make modifications
1606 // at \begin{document} time -- JMarc
1607 docstring bullets_def;
1608 for (int i = 0; i < 4; ++i) {
1609 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1610 if (bullets_def.empty())
1611 bullets_def += "\\AtBeginDocument{\n";
1612 bullets_def += " \\def\\labelitemi";
1614 // `i' is one less than the item to modify
1621 bullets_def += "ii";
1627 bullets_def += '{' +
1628 user_defined_bullet(i).getText()
1633 if (!bullets_def.empty())
1634 atlyxpreamble += bullets_def + "}\n\n";
1636 if (!atlyxpreamble.empty())
1637 lyxpreamble += "\n\\makeatletter\n"
1638 + atlyxpreamble + "\\makeatother\n\n";
1640 // We try to load babel late, in case it interferes with other packages.
1641 // Jurabib and Hyperref have to be called after babel, though.
1642 if (use_babel && !features.isRequired("jurabib")
1643 && !features.isRequired("hyperref")
1644 && !features.isRequired("vietnamese")
1645 && !features.isRequired("japanese")) {
1647 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1648 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1651 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1652 if (!i18npreamble.empty())
1653 lyxpreamble += i18npreamble + '\n';
1656 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1657 texrow.newlines(nlines);
1661 // these packages (xunicode, for that matter) need to be loaded at least
1662 // after amsmath, amssymb, esint and the other packages that provide
1665 os << "\\usepackage{xunicode}\n";
1667 os << "\\usepackage{xltxtra}\n";
1674 void BufferParams::useClassDefaults()
1676 DocumentClass const & tclass = documentClass();
1678 sides = tclass.sides();
1679 columns = tclass.columns();
1680 pagestyle = tclass.pagestyle();
1681 use_default_options = true;
1682 // Only if class has a ToC hierarchy
1683 if (tclass.hasTocLevels()) {
1684 secnumdepth = tclass.secnumdepth();
1685 tocdepth = tclass.tocdepth();
1690 bool BufferParams::hasClassDefaults() const
1692 DocumentClass const & tclass = documentClass();
1694 return sides == tclass.sides()
1695 && columns == tclass.columns()
1696 && pagestyle == tclass.pagestyle()
1697 && use_default_options
1698 && secnumdepth == tclass.secnumdepth()
1699 && tocdepth == tclass.tocdepth();
1703 DocumentClass const & BufferParams::documentClass() const
1709 DocumentClass const * BufferParams::documentClassPtr() const {
1714 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1715 // evil, but this function is evil
1716 doc_class_ = const_cast<DocumentClass *>(tc);
1720 bool BufferParams::setBaseClass(string const & classname)
1722 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1723 LayoutFileList & bcl = LayoutFileList::get();
1724 if (!bcl.haveClass(classname)) {
1726 bformat(_("The document class %1$s could not be found. "
1727 "A default textclass with default layouts will be used. "
1728 "LyX might not be able to produce output unless a correct "
1729 "textclass is selected from the document settings dialog."),
1730 from_utf8(classname));
1731 frontend::Alert::error(_("Document class not found"), s);
1732 bcl.addEmptyClass(classname);
1735 bool const success = bcl[classname].load();
1738 bformat(_("The document class %1$s could not be loaded."),
1739 from_utf8(classname));
1740 frontend::Alert::error(_("Could not load class"), s);
1744 pimpl_->baseClass_ = classname;
1745 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1750 LayoutFile const * BufferParams::baseClass() const
1752 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1753 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1759 LayoutFileIndex const & BufferParams::baseClassID() const
1761 return pimpl_->baseClass_;
1765 void BufferParams::makeDocumentClass()
1770 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1772 if (!local_layout.empty()) {
1773 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1774 docstring const msg = _("Error reading internal layout information");
1775 frontend::Alert::warning(_("Read Error"), msg);
1780 bool BufferParams::moduleCanBeAdded(string const & modName) const
1782 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1786 bool BufferParams::addLayoutModule(string const & modName)
1788 LayoutModuleList::const_iterator it = layoutModules_.begin();
1789 LayoutModuleList::const_iterator end = layoutModules_.end();
1790 for (; it != end; it++)
1793 layoutModules_.push_back(modName);
1798 Font const BufferParams::getFont() const
1800 FontInfo f = documentClass().defaultfont();
1801 if (fontsDefaultFamily == "rmdefault")
1802 f.setFamily(ROMAN_FAMILY);
1803 else if (fontsDefaultFamily == "sfdefault")
1804 f.setFamily(SANS_FAMILY);
1805 else if (fontsDefaultFamily == "ttdefault")
1806 f.setFamily(TYPEWRITER_FAMILY);
1807 return Font(f, language);
1811 void BufferParams::readPreamble(Lexer & lex)
1813 if (lex.getString() != "\\begin_preamble")
1814 lyxerr << "Error (BufferParams::readPreamble):"
1815 "consistency check failed." << endl;
1817 preamble = lex.getLongString("\\end_preamble");
1821 void BufferParams::readLocalLayout(Lexer & lex)
1823 if (lex.getString() != "\\begin_local_layout")
1824 lyxerr << "Error (BufferParams::readLocalLayout):"
1825 "consistency check failed." << endl;
1827 local_layout = lex.getLongString("\\end_local_layout");
1831 void BufferParams::readLanguage(Lexer & lex)
1833 if (!lex.next()) return;
1835 string const tmptok = lex.getString();
1837 // check if tmptok is part of tex_babel in tex-defs.h
1838 language = languages.getLanguage(tmptok);
1840 // Language tmptok was not found
1841 language = default_language;
1842 lyxerr << "Warning: Setting language `"
1843 << tmptok << "' to `" << language->lang()
1849 void BufferParams::readGraphicsDriver(Lexer & lex)
1854 string const tmptok = lex.getString();
1855 // check if tmptok is part of tex_graphics in tex_defs.h
1858 string const test = tex_graphics[n++];
1860 if (test == tmptok) {
1861 graphicsDriver = tmptok;
1866 "Warning: graphics driver `$$Token' not recognized!\n"
1867 " Setting graphics driver to `default'.\n");
1868 graphicsDriver = "default";
1875 void BufferParams::readBullets(Lexer & lex)
1880 int const index = lex.getInteger();
1882 int temp_int = lex.getInteger();
1883 user_defined_bullet(index).setFont(temp_int);
1884 temp_bullet(index).setFont(temp_int);
1886 user_defined_bullet(index).setCharacter(temp_int);
1887 temp_bullet(index).setCharacter(temp_int);
1889 user_defined_bullet(index).setSize(temp_int);
1890 temp_bullet(index).setSize(temp_int);
1894 void BufferParams::readBulletsLaTeX(Lexer & lex)
1896 // The bullet class should be able to read this.
1899 int const index = lex.getInteger();
1901 docstring const temp_str = lex.getDocString();
1903 user_defined_bullet(index).setText(temp_str);
1904 temp_bullet(index).setText(temp_str);
1908 void BufferParams::readModules(Lexer & lex)
1910 if (!lex.eatLine()) {
1911 lyxerr << "Error (BufferParams::readModules):"
1912 "Unexpected end of input." << endl;
1916 string mod = lex.getString();
1917 if (mod == "\\end_modules")
1919 addLayoutModule(mod);
1925 void BufferParams::readRemovedModules(Lexer & lex)
1927 if (!lex.eatLine()) {
1928 lyxerr << "Error (BufferParams::readRemovedModules):"
1929 "Unexpected end of input." << endl;
1933 string mod = lex.getString();
1934 if (mod == "\\end_removed_modules")
1936 removedModules_.push_back(mod);
1939 // now we want to remove any removed modules that were previously
1940 // added. normally, that will be because default modules were added in
1941 // setBaseClass(), which gets called when \textclass is read at the
1942 // start of the read.
1943 list<string>::const_iterator rit = removedModules_.begin();
1944 list<string>::const_iterator const ren = removedModules_.end();
1945 for (; rit != ren; rit++) {
1946 LayoutModuleList::iterator const mit = layoutModules_.begin();
1947 LayoutModuleList::iterator const men = layoutModules_.end();
1948 LayoutModuleList::iterator found = find(mit, men, *rit);
1951 layoutModules_.erase(found);
1956 void BufferParams::readIncludeonly(Lexer & lex)
1958 if (!lex.eatLine()) {
1959 lyxerr << "Error (BufferParams::readIncludeonly):"
1960 "Unexpected end of input." << endl;
1964 string child = lex.getString();
1965 if (child == "\\end_includeonly")
1967 includedChildren_.push_back(child);
1973 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1975 char real_papersize = papersize;
1976 if (real_papersize == PAPER_DEFAULT)
1977 real_papersize = lyxrc.default_papersize;
1979 switch (real_papersize) {
1981 // could be anything, so don't guess
1983 case PAPER_CUSTOM: {
1984 if (purpose == XDVI && !paperwidth.empty() &&
1985 !paperheight.empty()) {
1986 // heightxwidth<unit>
1987 string first = paperwidth;
1988 string second = paperheight;
1989 if (orientation == ORIENTATION_LANDSCAPE)
1992 return first.erase(first.length() - 2)
2004 // dvips and dvipdfm do not know this
2005 if (purpose == DVIPS || purpose == DVIPDFM)
2009 // dvipdfm does not know this
2010 if (purpose == DVIPDFM)
2014 // dvipdfm does not know this
2015 if (purpose == DVIPDFM)
2018 case PAPER_USEXECUTIVE:
2019 // dvipdfm does not know this
2020 if (purpose == DVIPDFM)
2025 case PAPER_USLETTER:
2027 if (purpose == XDVI)
2034 string const BufferParams::dvips_options() const
2039 && papersize == PAPER_CUSTOM
2040 && !lyxrc.print_paper_dimension_flag.empty()
2041 && !paperwidth.empty()
2042 && !paperheight.empty()) {
2043 // using a custom papersize
2044 result = lyxrc.print_paper_dimension_flag;
2045 result += ' ' + paperwidth;
2046 result += ',' + paperheight;
2048 string const paper_option = paperSizeName(DVIPS);
2049 if (!paper_option.empty() && (paper_option != "letter" ||
2050 orientation != ORIENTATION_LANDSCAPE)) {
2051 // dvips won't accept -t letter -t landscape.
2052 // In all other cases, include the paper size
2054 result = lyxrc.print_paper_flag;
2055 result += ' ' + paper_option;
2058 if (orientation == ORIENTATION_LANDSCAPE &&
2059 papersize != PAPER_CUSTOM)
2060 result += ' ' + lyxrc.print_landscape_flag;
2065 string const BufferParams::font_encoding() const
2067 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2071 string BufferParams::babelCall(string const & lang_opts) const
2073 string lang_pack = lyxrc.language_package;
2074 if (lang_pack != "\\usepackage{babel}")
2076 // suppress the babel call when there is no babel language defined
2077 // for the document language in the lib/languages file and if no
2078 // other languages are used (lang_opts is then empty)
2079 if (lang_opts.empty())
2081 // If Vietnamese is used, babel must directly be loaded with the
2082 // language options, see
2083 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2084 size_t viet = lang_opts.find("vietnam");
2085 // viet = string::npos when not found
2086 // the same is for all other languages that are not directly supported by
2087 // babel, but where LaTeX-packages add babel support.
2088 // this is currently the case for Latvian, Lithuanian, and Mongolian
2089 size_t latvian = lang_opts.find("latvian");
2090 size_t lithu = lang_opts.find("lithuanian");
2091 size_t mongo = lang_opts.find("mongolian");
2092 // If Japanese is used, babel must directly be loaded with the
2093 // language options, see
2094 // http://www.lyx.org/trac/ticket/4597#c4
2095 size_t japan = lang_opts.find("japanese");
2096 if (!lyxrc.language_global_options || viet != string::npos
2097 || japan != string::npos || latvian != string::npos
2098 || lithu != string::npos || mongo != string::npos)
2099 return "\\usepackage[" + lang_opts + "]{babel}";
2104 docstring BufferParams::getGraphicsDriver(string const & package) const
2108 if (package == "geometry") {
2109 if (graphicsDriver == "dvips"
2110 || graphicsDriver == "dvipdfm"
2111 || graphicsDriver == "pdftex"
2112 || graphicsDriver == "vtex")
2113 result = from_ascii(graphicsDriver);
2114 else if (graphicsDriver == "dvipdfmx")
2115 result = from_ascii("dvipdfm");
2122 void BufferParams::writeEncodingPreamble(odocstream & os,
2123 LaTeXFeatures & features, TexRow & texrow) const
2127 if (inputenc == "auto") {
2128 string const doc_encoding =
2129 language->encoding()->latexName();
2130 Encoding::Package const package =
2131 language->encoding()->package();
2133 // Create a list with all the input encodings used
2135 set<string> encodings =
2136 features.getEncodingSet(doc_encoding);
2138 // If the "japanese" package (i.e. pLaTeX) is used,
2139 // inputenc must be omitted.
2140 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2141 if (package == Encoding::japanese)
2142 features.require("japanese");
2144 if ((!encodings.empty() || package == Encoding::inputenc)
2145 && !features.isRequired("japanese")) {
2146 os << "\\usepackage[";
2147 set<string>::const_iterator it = encodings.begin();
2148 set<string>::const_iterator const end = encodings.end();
2150 os << from_ascii(*it);
2153 for (; it != end; ++it)
2154 os << ',' << from_ascii(*it);
2155 if (package == Encoding::inputenc) {
2156 if (!encodings.empty())
2158 os << from_ascii(doc_encoding);
2160 os << "]{inputenc}\n";
2163 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2164 if (language->encoding()->name() == "utf8-cjk"
2165 && LaTeXFeatures::isAvailable("CJKutf8"))
2166 os << "\\usepackage{CJKutf8}\n";
2168 os << "\\usepackage{CJK}\n";
2171 } else if (inputenc != "default") {
2172 switch (encoding().package()) {
2173 case Encoding::none:
2174 case Encoding::japanese:
2176 case Encoding::inputenc:
2177 // do not load inputenc if japanese is used
2178 if (features.isRequired("japanese"))
2180 os << "\\usepackage[" << from_ascii(inputenc)
2185 if (encoding().name() == "utf8-cjk"
2186 && LaTeXFeatures::isAvailable("CJKutf8"))
2187 os << "\\usepackage{CJKutf8}\n";
2189 os << "\\usepackage{CJK}\n";
2195 // The encoding "armscii8" (for Armenian) is only available when
2196 // the package "armtex" is loaded.
2197 if (language->encoding()->latexName() == "armscii8"
2198 || inputenc == "armscii8") {
2199 os << "\\usepackage{armtex}\n";
2205 string const BufferParams::parseFontName(string const & name) const
2207 string mangled = name;
2208 size_t const idx = mangled.find('[');
2209 if (idx == string::npos || idx == 0)
2212 return mangled.substr(0, idx - 1);
2216 string const BufferParams::loadFonts(string const & rm,
2217 string const & sf, string const & tt,
2218 bool const & sc, bool const & osf,
2219 int const & sfscale, int const & ttscale,
2220 bool const & xetex) const
2222 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2223 several packages have been replaced by others, that might not
2224 be installed on every system. We have to take care for that
2225 (see psnfss.pdf). We try to support all psnfss fonts as well
2226 as the fonts that have become de facto standard in the LaTeX
2227 world (e.g. Latin Modern). We do not support obsolete fonts
2228 (like PSLatex). In general, it should be possible to mix any
2229 rm font with any sf or tt font, respectively. (JSpitzm)
2231 -- separate math fonts.
2234 if (rm == "default" && sf == "default" && tt == "default")
2241 if (rm != "default")
2242 os << "\\setmainfont[Mapping=tex-text]{"
2243 << parseFontName(rm) << "}\n";
2244 if (sf != "default") {
2245 string const sans = parseFontName(sf);
2247 os << "\\setsansfont[Scale="
2248 << float(sfscale) / 100
2249 << ",Mapping=tex-text]{"
2252 os << "\\setsansfont[Mapping=tex-text]{"
2255 if (tt != "default") {
2256 string const mono = parseFontName(tt);
2258 os << "\\setmonofont[Scale="
2259 << float(sfscale) / 100
2263 os << "\\setmonofont[Mapping=tex-text]{"
2267 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2272 // Computer Modern (must be explicitly selectable -- there might be classes
2273 // that define a different default font!
2275 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2276 // osf for Computer Modern needs eco.sty
2278 os << "\\usepackage{eco}\n";
2280 // Latin Modern Roman
2281 else if (rm == "lmodern")
2282 os << "\\usepackage{lmodern}\n";
2284 else if (rm == "ae") {
2285 // not needed when using OT1 font encoding.
2286 if (font_encoding() != "default")
2287 os << "\\usepackage{ae,aecompl}\n";
2290 else if (rm == "times") {
2291 // try to load the best available package
2292 if (LaTeXFeatures::isAvailable("mathptmx"))
2293 os << "\\usepackage{mathptmx}\n";
2294 else if (LaTeXFeatures::isAvailable("mathptm"))
2295 os << "\\usepackage{mathptm}\n";
2297 os << "\\usepackage{times}\n";
2300 else if (rm == "palatino") {
2301 // try to load the best available package
2302 if (LaTeXFeatures::isAvailable("mathpazo")) {
2303 os << "\\usepackage";
2309 // "osf" includes "sc"!
2313 os << "{mathpazo}\n";
2315 else if (LaTeXFeatures::isAvailable("mathpple"))
2316 os << "\\usepackage{mathpple}\n";
2318 os << "\\usepackage{palatino}\n";
2321 else if (rm == "utopia") {
2322 // fourier supersedes utopia.sty, but does
2323 // not work with OT1 encoding.
2324 if (LaTeXFeatures::isAvailable("fourier")
2325 && font_encoding() != "default") {
2326 os << "\\usepackage";
2337 os << "{fourier}\n";
2340 os << "\\usepackage{utopia}\n";
2342 // Bera (complete fontset)
2343 else if (rm == "bera" && sf == "default" && tt == "default")
2344 os << "\\usepackage{bera}\n";
2346 else if (rm != "default")
2347 os << "\\usepackage" << "{" << rm << "}\n";
2350 // Helvetica, Bera Sans
2351 if (sf == "helvet" || sf == "berasans") {
2353 os << "\\usepackage[scaled=" << float(sfscale) / 100
2354 << "]{" << sf << "}\n";
2356 os << "\\usepackage{" << sf << "}\n";
2359 else if (sf == "avant")
2360 os << "\\usepackage{" << sf << "}\n";
2361 // Computer Modern, Latin Modern, CM Bright
2362 else if (sf != "default")
2363 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2365 // monospaced/typewriter
2366 // Courier, LuxiMono
2367 if (tt == "luximono" || tt == "beramono") {
2369 os << "\\usepackage[scaled=" << float(ttscale) / 100
2370 << "]{" << tt << "}\n";
2372 os << "\\usepackage{" << tt << "}\n";
2375 else if (tt == "courier" )
2376 os << "\\usepackage{" << tt << "}\n";
2377 // Computer Modern, Latin Modern, CM Bright
2378 else if (tt != "default")
2379 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2385 Encoding const & BufferParams::encoding() const
2388 return *(encodings.fromLaTeXName("utf8-plain"));
2389 if (inputenc == "auto" || inputenc == "default")
2390 return *language->encoding();
2391 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2394 LYXERR0("Unknown inputenc value `" << inputenc
2395 << "'. Using `auto' instead.");
2396 return *language->encoding();
2400 CiteEngine BufferParams::citeEngine() const
2402 // FIXME the class should provide the numerical/
2403 // authoryear choice
2404 if (documentClass().provides("natbib")
2405 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2406 return ENGINE_NATBIB_AUTHORYEAR;
2407 return cite_engine_;
2411 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2413 cite_engine_ = cite_engine;