2 * \file BufferParams.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Alfredo Braunstein
7 * \author Lars Gullik Bjønnes
8 * \author Jean-Marc Lasgouttes
10 * \author André Pönitz
11 * \author Martin Vermeer
13 * Full author contact details are available in file CREDITS.
18 #include "BufferParams.h"
21 #include "LayoutFile.h"
22 #include "BranchList.h"
23 #include "buffer_funcs.h"
29 #include "IndicesList.h"
31 #include "LaTeXFeatures.h"
32 #include "ModuleList.h"
36 #include "OutputParams.h"
40 #include "PDFOptions.h"
42 #include "frontends/alert.h"
44 #include "insets/InsetListingsParams.h"
46 #include "support/convert.h"
47 #include "support/debug.h"
48 #include "support/docstream.h"
49 #include "support/FileName.h"
50 #include "support/filetools.h"
51 #include "support/gettext.h"
52 #include "support/Messages.h"
53 #include "support/Translator.h"
54 #include "support/lstrings.h"
60 using namespace lyx::support;
63 static char const * const string_paragraph_separation[] = {
68 static char const * const string_quotes_language[] = {
69 "english", "swedish", "german", "polish", "french", "danish", ""
73 static char const * const string_papersize[] = {
74 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
75 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
79 static char const * const string_orientation[] = {
80 "portrait", "landscape", ""
84 static char const * const string_footnotekinds[] = {
85 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
89 static char const * const tex_graphics[] = {
90 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
91 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
92 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
93 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
104 // Paragraph separation
105 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
108 ParSepTranslator const init_parseptranslator()
110 ParSepTranslator translator
111 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
112 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
117 ParSepTranslator const & parseptranslator()
119 static ParSepTranslator translator = init_parseptranslator();
125 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
128 QuotesLangTranslator const init_quoteslangtranslator()
130 QuotesLangTranslator translator
131 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
132 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
133 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
134 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
135 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
136 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
141 QuotesLangTranslator const & quoteslangtranslator()
143 static QuotesLangTranslator translator = init_quoteslangtranslator();
149 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
152 static PaperSizeTranslator initPaperSizeTranslator()
154 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
155 translator.addPair(string_papersize[1], PAPER_CUSTOM);
156 translator.addPair(string_papersize[2], PAPER_USLETTER);
157 translator.addPair(string_papersize[3], PAPER_USLEGAL);
158 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
159 translator.addPair(string_papersize[5], PAPER_A3);
160 translator.addPair(string_papersize[6], PAPER_A4);
161 translator.addPair(string_papersize[7], PAPER_A5);
162 translator.addPair(string_papersize[8], PAPER_B3);
163 translator.addPair(string_papersize[9], PAPER_B4);
164 translator.addPair(string_papersize[10], PAPER_B5);
169 PaperSizeTranslator const & papersizetranslator()
171 static PaperSizeTranslator translator = initPaperSizeTranslator();
177 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
180 PaperOrientationTranslator const init_paperorientationtranslator()
182 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
183 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
188 PaperOrientationTranslator const & paperorientationtranslator()
190 static PaperOrientationTranslator translator = init_paperorientationtranslator();
196 typedef Translator<int, PageSides> SidesTranslator;
199 SidesTranslator const init_sidestranslator()
201 SidesTranslator translator(1, OneSide);
202 translator.addPair(2, TwoSides);
207 SidesTranslator const & sidestranslator()
209 static SidesTranslator translator = init_sidestranslator();
215 typedef Translator<int, BufferParams::Package> PackageTranslator;
218 PackageTranslator const init_packagetranslator()
220 PackageTranslator translator(0, BufferParams::package_off);
221 translator.addPair(1, BufferParams::package_auto);
222 translator.addPair(2, BufferParams::package_on);
227 PackageTranslator const & packagetranslator()
229 static PackageTranslator translator = init_packagetranslator();
235 typedef Translator<string, CiteEngine> CiteEngineTranslator;
238 CiteEngineTranslator const init_citeenginetranslator()
240 CiteEngineTranslator translator("basic", ENGINE_BASIC);
241 translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
242 translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
243 translator.addPair("jurabib", ENGINE_JURABIB);
248 CiteEngineTranslator const & citeenginetranslator()
250 static CiteEngineTranslator translator = init_citeenginetranslator();
256 typedef Translator<string, Spacing::Space> SpaceTranslator;
259 SpaceTranslator const init_spacetranslator()
261 SpaceTranslator translator("default", Spacing::Default);
262 translator.addPair("single", Spacing::Single);
263 translator.addPair("onehalf", Spacing::Onehalf);
264 translator.addPair("double", Spacing::Double);
265 translator.addPair("other", Spacing::Other);
270 SpaceTranslator const & spacetranslator()
272 static SpaceTranslator translator = init_spacetranslator();
279 class BufferParams::Impl
284 AuthorList authorlist;
285 BranchList branchlist;
286 Bullet temp_bullets[4];
287 Bullet user_defined_bullets[4];
288 IndicesList indiceslist;
290 /** This is the amount of space used for paragraph_separation "skip",
291 * and for detached paragraphs in "indented" documents.
295 PDFOptions pdfoptions;
296 LayoutFileIndex baseClass_;
300 BufferParams::Impl::Impl()
301 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
303 // set initial author
305 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
310 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
314 return new BufferParams::Impl(*ptr);
318 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
324 BufferParams::BufferParams()
327 setBaseClass(defaultBaseclass());
329 paragraph_separation = ParagraphIndentSeparation;
330 quotes_language = InsetQuotes::EnglishQuotes;
331 fontsize = "default";
334 papersize = PAPER_DEFAULT;
335 orientation = ORIENTATION_PORTRAIT;
336 use_geometry = false;
337 use_amsmath = package_auto;
338 use_esint = package_auto;
339 use_mhchem = package_auto;
340 cite_engine_ = ENGINE_BASIC;
341 use_bibtopic = false;
343 trackChanges = false;
344 outputChanges = false;
345 use_default_options = true;
346 maintain_unincluded_children = false;
349 language = default_language;
351 fontsRoman = "default";
352 fontsSans = "default";
353 fontsTypewriter = "default";
354 fontsDefaultFamily = "default";
358 fontsSansScale = 100;
359 fontsTypewriterScale = 100;
361 graphicsDriver = "default";
362 defaultOutputFormat = "default";
363 bibtex_command = "default";
364 index_command = "default";
367 listings_params = string();
368 pagestyle = "default";
369 suppress_date = false;
370 // white is equal to no background color
371 backgroundcolor = lyx::rgbFromHexName("#ffffff");
373 for (int iter = 0; iter < 4; ++iter) {
374 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
375 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
378 indiceslist().addDefault(B_("Index"));
379 html_be_strict = true;
380 html_use_mathml = true;
384 docstring BufferParams::B_(string const & l10n) const
386 LASSERT(language, /**/);
387 return getMessages(language->code()).get(l10n);
391 AuthorList & BufferParams::authors()
393 return pimpl_->authorlist;
397 AuthorList const & BufferParams::authors() const
399 return pimpl_->authorlist;
403 BranchList & BufferParams::branchlist()
405 return pimpl_->branchlist;
409 BranchList const & BufferParams::branchlist() const
411 return pimpl_->branchlist;
415 IndicesList & BufferParams::indiceslist()
417 return pimpl_->indiceslist;
421 IndicesList const & BufferParams::indiceslist() const
423 return pimpl_->indiceslist;
427 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
429 LASSERT(index < 4, /**/);
430 return pimpl_->temp_bullets[index];
434 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
436 LASSERT(index < 4, /**/);
437 return pimpl_->temp_bullets[index];
441 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
443 LASSERT(index < 4, /**/);
444 return pimpl_->user_defined_bullets[index];
448 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
450 LASSERT(index < 4, /**/);
451 return pimpl_->user_defined_bullets[index];
455 Spacing & BufferParams::spacing()
457 return pimpl_->spacing;
461 Spacing const & BufferParams::spacing() const
463 return pimpl_->spacing;
467 PDFOptions & BufferParams::pdfoptions()
469 return pimpl_->pdfoptions;
473 PDFOptions const & BufferParams::pdfoptions() const
475 return pimpl_->pdfoptions;
479 HSpace const & BufferParams::getIndentation() const
481 return pimpl_->indentation;
485 void BufferParams::setIndentation(HSpace const & indent)
487 pimpl_->indentation = indent;
491 VSpace const & BufferParams::getDefSkip() const
493 return pimpl_->defskip;
497 void BufferParams::setDefSkip(VSpace const & vs)
499 pimpl_->defskip = vs;
503 string BufferParams::readToken(Lexer & lex, string const & token,
504 FileName const & filepath)
506 if (token == "\\textclass") {
508 string const classname = lex.getString();
509 // if there exists a local layout file, ignore the system one
510 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
512 LayoutFileList & bcl = LayoutFileList::get();
513 if (tcp.empty() && !filepath.empty())
514 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
518 setBaseClass(classname);
519 // We assume that a tex class exists for local or unknown layouts so this warning
520 // will only be given for system layouts.
521 if (!baseClass()->isTeXClassAvailable()) {
522 docstring const msg =
523 bformat(_("The layout file requested by this document,\n"
525 "is not usable. This is probably because a LaTeX\n"
526 "class or style file required by it is not\n"
527 "available. See the Customization documentation\n"
528 "for more information.\n"), from_utf8(classname));
529 frontend::Alert::warning(_("Document class not available"),
530 msg + _("LyX will not be able to produce output."));
532 } else if (token == "\\begin_preamble") {
534 } else if (token == "\\begin_local_layout") {
535 readLocalLayout(lex);
536 } else if (token == "\\begin_modules") {
538 } else if (token == "\\begin_removed_modules") {
539 readRemovedModules(lex);
540 } else if (token == "\\begin_includeonly") {
541 readIncludeonly(lex);
542 } else if (token == "\\maintain_unincluded_children") {
543 lex >> maintain_unincluded_children;
544 } else if (token == "\\options") {
546 options = lex.getString();
547 } else if (token == "\\use_default_options") {
548 lex >> use_default_options;
549 } else if (token == "\\master") {
551 master = lex.getString();
552 } else if (token == "\\suppress_date") {
553 lex >> suppress_date;
554 } else if (token == "\\language") {
556 } else if (token == "\\inputencoding") {
558 } else if (token == "\\graphics") {
559 readGraphicsDriver(lex);
560 } else if (token == "\\default_output_format") {
561 lex >> defaultOutputFormat;
562 } else if (token == "\\bibtex_command") {
564 bibtex_command = lex.getString();
565 } else if (token == "\\index_command") {
567 index_command = lex.getString();
568 } else if (token == "\\fontencoding") {
570 fontenc = lex.getString();
571 } else if (token == "\\font_roman") {
573 fontsRoman = lex.getString();
574 } else if (token == "\\font_sans") {
576 fontsSans = lex.getString();
577 } else if (token == "\\font_typewriter") {
579 fontsTypewriter = lex.getString();
580 } else if (token == "\\font_default_family") {
581 lex >> fontsDefaultFamily;
582 } else if (token == "\\use_xetex") {
584 } else if (token == "\\font_sc") {
586 } else if (token == "\\font_osf") {
588 } else if (token == "\\font_sf_scale") {
589 lex >> fontsSansScale;
590 } else if (token == "\\font_tt_scale") {
591 lex >> fontsTypewriterScale;
592 } else if (token == "\\font_cjk") {
594 } else if (token == "\\paragraph_separation") {
597 paragraph_separation = parseptranslator().find(parsep);
598 } else if (token == "\\paragraph_indentation") {
600 string indentation = lex.getString();
601 pimpl_->indentation = HSpace(indentation);
602 } else if (token == "\\defskip") {
604 string defskip = lex.getString();
605 if (defskip == "defskip")
608 pimpl_->defskip = VSpace(defskip);
609 } else if (token == "\\quotes_language") {
612 quotes_language = quoteslangtranslator().find(quotes_lang);
613 } else if (token == "\\papersize") {
616 papersize = papersizetranslator().find(ppsize);
617 } else if (token == "\\use_geometry") {
619 } else if (token == "\\use_amsmath") {
622 use_amsmath = packagetranslator().find(use_ams);
623 } else if (token == "\\use_esint") {
626 use_esint = packagetranslator().find(useesint);
627 } else if (token == "\\use_mhchem") {
630 use_mhchem = packagetranslator().find(usemhchem);
631 } else if (token == "\\cite_engine") {
634 cite_engine_ = citeenginetranslator().find(engine);
635 } else if (token == "\\use_bibtopic") {
637 } else if (token == "\\use_indices") {
639 } else if (token == "\\tracking_changes") {
641 } else if (token == "\\output_changes") {
642 lex >> outputChanges;
643 } else if (token == "\\branch") {
645 docstring branch = lex.getDocString();
646 branchlist().add(branch);
649 string const tok = lex.getString();
650 if (tok == "\\end_branch")
652 Branch * branch_ptr = branchlist().find(branch);
653 if (tok == "\\selected") {
656 branch_ptr->setSelected(lex.getInteger());
658 if (tok == "\\filename_suffix") {
661 branch_ptr->setFilenameSuffix(lex.getInteger());
663 if (tok == "\\color") {
665 string color = lex.getString();
667 branch_ptr->setColor(color);
668 // Update also the Color table:
670 color = lcolor.getX11Name(Color_background);
672 lcolor.setColor(to_utf8(branch), color);
675 } else if (token == "\\index") {
677 docstring index = lex.getDocString();
679 indiceslist().add(index);
682 string const tok = lex.getString();
683 if (tok == "\\end_index")
685 Index * index_ptr = indiceslist().find(index);
686 if (tok == "\\shortcut") {
688 shortcut = lex.getDocString();
690 index_ptr->setShortcut(shortcut);
692 if (tok == "\\color") {
694 string color = lex.getString();
696 index_ptr->setColor(color);
697 // Update also the Color table:
699 color = lcolor.getX11Name(Color_background);
701 if (!shortcut.empty())
702 lcolor.setColor(to_utf8(shortcut), color);
705 } else if (token == "\\author") {
707 istringstream ss(lex.getString());
710 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
711 } else if (token == "\\paperorientation") {
714 orientation = paperorientationtranslator().find(orient);
715 } else if (token == "\\backgroundcolor") {
717 backgroundcolor = lyx::rgbFromHexName(lex.getString());
718 } else if (token == "\\paperwidth") {
720 } else if (token == "\\paperheight") {
722 } else if (token == "\\leftmargin") {
724 } else if (token == "\\topmargin") {
726 } else if (token == "\\rightmargin") {
728 } else if (token == "\\bottommargin") {
730 } else if (token == "\\headheight") {
732 } else if (token == "\\headsep") {
734 } else if (token == "\\footskip") {
736 } else if (token == "\\columnsep") {
738 } else if (token == "\\paperfontsize") {
740 } else if (token == "\\papercolumns") {
742 } else if (token == "\\listings_params") {
745 listings_params = InsetListingsParams(par).params();
746 } else if (token == "\\papersides") {
749 sides = sidestranslator().find(psides);
750 } else if (token == "\\paperpagestyle") {
752 } else if (token == "\\bullet") {
754 } else if (token == "\\bulletLaTeX") {
755 readBulletsLaTeX(lex);
756 } else if (token == "\\secnumdepth") {
758 } else if (token == "\\tocdepth") {
760 } else if (token == "\\spacing") {
764 if (nspacing == "other") {
767 spacing().set(spacetranslator().find(nspacing), tmp_val);
768 } else if (token == "\\float_placement") {
769 lex >> float_placement;
771 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
772 string toktmp = pdfoptions().readToken(lex, token);
773 if (!toktmp.empty()) {
774 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
778 } else if (token == "\\html_use_mathml") {
779 lex >> html_use_mathml;
780 } else if (token == "\\html_be_strict") {
781 lex >> html_be_strict;
783 lyxerr << "BufferParams::readToken(): Unknown token: " <<
792 void BufferParams::writeFile(ostream & os) const
794 // The top of the file is written by the buffer.
795 // Prints out the buffer info into the .lyx file given by file
798 os << "\\textclass " << baseClass()->name() << '\n';
801 if (!preamble.empty()) {
802 // remove '\n' from the end of preamble
803 string const tmppreamble = rtrim(preamble, "\n");
804 os << "\\begin_preamble\n"
806 << "\n\\end_preamble\n";
810 if (!options.empty()) {
811 os << "\\options " << options << '\n';
814 // use the class options defined in the layout?
815 os << "\\use_default_options "
816 << convert<string>(use_default_options) << "\n";
818 // the master document
819 if (!master.empty()) {
820 os << "\\master " << master << '\n';
824 if (!removedModules_.empty()) {
825 os << "\\begin_removed_modules" << '\n';
826 list<string>::const_iterator it = removedModules_.begin();
827 list<string>::const_iterator en = removedModules_.end();
828 for (; it != en; it++)
830 os << "\\end_removed_modules" << '\n';
834 if (!layoutModules_.empty()) {
835 os << "\\begin_modules" << '\n';
836 LayoutModuleList::const_iterator it = layoutModules_.begin();
837 LayoutModuleList::const_iterator en = layoutModules_.end();
838 for (; it != en; it++)
840 os << "\\end_modules" << '\n';
844 if (!includedChildren_.empty()) {
845 os << "\\begin_includeonly" << '\n';
846 list<string>::const_iterator it = includedChildren_.begin();
847 list<string>::const_iterator en = includedChildren_.end();
848 for (; it != en; it++)
850 os << "\\end_includeonly" << '\n';
852 os << "\\maintain_unincluded_children "
853 << convert<string>(maintain_unincluded_children) << '\n';
855 // local layout information
856 if (!local_layout.empty()) {
857 // remove '\n' from the end
858 string const tmplocal = rtrim(local_layout, "\n");
859 os << "\\begin_local_layout\n"
861 << "\n\\end_local_layout\n";
864 // then the text parameters
865 if (language != ignore_language)
866 os << "\\language " << language->lang() << '\n';
867 os << "\\inputencoding " << inputenc
868 << "\n\\fontencoding " << fontenc
869 << "\n\\font_roman " << fontsRoman
870 << "\n\\font_sans " << fontsSans
871 << "\n\\font_typewriter " << fontsTypewriter
872 << "\n\\font_default_family " << fontsDefaultFamily
873 << "\n\\use_xetex " << convert<string>(useXetex)
874 << "\n\\font_sc " << convert<string>(fontsSC)
875 << "\n\\font_osf " << convert<string>(fontsOSF)
876 << "\n\\font_sf_scale " << fontsSansScale
877 << "\n\\font_tt_scale " << fontsTypewriterScale
879 if (!fontsCJK.empty()) {
880 os << "\\font_cjk " << fontsCJK << '\n';
882 os << "\n\\graphics " << graphicsDriver << '\n';
883 os << "\\default_output_format " << defaultOutputFormat << '\n';
884 os << "\\bibtex_command " << bibtex_command << '\n';
885 os << "\\index_command " << index_command << '\n';
887 if (!float_placement.empty()) {
888 os << "\\float_placement " << float_placement << '\n';
890 os << "\\paperfontsize " << fontsize << '\n';
892 spacing().writeFile(os);
893 pdfoptions().writeFile(os);
895 os << "\\papersize " << string_papersize[papersize]
896 << "\n\\use_geometry " << convert<string>(use_geometry)
897 << "\n\\use_amsmath " << use_amsmath
898 << "\n\\use_esint " << use_esint
899 << "\n\\use_mhchem " << use_mhchem
900 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
901 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
902 << "\n\\use_indices " << convert<string>(use_indices)
903 << "\n\\paperorientation " << string_orientation[orientation]
904 << "\n\\suppress_date " << convert<string>(suppress_date)
906 if (backgroundcolor != lyx::rgbFromHexName("#ffffff"))
907 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
909 BranchList::const_iterator it = branchlist().begin();
910 BranchList::const_iterator end = branchlist().end();
911 for (; it != end; ++it) {
912 os << "\\branch " << to_utf8(it->branch())
913 << "\n\\selected " << it->isSelected()
914 << "\n\\filename_suffix " << it->hasFilenameSuffix()
915 << "\n\\color " << lyx::X11hexname(it->color())
920 IndicesList::const_iterator iit = indiceslist().begin();
921 IndicesList::const_iterator iend = indiceslist().end();
922 for (; iit != iend; ++iit) {
923 os << "\\index " << to_utf8(iit->index())
924 << "\n\\shortcut " << to_utf8(iit->shortcut())
925 << "\n\\color " << lyx::X11hexname(iit->color())
930 if (!paperwidth.empty())
931 os << "\\paperwidth "
932 << VSpace(paperwidth).asLyXCommand() << '\n';
933 if (!paperheight.empty())
934 os << "\\paperheight "
935 << VSpace(paperheight).asLyXCommand() << '\n';
936 if (!leftmargin.empty())
937 os << "\\leftmargin "
938 << VSpace(leftmargin).asLyXCommand() << '\n';
939 if (!topmargin.empty())
941 << VSpace(topmargin).asLyXCommand() << '\n';
942 if (!rightmargin.empty())
943 os << "\\rightmargin "
944 << VSpace(rightmargin).asLyXCommand() << '\n';
945 if (!bottommargin.empty())
946 os << "\\bottommargin "
947 << VSpace(bottommargin).asLyXCommand() << '\n';
948 if (!headheight.empty())
949 os << "\\headheight "
950 << VSpace(headheight).asLyXCommand() << '\n';
951 if (!headsep.empty())
953 << VSpace(headsep).asLyXCommand() << '\n';
954 if (!footskip.empty())
956 << VSpace(footskip).asLyXCommand() << '\n';
957 if (!columnsep.empty())
959 << VSpace(columnsep).asLyXCommand() << '\n';
960 os << "\\secnumdepth " << secnumdepth
961 << "\n\\tocdepth " << tocdepth
962 << "\n\\paragraph_separation "
963 << string_paragraph_separation[paragraph_separation];
964 if (!paragraph_separation)
965 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
967 os << "\n\\defskip " << getDefSkip().asLyXCommand();
968 os << "\n\\quotes_language "
969 << string_quotes_language[quotes_language]
970 << "\n\\papercolumns " << columns
971 << "\n\\papersides " << sides
972 << "\n\\paperpagestyle " << pagestyle << '\n';
973 if (!listings_params.empty())
974 os << "\\listings_params \"" <<
975 InsetListingsParams(listings_params).encodedString() << "\"\n";
976 for (int i = 0; i < 4; ++i) {
977 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
978 if (user_defined_bullet(i).getFont() != -1) {
979 os << "\\bullet " << i << " "
980 << user_defined_bullet(i).getFont() << " "
981 << user_defined_bullet(i).getCharacter() << " "
982 << user_defined_bullet(i).getSize() << "\n";
986 os << "\\bulletLaTeX " << i << " \""
987 << lyx::to_ascii(user_defined_bullet(i).getText())
993 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n"
994 << "\\output_changes " << convert<string>(outputChanges) << "\n"
995 << "\\html_use_mathml " << convert<string>(html_use_mathml) << "\n"
996 << "\\html_be_strict " << convert<string>(html_be_strict) << "\n";
998 os << pimpl_->authorlist;
1002 void BufferParams::validate(LaTeXFeatures & features) const
1004 features.require(documentClass().requires());
1006 if (outputChanges) {
1007 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1008 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1009 LaTeXFeatures::isAvailable("xcolor");
1011 switch (features.runparams().flavor) {
1012 case OutputParams::LATEX:
1014 features.require("ct-dvipost");
1015 features.require("dvipost");
1016 } else if (xcolorulem) {
1017 features.require("ct-xcolor-ulem");
1018 features.require("ulem");
1019 features.require("xcolor");
1021 features.require("ct-none");
1024 case OutputParams::PDFLATEX:
1025 case OutputParams::XETEX:
1027 features.require("ct-xcolor-ulem");
1028 features.require("ulem");
1029 features.require("xcolor");
1030 // improves color handling in PDF output
1031 features.require("pdfcolmk");
1033 features.require("ct-none");
1041 // Floats with 'Here definitely' as default setting.
1042 if (float_placement.find('H') != string::npos)
1043 features.require("float");
1045 // AMS Style is at document level
1046 if (use_amsmath == package_on
1047 || documentClass().provides("amsmath"))
1048 features.require("amsmath");
1049 if (use_esint == package_on)
1050 features.require("esint");
1051 if (use_mhchem == package_on)
1052 features.require("mhchem");
1054 // Document-level line spacing
1055 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1056 features.require("setspace");
1058 // the bullet shapes are buffer level not paragraph level
1059 // so they are tested here
1060 for (int i = 0; i < 4; ++i) {
1061 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1063 int const font = user_defined_bullet(i).getFont();
1065 int const c = user_defined_bullet(i).getCharacter();
1071 features.require("latexsym");
1073 } else if (font == 1) {
1074 features.require("amssymb");
1075 } else if (font >= 2 && font <= 5) {
1076 features.require("pifont");
1080 if (pdfoptions().use_hyperref) {
1081 features.require("hyperref");
1082 // due to interferences with babel and hyperref, the color package has to
1083 // be loaded after hyperref when hyperref is used with the colorlinks
1084 // option, see http://www.lyx.org/trac/ticket/5291
1085 if (pdfoptions().colorlinks)
1086 features.require("color");
1090 features.require("xetex");
1092 if (language->lang() == "vietnamese")
1093 features.require("vietnamese");
1094 else if (language->lang() == "japanese")
1095 features.require("japanese");
1099 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1100 TexRow & texrow, FileName const & filepath) const
1102 os << "\\documentclass";
1104 DocumentClass const & tclass = documentClass();
1106 ostringstream clsoptions; // the document class options.
1108 if (tokenPos(tclass.opt_fontsize(),
1109 '|', fontsize) >= 0) {
1110 // only write if existing in list (and not default)
1111 clsoptions << fontsize << "pt,";
1114 // custom, A3, B3 and B4 paper sizes need geometry
1115 bool nonstandard_papersize = papersize == PAPER_B3
1116 || papersize == PAPER_B4
1117 || papersize == PAPER_A3
1118 || papersize == PAPER_CUSTOM;
1120 if (!use_geometry) {
1121 switch (papersize) {
1123 clsoptions << "a4paper,";
1125 case PAPER_USLETTER:
1126 clsoptions << "letterpaper,";
1129 clsoptions << "a5paper,";
1132 clsoptions << "b5paper,";
1134 case PAPER_USEXECUTIVE:
1135 clsoptions << "executivepaper,";
1138 clsoptions << "legalpaper,";
1150 if (sides != tclass.sides()) {
1153 clsoptions << "oneside,";
1156 clsoptions << "twoside,";
1162 if (columns != tclass.columns()) {
1164 clsoptions << "twocolumn,";
1166 clsoptions << "onecolumn,";
1170 && orientation == ORIENTATION_LANDSCAPE)
1171 clsoptions << "landscape,";
1173 // language should be a parameter to \documentclass
1174 if (language->babel() == "hebrew"
1175 && default_language->babel() != "hebrew")
1176 // This seems necessary
1177 features.useLanguage(default_language);
1179 ostringstream language_options;
1180 bool const use_babel = features.useBabel();
1182 language_options << features.getLanguages();
1183 if (!language->babel().empty()) {
1184 if (!language_options.str().empty())
1185 language_options << ',';
1186 language_options << language->babel();
1188 // if Vietnamese is used, babel must directly be loaded
1189 // with language options, not in the class options, see
1190 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1191 size_t viet = language_options.str().find("vietnam");
1192 // viet = string::npos when not found
1193 // the same is for all other languages that are not directly supported by
1194 // babel, but where LaTeX-packages add babel support.
1195 // this is currently the case for Latvian, Lithuanian, and Mongolian
1196 size_t latvian = language_options.str().find("latvian");
1197 size_t lithu = language_options.str().find("lithuanian");
1198 size_t mongo = language_options.str().find("mongolian");
1199 // if Japanese is used, babel must directly be loaded
1200 // with language options, not in the class options, see
1201 // http://www.lyx.org/trac/ticket/4597#c4
1202 size_t japan = language_options.str().find("japanese");
1203 if (lyxrc.language_global_options && !language_options.str().empty()
1204 && viet == string::npos && japan == string::npos
1205 && latvian == string::npos && lithu == string::npos
1206 && mongo == string::npos)
1207 clsoptions << language_options.str() << ',';
1210 // the predefined options from the layout
1211 if (use_default_options && !tclass.options().empty())
1212 clsoptions << tclass.options() << ',';
1214 // the user-defined options
1215 if (!options.empty()) {
1216 clsoptions << options << ',';
1219 string strOptions(clsoptions.str());
1220 if (!strOptions.empty()) {
1221 strOptions = rtrim(strOptions, ",");
1223 os << '[' << from_utf8(strOptions) << ']';
1226 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1228 // end of \documentclass defs
1231 os << "\\usepackage{fontspec}\n";
1235 // font selection must be done before loading fontenc.sty
1236 string const fonts =
1237 loadFonts(fontsRoman, fontsSans,
1238 fontsTypewriter, fontsSC, fontsOSF,
1239 fontsSansScale, fontsTypewriterScale, useXetex);
1240 if (!fonts.empty()) {
1241 os << from_ascii(fonts);
1244 if (fontsDefaultFamily != "default")
1245 os << "\\renewcommand{\\familydefault}{\\"
1246 << from_ascii(fontsDefaultFamily) << "}\n";
1248 // set font encoding
1249 // for arabic_arabi and farsi we also need to load the LAE and
1251 // XeTeX works without fontenc
1252 if (font_encoding() != "default" && language->lang() != "japanese"
1254 if (language->lang() == "arabic_arabi"
1255 || language->lang() == "farsi") {
1256 os << "\\usepackage[" << from_ascii(font_encoding())
1257 << ",LFE,LAE]{fontenc}\n";
1260 os << "\\usepackage[" << from_ascii(font_encoding())
1266 // handle inputenc etc.
1267 writeEncodingPreamble(os, features, texrow);
1270 if (!features.runparams().includeall && !includedChildren_.empty()) {
1271 os << "\\includeonly{";
1272 list<string>::const_iterator it = includedChildren_.begin();
1274 for (; it != includedChildren_.end() ; ++it) {
1275 string incfile = *it;
1276 FileName inc = makeAbsPath(incfile, filepath.absFilename());
1277 string mangled = DocFileName(changeExtension(inc.absFilename(), ".tex")).
1279 if (!features.runparams().nice)
1281 // \includeonly doesn't want an extension
1282 incfile = changeExtension(incfile, string());
1283 incfile = latex_path(incfile);
1284 if (!incfile.empty()) {
1287 os << from_utf8(incfile);
1294 if (!listings_params.empty() || features.isRequired("listings")) {
1295 os << "\\usepackage{listings}\n";
1298 if (!listings_params.empty()) {
1300 // do not test validity because listings_params is
1301 // supposed to be valid
1303 InsetListingsParams(listings_params).separatedParams(true);
1304 // we can't support all packages, but we should load the color package
1305 if (par.find("\\color", 0) != string::npos)
1306 features.require("color");
1307 os << from_utf8(par);
1308 // count the number of newlines
1309 for (size_t i = 0; i < par.size(); ++i)
1315 if (!tclass.provides("geometry")
1316 && (use_geometry || nonstandard_papersize)) {
1317 odocstringstream ods;
1318 if (!getGraphicsDriver("geometry").empty())
1319 ods << getGraphicsDriver("geometry");
1320 if (orientation == ORIENTATION_LANDSCAPE)
1321 ods << ",landscape";
1322 switch (papersize) {
1324 if (!paperwidth.empty())
1325 ods << ",paperwidth="
1326 << from_ascii(paperwidth);
1327 if (!paperheight.empty())
1328 ods << ",paperheight="
1329 << from_ascii(paperheight);
1331 case PAPER_USLETTER:
1332 ods << ",letterpaper";
1335 ods << ",legalpaper";
1337 case PAPER_USEXECUTIVE:
1338 ods << ",executivepaper";
1359 // default papersize ie PAPER_DEFAULT
1360 switch (lyxrc.default_papersize) {
1361 case PAPER_DEFAULT: // keep compiler happy
1362 case PAPER_USLETTER:
1363 ods << ",letterpaper";
1366 ods << ",legalpaper";
1368 case PAPER_USEXECUTIVE:
1369 ods << ",executivepaper";
1389 docstring const g_options = trim(ods.str(), ",");
1390 os << "\\usepackage";
1391 if (!g_options.empty())
1392 os << '[' << g_options << ']';
1393 os << "{geometry}\n";
1395 os << "\\geometry{verbose";
1396 if (!topmargin.empty())
1397 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1398 if (!bottommargin.empty())
1399 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1400 if (!leftmargin.empty())
1401 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1402 if (!rightmargin.empty())
1403 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1404 if (!headheight.empty())
1405 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1406 if (!headsep.empty())
1407 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1408 if (!footskip.empty())
1409 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1410 if (!columnsep.empty())
1411 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1414 } else if (orientation == ORIENTATION_LANDSCAPE) {
1415 features.require("papersize");
1418 if (tokenPos(tclass.opt_pagestyle(),
1419 '|', pagestyle) >= 0) {
1420 if (pagestyle == "fancy") {
1421 os << "\\usepackage{fancyhdr}\n";
1424 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1428 // only output when the background color is not white
1429 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1430 // only require color here, the background color will be defined
1431 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1433 features.require("color");
1434 features.require("pagecolor");
1437 // Only if class has a ToC hierarchy
1438 if (tclass.hasTocLevels()) {
1439 if (secnumdepth != tclass.secnumdepth()) {
1440 os << "\\setcounter{secnumdepth}{"
1445 if (tocdepth != tclass.tocdepth()) {
1446 os << "\\setcounter{tocdepth}{"
1453 if (paragraph_separation) {
1454 // when skip separation
1455 switch (getDefSkip().kind()) {
1456 case VSpace::SMALLSKIP:
1457 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1459 case VSpace::MEDSKIP:
1460 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1462 case VSpace::BIGSKIP:
1463 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1465 case VSpace::LENGTH:
1466 os << "\\setlength{\\parskip}{"
1467 << from_utf8(getDefSkip().length().asLatexString())
1470 default: // should never happen // Then delete it.
1471 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1475 os << "\\setlength{\\parindent}{0pt}\n";
1478 // when separation by indentation
1479 // only output something when a width is given
1480 if (getIndentation().asLyXCommand() != "default") {
1481 os << "\\setlength{\\parindent}{"
1482 << from_utf8(getIndentation().asLatexCommand())
1488 // Now insert the LyX specific LaTeX commands...
1489 docstring lyxpreamble;
1491 // due to interferences with babel and hyperref, the color package has to
1492 // be loaded (when it is not already loaded) before babel when hyperref
1493 // is used with the colorlinks option, see
1494 // http://www.lyx.org/trac/ticket/5291
1495 // we decided therefore to load color always before babel, see
1496 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1497 lyxpreamble += from_ascii(features.getColorOptions());
1499 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1501 && (features.isRequired("jurabib")
1502 || features.isRequired("hyperref")
1503 || features.isRequired("vietnamese")
1504 || features.isRequired("japanese") ) ) {
1506 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1507 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1510 // The optional packages;
1511 lyxpreamble += from_ascii(features.getPackages());
1513 // Additional Indices
1514 if (features.isRequired("splitidx")) {
1515 IndicesList::const_iterator iit = indiceslist().begin();
1516 IndicesList::const_iterator iend = indiceslist().end();
1517 for (; iit != iend; ++iit) {
1518 lyxpreamble += "\\newindex[";
1519 lyxpreamble += iit->index();
1520 lyxpreamble += "]{";
1521 lyxpreamble += iit->shortcut();
1522 lyxpreamble += "}\n";
1527 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1530 // * Hyperref manual: "Make sure it comes last of your loaded
1531 // packages, to give it a fighting chance of not being over-written,
1532 // since its job is to redefine many LaTeX commands."
1533 // * Email from Heiko Oberdiek: "It is usually better to load babel
1534 // before hyperref. Then hyperref has a chance to detect babel.
1535 // * Has to be loaded before the "LyX specific LaTeX commands" to
1536 // avoid errors with algorithm floats.
1537 // use hyperref explicitely when it is required
1538 if (features.isRequired("hyperref")) {
1539 odocstringstream oss;
1540 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1541 lyxpreamble += oss.str();
1544 // Will be surrounded by \makeatletter and \makeatother when not empty
1545 docstring atlyxpreamble;
1547 // Some macros LyX will need
1548 docstring tmppreamble(features.getMacros());
1550 if (!tmppreamble.empty())
1551 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1552 "LyX specific LaTeX commands.\n"
1553 + tmppreamble + '\n';
1555 // the text class specific preamble
1556 tmppreamble = features.getTClassPreamble();
1557 if (!tmppreamble.empty())
1558 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1559 "Textclass specific LaTeX commands.\n"
1560 + tmppreamble + '\n';
1562 // suppress date if selected
1563 // use \@ifundefined because we cannot be sure that every document class
1564 // has a \date command
1566 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1568 /* the user-defined preamble */
1569 if (!containsOnly(preamble, " \n\t"))
1571 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1572 "User specified LaTeX commands.\n"
1573 + from_utf8(preamble) + '\n';
1575 // subfig loads internally the LaTeX package "caption". As
1576 // caption is a very popular package, users will load it in
1577 // the preamble. Therefore we must load subfig behind the
1578 // user-defined preamble and check if the caption package was
1579 // loaded or not. For the case that caption is loaded before
1580 // subfig, there is the subfig option "caption=false". This
1581 // option also works when a koma-script class is used and
1582 // koma's own caption commands are used instead of caption. We
1583 // use \PassOptionsToPackage here because the user could have
1584 // already loaded subfig in the preamble.
1585 if (features.isRequired("subfig")) {
1586 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1587 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1588 "\\usepackage{subfig}\n";
1591 // Itemize bullet settings need to be last in case the user
1592 // defines their own bullets that use a package included
1593 // in the user-defined preamble -- ARRae
1594 // Actually it has to be done much later than that
1595 // since some packages like frenchb make modifications
1596 // at \begin{document} time -- JMarc
1597 docstring bullets_def;
1598 for (int i = 0; i < 4; ++i) {
1599 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1600 if (bullets_def.empty())
1601 bullets_def += "\\AtBeginDocument{\n";
1602 bullets_def += " \\def\\labelitemi";
1604 // `i' is one less than the item to modify
1611 bullets_def += "ii";
1617 bullets_def += '{' +
1618 user_defined_bullet(i).getText()
1623 if (!bullets_def.empty())
1624 atlyxpreamble += bullets_def + "}\n\n";
1626 if (!atlyxpreamble.empty())
1627 lyxpreamble += "\n\\makeatletter\n"
1628 + atlyxpreamble + "\\makeatother\n\n";
1630 // We try to load babel late, in case it interferes with other packages.
1631 // Jurabib and Hyperref have to be called after babel, though.
1632 if (use_babel && !features.isRequired("jurabib")
1633 && !features.isRequired("hyperref")
1634 && !features.isRequired("vietnamese")
1635 && !features.isRequired("japanese")) {
1637 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1638 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1641 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1642 if (!i18npreamble.empty())
1643 lyxpreamble += i18npreamble + '\n';
1646 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1647 for (int j = 0; j != nlines; ++j) {
1653 // these packages (xunicode, for that matter) need to be loaded at least
1654 // after amsmath, amssymb, esint and the other packages that provide
1657 os << "\\usepackage{xunicode}\n";
1659 os << "\\usepackage{xltxtra}\n";
1666 void BufferParams::useClassDefaults()
1668 DocumentClass const & tclass = documentClass();
1670 sides = tclass.sides();
1671 columns = tclass.columns();
1672 pagestyle = tclass.pagestyle();
1673 use_default_options = true;
1674 // Only if class has a ToC hierarchy
1675 if (tclass.hasTocLevels()) {
1676 secnumdepth = tclass.secnumdepth();
1677 tocdepth = tclass.tocdepth();
1682 bool BufferParams::hasClassDefaults() const
1684 DocumentClass const & tclass = documentClass();
1686 return sides == tclass.sides()
1687 && columns == tclass.columns()
1688 && pagestyle == tclass.pagestyle()
1689 && use_default_options
1690 && secnumdepth == tclass.secnumdepth()
1691 && tocdepth == tclass.tocdepth();
1695 DocumentClass const & BufferParams::documentClass() const
1701 DocumentClass const * BufferParams::documentClassPtr() const {
1706 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1707 // evil, but this function is evil
1708 doc_class_ = const_cast<DocumentClass *>(tc);
1712 bool BufferParams::setBaseClass(string const & classname)
1714 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1715 LayoutFileList & bcl = LayoutFileList::get();
1716 if (!bcl.haveClass(classname)) {
1718 bformat(_("The document class %1$s could not be found. "
1719 "A default textclass with default layouts will be used. "
1720 "LyX might not be able to produce output unless a correct "
1721 "textclass is selected from the document settings dialog."),
1722 from_utf8(classname));
1723 frontend::Alert::error(_("Document class not found"), s);
1724 bcl.addEmptyClass(classname);
1727 bool const success = bcl[classname].load();
1730 bformat(_("The document class %1$s could not be loaded."),
1731 from_utf8(classname));
1732 frontend::Alert::error(_("Could not load class"), s);
1736 pimpl_->baseClass_ = classname;
1737 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1742 LayoutFile const * BufferParams::baseClass() const
1744 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1745 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1751 LayoutFileIndex const & BufferParams::baseClassID() const
1753 return pimpl_->baseClass_;
1757 void BufferParams::makeDocumentClass()
1762 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1764 if (!local_layout.empty()) {
1765 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1766 docstring const msg = _("Error reading internal layout information");
1767 frontend::Alert::warning(_("Read Error"), msg);
1772 bool BufferParams::moduleCanBeAdded(string const & modName) const
1774 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1778 bool BufferParams::addLayoutModule(string const & modName)
1780 LayoutModuleList::const_iterator it = layoutModules_.begin();
1781 LayoutModuleList::const_iterator end = layoutModules_.end();
1782 for (; it != end; it++)
1785 layoutModules_.push_back(modName);
1790 Font const BufferParams::getFont() const
1792 FontInfo f = documentClass().defaultfont();
1793 if (fontsDefaultFamily == "rmdefault")
1794 f.setFamily(ROMAN_FAMILY);
1795 else if (fontsDefaultFamily == "sfdefault")
1796 f.setFamily(SANS_FAMILY);
1797 else if (fontsDefaultFamily == "ttdefault")
1798 f.setFamily(TYPEWRITER_FAMILY);
1799 return Font(f, language);
1803 void BufferParams::readPreamble(Lexer & lex)
1805 if (lex.getString() != "\\begin_preamble")
1806 lyxerr << "Error (BufferParams::readPreamble):"
1807 "consistency check failed." << endl;
1809 preamble = lex.getLongString("\\end_preamble");
1813 void BufferParams::readLocalLayout(Lexer & lex)
1815 if (lex.getString() != "\\begin_local_layout")
1816 lyxerr << "Error (BufferParams::readLocalLayout):"
1817 "consistency check failed." << endl;
1819 local_layout = lex.getLongString("\\end_local_layout");
1823 void BufferParams::readLanguage(Lexer & lex)
1825 if (!lex.next()) return;
1827 string const tmptok = lex.getString();
1829 // check if tmptok is part of tex_babel in tex-defs.h
1830 language = languages.getLanguage(tmptok);
1832 // Language tmptok was not found
1833 language = default_language;
1834 lyxerr << "Warning: Setting language `"
1835 << tmptok << "' to `" << language->lang()
1841 void BufferParams::readGraphicsDriver(Lexer & lex)
1846 string const tmptok = lex.getString();
1847 // check if tmptok is part of tex_graphics in tex_defs.h
1850 string const test = tex_graphics[n++];
1852 if (test == tmptok) {
1853 graphicsDriver = tmptok;
1858 "Warning: graphics driver `$$Token' not recognized!\n"
1859 " Setting graphics driver to `default'.\n");
1860 graphicsDriver = "default";
1867 void BufferParams::readBullets(Lexer & lex)
1872 int const index = lex.getInteger();
1874 int temp_int = lex.getInteger();
1875 user_defined_bullet(index).setFont(temp_int);
1876 temp_bullet(index).setFont(temp_int);
1878 user_defined_bullet(index).setCharacter(temp_int);
1879 temp_bullet(index).setCharacter(temp_int);
1881 user_defined_bullet(index).setSize(temp_int);
1882 temp_bullet(index).setSize(temp_int);
1886 void BufferParams::readBulletsLaTeX(Lexer & lex)
1888 // The bullet class should be able to read this.
1891 int const index = lex.getInteger();
1893 docstring const temp_str = lex.getDocString();
1895 user_defined_bullet(index).setText(temp_str);
1896 temp_bullet(index).setText(temp_str);
1900 void BufferParams::readModules(Lexer & lex)
1902 if (!lex.eatLine()) {
1903 lyxerr << "Error (BufferParams::readModules):"
1904 "Unexpected end of input." << endl;
1908 string mod = lex.getString();
1909 if (mod == "\\end_modules")
1911 addLayoutModule(mod);
1917 void BufferParams::readRemovedModules(Lexer & lex)
1919 if (!lex.eatLine()) {
1920 lyxerr << "Error (BufferParams::readRemovedModules):"
1921 "Unexpected end of input." << endl;
1925 string mod = lex.getString();
1926 if (mod == "\\end_removed_modules")
1928 removedModules_.push_back(mod);
1931 // now we want to remove any removed modules that were previously
1932 // added. normally, that will be because default modules were added in
1933 // setBaseClass(), which gets called when \textclass is read at the
1934 // start of the read.
1935 list<string>::const_iterator rit = removedModules_.begin();
1936 list<string>::const_iterator const ren = removedModules_.end();
1937 for (; rit != ren; rit++) {
1938 LayoutModuleList::iterator const mit = layoutModules_.begin();
1939 LayoutModuleList::iterator const men = layoutModules_.end();
1940 LayoutModuleList::iterator found = find(mit, men, *rit);
1943 layoutModules_.erase(found);
1948 void BufferParams::readIncludeonly(Lexer & lex)
1950 if (!lex.eatLine()) {
1951 lyxerr << "Error (BufferParams::readIncludeonly):"
1952 "Unexpected end of input." << endl;
1956 string child = lex.getString();
1957 if (child == "\\end_includeonly")
1959 includedChildren_.push_back(child);
1965 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1967 char real_papersize = papersize;
1968 if (real_papersize == PAPER_DEFAULT)
1969 real_papersize = lyxrc.default_papersize;
1971 switch (real_papersize) {
1973 // could be anything, so don't guess
1975 case PAPER_CUSTOM: {
1976 if (purpose == XDVI && !paperwidth.empty() &&
1977 !paperheight.empty()) {
1978 // heightxwidth<unit>
1979 string first = paperwidth;
1980 string second = paperheight;
1981 if (orientation == ORIENTATION_LANDSCAPE)
1984 return first.erase(first.length() - 2)
1996 // dvips and dvipdfm do not know this
1997 if (purpose == DVIPS || purpose == DVIPDFM)
2001 // dvipdfm does not know this
2002 if (purpose == DVIPDFM)
2006 // dvipdfm does not know this
2007 if (purpose == DVIPDFM)
2010 case PAPER_USEXECUTIVE:
2011 // dvipdfm does not know this
2012 if (purpose == DVIPDFM)
2017 case PAPER_USLETTER:
2019 if (purpose == XDVI)
2026 string const BufferParams::dvips_options() const
2031 && papersize == PAPER_CUSTOM
2032 && !lyxrc.print_paper_dimension_flag.empty()
2033 && !paperwidth.empty()
2034 && !paperheight.empty()) {
2035 // using a custom papersize
2036 result = lyxrc.print_paper_dimension_flag;
2037 result += ' ' + paperwidth;
2038 result += ',' + paperheight;
2040 string const paper_option = paperSizeName(DVIPS);
2041 if (!paper_option.empty() && (paper_option != "letter" ||
2042 orientation != ORIENTATION_LANDSCAPE)) {
2043 // dvips won't accept -t letter -t landscape.
2044 // In all other cases, include the paper size
2046 result = lyxrc.print_paper_flag;
2047 result += ' ' + paper_option;
2050 if (orientation == ORIENTATION_LANDSCAPE &&
2051 papersize != PAPER_CUSTOM)
2052 result += ' ' + lyxrc.print_landscape_flag;
2057 string const BufferParams::font_encoding() const
2059 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2063 string BufferParams::babelCall(string const & lang_opts) const
2065 string lang_pack = lyxrc.language_package;
2066 if (lang_pack != "\\usepackage{babel}")
2068 // suppress the babel call when there is no babel language defined
2069 // for the document language in the lib/languages file and if no
2070 // other languages are used (lang_opts is then empty)
2071 if (lang_opts.empty())
2073 // If Vietnamese is used, babel must directly be loaded with the
2074 // language options, see
2075 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2076 size_t viet = lang_opts.find("vietnam");
2077 // viet = string::npos when not found
2078 // the same is for all other languages that are not directly supported by
2079 // babel, but where LaTeX-packages add babel support.
2080 // this is currently the case for Latvian, Lithuanian, and Mongolian
2081 size_t latvian = lang_opts.find("latvian");
2082 size_t lithu = lang_opts.find("lithuanian");
2083 size_t mongo = lang_opts.find("mongolian");
2084 // If Japanese is used, babel must directly be loaded with the
2085 // language options, see
2086 // http://www.lyx.org/trac/ticket/4597#c4
2087 size_t japan = lang_opts.find("japanese");
2088 if (!lyxrc.language_global_options || viet != string::npos
2089 || japan != string::npos || latvian != string::npos
2090 || lithu != string::npos || mongo != string::npos)
2091 return "\\usepackage[" + lang_opts + "]{babel}";
2096 docstring BufferParams::getGraphicsDriver(string const & package) const
2100 if (package == "geometry") {
2101 if (graphicsDriver == "dvips"
2102 || graphicsDriver == "dvipdfm"
2103 || graphicsDriver == "pdftex"
2104 || graphicsDriver == "vtex")
2105 result = from_ascii(graphicsDriver);
2106 else if (graphicsDriver == "dvipdfmx")
2107 result = from_ascii("dvipdfm");
2114 void BufferParams::writeEncodingPreamble(odocstream & os,
2115 LaTeXFeatures & features, TexRow & texrow) const
2119 if (inputenc == "auto") {
2120 string const doc_encoding =
2121 language->encoding()->latexName();
2122 Encoding::Package const package =
2123 language->encoding()->package();
2125 // Create a list with all the input encodings used
2127 set<string> encodings =
2128 features.getEncodingSet(doc_encoding);
2130 // If the "japanese" package (i.e. pLaTeX) is used,
2131 // inputenc must be omitted.
2132 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2133 if (package == Encoding::japanese)
2134 features.require("japanese");
2136 if ((!encodings.empty() || package == Encoding::inputenc)
2137 && !features.isRequired("japanese")) {
2138 os << "\\usepackage[";
2139 set<string>::const_iterator it = encodings.begin();
2140 set<string>::const_iterator const end = encodings.end();
2142 os << from_ascii(*it);
2145 for (; it != end; ++it)
2146 os << ',' << from_ascii(*it);
2147 if (package == Encoding::inputenc) {
2148 if (!encodings.empty())
2150 os << from_ascii(doc_encoding);
2152 os << "]{inputenc}\n";
2155 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2156 if (language->encoding()->name() == "utf8-cjk"
2157 && LaTeXFeatures::isAvailable("CJKutf8"))
2158 os << "\\usepackage{CJKutf8}\n";
2160 os << "\\usepackage{CJK}\n";
2163 } else if (inputenc != "default") {
2164 switch (encoding().package()) {
2165 case Encoding::none:
2166 case Encoding::japanese:
2168 case Encoding::inputenc:
2169 // do not load inputenc if japanese is used
2170 if (features.isRequired("japanese"))
2172 os << "\\usepackage[" << from_ascii(inputenc)
2177 if (encoding().name() == "utf8-cjk"
2178 && LaTeXFeatures::isAvailable("CJKutf8"))
2179 os << "\\usepackage{CJKutf8}\n";
2181 os << "\\usepackage{CJK}\n";
2187 // The encoding "armscii8" (for Armenian) is only available when
2188 // the package "armtex" is loaded.
2189 if (language->encoding()->latexName() == "armscii8"
2190 || inputenc == "armscii8") {
2191 os << "\\usepackage{armtex}\n";
2197 string const BufferParams::parseFontName(string const & name) const
2199 string mangled = name;
2200 size_t const idx = mangled.find('[');
2201 if (idx == string::npos || idx == 0)
2204 return mangled.substr(0, idx - 1);
2208 string const BufferParams::loadFonts(string const & rm,
2209 string const & sf, string const & tt,
2210 bool const & sc, bool const & osf,
2211 int const & sfscale, int const & ttscale,
2212 bool const & xetex) const
2214 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2215 several packages have been replaced by others, that might not
2216 be installed on every system. We have to take care for that
2217 (see psnfss.pdf). We try to support all psnfss fonts as well
2218 as the fonts that have become de facto standard in the LaTeX
2219 world (e.g. Latin Modern). We do not support obsolete fonts
2220 (like PSLatex). In general, it should be possible to mix any
2221 rm font with any sf or tt font, respectively. (JSpitzm)
2223 -- separate math fonts.
2226 if (rm == "default" && sf == "default" && tt == "default")
2233 if (rm != "default")
2234 os << "\\setmainfont[Mapping=tex-text]{"
2235 << parseFontName(rm) << "}\n";
2236 if (sf != "default") {
2237 string const sans = parseFontName(sf);
2239 os << "\\setsansfont[Scale="
2240 << float(sfscale) / 100
2241 << ",Mapping=tex-text]{"
2244 os << "\\setsansfont[Mapping=tex-text]{"
2247 if (tt != "default") {
2248 string const mono = parseFontName(tt);
2250 os << "\\setmonofont[Scale="
2251 << float(sfscale) / 100
2255 os << "\\setmonofont[Mapping=tex-text]{"
2259 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2264 // Computer Modern (must be explicitely selectable -- there might be classes
2265 // that define a different default font!
2267 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2268 // osf for Computer Modern needs eco.sty
2270 os << "\\usepackage{eco}\n";
2272 // Latin Modern Roman
2273 else if (rm == "lmodern")
2274 os << "\\usepackage{lmodern}\n";
2276 else if (rm == "ae") {
2277 // not needed when using OT1 font encoding.
2278 if (font_encoding() != "default")
2279 os << "\\usepackage{ae,aecompl}\n";
2282 else if (rm == "times") {
2283 // try to load the best available package
2284 if (LaTeXFeatures::isAvailable("mathptmx"))
2285 os << "\\usepackage{mathptmx}\n";
2286 else if (LaTeXFeatures::isAvailable("mathptm"))
2287 os << "\\usepackage{mathptm}\n";
2289 os << "\\usepackage{times}\n";
2292 else if (rm == "palatino") {
2293 // try to load the best available package
2294 if (LaTeXFeatures::isAvailable("mathpazo")) {
2295 os << "\\usepackage";
2301 // "osf" includes "sc"!
2305 os << "{mathpazo}\n";
2307 else if (LaTeXFeatures::isAvailable("mathpple"))
2308 os << "\\usepackage{mathpple}\n";
2310 os << "\\usepackage{palatino}\n";
2313 else if (rm == "utopia") {
2314 // fourier supersedes utopia.sty, but does
2315 // not work with OT1 encoding.
2316 if (LaTeXFeatures::isAvailable("fourier")
2317 && font_encoding() != "default") {
2318 os << "\\usepackage";
2329 os << "{fourier}\n";
2332 os << "\\usepackage{utopia}\n";
2334 // Bera (complete fontset)
2335 else if (rm == "bera" && sf == "default" && tt == "default")
2336 os << "\\usepackage{bera}\n";
2338 else if (rm != "default")
2339 os << "\\usepackage" << "{" << rm << "}\n";
2342 // Helvetica, Bera Sans
2343 if (sf == "helvet" || sf == "berasans") {
2345 os << "\\usepackage[scaled=" << float(sfscale) / 100
2346 << "]{" << sf << "}\n";
2348 os << "\\usepackage{" << sf << "}\n";
2351 else if (sf == "avant")
2352 os << "\\usepackage{" << sf << "}\n";
2353 // Computer Modern, Latin Modern, CM Bright
2354 else if (sf != "default")
2355 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2357 // monospaced/typewriter
2358 // Courier, LuxiMono
2359 if (tt == "luximono" || tt == "beramono") {
2361 os << "\\usepackage[scaled=" << float(ttscale) / 100
2362 << "]{" << tt << "}\n";
2364 os << "\\usepackage{" << tt << "}\n";
2367 else if (tt == "courier" )
2368 os << "\\usepackage{" << tt << "}\n";
2369 // Computer Modern, Latin Modern, CM Bright
2370 else if (tt != "default")
2371 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2377 Encoding const & BufferParams::encoding() const
2380 return *(encodings.fromLaTeXName("utf8-plain"));
2381 if (inputenc == "auto" || inputenc == "default")
2382 return *language->encoding();
2383 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2386 LYXERR0("Unknown inputenc value `" << inputenc
2387 << "'. Using `auto' instead.");
2388 return *language->encoding();
2392 CiteEngine BufferParams::citeEngine() const
2394 // FIXME the class should provide the numerical/
2395 // authoryear choice
2396 if (documentClass().provides("natbib")
2397 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2398 return ENGINE_NATBIB_AUTHORYEAR;
2399 return cite_engine_;
2403 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2405 cite_engine_ = cite_engine;