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");
372 compressed = lyxrc.save_compressed;
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()) {
523 translateIfPossible(from_utf8(baseClass()->description()));
524 docstring const msg =
525 bformat(_("The document class requested\n"
527 "requires external files that are not available.\n"
528 "The document class can still be used, but LyX\n"
529 "will not be able to produce output until the\n"
530 "following prerequisites are installed:\n"
532 "See section 3.1.2.2 of the User's Guide for\n"
533 "more information."),
534 desc, from_utf8(baseClass()->prerequisites()));
535 frontend::Alert::warning(_("Document class not available"),
538 } else if (token == "\\begin_preamble") {
540 } else if (token == "\\begin_local_layout") {
541 readLocalLayout(lex);
542 } else if (token == "\\begin_modules") {
544 } else if (token == "\\begin_removed_modules") {
545 readRemovedModules(lex);
546 } else if (token == "\\begin_includeonly") {
547 readIncludeonly(lex);
548 } else if (token == "\\maintain_unincluded_children") {
549 lex >> maintain_unincluded_children;
550 } else if (token == "\\options") {
552 options = lex.getString();
553 } else if (token == "\\use_default_options") {
554 lex >> use_default_options;
555 } else if (token == "\\master") {
557 master = lex.getString();
558 } else if (token == "\\suppress_date") {
559 lex >> suppress_date;
560 } else if (token == "\\language") {
562 } else if (token == "\\inputencoding") {
564 } else if (token == "\\graphics") {
565 readGraphicsDriver(lex);
566 } else if (token == "\\default_output_format") {
567 lex >> defaultOutputFormat;
568 } else if (token == "\\bibtex_command") {
570 bibtex_command = lex.getString();
571 } else if (token == "\\index_command") {
573 index_command = lex.getString();
574 } else if (token == "\\fontencoding") {
576 fontenc = lex.getString();
577 } else if (token == "\\font_roman") {
579 fontsRoman = lex.getString();
580 } else if (token == "\\font_sans") {
582 fontsSans = lex.getString();
583 } else if (token == "\\font_typewriter") {
585 fontsTypewriter = lex.getString();
586 } else if (token == "\\font_default_family") {
587 lex >> fontsDefaultFamily;
588 } else if (token == "\\use_xetex") {
590 } else if (token == "\\font_sc") {
592 } else if (token == "\\font_osf") {
594 } else if (token == "\\font_sf_scale") {
595 lex >> fontsSansScale;
596 } else if (token == "\\font_tt_scale") {
597 lex >> fontsTypewriterScale;
598 } else if (token == "\\font_cjk") {
600 } else if (token == "\\paragraph_separation") {
603 paragraph_separation = parseptranslator().find(parsep);
604 } else if (token == "\\paragraph_indentation") {
606 string indentation = lex.getString();
607 pimpl_->indentation = HSpace(indentation);
608 } else if (token == "\\defskip") {
610 string defskip = lex.getString();
611 if (defskip == "defskip")
614 pimpl_->defskip = VSpace(defskip);
615 } else if (token == "\\quotes_language") {
618 quotes_language = quoteslangtranslator().find(quotes_lang);
619 } else if (token == "\\papersize") {
622 papersize = papersizetranslator().find(ppsize);
623 } else if (token == "\\use_geometry") {
625 } else if (token == "\\use_amsmath") {
628 use_amsmath = packagetranslator().find(use_ams);
629 } else if (token == "\\use_esint") {
632 use_esint = packagetranslator().find(useesint);
633 } else if (token == "\\use_mhchem") {
636 use_mhchem = packagetranslator().find(usemhchem);
637 } else if (token == "\\cite_engine") {
640 cite_engine_ = citeenginetranslator().find(engine);
641 } else if (token == "\\use_bibtopic") {
643 } else if (token == "\\use_indices") {
645 } else if (token == "\\tracking_changes") {
647 } else if (token == "\\output_changes") {
648 lex >> outputChanges;
649 } else if (token == "\\branch") {
651 docstring branch = lex.getDocString();
652 branchlist().add(branch);
655 string const tok = lex.getString();
656 if (tok == "\\end_branch")
658 Branch * branch_ptr = branchlist().find(branch);
659 if (tok == "\\selected") {
662 branch_ptr->setSelected(lex.getInteger());
664 if (tok == "\\filename_suffix") {
667 branch_ptr->setFilenameSuffix(lex.getInteger());
669 if (tok == "\\color") {
671 string color = lex.getString();
673 branch_ptr->setColor(color);
674 // Update also the Color table:
676 color = lcolor.getX11Name(Color_background);
678 lcolor.setColor(to_utf8(branch), color);
681 } else if (token == "\\index") {
683 docstring index = lex.getDocString();
685 indiceslist().add(index);
688 string const tok = lex.getString();
689 if (tok == "\\end_index")
691 Index * index_ptr = indiceslist().find(index);
692 if (tok == "\\shortcut") {
694 shortcut = lex.getDocString();
696 index_ptr->setShortcut(shortcut);
698 if (tok == "\\color") {
700 string color = lex.getString();
702 index_ptr->setColor(color);
703 // Update also the Color table:
705 color = lcolor.getX11Name(Color_background);
707 if (!shortcut.empty())
708 lcolor.setColor(to_utf8(shortcut), color);
711 } else if (token == "\\author") {
713 istringstream ss(lex.getString());
716 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
717 } else if (token == "\\paperorientation") {
720 orientation = paperorientationtranslator().find(orient);
721 } else if (token == "\\backgroundcolor") {
723 backgroundcolor = lyx::rgbFromHexName(lex.getString());
724 } else if (token == "\\paperwidth") {
726 } else if (token == "\\paperheight") {
728 } else if (token == "\\leftmargin") {
730 } else if (token == "\\topmargin") {
732 } else if (token == "\\rightmargin") {
734 } else if (token == "\\bottommargin") {
736 } else if (token == "\\headheight") {
738 } else if (token == "\\headsep") {
740 } else if (token == "\\footskip") {
742 } else if (token == "\\columnsep") {
744 } else if (token == "\\paperfontsize") {
746 } else if (token == "\\papercolumns") {
748 } else if (token == "\\listings_params") {
751 listings_params = InsetListingsParams(par).params();
752 } else if (token == "\\papersides") {
755 sides = sidestranslator().find(psides);
756 } else if (token == "\\paperpagestyle") {
758 } else if (token == "\\bullet") {
760 } else if (token == "\\bulletLaTeX") {
761 readBulletsLaTeX(lex);
762 } else if (token == "\\secnumdepth") {
764 } else if (token == "\\tocdepth") {
766 } else if (token == "\\spacing") {
770 if (nspacing == "other") {
773 spacing().set(spacetranslator().find(nspacing), tmp_val);
774 } else if (token == "\\float_placement") {
775 lex >> float_placement;
777 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
778 string toktmp = pdfoptions().readToken(lex, token);
779 if (!toktmp.empty()) {
780 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
784 } else if (token == "\\html_math_output") {
787 html_math_output = static_cast<MathOutput>(temp);
788 } else if (token == "\\html_be_strict") {
789 lex >> html_be_strict;
791 lyxerr << "BufferParams::readToken(): Unknown token: " <<
800 void BufferParams::writeFile(ostream & os) const
802 // The top of the file is written by the buffer.
803 // Prints out the buffer info into the .lyx file given by file
806 os << "\\textclass " << baseClass()->name() << '\n';
809 if (!preamble.empty()) {
810 // remove '\n' from the end of preamble
811 string const tmppreamble = rtrim(preamble, "\n");
812 os << "\\begin_preamble\n"
814 << "\n\\end_preamble\n";
818 if (!options.empty()) {
819 os << "\\options " << options << '\n';
822 // use the class options defined in the layout?
823 os << "\\use_default_options "
824 << convert<string>(use_default_options) << "\n";
826 // the master document
827 if (!master.empty()) {
828 os << "\\master " << master << '\n';
832 if (!removedModules_.empty()) {
833 os << "\\begin_removed_modules" << '\n';
834 list<string>::const_iterator it = removedModules_.begin();
835 list<string>::const_iterator en = removedModules_.end();
836 for (; it != en; it++)
838 os << "\\end_removed_modules" << '\n';
842 if (!layoutModules_.empty()) {
843 os << "\\begin_modules" << '\n';
844 LayoutModuleList::const_iterator it = layoutModules_.begin();
845 LayoutModuleList::const_iterator en = layoutModules_.end();
846 for (; it != en; it++)
848 os << "\\end_modules" << '\n';
852 if (!includedChildren_.empty()) {
853 os << "\\begin_includeonly" << '\n';
854 list<string>::const_iterator it = includedChildren_.begin();
855 list<string>::const_iterator en = includedChildren_.end();
856 for (; it != en; it++)
858 os << "\\end_includeonly" << '\n';
860 os << "\\maintain_unincluded_children "
861 << convert<string>(maintain_unincluded_children) << '\n';
863 // local layout information
864 if (!local_layout.empty()) {
865 // remove '\n' from the end
866 string const tmplocal = rtrim(local_layout, "\n");
867 os << "\\begin_local_layout\n"
869 << "\n\\end_local_layout\n";
872 // then the text parameters
873 if (language != ignore_language)
874 os << "\\language " << language->lang() << '\n';
875 os << "\\inputencoding " << inputenc
876 << "\n\\fontencoding " << fontenc
877 << "\n\\font_roman " << fontsRoman
878 << "\n\\font_sans " << fontsSans
879 << "\n\\font_typewriter " << fontsTypewriter
880 << "\n\\font_default_family " << fontsDefaultFamily
881 << "\n\\use_xetex " << convert<string>(useXetex)
882 << "\n\\font_sc " << convert<string>(fontsSC)
883 << "\n\\font_osf " << convert<string>(fontsOSF)
884 << "\n\\font_sf_scale " << fontsSansScale
885 << "\n\\font_tt_scale " << fontsTypewriterScale
887 if (!fontsCJK.empty()) {
888 os << "\\font_cjk " << fontsCJK << '\n';
890 os << "\n\\graphics " << graphicsDriver << '\n';
891 os << "\\default_output_format " << defaultOutputFormat << '\n';
892 os << "\\bibtex_command " << bibtex_command << '\n';
893 os << "\\index_command " << index_command << '\n';
895 if (!float_placement.empty()) {
896 os << "\\float_placement " << float_placement << '\n';
898 os << "\\paperfontsize " << fontsize << '\n';
900 spacing().writeFile(os);
901 pdfoptions().writeFile(os);
903 os << "\\papersize " << string_papersize[papersize]
904 << "\n\\use_geometry " << convert<string>(use_geometry)
905 << "\n\\use_amsmath " << use_amsmath
906 << "\n\\use_esint " << use_esint
907 << "\n\\use_mhchem " << use_mhchem
908 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
909 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
910 << "\n\\use_indices " << convert<string>(use_indices)
911 << "\n\\paperorientation " << string_orientation[orientation]
912 << "\n\\suppress_date " << convert<string>(suppress_date)
914 if (backgroundcolor != lyx::rgbFromHexName("#ffffff"))
915 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
917 BranchList::const_iterator it = branchlist().begin();
918 BranchList::const_iterator end = branchlist().end();
919 for (; it != end; ++it) {
920 os << "\\branch " << to_utf8(it->branch())
921 << "\n\\selected " << it->isSelected()
922 << "\n\\filename_suffix " << it->hasFilenameSuffix()
923 << "\n\\color " << lyx::X11hexname(it->color())
928 IndicesList::const_iterator iit = indiceslist().begin();
929 IndicesList::const_iterator iend = indiceslist().end();
930 for (; iit != iend; ++iit) {
931 os << "\\index " << to_utf8(iit->index())
932 << "\n\\shortcut " << to_utf8(iit->shortcut())
933 << "\n\\color " << lyx::X11hexname(iit->color())
938 if (!paperwidth.empty())
939 os << "\\paperwidth "
940 << VSpace(paperwidth).asLyXCommand() << '\n';
941 if (!paperheight.empty())
942 os << "\\paperheight "
943 << VSpace(paperheight).asLyXCommand() << '\n';
944 if (!leftmargin.empty())
945 os << "\\leftmargin "
946 << VSpace(leftmargin).asLyXCommand() << '\n';
947 if (!topmargin.empty())
949 << VSpace(topmargin).asLyXCommand() << '\n';
950 if (!rightmargin.empty())
951 os << "\\rightmargin "
952 << VSpace(rightmargin).asLyXCommand() << '\n';
953 if (!bottommargin.empty())
954 os << "\\bottommargin "
955 << VSpace(bottommargin).asLyXCommand() << '\n';
956 if (!headheight.empty())
957 os << "\\headheight "
958 << VSpace(headheight).asLyXCommand() << '\n';
959 if (!headsep.empty())
961 << VSpace(headsep).asLyXCommand() << '\n';
962 if (!footskip.empty())
964 << VSpace(footskip).asLyXCommand() << '\n';
965 if (!columnsep.empty())
967 << VSpace(columnsep).asLyXCommand() << '\n';
968 os << "\\secnumdepth " << secnumdepth
969 << "\n\\tocdepth " << tocdepth
970 << "\n\\paragraph_separation "
971 << string_paragraph_separation[paragraph_separation];
972 if (!paragraph_separation)
973 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
975 os << "\n\\defskip " << getDefSkip().asLyXCommand();
976 os << "\n\\quotes_language "
977 << string_quotes_language[quotes_language]
978 << "\n\\papercolumns " << columns
979 << "\n\\papersides " << sides
980 << "\n\\paperpagestyle " << pagestyle << '\n';
981 if (!listings_params.empty())
982 os << "\\listings_params \"" <<
983 InsetListingsParams(listings_params).encodedString() << "\"\n";
984 for (int i = 0; i < 4; ++i) {
985 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
986 if (user_defined_bullet(i).getFont() != -1) {
987 os << "\\bullet " << i << " "
988 << user_defined_bullet(i).getFont() << " "
989 << user_defined_bullet(i).getCharacter() << " "
990 << user_defined_bullet(i).getSize() << "\n";
994 os << "\\bulletLaTeX " << i << " \""
995 << lyx::to_ascii(user_defined_bullet(i).getText())
1001 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n"
1002 << "\\output_changes " << convert<string>(outputChanges) << "\n"
1003 << "\\html_math_output " << html_math_output << "\n"
1004 << "\\html_be_strict " << convert<string>(html_be_strict) << "\n";
1006 os << pimpl_->authorlist;
1010 void BufferParams::validate(LaTeXFeatures & features) const
1012 features.require(documentClass().requires());
1014 if (outputChanges) {
1015 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1016 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1017 LaTeXFeatures::isAvailable("xcolor");
1019 switch (features.runparams().flavor) {
1020 case OutputParams::LATEX:
1022 features.require("ct-dvipost");
1023 features.require("dvipost");
1024 } else if (xcolorulem) {
1025 features.require("ct-xcolor-ulem");
1026 features.require("ulem");
1027 features.require("xcolor");
1029 features.require("ct-none");
1032 case OutputParams::PDFLATEX:
1033 case OutputParams::XETEX:
1035 features.require("ct-xcolor-ulem");
1036 features.require("ulem");
1037 features.require("xcolor");
1038 // improves color handling in PDF output
1039 features.require("pdfcolmk");
1041 features.require("ct-none");
1049 // Floats with 'Here definitely' as default setting.
1050 if (float_placement.find('H') != string::npos)
1051 features.require("float");
1053 // AMS Style is at document level
1054 if (use_amsmath == package_on
1055 || documentClass().provides("amsmath"))
1056 features.require("amsmath");
1057 if (use_esint == package_on)
1058 features.require("esint");
1059 if (use_mhchem == package_on)
1060 features.require("mhchem");
1062 // Document-level line spacing
1063 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1064 features.require("setspace");
1066 // the bullet shapes are buffer level not paragraph level
1067 // so they are tested here
1068 for (int i = 0; i < 4; ++i) {
1069 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1071 int const font = user_defined_bullet(i).getFont();
1073 int const c = user_defined_bullet(i).getCharacter();
1079 features.require("latexsym");
1081 } else if (font == 1) {
1082 features.require("amssymb");
1083 } else if (font >= 2 && font <= 5) {
1084 features.require("pifont");
1088 if (pdfoptions().use_hyperref) {
1089 features.require("hyperref");
1090 // due to interferences with babel and hyperref, the color package has to
1091 // be loaded after hyperref when hyperref is used with the colorlinks
1092 // option, see http://www.lyx.org/trac/ticket/5291
1093 if (pdfoptions().colorlinks)
1094 features.require("color");
1098 features.require("xetex");
1100 if (language->lang() == "vietnamese")
1101 features.require("vietnamese");
1102 else if (language->lang() == "japanese")
1103 features.require("japanese");
1107 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1108 TexRow & texrow, FileName const & filepath) const
1110 os << "\\documentclass";
1112 DocumentClass const & tclass = documentClass();
1114 ostringstream clsoptions; // the document class options.
1116 if (tokenPos(tclass.opt_fontsize(),
1117 '|', fontsize) >= 0) {
1118 // only write if existing in list (and not default)
1119 clsoptions << fontsize << "pt,";
1122 // custom, A3, B3 and B4 paper sizes need geometry
1123 bool nonstandard_papersize = papersize == PAPER_B3
1124 || papersize == PAPER_B4
1125 || papersize == PAPER_A3
1126 || papersize == PAPER_CUSTOM;
1128 if (!use_geometry) {
1129 switch (papersize) {
1131 clsoptions << "a4paper,";
1133 case PAPER_USLETTER:
1134 clsoptions << "letterpaper,";
1137 clsoptions << "a5paper,";
1140 clsoptions << "b5paper,";
1142 case PAPER_USEXECUTIVE:
1143 clsoptions << "executivepaper,";
1146 clsoptions << "legalpaper,";
1158 if (sides != tclass.sides()) {
1161 clsoptions << "oneside,";
1164 clsoptions << "twoside,";
1170 if (columns != tclass.columns()) {
1172 clsoptions << "twocolumn,";
1174 clsoptions << "onecolumn,";
1178 && orientation == ORIENTATION_LANDSCAPE)
1179 clsoptions << "landscape,";
1181 // language should be a parameter to \documentclass
1182 if (language->babel() == "hebrew"
1183 && default_language->babel() != "hebrew")
1184 // This seems necessary
1185 features.useLanguage(default_language);
1187 ostringstream language_options;
1188 bool const use_babel = features.useBabel();
1190 language_options << features.getLanguages();
1191 if (!language->babel().empty()) {
1192 if (!language_options.str().empty())
1193 language_options << ',';
1194 language_options << language->babel();
1196 // if Vietnamese is used, babel must directly be loaded
1197 // with language options, not in the class options, see
1198 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1199 size_t viet = language_options.str().find("vietnam");
1200 // viet = string::npos when not found
1201 // the same is for all other languages that are not directly supported by
1202 // babel, but where LaTeX-packages add babel support.
1203 // this is currently the case for Latvian, Lithuanian, and Mongolian
1204 size_t latvian = language_options.str().find("latvian");
1205 size_t lithu = language_options.str().find("lithuanian");
1206 size_t mongo = language_options.str().find("mongolian");
1207 // if Japanese is used, babel must directly be loaded
1208 // with language options, not in the class options, see
1209 // http://www.lyx.org/trac/ticket/4597#c4
1210 size_t japan = language_options.str().find("japanese");
1211 if (lyxrc.language_global_options && !language_options.str().empty()
1212 && viet == string::npos && japan == string::npos
1213 && latvian == string::npos && lithu == string::npos
1214 && mongo == string::npos)
1215 clsoptions << language_options.str() << ',';
1218 // the predefined options from the layout
1219 if (use_default_options && !tclass.options().empty())
1220 clsoptions << tclass.options() << ',';
1222 // the user-defined options
1223 if (!options.empty()) {
1224 clsoptions << options << ',';
1227 string strOptions(clsoptions.str());
1228 if (!strOptions.empty()) {
1229 strOptions = rtrim(strOptions, ",");
1231 os << '[' << from_utf8(strOptions) << ']';
1234 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1236 // end of \documentclass defs
1239 os << "\\usepackage{fontspec}\n";
1243 // font selection must be done before loading fontenc.sty
1244 string const fonts =
1245 loadFonts(fontsRoman, fontsSans,
1246 fontsTypewriter, fontsSC, fontsOSF,
1247 fontsSansScale, fontsTypewriterScale, useXetex);
1248 if (!fonts.empty()) {
1249 os << from_ascii(fonts);
1252 if (fontsDefaultFamily != "default")
1253 os << "\\renewcommand{\\familydefault}{\\"
1254 << from_ascii(fontsDefaultFamily) << "}\n";
1256 // set font encoding
1257 // for arabic_arabi and farsi we also need to load the LAE and
1259 // XeTeX works without fontenc
1260 if (font_encoding() != "default" && language->lang() != "japanese"
1262 if (language->lang() == "arabic_arabi"
1263 || language->lang() == "farsi") {
1264 os << "\\usepackage[" << from_ascii(font_encoding())
1265 << ",LFE,LAE]{fontenc}\n";
1268 os << "\\usepackage[" << from_ascii(font_encoding())
1274 // handle inputenc etc.
1275 writeEncodingPreamble(os, features, texrow);
1278 if (!features.runparams().includeall && !includedChildren_.empty()) {
1279 os << "\\includeonly{";
1280 list<string>::const_iterator it = includedChildren_.begin();
1282 for (; it != includedChildren_.end() ; ++it) {
1283 string incfile = *it;
1284 FileName inc = makeAbsPath(incfile, filepath.absFilename());
1285 string mangled = DocFileName(changeExtension(inc.absFilename(), ".tex")).
1287 if (!features.runparams().nice)
1289 // \includeonly doesn't want an extension
1290 incfile = changeExtension(incfile, string());
1291 incfile = support::latex_path(incfile);
1292 if (!incfile.empty()) {
1295 os << from_utf8(incfile);
1302 if (!listings_params.empty() || features.isRequired("listings")) {
1303 os << "\\usepackage{listings}\n";
1306 if (!listings_params.empty()) {
1308 // do not test validity because listings_params is
1309 // supposed to be valid
1311 InsetListingsParams(listings_params).separatedParams(true);
1312 // we can't support all packages, but we should load the color package
1313 if (par.find("\\color", 0) != string::npos)
1314 features.require("color");
1315 os << from_utf8(par);
1316 // count the number of newlines
1317 for (size_t i = 0; i < par.size(); ++i)
1323 if (!tclass.provides("geometry")
1324 && (use_geometry || nonstandard_papersize)) {
1325 odocstringstream ods;
1326 if (!getGraphicsDriver("geometry").empty())
1327 ods << getGraphicsDriver("geometry");
1328 if (orientation == ORIENTATION_LANDSCAPE)
1329 ods << ",landscape";
1330 switch (papersize) {
1332 if (!paperwidth.empty())
1333 ods << ",paperwidth="
1334 << from_ascii(paperwidth);
1335 if (!paperheight.empty())
1336 ods << ",paperheight="
1337 << from_ascii(paperheight);
1339 case PAPER_USLETTER:
1340 ods << ",letterpaper";
1343 ods << ",legalpaper";
1345 case PAPER_USEXECUTIVE:
1346 ods << ",executivepaper";
1367 // default papersize ie PAPER_DEFAULT
1368 switch (lyxrc.default_papersize) {
1369 case PAPER_DEFAULT: // keep compiler happy
1370 case PAPER_USLETTER:
1371 ods << ",letterpaper";
1374 ods << ",legalpaper";
1376 case PAPER_USEXECUTIVE:
1377 ods << ",executivepaper";
1397 docstring const g_options = trim(ods.str(), ",");
1398 os << "\\usepackage";
1399 if (!g_options.empty())
1400 os << '[' << g_options << ']';
1401 os << "{geometry}\n";
1403 os << "\\geometry{verbose";
1404 if (!topmargin.empty())
1405 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1406 if (!bottommargin.empty())
1407 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1408 if (!leftmargin.empty())
1409 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1410 if (!rightmargin.empty())
1411 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1412 if (!headheight.empty())
1413 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1414 if (!headsep.empty())
1415 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1416 if (!footskip.empty())
1417 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1418 if (!columnsep.empty())
1419 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1422 } else if (orientation == ORIENTATION_LANDSCAPE) {
1423 features.require("papersize");
1426 if (tokenPos(tclass.opt_pagestyle(),
1427 '|', pagestyle) >= 0) {
1428 if (pagestyle == "fancy") {
1429 os << "\\usepackage{fancyhdr}\n";
1432 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1436 // only output when the background color is not white
1437 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1438 // only require color here, the background color will be defined
1439 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1441 features.require("color");
1442 features.require("pagecolor");
1445 // Only if class has a ToC hierarchy
1446 if (tclass.hasTocLevels()) {
1447 if (secnumdepth != tclass.secnumdepth()) {
1448 os << "\\setcounter{secnumdepth}{"
1453 if (tocdepth != tclass.tocdepth()) {
1454 os << "\\setcounter{tocdepth}{"
1461 if (paragraph_separation) {
1462 // when skip separation
1463 switch (getDefSkip().kind()) {
1464 case VSpace::SMALLSKIP:
1465 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1467 case VSpace::MEDSKIP:
1468 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1470 case VSpace::BIGSKIP:
1471 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1473 case VSpace::LENGTH:
1474 os << "\\setlength{\\parskip}{"
1475 << from_utf8(getDefSkip().length().asLatexString())
1478 default: // should never happen // Then delete it.
1479 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1483 os << "\\setlength{\\parindent}{0pt}\n";
1486 // when separation by indentation
1487 // only output something when a width is given
1488 if (getIndentation().asLyXCommand() != "default") {
1489 os << "\\setlength{\\parindent}{"
1490 << from_utf8(getIndentation().asLatexCommand())
1496 // Now insert the LyX specific LaTeX commands...
1497 docstring lyxpreamble;
1499 // due to interferences with babel and hyperref, the color package has to
1500 // be loaded (when it is not already loaded) before babel when hyperref
1501 // is used with the colorlinks option, see
1502 // http://www.lyx.org/trac/ticket/5291
1503 // we decided therefore to load color always before babel, see
1504 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1505 lyxpreamble += from_ascii(features.getColorOptions());
1507 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1509 && (features.isRequired("jurabib")
1510 || features.isRequired("hyperref")
1511 || features.isRequired("vietnamese")
1512 || features.isRequired("japanese") ) ) {
1514 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1515 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1518 // The optional packages;
1519 lyxpreamble += from_ascii(features.getPackages());
1521 // Additional Indices
1522 if (features.isRequired("splitidx")) {
1523 IndicesList::const_iterator iit = indiceslist().begin();
1524 IndicesList::const_iterator iend = indiceslist().end();
1525 for (; iit != iend; ++iit) {
1526 lyxpreamble += "\\newindex[";
1527 lyxpreamble += iit->index();
1528 lyxpreamble += "]{";
1529 lyxpreamble += iit->shortcut();
1530 lyxpreamble += "}\n";
1535 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1538 // * Hyperref manual: "Make sure it comes last of your loaded
1539 // packages, to give it a fighting chance of not being over-written,
1540 // since its job is to redefine many LaTeX commands."
1541 // * Email from Heiko Oberdiek: "It is usually better to load babel
1542 // before hyperref. Then hyperref has a chance to detect babel.
1543 // * Has to be loaded before the "LyX specific LaTeX commands" to
1544 // avoid errors with algorithm floats.
1545 // use hyperref explicitly if it is required
1546 if (features.isRequired("hyperref")) {
1547 // pass what we have to stream here, since we need
1548 // to access the stream itself in PDFOptions.
1552 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1554 OutputParams tmp_params = features.runparams();
1555 lines += pdfoptions().writeLaTeX(tmp_params, os,
1556 documentClass().provides("hyperref"));
1557 texrow.newlines(lines);
1558 // set back for the rest
1559 lyxpreamble.clear();
1562 // Will be surrounded by \makeatletter and \makeatother when not empty
1563 docstring atlyxpreamble;
1565 // Some macros LyX will need
1566 docstring tmppreamble(features.getMacros());
1568 if (!tmppreamble.empty())
1569 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1570 "LyX specific LaTeX commands.\n"
1571 + tmppreamble + '\n';
1573 // the text class specific preamble
1574 tmppreamble = features.getTClassPreamble();
1575 if (!tmppreamble.empty())
1576 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1577 "Textclass specific LaTeX commands.\n"
1578 + tmppreamble + '\n';
1580 // suppress date if selected
1581 // use \@ifundefined because we cannot be sure that every document class
1582 // has a \date command
1584 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1586 /* the user-defined preamble */
1587 if (!containsOnly(preamble, " \n\t"))
1589 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1590 "User specified LaTeX commands.\n"
1591 + from_utf8(preamble) + '\n';
1593 // subfig loads internally the LaTeX package "caption". As
1594 // caption is a very popular package, users will load it in
1595 // the preamble. Therefore we must load subfig behind the
1596 // user-defined preamble and check if the caption package was
1597 // loaded or not. For the case that caption is loaded before
1598 // subfig, there is the subfig option "caption=false". This
1599 // option also works when a koma-script class is used and
1600 // koma's own caption commands are used instead of caption. We
1601 // use \PassOptionsToPackage here because the user could have
1602 // already loaded subfig in the preamble.
1603 if (features.isRequired("subfig")) {
1604 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1605 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1606 "\\usepackage{subfig}\n";
1609 // Itemize bullet settings need to be last in case the user
1610 // defines their own bullets that use a package included
1611 // in the user-defined preamble -- ARRae
1612 // Actually it has to be done much later than that
1613 // since some packages like frenchb make modifications
1614 // at \begin{document} time -- JMarc
1615 docstring bullets_def;
1616 for (int i = 0; i < 4; ++i) {
1617 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1618 if (bullets_def.empty())
1619 bullets_def += "\\AtBeginDocument{\n";
1620 bullets_def += " \\def\\labelitemi";
1622 // `i' is one less than the item to modify
1629 bullets_def += "ii";
1635 bullets_def += '{' +
1636 user_defined_bullet(i).getText()
1641 if (!bullets_def.empty())
1642 atlyxpreamble += bullets_def + "}\n\n";
1644 if (!atlyxpreamble.empty())
1645 lyxpreamble += "\n\\makeatletter\n"
1646 + atlyxpreamble + "\\makeatother\n\n";
1648 // We try to load babel late, in case it interferes with other packages.
1649 // Jurabib and Hyperref have to be called after babel, though.
1650 if (use_babel && !features.isRequired("jurabib")
1651 && !features.isRequired("hyperref")
1652 && !features.isRequired("vietnamese")
1653 && !features.isRequired("japanese")) {
1655 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1656 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1659 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1660 if (!i18npreamble.empty())
1661 lyxpreamble += i18npreamble + '\n';
1664 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1665 texrow.newlines(nlines);
1669 // these packages (xunicode, for that matter) need to be loaded at least
1670 // after amsmath, amssymb, esint and the other packages that provide
1673 os << "\\usepackage{xunicode}\n";
1675 os << "\\usepackage{xltxtra}\n";
1682 void BufferParams::useClassDefaults()
1684 DocumentClass const & tclass = documentClass();
1686 sides = tclass.sides();
1687 columns = tclass.columns();
1688 pagestyle = tclass.pagestyle();
1689 use_default_options = true;
1690 // Only if class has a ToC hierarchy
1691 if (tclass.hasTocLevels()) {
1692 secnumdepth = tclass.secnumdepth();
1693 tocdepth = tclass.tocdepth();
1698 bool BufferParams::hasClassDefaults() const
1700 DocumentClass const & tclass = documentClass();
1702 return sides == tclass.sides()
1703 && columns == tclass.columns()
1704 && pagestyle == tclass.pagestyle()
1705 && use_default_options
1706 && secnumdepth == tclass.secnumdepth()
1707 && tocdepth == tclass.tocdepth();
1711 DocumentClass const & BufferParams::documentClass() const
1717 DocumentClass const * BufferParams::documentClassPtr() const {
1722 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1723 // evil, but this function is evil
1724 doc_class_ = const_cast<DocumentClass *>(tc);
1728 bool BufferParams::setBaseClass(string const & classname)
1730 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1731 LayoutFileList & bcl = LayoutFileList::get();
1732 if (!bcl.haveClass(classname)) {
1734 bformat(_("The document class %1$s could not be found. "
1735 "A default textclass with default layouts will be used. "
1736 "LyX might not be able to produce output unless a correct "
1737 "textclass is selected from the document settings dialog."),
1738 from_utf8(classname));
1739 frontend::Alert::error(_("Document class not found"), s);
1740 bcl.addEmptyClass(classname);
1743 bool const success = bcl[classname].load();
1746 bformat(_("The document class %1$s could not be loaded."),
1747 from_utf8(classname));
1748 frontend::Alert::error(_("Could not load class"), s);
1752 pimpl_->baseClass_ = classname;
1753 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1758 LayoutFile const * BufferParams::baseClass() const
1760 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1761 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1767 LayoutFileIndex const & BufferParams::baseClassID() const
1769 return pimpl_->baseClass_;
1773 void BufferParams::makeDocumentClass()
1778 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1780 if (!local_layout.empty()) {
1781 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1782 docstring const msg = _("Error reading internal layout information");
1783 frontend::Alert::warning(_("Read Error"), msg);
1788 bool BufferParams::moduleCanBeAdded(string const & modName) const
1790 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1794 bool BufferParams::addLayoutModule(string const & modName)
1796 LayoutModuleList::const_iterator it = layoutModules_.begin();
1797 LayoutModuleList::const_iterator end = layoutModules_.end();
1798 for (; it != end; it++)
1801 layoutModules_.push_back(modName);
1806 Font const BufferParams::getFont() const
1808 FontInfo f = documentClass().defaultfont();
1809 if (fontsDefaultFamily == "rmdefault")
1810 f.setFamily(ROMAN_FAMILY);
1811 else if (fontsDefaultFamily == "sfdefault")
1812 f.setFamily(SANS_FAMILY);
1813 else if (fontsDefaultFamily == "ttdefault")
1814 f.setFamily(TYPEWRITER_FAMILY);
1815 return Font(f, language);
1819 void BufferParams::readPreamble(Lexer & lex)
1821 if (lex.getString() != "\\begin_preamble")
1822 lyxerr << "Error (BufferParams::readPreamble):"
1823 "consistency check failed." << endl;
1825 preamble = lex.getLongString("\\end_preamble");
1829 void BufferParams::readLocalLayout(Lexer & lex)
1831 if (lex.getString() != "\\begin_local_layout")
1832 lyxerr << "Error (BufferParams::readLocalLayout):"
1833 "consistency check failed." << endl;
1835 local_layout = lex.getLongString("\\end_local_layout");
1839 void BufferParams::readLanguage(Lexer & lex)
1841 if (!lex.next()) return;
1843 string const tmptok = lex.getString();
1845 // check if tmptok is part of tex_babel in tex-defs.h
1846 language = languages.getLanguage(tmptok);
1848 // Language tmptok was not found
1849 language = default_language;
1850 lyxerr << "Warning: Setting language `"
1851 << tmptok << "' to `" << language->lang()
1857 void BufferParams::readGraphicsDriver(Lexer & lex)
1862 string const tmptok = lex.getString();
1863 // check if tmptok is part of tex_graphics in tex_defs.h
1866 string const test = tex_graphics[n++];
1868 if (test == tmptok) {
1869 graphicsDriver = tmptok;
1874 "Warning: graphics driver `$$Token' not recognized!\n"
1875 " Setting graphics driver to `default'.\n");
1876 graphicsDriver = "default";
1883 void BufferParams::readBullets(Lexer & lex)
1888 int const index = lex.getInteger();
1890 int temp_int = lex.getInteger();
1891 user_defined_bullet(index).setFont(temp_int);
1892 temp_bullet(index).setFont(temp_int);
1894 user_defined_bullet(index).setCharacter(temp_int);
1895 temp_bullet(index).setCharacter(temp_int);
1897 user_defined_bullet(index).setSize(temp_int);
1898 temp_bullet(index).setSize(temp_int);
1902 void BufferParams::readBulletsLaTeX(Lexer & lex)
1904 // The bullet class should be able to read this.
1907 int const index = lex.getInteger();
1909 docstring const temp_str = lex.getDocString();
1911 user_defined_bullet(index).setText(temp_str);
1912 temp_bullet(index).setText(temp_str);
1916 void BufferParams::readModules(Lexer & lex)
1918 if (!lex.eatLine()) {
1919 lyxerr << "Error (BufferParams::readModules):"
1920 "Unexpected end of input." << endl;
1924 string mod = lex.getString();
1925 if (mod == "\\end_modules")
1927 addLayoutModule(mod);
1933 void BufferParams::readRemovedModules(Lexer & lex)
1935 if (!lex.eatLine()) {
1936 lyxerr << "Error (BufferParams::readRemovedModules):"
1937 "Unexpected end of input." << endl;
1941 string mod = lex.getString();
1942 if (mod == "\\end_removed_modules")
1944 removedModules_.push_back(mod);
1947 // now we want to remove any removed modules that were previously
1948 // added. normally, that will be because default modules were added in
1949 // setBaseClass(), which gets called when \textclass is read at the
1950 // start of the read.
1951 list<string>::const_iterator rit = removedModules_.begin();
1952 list<string>::const_iterator const ren = removedModules_.end();
1953 for (; rit != ren; rit++) {
1954 LayoutModuleList::iterator const mit = layoutModules_.begin();
1955 LayoutModuleList::iterator const men = layoutModules_.end();
1956 LayoutModuleList::iterator found = find(mit, men, *rit);
1959 layoutModules_.erase(found);
1964 void BufferParams::readIncludeonly(Lexer & lex)
1966 if (!lex.eatLine()) {
1967 lyxerr << "Error (BufferParams::readIncludeonly):"
1968 "Unexpected end of input." << endl;
1972 string child = lex.getString();
1973 if (child == "\\end_includeonly")
1975 includedChildren_.push_back(child);
1981 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1983 char real_papersize = papersize;
1984 if (real_papersize == PAPER_DEFAULT)
1985 real_papersize = lyxrc.default_papersize;
1987 switch (real_papersize) {
1989 // could be anything, so don't guess
1991 case PAPER_CUSTOM: {
1992 if (purpose == XDVI && !paperwidth.empty() &&
1993 !paperheight.empty()) {
1994 // heightxwidth<unit>
1995 string first = paperwidth;
1996 string second = paperheight;
1997 if (orientation == ORIENTATION_LANDSCAPE)
2000 return first.erase(first.length() - 2)
2012 // dvips and dvipdfm do not know this
2013 if (purpose == DVIPS || purpose == DVIPDFM)
2017 // dvipdfm does not know this
2018 if (purpose == DVIPDFM)
2022 // dvipdfm does not know this
2023 if (purpose == DVIPDFM)
2026 case PAPER_USEXECUTIVE:
2027 // dvipdfm does not know this
2028 if (purpose == DVIPDFM)
2033 case PAPER_USLETTER:
2035 if (purpose == XDVI)
2042 string const BufferParams::dvips_options() const
2047 && papersize == PAPER_CUSTOM
2048 && !lyxrc.print_paper_dimension_flag.empty()
2049 && !paperwidth.empty()
2050 && !paperheight.empty()) {
2051 // using a custom papersize
2052 result = lyxrc.print_paper_dimension_flag;
2053 result += ' ' + paperwidth;
2054 result += ',' + paperheight;
2056 string const paper_option = paperSizeName(DVIPS);
2057 if (!paper_option.empty() && (paper_option != "letter" ||
2058 orientation != ORIENTATION_LANDSCAPE)) {
2059 // dvips won't accept -t letter -t landscape.
2060 // In all other cases, include the paper size
2062 result = lyxrc.print_paper_flag;
2063 result += ' ' + paper_option;
2066 if (orientation == ORIENTATION_LANDSCAPE &&
2067 papersize != PAPER_CUSTOM)
2068 result += ' ' + lyxrc.print_landscape_flag;
2073 string const BufferParams::font_encoding() const
2075 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2079 string BufferParams::babelCall(string const & lang_opts) const
2081 string lang_pack = lyxrc.language_package;
2082 if (lang_pack != "\\usepackage{babel}")
2084 // suppress the babel call when there is no babel language defined
2085 // for the document language in the lib/languages file and if no
2086 // other languages are used (lang_opts is then empty)
2087 if (lang_opts.empty())
2089 // If Vietnamese is used, babel must directly be loaded with the
2090 // language options, see
2091 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2092 size_t viet = lang_opts.find("vietnam");
2093 // viet = string::npos when not found
2094 // the same is for all other languages that are not directly supported by
2095 // babel, but where LaTeX-packages add babel support.
2096 // this is currently the case for Latvian, Lithuanian, and Mongolian
2097 size_t latvian = lang_opts.find("latvian");
2098 size_t lithu = lang_opts.find("lithuanian");
2099 size_t mongo = lang_opts.find("mongolian");
2100 // If Japanese is used, babel must directly be loaded with the
2101 // language options, see
2102 // http://www.lyx.org/trac/ticket/4597#c4
2103 size_t japan = lang_opts.find("japanese");
2104 if (!lyxrc.language_global_options || viet != string::npos
2105 || japan != string::npos || latvian != string::npos
2106 || lithu != string::npos || mongo != string::npos)
2107 return "\\usepackage[" + lang_opts + "]{babel}";
2112 docstring BufferParams::getGraphicsDriver(string const & package) const
2116 if (package == "geometry") {
2117 if (graphicsDriver == "dvips"
2118 || graphicsDriver == "dvipdfm"
2119 || graphicsDriver == "pdftex"
2120 || graphicsDriver == "vtex")
2121 result = from_ascii(graphicsDriver);
2122 else if (graphicsDriver == "dvipdfmx")
2123 result = from_ascii("dvipdfm");
2130 void BufferParams::writeEncodingPreamble(odocstream & os,
2131 LaTeXFeatures & features, TexRow & texrow) const
2135 if (inputenc == "auto") {
2136 string const doc_encoding =
2137 language->encoding()->latexName();
2138 Encoding::Package const package =
2139 language->encoding()->package();
2141 // Create a list with all the input encodings used
2143 set<string> encodings =
2144 features.getEncodingSet(doc_encoding);
2146 // If the "japanese" package (i.e. pLaTeX) is used,
2147 // inputenc must be omitted.
2148 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2149 if (package == Encoding::japanese)
2150 features.require("japanese");
2152 if ((!encodings.empty() || package == Encoding::inputenc)
2153 && !features.isRequired("japanese")) {
2154 os << "\\usepackage[";
2155 set<string>::const_iterator it = encodings.begin();
2156 set<string>::const_iterator const end = encodings.end();
2158 os << from_ascii(*it);
2161 for (; it != end; ++it)
2162 os << ',' << from_ascii(*it);
2163 if (package == Encoding::inputenc) {
2164 if (!encodings.empty())
2166 os << from_ascii(doc_encoding);
2168 os << "]{inputenc}\n";
2171 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2172 if (language->encoding()->name() == "utf8-cjk"
2173 && LaTeXFeatures::isAvailable("CJKutf8"))
2174 os << "\\usepackage{CJKutf8}\n";
2176 os << "\\usepackage{CJK}\n";
2179 } else if (inputenc != "default") {
2180 switch (encoding().package()) {
2181 case Encoding::none:
2182 case Encoding::japanese:
2184 case Encoding::inputenc:
2185 // do not load inputenc if japanese is used
2186 if (features.isRequired("japanese"))
2188 os << "\\usepackage[" << from_ascii(inputenc)
2193 if (encoding().name() == "utf8-cjk"
2194 && LaTeXFeatures::isAvailable("CJKutf8"))
2195 os << "\\usepackage{CJKutf8}\n";
2197 os << "\\usepackage{CJK}\n";
2203 // The encoding "armscii8" (for Armenian) is only available when
2204 // the package "armtex" is loaded.
2205 if (language->encoding()->latexName() == "armscii8"
2206 || inputenc == "armscii8") {
2207 os << "\\usepackage{armtex}\n";
2213 string const BufferParams::parseFontName(string const & name) const
2215 string mangled = name;
2216 size_t const idx = mangled.find('[');
2217 if (idx == string::npos || idx == 0)
2220 return mangled.substr(0, idx - 1);
2224 string const BufferParams::loadFonts(string const & rm,
2225 string const & sf, string const & tt,
2226 bool const & sc, bool const & osf,
2227 int const & sfscale, int const & ttscale,
2228 bool const & xetex) const
2230 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2231 several packages have been replaced by others, that might not
2232 be installed on every system. We have to take care for that
2233 (see psnfss.pdf). We try to support all psnfss fonts as well
2234 as the fonts that have become de facto standard in the LaTeX
2235 world (e.g. Latin Modern). We do not support obsolete fonts
2236 (like PSLatex). In general, it should be possible to mix any
2237 rm font with any sf or tt font, respectively. (JSpitzm)
2239 -- separate math fonts.
2242 if (rm == "default" && sf == "default" && tt == "default")
2249 if (rm != "default")
2250 os << "\\setmainfont[Mapping=tex-text]{"
2251 << parseFontName(rm) << "}\n";
2252 if (sf != "default") {
2253 string const sans = parseFontName(sf);
2255 os << "\\setsansfont[Scale="
2256 << float(sfscale) / 100
2257 << ",Mapping=tex-text]{"
2260 os << "\\setsansfont[Mapping=tex-text]{"
2263 if (tt != "default") {
2264 string const mono = parseFontName(tt);
2266 os << "\\setmonofont[Scale="
2267 << float(sfscale) / 100
2271 os << "\\setmonofont[Mapping=tex-text]{"
2275 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2280 // Computer Modern (must be explicitly selectable -- there might be classes
2281 // that define a different default font!
2283 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2284 // osf for Computer Modern needs eco.sty
2286 os << "\\usepackage{eco}\n";
2288 // Latin Modern Roman
2289 else if (rm == "lmodern")
2290 os << "\\usepackage{lmodern}\n";
2292 else if (rm == "ae") {
2293 // not needed when using OT1 font encoding.
2294 if (font_encoding() != "default")
2295 os << "\\usepackage{ae,aecompl}\n";
2298 else if (rm == "times") {
2299 // try to load the best available package
2300 if (LaTeXFeatures::isAvailable("mathptmx"))
2301 os << "\\usepackage{mathptmx}\n";
2302 else if (LaTeXFeatures::isAvailable("mathptm"))
2303 os << "\\usepackage{mathptm}\n";
2305 os << "\\usepackage{times}\n";
2308 else if (rm == "palatino") {
2309 // try to load the best available package
2310 if (LaTeXFeatures::isAvailable("mathpazo")) {
2311 os << "\\usepackage";
2317 // "osf" includes "sc"!
2321 os << "{mathpazo}\n";
2323 else if (LaTeXFeatures::isAvailable("mathpple"))
2324 os << "\\usepackage{mathpple}\n";
2326 os << "\\usepackage{palatino}\n";
2329 else if (rm == "utopia") {
2330 // fourier supersedes utopia.sty, but does
2331 // not work with OT1 encoding.
2332 if (LaTeXFeatures::isAvailable("fourier")
2333 && font_encoding() != "default") {
2334 os << "\\usepackage";
2345 os << "{fourier}\n";
2348 os << "\\usepackage{utopia}\n";
2350 // Bera (complete fontset)
2351 else if (rm == "bera" && sf == "default" && tt == "default")
2352 os << "\\usepackage{bera}\n";
2354 else if (rm != "default")
2355 os << "\\usepackage" << "{" << rm << "}\n";
2358 // Helvetica, Bera Sans
2359 if (sf == "helvet" || sf == "berasans") {
2361 os << "\\usepackage[scaled=" << float(sfscale) / 100
2362 << "]{" << sf << "}\n";
2364 os << "\\usepackage{" << sf << "}\n";
2367 else if (sf == "avant")
2368 os << "\\usepackage{" << sf << "}\n";
2369 // Computer Modern, Latin Modern, CM Bright
2370 else if (sf != "default")
2371 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2373 // monospaced/typewriter
2374 // Courier, LuxiMono
2375 if (tt == "luximono" || tt == "beramono") {
2377 os << "\\usepackage[scaled=" << float(ttscale) / 100
2378 << "]{" << tt << "}\n";
2380 os << "\\usepackage{" << tt << "}\n";
2383 else if (tt == "courier" )
2384 os << "\\usepackage{" << tt << "}\n";
2385 // Computer Modern, Latin Modern, CM Bright
2386 else if (tt != "default")
2387 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2393 Encoding const & BufferParams::encoding() const
2396 return *(encodings.fromLaTeXName("utf8-plain"));
2397 if (inputenc == "auto" || inputenc == "default")
2398 return *language->encoding();
2399 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2402 LYXERR0("Unknown inputenc value `" << inputenc
2403 << "'. Using `auto' instead.");
2404 return *language->encoding();
2408 CiteEngine BufferParams::citeEngine() const
2410 // FIXME the class should provide the numerical/
2411 // authoryear choice
2412 if (documentClass().provides("natbib")
2413 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2414 return ENGINE_NATBIB_AUTHORYEAR;
2415 return cite_engine_;
2419 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2421 cite_engine_ = cite_engine;