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. The following prerequisites\n"
526 "are missing:\n%2$s\n"),
527 from_utf8(classname), from_utf8(baseClass()->prerequisites()));
528 frontend::Alert::warning(_("Document class not available"),
529 msg + _("LyX will not be able to produce output."));
531 } else if (token == "\\begin_preamble") {
533 } else if (token == "\\begin_local_layout") {
534 readLocalLayout(lex);
535 } else if (token == "\\begin_modules") {
537 } else if (token == "\\begin_removed_modules") {
538 readRemovedModules(lex);
539 } else if (token == "\\begin_includeonly") {
540 readIncludeonly(lex);
541 } else if (token == "\\maintain_unincluded_children") {
542 lex >> maintain_unincluded_children;
543 } else if (token == "\\options") {
545 options = lex.getString();
546 } else if (token == "\\use_default_options") {
547 lex >> use_default_options;
548 } else if (token == "\\master") {
550 master = lex.getString();
551 } else if (token == "\\suppress_date") {
552 lex >> suppress_date;
553 } else if (token == "\\language") {
555 } else if (token == "\\inputencoding") {
557 } else if (token == "\\graphics") {
558 readGraphicsDriver(lex);
559 } else if (token == "\\default_output_format") {
560 lex >> defaultOutputFormat;
561 } else if (token == "\\bibtex_command") {
563 bibtex_command = lex.getString();
564 } else if (token == "\\index_command") {
566 index_command = lex.getString();
567 } else if (token == "\\fontencoding") {
569 fontenc = lex.getString();
570 } else if (token == "\\font_roman") {
572 fontsRoman = lex.getString();
573 } else if (token == "\\font_sans") {
575 fontsSans = lex.getString();
576 } else if (token == "\\font_typewriter") {
578 fontsTypewriter = lex.getString();
579 } else if (token == "\\font_default_family") {
580 lex >> fontsDefaultFamily;
581 } else if (token == "\\use_xetex") {
583 } else if (token == "\\font_sc") {
585 } else if (token == "\\font_osf") {
587 } else if (token == "\\font_sf_scale") {
588 lex >> fontsSansScale;
589 } else if (token == "\\font_tt_scale") {
590 lex >> fontsTypewriterScale;
591 } else if (token == "\\font_cjk") {
593 } else if (token == "\\paragraph_separation") {
596 paragraph_separation = parseptranslator().find(parsep);
597 } else if (token == "\\paragraph_indentation") {
599 string indentation = lex.getString();
600 pimpl_->indentation = HSpace(indentation);
601 } else if (token == "\\defskip") {
603 string defskip = lex.getString();
604 if (defskip == "defskip")
607 pimpl_->defskip = VSpace(defskip);
608 } else if (token == "\\quotes_language") {
611 quotes_language = quoteslangtranslator().find(quotes_lang);
612 } else if (token == "\\papersize") {
615 papersize = papersizetranslator().find(ppsize);
616 } else if (token == "\\use_geometry") {
618 } else if (token == "\\use_amsmath") {
621 use_amsmath = packagetranslator().find(use_ams);
622 } else if (token == "\\use_esint") {
625 use_esint = packagetranslator().find(useesint);
626 } else if (token == "\\use_mhchem") {
629 use_mhchem = packagetranslator().find(usemhchem);
630 } else if (token == "\\cite_engine") {
633 cite_engine_ = citeenginetranslator().find(engine);
634 } else if (token == "\\use_bibtopic") {
636 } else if (token == "\\use_indices") {
638 } else if (token == "\\tracking_changes") {
640 } else if (token == "\\output_changes") {
641 lex >> outputChanges;
642 } else if (token == "\\branch") {
644 docstring branch = lex.getDocString();
645 branchlist().add(branch);
648 string const tok = lex.getString();
649 if (tok == "\\end_branch")
651 Branch * branch_ptr = branchlist().find(branch);
652 if (tok == "\\selected") {
655 branch_ptr->setSelected(lex.getInteger());
657 if (tok == "\\filename_suffix") {
660 branch_ptr->setFilenameSuffix(lex.getInteger());
662 if (tok == "\\color") {
664 string color = lex.getString();
666 branch_ptr->setColor(color);
667 // Update also the Color table:
669 color = lcolor.getX11Name(Color_background);
671 lcolor.setColor(to_utf8(branch), color);
674 } else if (token == "\\index") {
676 docstring index = lex.getDocString();
678 indiceslist().add(index);
681 string const tok = lex.getString();
682 if (tok == "\\end_index")
684 Index * index_ptr = indiceslist().find(index);
685 if (tok == "\\shortcut") {
687 shortcut = lex.getDocString();
689 index_ptr->setShortcut(shortcut);
691 if (tok == "\\color") {
693 string color = lex.getString();
695 index_ptr->setColor(color);
696 // Update also the Color table:
698 color = lcolor.getX11Name(Color_background);
700 if (!shortcut.empty())
701 lcolor.setColor(to_utf8(shortcut), color);
704 } else if (token == "\\author") {
706 istringstream ss(lex.getString());
709 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
710 } else if (token == "\\paperorientation") {
713 orientation = paperorientationtranslator().find(orient);
714 } else if (token == "\\backgroundcolor") {
716 backgroundcolor = lyx::rgbFromHexName(lex.getString());
717 } else if (token == "\\paperwidth") {
719 } else if (token == "\\paperheight") {
721 } else if (token == "\\leftmargin") {
723 } else if (token == "\\topmargin") {
725 } else if (token == "\\rightmargin") {
727 } else if (token == "\\bottommargin") {
729 } else if (token == "\\headheight") {
731 } else if (token == "\\headsep") {
733 } else if (token == "\\footskip") {
735 } else if (token == "\\columnsep") {
737 } else if (token == "\\paperfontsize") {
739 } else if (token == "\\papercolumns") {
741 } else if (token == "\\listings_params") {
744 listings_params = InsetListingsParams(par).params();
745 } else if (token == "\\papersides") {
748 sides = sidestranslator().find(psides);
749 } else if (token == "\\paperpagestyle") {
751 } else if (token == "\\bullet") {
753 } else if (token == "\\bulletLaTeX") {
754 readBulletsLaTeX(lex);
755 } else if (token == "\\secnumdepth") {
757 } else if (token == "\\tocdepth") {
759 } else if (token == "\\spacing") {
763 if (nspacing == "other") {
766 spacing().set(spacetranslator().find(nspacing), tmp_val);
767 } else if (token == "\\float_placement") {
768 lex >> float_placement;
770 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
771 string toktmp = pdfoptions().readToken(lex, token);
772 if (!toktmp.empty()) {
773 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
777 } else if (token == "\\html_math_output") {
780 html_math_output = static_cast<MathOutput>(temp);
781 } else if (token == "\\html_be_strict") {
782 lex >> html_be_strict;
784 lyxerr << "BufferParams::readToken(): Unknown token: " <<
793 void BufferParams::writeFile(ostream & os) const
795 // The top of the file is written by the buffer.
796 // Prints out the buffer info into the .lyx file given by file
799 os << "\\textclass " << baseClass()->name() << '\n';
802 if (!preamble.empty()) {
803 // remove '\n' from the end of preamble
804 string const tmppreamble = rtrim(preamble, "\n");
805 os << "\\begin_preamble\n"
807 << "\n\\end_preamble\n";
811 if (!options.empty()) {
812 os << "\\options " << options << '\n';
815 // use the class options defined in the layout?
816 os << "\\use_default_options "
817 << convert<string>(use_default_options) << "\n";
819 // the master document
820 if (!master.empty()) {
821 os << "\\master " << master << '\n';
825 if (!removedModules_.empty()) {
826 os << "\\begin_removed_modules" << '\n';
827 list<string>::const_iterator it = removedModules_.begin();
828 list<string>::const_iterator en = removedModules_.end();
829 for (; it != en; it++)
831 os << "\\end_removed_modules" << '\n';
835 if (!layoutModules_.empty()) {
836 os << "\\begin_modules" << '\n';
837 LayoutModuleList::const_iterator it = layoutModules_.begin();
838 LayoutModuleList::const_iterator en = layoutModules_.end();
839 for (; it != en; it++)
841 os << "\\end_modules" << '\n';
845 if (!includedChildren_.empty()) {
846 os << "\\begin_includeonly" << '\n';
847 list<string>::const_iterator it = includedChildren_.begin();
848 list<string>::const_iterator en = includedChildren_.end();
849 for (; it != en; it++)
851 os << "\\end_includeonly" << '\n';
853 os << "\\maintain_unincluded_children "
854 << convert<string>(maintain_unincluded_children) << '\n';
856 // local layout information
857 if (!local_layout.empty()) {
858 // remove '\n' from the end
859 string const tmplocal = rtrim(local_layout, "\n");
860 os << "\\begin_local_layout\n"
862 << "\n\\end_local_layout\n";
865 // then the text parameters
866 if (language != ignore_language)
867 os << "\\language " << language->lang() << '\n';
868 os << "\\inputencoding " << inputenc
869 << "\n\\fontencoding " << fontenc
870 << "\n\\font_roman " << fontsRoman
871 << "\n\\font_sans " << fontsSans
872 << "\n\\font_typewriter " << fontsTypewriter
873 << "\n\\font_default_family " << fontsDefaultFamily
874 << "\n\\use_xetex " << convert<string>(useXetex)
875 << "\n\\font_sc " << convert<string>(fontsSC)
876 << "\n\\font_osf " << convert<string>(fontsOSF)
877 << "\n\\font_sf_scale " << fontsSansScale
878 << "\n\\font_tt_scale " << fontsTypewriterScale
880 if (!fontsCJK.empty()) {
881 os << "\\font_cjk " << fontsCJK << '\n';
883 os << "\n\\graphics " << graphicsDriver << '\n';
884 os << "\\default_output_format " << defaultOutputFormat << '\n';
885 os << "\\bibtex_command " << bibtex_command << '\n';
886 os << "\\index_command " << index_command << '\n';
888 if (!float_placement.empty()) {
889 os << "\\float_placement " << float_placement << '\n';
891 os << "\\paperfontsize " << fontsize << '\n';
893 spacing().writeFile(os);
894 pdfoptions().writeFile(os);
896 os << "\\papersize " << string_papersize[papersize]
897 << "\n\\use_geometry " << convert<string>(use_geometry)
898 << "\n\\use_amsmath " << use_amsmath
899 << "\n\\use_esint " << use_esint
900 << "\n\\use_mhchem " << use_mhchem
901 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
902 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
903 << "\n\\use_indices " << convert<string>(use_indices)
904 << "\n\\paperorientation " << string_orientation[orientation]
905 << "\n\\suppress_date " << convert<string>(suppress_date)
907 if (backgroundcolor != lyx::rgbFromHexName("#ffffff"))
908 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
910 BranchList::const_iterator it = branchlist().begin();
911 BranchList::const_iterator end = branchlist().end();
912 for (; it != end; ++it) {
913 os << "\\branch " << to_utf8(it->branch())
914 << "\n\\selected " << it->isSelected()
915 << "\n\\filename_suffix " << it->hasFilenameSuffix()
916 << "\n\\color " << lyx::X11hexname(it->color())
921 IndicesList::const_iterator iit = indiceslist().begin();
922 IndicesList::const_iterator iend = indiceslist().end();
923 for (; iit != iend; ++iit) {
924 os << "\\index " << to_utf8(iit->index())
925 << "\n\\shortcut " << to_utf8(iit->shortcut())
926 << "\n\\color " << lyx::X11hexname(iit->color())
931 if (!paperwidth.empty())
932 os << "\\paperwidth "
933 << VSpace(paperwidth).asLyXCommand() << '\n';
934 if (!paperheight.empty())
935 os << "\\paperheight "
936 << VSpace(paperheight).asLyXCommand() << '\n';
937 if (!leftmargin.empty())
938 os << "\\leftmargin "
939 << VSpace(leftmargin).asLyXCommand() << '\n';
940 if (!topmargin.empty())
942 << VSpace(topmargin).asLyXCommand() << '\n';
943 if (!rightmargin.empty())
944 os << "\\rightmargin "
945 << VSpace(rightmargin).asLyXCommand() << '\n';
946 if (!bottommargin.empty())
947 os << "\\bottommargin "
948 << VSpace(bottommargin).asLyXCommand() << '\n';
949 if (!headheight.empty())
950 os << "\\headheight "
951 << VSpace(headheight).asLyXCommand() << '\n';
952 if (!headsep.empty())
954 << VSpace(headsep).asLyXCommand() << '\n';
955 if (!footskip.empty())
957 << VSpace(footskip).asLyXCommand() << '\n';
958 if (!columnsep.empty())
960 << VSpace(columnsep).asLyXCommand() << '\n';
961 os << "\\secnumdepth " << secnumdepth
962 << "\n\\tocdepth " << tocdepth
963 << "\n\\paragraph_separation "
964 << string_paragraph_separation[paragraph_separation];
965 if (!paragraph_separation)
966 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
968 os << "\n\\defskip " << getDefSkip().asLyXCommand();
969 os << "\n\\quotes_language "
970 << string_quotes_language[quotes_language]
971 << "\n\\papercolumns " << columns
972 << "\n\\papersides " << sides
973 << "\n\\paperpagestyle " << pagestyle << '\n';
974 if (!listings_params.empty())
975 os << "\\listings_params \"" <<
976 InsetListingsParams(listings_params).encodedString() << "\"\n";
977 for (int i = 0; i < 4; ++i) {
978 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
979 if (user_defined_bullet(i).getFont() != -1) {
980 os << "\\bullet " << i << " "
981 << user_defined_bullet(i).getFont() << " "
982 << user_defined_bullet(i).getCharacter() << " "
983 << user_defined_bullet(i).getSize() << "\n";
987 os << "\\bulletLaTeX " << i << " \""
988 << lyx::to_ascii(user_defined_bullet(i).getText())
994 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n"
995 << "\\output_changes " << convert<string>(outputChanges) << "\n"
996 << "\\html_math_output " << html_math_output << "\n"
997 << "\\html_be_strict " << convert<string>(html_be_strict) << "\n";
999 os << pimpl_->authorlist;
1003 void BufferParams::validate(LaTeXFeatures & features) const
1005 features.require(documentClass().requires());
1007 if (outputChanges) {
1008 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1009 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1010 LaTeXFeatures::isAvailable("xcolor");
1012 switch (features.runparams().flavor) {
1013 case OutputParams::LATEX:
1015 features.require("ct-dvipost");
1016 features.require("dvipost");
1017 } else if (xcolorulem) {
1018 features.require("ct-xcolor-ulem");
1019 features.require("ulem");
1020 features.require("xcolor");
1022 features.require("ct-none");
1025 case OutputParams::PDFLATEX:
1026 case OutputParams::XETEX:
1028 features.require("ct-xcolor-ulem");
1029 features.require("ulem");
1030 features.require("xcolor");
1031 // improves color handling in PDF output
1032 features.require("pdfcolmk");
1034 features.require("ct-none");
1042 // Floats with 'Here definitely' as default setting.
1043 if (float_placement.find('H') != string::npos)
1044 features.require("float");
1046 // AMS Style is at document level
1047 if (use_amsmath == package_on
1048 || documentClass().provides("amsmath"))
1049 features.require("amsmath");
1050 if (use_esint == package_on)
1051 features.require("esint");
1052 if (use_mhchem == package_on)
1053 features.require("mhchem");
1055 // Document-level line spacing
1056 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1057 features.require("setspace");
1059 // the bullet shapes are buffer level not paragraph level
1060 // so they are tested here
1061 for (int i = 0; i < 4; ++i) {
1062 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1064 int const font = user_defined_bullet(i).getFont();
1066 int const c = user_defined_bullet(i).getCharacter();
1072 features.require("latexsym");
1074 } else if (font == 1) {
1075 features.require("amssymb");
1076 } else if (font >= 2 && font <= 5) {
1077 features.require("pifont");
1081 if (pdfoptions().use_hyperref) {
1082 features.require("hyperref");
1083 // due to interferences with babel and hyperref, the color package has to
1084 // be loaded after hyperref when hyperref is used with the colorlinks
1085 // option, see http://www.lyx.org/trac/ticket/5291
1086 if (pdfoptions().colorlinks)
1087 features.require("color");
1091 features.require("xetex");
1093 if (language->lang() == "vietnamese")
1094 features.require("vietnamese");
1095 else if (language->lang() == "japanese")
1096 features.require("japanese");
1100 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1101 TexRow & texrow, FileName const & filepath) const
1103 os << "\\documentclass";
1105 DocumentClass const & tclass = documentClass();
1107 ostringstream clsoptions; // the document class options.
1109 if (tokenPos(tclass.opt_fontsize(),
1110 '|', fontsize) >= 0) {
1111 // only write if existing in list (and not default)
1112 clsoptions << fontsize << "pt,";
1115 // custom, A3, B3 and B4 paper sizes need geometry
1116 bool nonstandard_papersize = papersize == PAPER_B3
1117 || papersize == PAPER_B4
1118 || papersize == PAPER_A3
1119 || papersize == PAPER_CUSTOM;
1121 if (!use_geometry) {
1122 switch (papersize) {
1124 clsoptions << "a4paper,";
1126 case PAPER_USLETTER:
1127 clsoptions << "letterpaper,";
1130 clsoptions << "a5paper,";
1133 clsoptions << "b5paper,";
1135 case PAPER_USEXECUTIVE:
1136 clsoptions << "executivepaper,";
1139 clsoptions << "legalpaper,";
1151 if (sides != tclass.sides()) {
1154 clsoptions << "oneside,";
1157 clsoptions << "twoside,";
1163 if (columns != tclass.columns()) {
1165 clsoptions << "twocolumn,";
1167 clsoptions << "onecolumn,";
1171 && orientation == ORIENTATION_LANDSCAPE)
1172 clsoptions << "landscape,";
1174 // language should be a parameter to \documentclass
1175 if (language->babel() == "hebrew"
1176 && default_language->babel() != "hebrew")
1177 // This seems necessary
1178 features.useLanguage(default_language);
1180 ostringstream language_options;
1181 bool const use_babel = features.useBabel();
1183 language_options << features.getLanguages();
1184 if (!language->babel().empty()) {
1185 if (!language_options.str().empty())
1186 language_options << ',';
1187 language_options << language->babel();
1189 // if Vietnamese is used, babel must directly be loaded
1190 // with language options, not in the class options, see
1191 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1192 size_t viet = language_options.str().find("vietnam");
1193 // viet = string::npos when not found
1194 // the same is for all other languages that are not directly supported by
1195 // babel, but where LaTeX-packages add babel support.
1196 // this is currently the case for Latvian, Lithuanian, and Mongolian
1197 size_t latvian = language_options.str().find("latvian");
1198 size_t lithu = language_options.str().find("lithuanian");
1199 size_t mongo = language_options.str().find("mongolian");
1200 // if Japanese is used, babel must directly be loaded
1201 // with language options, not in the class options, see
1202 // http://www.lyx.org/trac/ticket/4597#c4
1203 size_t japan = language_options.str().find("japanese");
1204 if (lyxrc.language_global_options && !language_options.str().empty()
1205 && viet == string::npos && japan == string::npos
1206 && latvian == string::npos && lithu == string::npos
1207 && mongo == string::npos)
1208 clsoptions << language_options.str() << ',';
1211 // the predefined options from the layout
1212 if (use_default_options && !tclass.options().empty())
1213 clsoptions << tclass.options() << ',';
1215 // the user-defined options
1216 if (!options.empty()) {
1217 clsoptions << options << ',';
1220 string strOptions(clsoptions.str());
1221 if (!strOptions.empty()) {
1222 strOptions = rtrim(strOptions, ",");
1224 os << '[' << from_utf8(strOptions) << ']';
1227 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1229 // end of \documentclass defs
1232 os << "\\usepackage{fontspec}\n";
1236 // font selection must be done before loading fontenc.sty
1237 string const fonts =
1238 loadFonts(fontsRoman, fontsSans,
1239 fontsTypewriter, fontsSC, fontsOSF,
1240 fontsSansScale, fontsTypewriterScale, useXetex);
1241 if (!fonts.empty()) {
1242 os << from_ascii(fonts);
1245 if (fontsDefaultFamily != "default")
1246 os << "\\renewcommand{\\familydefault}{\\"
1247 << from_ascii(fontsDefaultFamily) << "}\n";
1249 // set font encoding
1250 // for arabic_arabi and farsi we also need to load the LAE and
1252 // XeTeX works without fontenc
1253 if (font_encoding() != "default" && language->lang() != "japanese"
1255 if (language->lang() == "arabic_arabi"
1256 || language->lang() == "farsi") {
1257 os << "\\usepackage[" << from_ascii(font_encoding())
1258 << ",LFE,LAE]{fontenc}\n";
1261 os << "\\usepackage[" << from_ascii(font_encoding())
1267 // handle inputenc etc.
1268 writeEncodingPreamble(os, features, texrow);
1271 if (!features.runparams().includeall && !includedChildren_.empty()) {
1272 os << "\\includeonly{";
1273 list<string>::const_iterator it = includedChildren_.begin();
1275 for (; it != includedChildren_.end() ; ++it) {
1276 string incfile = *it;
1277 FileName inc = makeAbsPath(incfile, filepath.absFilename());
1278 string mangled = DocFileName(changeExtension(inc.absFilename(), ".tex")).
1280 if (!features.runparams().nice)
1282 // \includeonly doesn't want an extension
1283 incfile = changeExtension(incfile, string());
1284 incfile = support::latex_path(incfile);
1285 if (!incfile.empty()) {
1288 os << from_utf8(incfile);
1295 if (!listings_params.empty() || features.isRequired("listings")) {
1296 os << "\\usepackage{listings}\n";
1299 if (!listings_params.empty()) {
1301 // do not test validity because listings_params is
1302 // supposed to be valid
1304 InsetListingsParams(listings_params).separatedParams(true);
1305 // we can't support all packages, but we should load the color package
1306 if (par.find("\\color", 0) != string::npos)
1307 features.require("color");
1308 os << from_utf8(par);
1309 // count the number of newlines
1310 for (size_t i = 0; i < par.size(); ++i)
1316 if (!tclass.provides("geometry")
1317 && (use_geometry || nonstandard_papersize)) {
1318 odocstringstream ods;
1319 if (!getGraphicsDriver("geometry").empty())
1320 ods << getGraphicsDriver("geometry");
1321 if (orientation == ORIENTATION_LANDSCAPE)
1322 ods << ",landscape";
1323 switch (papersize) {
1325 if (!paperwidth.empty())
1326 ods << ",paperwidth="
1327 << from_ascii(paperwidth);
1328 if (!paperheight.empty())
1329 ods << ",paperheight="
1330 << from_ascii(paperheight);
1332 case PAPER_USLETTER:
1333 ods << ",letterpaper";
1336 ods << ",legalpaper";
1338 case PAPER_USEXECUTIVE:
1339 ods << ",executivepaper";
1360 // default papersize ie PAPER_DEFAULT
1361 switch (lyxrc.default_papersize) {
1362 case PAPER_DEFAULT: // keep compiler happy
1363 case PAPER_USLETTER:
1364 ods << ",letterpaper";
1367 ods << ",legalpaper";
1369 case PAPER_USEXECUTIVE:
1370 ods << ",executivepaper";
1390 docstring const g_options = trim(ods.str(), ",");
1391 os << "\\usepackage";
1392 if (!g_options.empty())
1393 os << '[' << g_options << ']';
1394 os << "{geometry}\n";
1396 os << "\\geometry{verbose";
1397 if (!topmargin.empty())
1398 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1399 if (!bottommargin.empty())
1400 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1401 if (!leftmargin.empty())
1402 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1403 if (!rightmargin.empty())
1404 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1405 if (!headheight.empty())
1406 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1407 if (!headsep.empty())
1408 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1409 if (!footskip.empty())
1410 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1411 if (!columnsep.empty())
1412 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1415 } else if (orientation == ORIENTATION_LANDSCAPE) {
1416 features.require("papersize");
1419 if (tokenPos(tclass.opt_pagestyle(),
1420 '|', pagestyle) >= 0) {
1421 if (pagestyle == "fancy") {
1422 os << "\\usepackage{fancyhdr}\n";
1425 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1429 // only output when the background color is not white
1430 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1431 // only require color here, the background color will be defined
1432 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1434 features.require("color");
1435 features.require("pagecolor");
1438 // Only if class has a ToC hierarchy
1439 if (tclass.hasTocLevels()) {
1440 if (secnumdepth != tclass.secnumdepth()) {
1441 os << "\\setcounter{secnumdepth}{"
1446 if (tocdepth != tclass.tocdepth()) {
1447 os << "\\setcounter{tocdepth}{"
1454 if (paragraph_separation) {
1455 // when skip separation
1456 switch (getDefSkip().kind()) {
1457 case VSpace::SMALLSKIP:
1458 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1460 case VSpace::MEDSKIP:
1461 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1463 case VSpace::BIGSKIP:
1464 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1466 case VSpace::LENGTH:
1467 os << "\\setlength{\\parskip}{"
1468 << from_utf8(getDefSkip().length().asLatexString())
1471 default: // should never happen // Then delete it.
1472 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1476 os << "\\setlength{\\parindent}{0pt}\n";
1479 // when separation by indentation
1480 // only output something when a width is given
1481 if (getIndentation().asLyXCommand() != "default") {
1482 os << "\\setlength{\\parindent}{"
1483 << from_utf8(getIndentation().asLatexCommand())
1489 // Now insert the LyX specific LaTeX commands...
1490 docstring lyxpreamble;
1492 // due to interferences with babel and hyperref, the color package has to
1493 // be loaded (when it is not already loaded) before babel when hyperref
1494 // is used with the colorlinks option, see
1495 // http://www.lyx.org/trac/ticket/5291
1496 // we decided therefore to load color always before babel, see
1497 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1498 lyxpreamble += from_ascii(features.getColorOptions());
1500 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1502 && (features.isRequired("jurabib")
1503 || features.isRequired("hyperref")
1504 || features.isRequired("vietnamese")
1505 || features.isRequired("japanese") ) ) {
1507 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1508 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1511 // The optional packages;
1512 lyxpreamble += from_ascii(features.getPackages());
1514 // Additional Indices
1515 if (features.isRequired("splitidx")) {
1516 IndicesList::const_iterator iit = indiceslist().begin();
1517 IndicesList::const_iterator iend = indiceslist().end();
1518 for (; iit != iend; ++iit) {
1519 lyxpreamble += "\\newindex[";
1520 lyxpreamble += iit->index();
1521 lyxpreamble += "]{";
1522 lyxpreamble += iit->shortcut();
1523 lyxpreamble += "}\n";
1528 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1531 // * Hyperref manual: "Make sure it comes last of your loaded
1532 // packages, to give it a fighting chance of not being over-written,
1533 // since its job is to redefine many LaTeX commands."
1534 // * Email from Heiko Oberdiek: "It is usually better to load babel
1535 // before hyperref. Then hyperref has a chance to detect babel.
1536 // * Has to be loaded before the "LyX specific LaTeX commands" to
1537 // avoid errors with algorithm floats.
1538 // use hyperref explicitly if it is required
1539 if (features.isRequired("hyperref")) {
1540 // pass what we have to stream here, since we need
1541 // to access the stream itself in PDFOptions.
1545 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1547 OutputParams tmp_params = features.runparams();
1548 lines += pdfoptions().writeLaTeX(tmp_params, os,
1549 documentClass().provides("hyperref"));
1550 texrow.newlines(lines);
1551 // set back for the rest
1552 lyxpreamble.clear();
1555 // Will be surrounded by \makeatletter and \makeatother when not empty
1556 docstring atlyxpreamble;
1558 // Some macros LyX will need
1559 docstring tmppreamble(features.getMacros());
1561 if (!tmppreamble.empty())
1562 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1563 "LyX specific LaTeX commands.\n"
1564 + tmppreamble + '\n';
1566 // the text class specific preamble
1567 tmppreamble = features.getTClassPreamble();
1568 if (!tmppreamble.empty())
1569 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1570 "Textclass specific LaTeX commands.\n"
1571 + tmppreamble + '\n';
1573 // suppress date if selected
1574 // use \@ifundefined because we cannot be sure that every document class
1575 // has a \date command
1577 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1579 /* the user-defined preamble */
1580 if (!containsOnly(preamble, " \n\t"))
1582 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1583 "User specified LaTeX commands.\n"
1584 + from_utf8(preamble) + '\n';
1586 // subfig loads internally the LaTeX package "caption". As
1587 // caption is a very popular package, users will load it in
1588 // the preamble. Therefore we must load subfig behind the
1589 // user-defined preamble and check if the caption package was
1590 // loaded or not. For the case that caption is loaded before
1591 // subfig, there is the subfig option "caption=false". This
1592 // option also works when a koma-script class is used and
1593 // koma's own caption commands are used instead of caption. We
1594 // use \PassOptionsToPackage here because the user could have
1595 // already loaded subfig in the preamble.
1596 if (features.isRequired("subfig")) {
1597 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1598 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1599 "\\usepackage{subfig}\n";
1602 // Itemize bullet settings need to be last in case the user
1603 // defines their own bullets that use a package included
1604 // in the user-defined preamble -- ARRae
1605 // Actually it has to be done much later than that
1606 // since some packages like frenchb make modifications
1607 // at \begin{document} time -- JMarc
1608 docstring bullets_def;
1609 for (int i = 0; i < 4; ++i) {
1610 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1611 if (bullets_def.empty())
1612 bullets_def += "\\AtBeginDocument{\n";
1613 bullets_def += " \\def\\labelitemi";
1615 // `i' is one less than the item to modify
1622 bullets_def += "ii";
1628 bullets_def += '{' +
1629 user_defined_bullet(i).getText()
1634 if (!bullets_def.empty())
1635 atlyxpreamble += bullets_def + "}\n\n";
1637 if (!atlyxpreamble.empty())
1638 lyxpreamble += "\n\\makeatletter\n"
1639 + atlyxpreamble + "\\makeatother\n\n";
1641 // We try to load babel late, in case it interferes with other packages.
1642 // Jurabib and Hyperref have to be called after babel, though.
1643 if (use_babel && !features.isRequired("jurabib")
1644 && !features.isRequired("hyperref")
1645 && !features.isRequired("vietnamese")
1646 && !features.isRequired("japanese")) {
1648 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1649 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1652 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1653 if (!i18npreamble.empty())
1654 lyxpreamble += i18npreamble + '\n';
1657 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1658 texrow.newlines(nlines);
1662 // these packages (xunicode, for that matter) need to be loaded at least
1663 // after amsmath, amssymb, esint and the other packages that provide
1666 os << "\\usepackage{xunicode}\n";
1668 os << "\\usepackage{xltxtra}\n";
1675 void BufferParams::useClassDefaults()
1677 DocumentClass const & tclass = documentClass();
1679 sides = tclass.sides();
1680 columns = tclass.columns();
1681 pagestyle = tclass.pagestyle();
1682 use_default_options = true;
1683 // Only if class has a ToC hierarchy
1684 if (tclass.hasTocLevels()) {
1685 secnumdepth = tclass.secnumdepth();
1686 tocdepth = tclass.tocdepth();
1691 bool BufferParams::hasClassDefaults() const
1693 DocumentClass const & tclass = documentClass();
1695 return sides == tclass.sides()
1696 && columns == tclass.columns()
1697 && pagestyle == tclass.pagestyle()
1698 && use_default_options
1699 && secnumdepth == tclass.secnumdepth()
1700 && tocdepth == tclass.tocdepth();
1704 DocumentClass const & BufferParams::documentClass() const
1710 DocumentClass const * BufferParams::documentClassPtr() const {
1715 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1716 // evil, but this function is evil
1717 doc_class_ = const_cast<DocumentClass *>(tc);
1721 bool BufferParams::setBaseClass(string const & classname)
1723 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1724 LayoutFileList & bcl = LayoutFileList::get();
1725 if (!bcl.haveClass(classname)) {
1727 bformat(_("The document class %1$s could not be found. "
1728 "A default textclass with default layouts will be used. "
1729 "LyX might not be able to produce output unless a correct "
1730 "textclass is selected from the document settings dialog."),
1731 from_utf8(classname));
1732 frontend::Alert::error(_("Document class not found"), s);
1733 bcl.addEmptyClass(classname);
1736 bool const success = bcl[classname].load();
1739 bformat(_("The document class %1$s could not be loaded."),
1740 from_utf8(classname));
1741 frontend::Alert::error(_("Could not load class"), s);
1745 pimpl_->baseClass_ = classname;
1746 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1751 LayoutFile const * BufferParams::baseClass() const
1753 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1754 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1760 LayoutFileIndex const & BufferParams::baseClassID() const
1762 return pimpl_->baseClass_;
1766 void BufferParams::makeDocumentClass()
1771 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1773 if (!local_layout.empty()) {
1774 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1775 docstring const msg = _("Error reading internal layout information");
1776 frontend::Alert::warning(_("Read Error"), msg);
1781 bool BufferParams::moduleCanBeAdded(string const & modName) const
1783 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1787 bool BufferParams::addLayoutModule(string const & modName)
1789 LayoutModuleList::const_iterator it = layoutModules_.begin();
1790 LayoutModuleList::const_iterator end = layoutModules_.end();
1791 for (; it != end; it++)
1794 layoutModules_.push_back(modName);
1799 Font const BufferParams::getFont() const
1801 FontInfo f = documentClass().defaultfont();
1802 if (fontsDefaultFamily == "rmdefault")
1803 f.setFamily(ROMAN_FAMILY);
1804 else if (fontsDefaultFamily == "sfdefault")
1805 f.setFamily(SANS_FAMILY);
1806 else if (fontsDefaultFamily == "ttdefault")
1807 f.setFamily(TYPEWRITER_FAMILY);
1808 return Font(f, language);
1812 void BufferParams::readPreamble(Lexer & lex)
1814 if (lex.getString() != "\\begin_preamble")
1815 lyxerr << "Error (BufferParams::readPreamble):"
1816 "consistency check failed." << endl;
1818 preamble = lex.getLongString("\\end_preamble");
1822 void BufferParams::readLocalLayout(Lexer & lex)
1824 if (lex.getString() != "\\begin_local_layout")
1825 lyxerr << "Error (BufferParams::readLocalLayout):"
1826 "consistency check failed." << endl;
1828 local_layout = lex.getLongString("\\end_local_layout");
1832 void BufferParams::readLanguage(Lexer & lex)
1834 if (!lex.next()) return;
1836 string const tmptok = lex.getString();
1838 // check if tmptok is part of tex_babel in tex-defs.h
1839 language = languages.getLanguage(tmptok);
1841 // Language tmptok was not found
1842 language = default_language;
1843 lyxerr << "Warning: Setting language `"
1844 << tmptok << "' to `" << language->lang()
1850 void BufferParams::readGraphicsDriver(Lexer & lex)
1855 string const tmptok = lex.getString();
1856 // check if tmptok is part of tex_graphics in tex_defs.h
1859 string const test = tex_graphics[n++];
1861 if (test == tmptok) {
1862 graphicsDriver = tmptok;
1867 "Warning: graphics driver `$$Token' not recognized!\n"
1868 " Setting graphics driver to `default'.\n");
1869 graphicsDriver = "default";
1876 void BufferParams::readBullets(Lexer & lex)
1881 int const index = lex.getInteger();
1883 int temp_int = lex.getInteger();
1884 user_defined_bullet(index).setFont(temp_int);
1885 temp_bullet(index).setFont(temp_int);
1887 user_defined_bullet(index).setCharacter(temp_int);
1888 temp_bullet(index).setCharacter(temp_int);
1890 user_defined_bullet(index).setSize(temp_int);
1891 temp_bullet(index).setSize(temp_int);
1895 void BufferParams::readBulletsLaTeX(Lexer & lex)
1897 // The bullet class should be able to read this.
1900 int const index = lex.getInteger();
1902 docstring const temp_str = lex.getDocString();
1904 user_defined_bullet(index).setText(temp_str);
1905 temp_bullet(index).setText(temp_str);
1909 void BufferParams::readModules(Lexer & lex)
1911 if (!lex.eatLine()) {
1912 lyxerr << "Error (BufferParams::readModules):"
1913 "Unexpected end of input." << endl;
1917 string mod = lex.getString();
1918 if (mod == "\\end_modules")
1920 addLayoutModule(mod);
1926 void BufferParams::readRemovedModules(Lexer & lex)
1928 if (!lex.eatLine()) {
1929 lyxerr << "Error (BufferParams::readRemovedModules):"
1930 "Unexpected end of input." << endl;
1934 string mod = lex.getString();
1935 if (mod == "\\end_removed_modules")
1937 removedModules_.push_back(mod);
1940 // now we want to remove any removed modules that were previously
1941 // added. normally, that will be because default modules were added in
1942 // setBaseClass(), which gets called when \textclass is read at the
1943 // start of the read.
1944 list<string>::const_iterator rit = removedModules_.begin();
1945 list<string>::const_iterator const ren = removedModules_.end();
1946 for (; rit != ren; rit++) {
1947 LayoutModuleList::iterator const mit = layoutModules_.begin();
1948 LayoutModuleList::iterator const men = layoutModules_.end();
1949 LayoutModuleList::iterator found = find(mit, men, *rit);
1952 layoutModules_.erase(found);
1957 void BufferParams::readIncludeonly(Lexer & lex)
1959 if (!lex.eatLine()) {
1960 lyxerr << "Error (BufferParams::readIncludeonly):"
1961 "Unexpected end of input." << endl;
1965 string child = lex.getString();
1966 if (child == "\\end_includeonly")
1968 includedChildren_.push_back(child);
1974 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1976 char real_papersize = papersize;
1977 if (real_papersize == PAPER_DEFAULT)
1978 real_papersize = lyxrc.default_papersize;
1980 switch (real_papersize) {
1982 // could be anything, so don't guess
1984 case PAPER_CUSTOM: {
1985 if (purpose == XDVI && !paperwidth.empty() &&
1986 !paperheight.empty()) {
1987 // heightxwidth<unit>
1988 string first = paperwidth;
1989 string second = paperheight;
1990 if (orientation == ORIENTATION_LANDSCAPE)
1993 return first.erase(first.length() - 2)
2005 // dvips and dvipdfm do not know this
2006 if (purpose == DVIPS || purpose == DVIPDFM)
2010 // dvipdfm does not know this
2011 if (purpose == DVIPDFM)
2015 // dvipdfm does not know this
2016 if (purpose == DVIPDFM)
2019 case PAPER_USEXECUTIVE:
2020 // dvipdfm does not know this
2021 if (purpose == DVIPDFM)
2026 case PAPER_USLETTER:
2028 if (purpose == XDVI)
2035 string const BufferParams::dvips_options() const
2040 && papersize == PAPER_CUSTOM
2041 && !lyxrc.print_paper_dimension_flag.empty()
2042 && !paperwidth.empty()
2043 && !paperheight.empty()) {
2044 // using a custom papersize
2045 result = lyxrc.print_paper_dimension_flag;
2046 result += ' ' + paperwidth;
2047 result += ',' + paperheight;
2049 string const paper_option = paperSizeName(DVIPS);
2050 if (!paper_option.empty() && (paper_option != "letter" ||
2051 orientation != ORIENTATION_LANDSCAPE)) {
2052 // dvips won't accept -t letter -t landscape.
2053 // In all other cases, include the paper size
2055 result = lyxrc.print_paper_flag;
2056 result += ' ' + paper_option;
2059 if (orientation == ORIENTATION_LANDSCAPE &&
2060 papersize != PAPER_CUSTOM)
2061 result += ' ' + lyxrc.print_landscape_flag;
2066 string const BufferParams::font_encoding() const
2068 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2072 string BufferParams::babelCall(string const & lang_opts) const
2074 string lang_pack = lyxrc.language_package;
2075 if (lang_pack != "\\usepackage{babel}")
2077 // suppress the babel call when there is no babel language defined
2078 // for the document language in the lib/languages file and if no
2079 // other languages are used (lang_opts is then empty)
2080 if (lang_opts.empty())
2082 // If Vietnamese is used, babel must directly be loaded with the
2083 // language options, see
2084 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2085 size_t viet = lang_opts.find("vietnam");
2086 // viet = string::npos when not found
2087 // the same is for all other languages that are not directly supported by
2088 // babel, but where LaTeX-packages add babel support.
2089 // this is currently the case for Latvian, Lithuanian, and Mongolian
2090 size_t latvian = lang_opts.find("latvian");
2091 size_t lithu = lang_opts.find("lithuanian");
2092 size_t mongo = lang_opts.find("mongolian");
2093 // If Japanese is used, babel must directly be loaded with the
2094 // language options, see
2095 // http://www.lyx.org/trac/ticket/4597#c4
2096 size_t japan = lang_opts.find("japanese");
2097 if (!lyxrc.language_global_options || viet != string::npos
2098 || japan != string::npos || latvian != string::npos
2099 || lithu != string::npos || mongo != string::npos)
2100 return "\\usepackage[" + lang_opts + "]{babel}";
2105 docstring BufferParams::getGraphicsDriver(string const & package) const
2109 if (package == "geometry") {
2110 if (graphicsDriver == "dvips"
2111 || graphicsDriver == "dvipdfm"
2112 || graphicsDriver == "pdftex"
2113 || graphicsDriver == "vtex")
2114 result = from_ascii(graphicsDriver);
2115 else if (graphicsDriver == "dvipdfmx")
2116 result = from_ascii("dvipdfm");
2123 void BufferParams::writeEncodingPreamble(odocstream & os,
2124 LaTeXFeatures & features, TexRow & texrow) const
2128 if (inputenc == "auto") {
2129 string const doc_encoding =
2130 language->encoding()->latexName();
2131 Encoding::Package const package =
2132 language->encoding()->package();
2134 // Create a list with all the input encodings used
2136 set<string> encodings =
2137 features.getEncodingSet(doc_encoding);
2139 // If the "japanese" package (i.e. pLaTeX) is used,
2140 // inputenc must be omitted.
2141 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2142 if (package == Encoding::japanese)
2143 features.require("japanese");
2145 if ((!encodings.empty() || package == Encoding::inputenc)
2146 && !features.isRequired("japanese")) {
2147 os << "\\usepackage[";
2148 set<string>::const_iterator it = encodings.begin();
2149 set<string>::const_iterator const end = encodings.end();
2151 os << from_ascii(*it);
2154 for (; it != end; ++it)
2155 os << ',' << from_ascii(*it);
2156 if (package == Encoding::inputenc) {
2157 if (!encodings.empty())
2159 os << from_ascii(doc_encoding);
2161 os << "]{inputenc}\n";
2164 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2165 if (language->encoding()->name() == "utf8-cjk"
2166 && LaTeXFeatures::isAvailable("CJKutf8"))
2167 os << "\\usepackage{CJKutf8}\n";
2169 os << "\\usepackage{CJK}\n";
2172 } else if (inputenc != "default") {
2173 switch (encoding().package()) {
2174 case Encoding::none:
2175 case Encoding::japanese:
2177 case Encoding::inputenc:
2178 // do not load inputenc if japanese is used
2179 if (features.isRequired("japanese"))
2181 os << "\\usepackage[" << from_ascii(inputenc)
2186 if (encoding().name() == "utf8-cjk"
2187 && LaTeXFeatures::isAvailable("CJKutf8"))
2188 os << "\\usepackage{CJKutf8}\n";
2190 os << "\\usepackage{CJK}\n";
2196 // The encoding "armscii8" (for Armenian) is only available when
2197 // the package "armtex" is loaded.
2198 if (language->encoding()->latexName() == "armscii8"
2199 || inputenc == "armscii8") {
2200 os << "\\usepackage{armtex}\n";
2206 string const BufferParams::parseFontName(string const & name) const
2208 string mangled = name;
2209 size_t const idx = mangled.find('[');
2210 if (idx == string::npos || idx == 0)
2213 return mangled.substr(0, idx - 1);
2217 string const BufferParams::loadFonts(string const & rm,
2218 string const & sf, string const & tt,
2219 bool const & sc, bool const & osf,
2220 int const & sfscale, int const & ttscale,
2221 bool const & xetex) const
2223 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2224 several packages have been replaced by others, that might not
2225 be installed on every system. We have to take care for that
2226 (see psnfss.pdf). We try to support all psnfss fonts as well
2227 as the fonts that have become de facto standard in the LaTeX
2228 world (e.g. Latin Modern). We do not support obsolete fonts
2229 (like PSLatex). In general, it should be possible to mix any
2230 rm font with any sf or tt font, respectively. (JSpitzm)
2232 -- separate math fonts.
2235 if (rm == "default" && sf == "default" && tt == "default")
2242 if (rm != "default")
2243 os << "\\setmainfont[Mapping=tex-text]{"
2244 << parseFontName(rm) << "}\n";
2245 if (sf != "default") {
2246 string const sans = parseFontName(sf);
2248 os << "\\setsansfont[Scale="
2249 << float(sfscale) / 100
2250 << ",Mapping=tex-text]{"
2253 os << "\\setsansfont[Mapping=tex-text]{"
2256 if (tt != "default") {
2257 string const mono = parseFontName(tt);
2259 os << "\\setmonofont[Scale="
2260 << float(sfscale) / 100
2264 os << "\\setmonofont[Mapping=tex-text]{"
2268 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2273 // Computer Modern (must be explicitly selectable -- there might be classes
2274 // that define a different default font!
2276 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2277 // osf for Computer Modern needs eco.sty
2279 os << "\\usepackage{eco}\n";
2281 // Latin Modern Roman
2282 else if (rm == "lmodern")
2283 os << "\\usepackage{lmodern}\n";
2285 else if (rm == "ae") {
2286 // not needed when using OT1 font encoding.
2287 if (font_encoding() != "default")
2288 os << "\\usepackage{ae,aecompl}\n";
2291 else if (rm == "times") {
2292 // try to load the best available package
2293 if (LaTeXFeatures::isAvailable("mathptmx"))
2294 os << "\\usepackage{mathptmx}\n";
2295 else if (LaTeXFeatures::isAvailable("mathptm"))
2296 os << "\\usepackage{mathptm}\n";
2298 os << "\\usepackage{times}\n";
2301 else if (rm == "palatino") {
2302 // try to load the best available package
2303 if (LaTeXFeatures::isAvailable("mathpazo")) {
2304 os << "\\usepackage";
2310 // "osf" includes "sc"!
2314 os << "{mathpazo}\n";
2316 else if (LaTeXFeatures::isAvailable("mathpple"))
2317 os << "\\usepackage{mathpple}\n";
2319 os << "\\usepackage{palatino}\n";
2322 else if (rm == "utopia") {
2323 // fourier supersedes utopia.sty, but does
2324 // not work with OT1 encoding.
2325 if (LaTeXFeatures::isAvailable("fourier")
2326 && font_encoding() != "default") {
2327 os << "\\usepackage";
2338 os << "{fourier}\n";
2341 os << "\\usepackage{utopia}\n";
2343 // Bera (complete fontset)
2344 else if (rm == "bera" && sf == "default" && tt == "default")
2345 os << "\\usepackage{bera}\n";
2347 else if (rm != "default")
2348 os << "\\usepackage" << "{" << rm << "}\n";
2351 // Helvetica, Bera Sans
2352 if (sf == "helvet" || sf == "berasans") {
2354 os << "\\usepackage[scaled=" << float(sfscale) / 100
2355 << "]{" << sf << "}\n";
2357 os << "\\usepackage{" << sf << "}\n";
2360 else if (sf == "avant")
2361 os << "\\usepackage{" << sf << "}\n";
2362 // Computer Modern, Latin Modern, CM Bright
2363 else if (sf != "default")
2364 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2366 // monospaced/typewriter
2367 // Courier, LuxiMono
2368 if (tt == "luximono" || tt == "beramono") {
2370 os << "\\usepackage[scaled=" << float(ttscale) / 100
2371 << "]{" << tt << "}\n";
2373 os << "\\usepackage{" << tt << "}\n";
2376 else if (tt == "courier" )
2377 os << "\\usepackage{" << tt << "}\n";
2378 // Computer Modern, Latin Modern, CM Bright
2379 else if (tt != "default")
2380 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2386 Encoding const & BufferParams::encoding() const
2389 return *(encodings.fromLaTeXName("utf8-plain"));
2390 if (inputenc == "auto" || inputenc == "default")
2391 return *language->encoding();
2392 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2395 LYXERR0("Unknown inputenc value `" << inputenc
2396 << "'. Using `auto' instead.");
2397 return *language->encoding();
2401 CiteEngine BufferParams::citeEngine() const
2403 // FIXME the class should provide the numerical/
2404 // authoryear choice
2405 if (documentClass().provides("natbib")
2406 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2407 return ENGINE_NATBIB_AUTHORYEAR;
2408 return cite_engine_;
2412 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2414 cite_engine_ = cite_engine;