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;
348 language = default_language;
350 fontsRoman = "default";
351 fontsSans = "default";
352 fontsTypewriter = "default";
353 fontsDefaultFamily = "default";
357 fontsSansScale = 100;
358 fontsTypewriterScale = 100;
360 graphicsDriver = "default";
361 defaultOutputFormat = "default";
362 bibtex_command = "default";
363 index_command = "default";
366 listings_params = string();
367 pagestyle = "default";
368 suppress_date = false;
369 // white is equal to no background color
370 backgroundcolor = lyx::rgbFromHexName("#ffffff");
372 for (int iter = 0; iter < 4; ++iter) {
373 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
374 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
377 indiceslist().addDefault(B_("Index"));
378 html_be_strict = true;
379 html_use_mathml = true;
383 docstring BufferParams::B_(string const & l10n) const
385 LASSERT(language, /**/);
386 return getMessages(language->code()).get(l10n);
390 AuthorList & BufferParams::authors()
392 return pimpl_->authorlist;
396 AuthorList const & BufferParams::authors() const
398 return pimpl_->authorlist;
402 BranchList & BufferParams::branchlist()
404 return pimpl_->branchlist;
408 BranchList const & BufferParams::branchlist() const
410 return pimpl_->branchlist;
414 IndicesList & BufferParams::indiceslist()
416 return pimpl_->indiceslist;
420 IndicesList const & BufferParams::indiceslist() const
422 return pimpl_->indiceslist;
426 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
428 LASSERT(index < 4, /**/);
429 return pimpl_->temp_bullets[index];
433 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
435 LASSERT(index < 4, /**/);
436 return pimpl_->temp_bullets[index];
440 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
442 LASSERT(index < 4, /**/);
443 return pimpl_->user_defined_bullets[index];
447 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
449 LASSERT(index < 4, /**/);
450 return pimpl_->user_defined_bullets[index];
454 Spacing & BufferParams::spacing()
456 return pimpl_->spacing;
460 Spacing const & BufferParams::spacing() const
462 return pimpl_->spacing;
466 PDFOptions & BufferParams::pdfoptions()
468 return pimpl_->pdfoptions;
472 PDFOptions const & BufferParams::pdfoptions() const
474 return pimpl_->pdfoptions;
478 HSpace const & BufferParams::getIndentation() const
480 return pimpl_->indentation;
484 void BufferParams::setIndentation(HSpace const & indent)
486 pimpl_->indentation = indent;
490 VSpace const & BufferParams::getDefSkip() const
492 return pimpl_->defskip;
496 void BufferParams::setDefSkip(VSpace const & vs)
498 pimpl_->defskip = vs;
502 string BufferParams::readToken(Lexer & lex, string const & token,
503 FileName const & filepath)
505 if (token == "\\textclass") {
507 string const classname = lex.getString();
508 // if there exists a local layout file, ignore the system one
509 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
511 LayoutFileList & bcl = LayoutFileList::get();
512 if (tcp.empty() && !filepath.empty())
513 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
517 setBaseClass(classname);
518 // We assume that a tex class exists for local or unknown layouts so this warning
519 // will only be given for system layouts.
520 if (!baseClass()->isTeXClassAvailable()) {
521 docstring const msg =
522 bformat(_("The layout file requested by this document,\n"
524 "is not usable. This is probably because a LaTeX\n"
525 "class or style file required by it is not\n"
526 "available. See the Customization documentation\n"
527 "for more information.\n"), from_utf8(classname));
528 frontend::Alert::warning(_("Document class not available"),
529 msg + _("LyX will not be able to produce output."));
531 } else if (token == "\\begin_preamble") {
533 } else if (token == "\\begin_local_layout") {
534 readLocalLayout(lex);
535 } else if (token == "\\begin_modules") {
537 } else if (token == "\\begin_removed_modules") {
538 readRemovedModules(lex);
539 } else if (token == "\\begin_includeonly") {
540 readIncludeonly(lex);
541 } else if (token == "\\options") {
543 options = lex.getString();
544 } else if (token == "\\use_default_options") {
545 lex >> use_default_options;
546 } else if (token == "\\master") {
548 master = lex.getString();
549 } else if (token == "\\suppress_date") {
550 lex >> suppress_date;
551 } else if (token == "\\language") {
553 } else if (token == "\\inputencoding") {
555 } else if (token == "\\graphics") {
556 readGraphicsDriver(lex);
557 } else if (token == "\\default_output_format") {
558 lex >> defaultOutputFormat;
559 } else if (token == "\\bibtex_command") {
561 bibtex_command = lex.getString();
562 } else if (token == "\\index_command") {
564 index_command = lex.getString();
565 } else if (token == "\\fontencoding") {
567 fontenc = lex.getString();
568 } else if (token == "\\font_roman") {
570 fontsRoman = lex.getString();
571 } else if (token == "\\font_sans") {
573 fontsSans = lex.getString();
574 } else if (token == "\\font_typewriter") {
576 fontsTypewriter = lex.getString();
577 } else if (token == "\\font_default_family") {
578 lex >> fontsDefaultFamily;
579 } else if (token == "\\use_xetex") {
581 } else if (token == "\\font_sc") {
583 } else if (token == "\\font_osf") {
585 } else if (token == "\\font_sf_scale") {
586 lex >> fontsSansScale;
587 } else if (token == "\\font_tt_scale") {
588 lex >> fontsTypewriterScale;
589 } else if (token == "\\font_cjk") {
591 } else if (token == "\\paragraph_separation") {
594 paragraph_separation = parseptranslator().find(parsep);
595 } else if (token == "\\paragraph_indentation") {
597 string indentation = lex.getString();
598 pimpl_->indentation = HSpace(indentation);
599 } else if (token == "\\defskip") {
601 string defskip = lex.getString();
602 if (defskip == "defskip")
605 pimpl_->defskip = VSpace(defskip);
606 } else if (token == "\\quotes_language") {
609 quotes_language = quoteslangtranslator().find(quotes_lang);
610 } else if (token == "\\papersize") {
613 papersize = papersizetranslator().find(ppsize);
614 } else if (token == "\\use_geometry") {
616 } else if (token == "\\use_amsmath") {
619 use_amsmath = packagetranslator().find(use_ams);
620 } else if (token == "\\use_esint") {
623 use_esint = packagetranslator().find(useesint);
624 } else if (token == "\\use_mhchem") {
627 use_mhchem = packagetranslator().find(usemhchem);
628 } else if (token == "\\cite_engine") {
631 cite_engine_ = citeenginetranslator().find(engine);
632 } else if (token == "\\use_bibtopic") {
634 } else if (token == "\\use_indices") {
636 } else if (token == "\\tracking_changes") {
638 } else if (token == "\\output_changes") {
639 lex >> outputChanges;
640 } else if (token == "\\branch") {
642 docstring branch = lex.getDocString();
643 branchlist().add(branch);
646 string const tok = lex.getString();
647 if (tok == "\\end_branch")
649 Branch * branch_ptr = branchlist().find(branch);
650 if (tok == "\\selected") {
653 branch_ptr->setSelected(lex.getInteger());
655 if (tok == "\\filename_suffix") {
658 branch_ptr->setFilenameSuffix(lex.getInteger());
660 if (tok == "\\color") {
662 string color = lex.getString();
664 branch_ptr->setColor(color);
665 // Update also the Color table:
667 color = lcolor.getX11Name(Color_background);
669 lcolor.setColor(to_utf8(branch), color);
672 } else if (token == "\\index") {
674 docstring index = lex.getDocString();
676 indiceslist().add(index);
679 string const tok = lex.getString();
680 if (tok == "\\end_index")
682 Index * index_ptr = indiceslist().find(index);
683 if (tok == "\\shortcut") {
685 shortcut = lex.getDocString();
687 index_ptr->setShortcut(shortcut);
689 if (tok == "\\color") {
691 string color = lex.getString();
693 index_ptr->setColor(color);
694 // Update also the Color table:
696 color = lcolor.getX11Name(Color_background);
698 if (!shortcut.empty())
699 lcolor.setColor(to_utf8(shortcut), color);
702 } else if (token == "\\author") {
704 istringstream ss(lex.getString());
707 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
708 } else if (token == "\\paperorientation") {
711 orientation = paperorientationtranslator().find(orient);
712 } else if (token == "\\backgroundcolor") {
714 backgroundcolor = lyx::rgbFromHexName(lex.getString());
715 } else if (token == "\\paperwidth") {
717 } else if (token == "\\paperheight") {
719 } else if (token == "\\leftmargin") {
721 } else if (token == "\\topmargin") {
723 } else if (token == "\\rightmargin") {
725 } else if (token == "\\bottommargin") {
727 } else if (token == "\\headheight") {
729 } else if (token == "\\headsep") {
731 } else if (token == "\\footskip") {
733 } else if (token == "\\columnsep") {
735 } else if (token == "\\paperfontsize") {
737 } else if (token == "\\papercolumns") {
739 } else if (token == "\\listings_params") {
742 listings_params = InsetListingsParams(par).params();
743 } else if (token == "\\papersides") {
746 sides = sidestranslator().find(psides);
747 } else if (token == "\\paperpagestyle") {
749 } else if (token == "\\bullet") {
751 } else if (token == "\\bulletLaTeX") {
752 readBulletsLaTeX(lex);
753 } else if (token == "\\secnumdepth") {
755 } else if (token == "\\tocdepth") {
757 } else if (token == "\\spacing") {
761 if (nspacing == "other") {
764 spacing().set(spacetranslator().find(nspacing), tmp_val);
765 } else if (token == "\\float_placement") {
766 lex >> float_placement;
768 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
769 string toktmp = pdfoptions().readToken(lex, token);
770 if (!toktmp.empty()) {
771 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
775 } else if (token == "\\html_use_mathml") {
776 lex >> html_use_mathml;
777 } else if (token == "\\html_be_strict") {
778 lex >> html_be_strict;
780 lyxerr << "BufferParams::readToken(): Unknown token: " <<
789 void BufferParams::writeFile(ostream & os) const
791 // The top of the file is written by the buffer.
792 // Prints out the buffer info into the .lyx file given by file
795 os << "\\textclass " << baseClass()->name() << '\n';
798 if (!preamble.empty()) {
799 // remove '\n' from the end of preamble
800 string const tmppreamble = rtrim(preamble, "\n");
801 os << "\\begin_preamble\n"
803 << "\n\\end_preamble\n";
807 if (!options.empty()) {
808 os << "\\options " << options << '\n';
811 // use the class options defined in the layout?
812 os << "\\use_default_options "
813 << convert<string>(use_default_options) << "\n";
815 // the master document
816 if (!master.empty()) {
817 os << "\\master " << master << '\n';
821 if (!removedModules_.empty()) {
822 os << "\\begin_removed_modules" << '\n';
823 list<string>::const_iterator it = removedModules_.begin();
824 list<string>::const_iterator en = removedModules_.end();
825 for (; it != en; it++)
827 os << "\\end_removed_modules" << '\n';
831 if (!layoutModules_.empty()) {
832 os << "\\begin_modules" << '\n';
833 LayoutModuleList::const_iterator it = layoutModules_.begin();
834 LayoutModuleList::const_iterator en = layoutModules_.end();
835 for (; it != en; it++)
837 os << "\\end_modules" << '\n';
841 if (!includedChildren_.empty()) {
842 os << "\\begin_includeonly" << '\n';
843 list<string>::const_iterator it = includedChildren_.begin();
844 list<string>::const_iterator en = includedChildren_.end();
845 for (; it != en; it++)
847 os << "\\end_includeonly" << '\n';
850 // local layout information
851 if (!local_layout.empty()) {
852 // remove '\n' from the end
853 string const tmplocal = rtrim(local_layout, "\n");
854 os << "\\begin_local_layout\n"
856 << "\n\\end_local_layout\n";
859 // then the text parameters
860 if (language != ignore_language)
861 os << "\\language " << language->lang() << '\n';
862 os << "\\inputencoding " << inputenc
863 << "\n\\fontencoding " << fontenc
864 << "\n\\font_roman " << fontsRoman
865 << "\n\\font_sans " << fontsSans
866 << "\n\\font_typewriter " << fontsTypewriter
867 << "\n\\font_default_family " << fontsDefaultFamily
868 << "\n\\use_xetex " << convert<string>(useXetex)
869 << "\n\\font_sc " << convert<string>(fontsSC)
870 << "\n\\font_osf " << convert<string>(fontsOSF)
871 << "\n\\font_sf_scale " << fontsSansScale
872 << "\n\\font_tt_scale " << fontsTypewriterScale
874 if (!fontsCJK.empty()) {
875 os << "\\font_cjk " << fontsCJK << '\n';
877 os << "\n\\graphics " << graphicsDriver << '\n';
878 os << "\\default_output_format " << defaultOutputFormat << '\n';
879 os << "\\bibtex_command " << bibtex_command << '\n';
880 os << "\\index_command " << index_command << '\n';
882 if (!float_placement.empty()) {
883 os << "\\float_placement " << float_placement << '\n';
885 os << "\\paperfontsize " << fontsize << '\n';
887 spacing().writeFile(os);
888 pdfoptions().writeFile(os);
890 os << "\\papersize " << string_papersize[papersize]
891 << "\n\\use_geometry " << convert<string>(use_geometry)
892 << "\n\\use_amsmath " << use_amsmath
893 << "\n\\use_esint " << use_esint
894 << "\n\\use_mhchem " << use_mhchem
895 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
896 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
897 << "\n\\use_indices " << convert<string>(use_indices)
898 << "\n\\paperorientation " << string_orientation[orientation]
899 << "\n\\suppress_date " << convert<string>(suppress_date)
901 if (backgroundcolor != lyx::rgbFromHexName("#ffffff"))
902 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
904 BranchList::const_iterator it = branchlist().begin();
905 BranchList::const_iterator end = branchlist().end();
906 for (; it != end; ++it) {
907 os << "\\branch " << to_utf8(it->branch())
908 << "\n\\selected " << it->isSelected()
909 << "\n\\filename_suffix " << it->hasFilenameSuffix()
910 << "\n\\color " << lyx::X11hexname(it->color())
915 IndicesList::const_iterator iit = indiceslist().begin();
916 IndicesList::const_iterator iend = indiceslist().end();
917 for (; iit != iend; ++iit) {
918 os << "\\index " << to_utf8(iit->index())
919 << "\n\\shortcut " << to_utf8(iit->shortcut())
920 << "\n\\color " << lyx::X11hexname(iit->color())
925 if (!paperwidth.empty())
926 os << "\\paperwidth "
927 << VSpace(paperwidth).asLyXCommand() << '\n';
928 if (!paperheight.empty())
929 os << "\\paperheight "
930 << VSpace(paperheight).asLyXCommand() << '\n';
931 if (!leftmargin.empty())
932 os << "\\leftmargin "
933 << VSpace(leftmargin).asLyXCommand() << '\n';
934 if (!topmargin.empty())
936 << VSpace(topmargin).asLyXCommand() << '\n';
937 if (!rightmargin.empty())
938 os << "\\rightmargin "
939 << VSpace(rightmargin).asLyXCommand() << '\n';
940 if (!bottommargin.empty())
941 os << "\\bottommargin "
942 << VSpace(bottommargin).asLyXCommand() << '\n';
943 if (!headheight.empty())
944 os << "\\headheight "
945 << VSpace(headheight).asLyXCommand() << '\n';
946 if (!headsep.empty())
948 << VSpace(headsep).asLyXCommand() << '\n';
949 if (!footskip.empty())
951 << VSpace(footskip).asLyXCommand() << '\n';
952 if (!columnsep.empty())
954 << VSpace(columnsep).asLyXCommand() << '\n';
955 os << "\\secnumdepth " << secnumdepth
956 << "\n\\tocdepth " << tocdepth
957 << "\n\\paragraph_separation "
958 << string_paragraph_separation[paragraph_separation];
959 if (!paragraph_separation)
960 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
962 os << "\n\\defskip " << getDefSkip().asLyXCommand();
963 os << "\n\\quotes_language "
964 << string_quotes_language[quotes_language]
965 << "\n\\papercolumns " << columns
966 << "\n\\papersides " << sides
967 << "\n\\paperpagestyle " << pagestyle << '\n';
968 if (!listings_params.empty())
969 os << "\\listings_params \"" <<
970 InsetListingsParams(listings_params).encodedString() << "\"\n";
971 for (int i = 0; i < 4; ++i) {
972 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
973 if (user_defined_bullet(i).getFont() != -1) {
974 os << "\\bullet " << i << " "
975 << user_defined_bullet(i).getFont() << " "
976 << user_defined_bullet(i).getCharacter() << " "
977 << user_defined_bullet(i).getSize() << "\n";
981 os << "\\bulletLaTeX " << i << " \""
982 << lyx::to_ascii(user_defined_bullet(i).getText())
988 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n"
989 << "\\output_changes " << convert<string>(outputChanges) << "\n"
990 << "\\html_use_mathml " << convert<string>(html_use_mathml) << "\n"
991 << "\\html_be_strict " << convert<string>(html_be_strict) << "\n";
993 os << pimpl_->authorlist;
997 void BufferParams::validate(LaTeXFeatures & features) const
999 features.require(documentClass().requires());
1001 if (outputChanges) {
1002 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1003 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1004 LaTeXFeatures::isAvailable("xcolor");
1006 switch (features.runparams().flavor) {
1007 case OutputParams::LATEX:
1009 features.require("ct-dvipost");
1010 features.require("dvipost");
1011 } else if (xcolorulem) {
1012 features.require("ct-xcolor-ulem");
1013 features.require("ulem");
1014 features.require("xcolor");
1016 features.require("ct-none");
1019 case OutputParams::PDFLATEX:
1020 case OutputParams::XETEX:
1022 features.require("ct-xcolor-ulem");
1023 features.require("ulem");
1024 features.require("xcolor");
1025 // improves color handling in PDF output
1026 features.require("pdfcolmk");
1028 features.require("ct-none");
1036 // Floats with 'Here definitely' as default setting.
1037 if (float_placement.find('H') != string::npos)
1038 features.require("float");
1040 // AMS Style is at document level
1041 if (use_amsmath == package_on
1042 || documentClass().provides("amsmath"))
1043 features.require("amsmath");
1044 if (use_esint == package_on)
1045 features.require("esint");
1046 if (use_mhchem == package_on)
1047 features.require("mhchem");
1049 // Document-level line spacing
1050 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1051 features.require("setspace");
1053 // the bullet shapes are buffer level not paragraph level
1054 // so they are tested here
1055 for (int i = 0; i < 4; ++i) {
1056 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1058 int const font = user_defined_bullet(i).getFont();
1060 int const c = user_defined_bullet(i).getCharacter();
1066 features.require("latexsym");
1068 } else if (font == 1) {
1069 features.require("amssymb");
1070 } else if (font >= 2 && font <= 5) {
1071 features.require("pifont");
1075 if (pdfoptions().use_hyperref) {
1076 features.require("hyperref");
1077 // due to interferences with babel and hyperref, the color package has to
1078 // be loaded after hyperref when hyperref is used with the colorlinks
1079 // option, see http://www.lyx.org/trac/ticket/5291
1080 if (pdfoptions().colorlinks)
1081 features.require("color");
1085 features.require("xetex");
1087 if (language->lang() == "vietnamese")
1088 features.require("vietnamese");
1089 else if (language->lang() == "japanese")
1090 features.require("japanese");
1094 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1095 TexRow & texrow, FileName const & filepath) const
1097 os << "\\documentclass";
1099 DocumentClass const & tclass = documentClass();
1101 ostringstream clsoptions; // the document class options.
1103 if (tokenPos(tclass.opt_fontsize(),
1104 '|', fontsize) >= 0) {
1105 // only write if existing in list (and not default)
1106 clsoptions << fontsize << "pt,";
1109 // custom, A3, B3 and B4 paper sizes need geometry
1110 bool nonstandard_papersize = papersize == PAPER_B3
1111 || papersize == PAPER_B4
1112 || papersize == PAPER_A3
1113 || papersize == PAPER_CUSTOM;
1115 if (!use_geometry) {
1116 switch (papersize) {
1118 clsoptions << "a4paper,";
1120 case PAPER_USLETTER:
1121 clsoptions << "letterpaper,";
1124 clsoptions << "a5paper,";
1127 clsoptions << "b5paper,";
1129 case PAPER_USEXECUTIVE:
1130 clsoptions << "executivepaper,";
1133 clsoptions << "legalpaper,";
1145 if (sides != tclass.sides()) {
1148 clsoptions << "oneside,";
1151 clsoptions << "twoside,";
1157 if (columns != tclass.columns()) {
1159 clsoptions << "twocolumn,";
1161 clsoptions << "onecolumn,";
1165 && orientation == ORIENTATION_LANDSCAPE)
1166 clsoptions << "landscape,";
1168 // language should be a parameter to \documentclass
1169 if (language->babel() == "hebrew"
1170 && default_language->babel() != "hebrew")
1171 // This seems necessary
1172 features.useLanguage(default_language);
1174 ostringstream language_options;
1175 bool const use_babel = features.useBabel();
1177 language_options << features.getLanguages();
1178 if (!language->babel().empty()) {
1179 if (!language_options.str().empty())
1180 language_options << ',';
1181 language_options << language->babel();
1183 // if Vietnamese is used, babel must directly be loaded
1184 // with language options, not in the class options, see
1185 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1186 size_t viet = language_options.str().find("vietnam");
1187 // viet = string::npos when not found
1188 // the same is for all other languages that are not directly supported by
1189 // babel, but where LaTeX-packages add babel support.
1190 // this is currently the case for Latvian, Lithuanian, and Mongolian
1191 size_t latvian = language_options.str().find("latvian");
1192 size_t lithu = language_options.str().find("lithuanian");
1193 size_t mongo = language_options.str().find("mongolian");
1194 // if Japanese is used, babel must directly be loaded
1195 // with language options, not in the class options, see
1196 // http://www.lyx.org/trac/ticket/4597#c4
1197 size_t japan = language_options.str().find("japanese");
1198 if (lyxrc.language_global_options && !language_options.str().empty()
1199 && viet == string::npos && japan == string::npos
1200 && latvian == string::npos && lithu == string::npos
1201 && mongo == string::npos)
1202 clsoptions << language_options.str() << ',';
1205 // the predefined options from the layout
1206 if (use_default_options && !tclass.options().empty())
1207 clsoptions << tclass.options() << ',';
1209 // the user-defined options
1210 if (!options.empty()) {
1211 clsoptions << options << ',';
1214 string strOptions(clsoptions.str());
1215 if (!strOptions.empty()) {
1216 strOptions = rtrim(strOptions, ",");
1218 os << '[' << from_utf8(strOptions) << ']';
1221 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1223 // end of \documentclass defs
1226 os << "\\usepackage{fontspec}\n";
1230 // font selection must be done before loading fontenc.sty
1231 string const fonts =
1232 loadFonts(fontsRoman, fontsSans,
1233 fontsTypewriter, fontsSC, fontsOSF,
1234 fontsSansScale, fontsTypewriterScale, useXetex);
1235 if (!fonts.empty()) {
1236 os << from_ascii(fonts);
1239 if (fontsDefaultFamily != "default")
1240 os << "\\renewcommand{\\familydefault}{\\"
1241 << from_ascii(fontsDefaultFamily) << "}\n";
1243 // set font encoding
1244 // for arabic_arabi and farsi we also need to load the LAE and
1246 // XeTeX works without fontenc
1247 if (font_encoding() != "default" && language->lang() != "japanese"
1249 if (language->lang() == "arabic_arabi"
1250 || language->lang() == "farsi") {
1251 os << "\\usepackage[" << from_ascii(font_encoding())
1252 << ",LFE,LAE]{fontenc}\n";
1255 os << "\\usepackage[" << from_ascii(font_encoding())
1261 // handle inputenc etc.
1262 writeEncodingPreamble(os, features, texrow);
1265 if (!includedChildren_.empty()) {
1266 os << "\\includeonly{";
1267 list<string>::const_iterator it = includedChildren_.begin();
1269 for (; it != includedChildren_.end() ; ++it) {
1270 string incfile = *it;
1271 FileName inc = makeAbsPath(incfile, filepath.absFilename());
1272 string mangled = DocFileName(changeExtension(inc.absFilename(), ".tex")).
1274 if (!features.runparams().nice)
1276 // \includeonly doesn't want an extension
1277 incfile = changeExtension(incfile, string());
1278 incfile = latex_path(incfile);
1279 if (!incfile.empty()) {
1282 os << from_utf8(incfile);
1289 if (!listings_params.empty() || features.isRequired("listings")) {
1290 os << "\\usepackage{listings}\n";
1293 if (!listings_params.empty()) {
1295 // do not test validity because listings_params is
1296 // supposed to be valid
1298 InsetListingsParams(listings_params).separatedParams(true);
1299 // we can't support all packages, but we should load the color package
1300 if (par.find("\\color", 0) != string::npos)
1301 features.require("color");
1302 os << from_utf8(par);
1303 // count the number of newlines
1304 for (size_t i = 0; i < par.size(); ++i)
1310 if (!tclass.provides("geometry")
1311 && (use_geometry || nonstandard_papersize)) {
1312 odocstringstream ods;
1313 if (!getGraphicsDriver("geometry").empty())
1314 ods << getGraphicsDriver("geometry");
1315 if (orientation == ORIENTATION_LANDSCAPE)
1316 ods << ",landscape";
1317 switch (papersize) {
1319 if (!paperwidth.empty())
1320 ods << ",paperwidth="
1321 << from_ascii(paperwidth);
1322 if (!paperheight.empty())
1323 ods << ",paperheight="
1324 << from_ascii(paperheight);
1326 case PAPER_USLETTER:
1327 ods << ",letterpaper";
1330 ods << ",legalpaper";
1332 case PAPER_USEXECUTIVE:
1333 ods << ",executivepaper";
1354 // default papersize ie PAPER_DEFAULT
1355 switch (lyxrc.default_papersize) {
1356 case PAPER_DEFAULT: // keep compiler happy
1357 case PAPER_USLETTER:
1358 ods << ",letterpaper";
1361 ods << ",legalpaper";
1363 case PAPER_USEXECUTIVE:
1364 ods << ",executivepaper";
1384 docstring const g_options = trim(ods.str(), ",");
1385 os << "\\usepackage";
1386 if (!g_options.empty())
1387 os << '[' << g_options << ']';
1388 os << "{geometry}\n";
1390 os << "\\geometry{verbose";
1391 if (!topmargin.empty())
1392 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1393 if (!bottommargin.empty())
1394 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1395 if (!leftmargin.empty())
1396 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1397 if (!rightmargin.empty())
1398 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1399 if (!headheight.empty())
1400 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1401 if (!headsep.empty())
1402 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1403 if (!footskip.empty())
1404 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1405 if (!columnsep.empty())
1406 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1409 } else if (orientation == ORIENTATION_LANDSCAPE) {
1410 features.require("papersize");
1413 if (tokenPos(tclass.opt_pagestyle(),
1414 '|', pagestyle) >= 0) {
1415 if (pagestyle == "fancy") {
1416 os << "\\usepackage{fancyhdr}\n";
1419 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1423 // only output when the background color is not white
1424 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1425 // only require color here, the background color will be defined
1426 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1428 features.require("color");
1429 features.require("pagecolor");
1432 // Only if class has a ToC hierarchy
1433 if (tclass.hasTocLevels()) {
1434 if (secnumdepth != tclass.secnumdepth()) {
1435 os << "\\setcounter{secnumdepth}{"
1440 if (tocdepth != tclass.tocdepth()) {
1441 os << "\\setcounter{tocdepth}{"
1448 if (paragraph_separation) {
1449 // when skip separation
1450 switch (getDefSkip().kind()) {
1451 case VSpace::SMALLSKIP:
1452 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1454 case VSpace::MEDSKIP:
1455 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1457 case VSpace::BIGSKIP:
1458 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1460 case VSpace::LENGTH:
1461 os << "\\setlength{\\parskip}{"
1462 << from_utf8(getDefSkip().length().asLatexString())
1465 default: // should never happen // Then delete it.
1466 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1470 os << "\\setlength{\\parindent}{0pt}\n";
1473 // when separation by indentation
1474 // only output something when a width is given
1475 if (getIndentation().asLyXCommand() != "default") {
1476 os << "\\setlength{\\parindent}{"
1477 << from_utf8(getIndentation().asLatexCommand())
1483 // Now insert the LyX specific LaTeX commands...
1484 docstring lyxpreamble;
1486 // due to interferences with babel and hyperref, the color package has to
1487 // be loaded (when it is not already loaded) before babel when hyperref
1488 // is used with the colorlinks option, see
1489 // http://www.lyx.org/trac/ticket/5291
1490 // we decided therefore to load color always before babel, see
1491 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1492 lyxpreamble += from_ascii(features.getColorOptions());
1494 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1496 && (features.isRequired("jurabib")
1497 || features.isRequired("hyperref")
1498 || features.isRequired("vietnamese")
1499 || features.isRequired("japanese") ) ) {
1501 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1502 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1505 // The optional packages;
1506 lyxpreamble += from_ascii(features.getPackages());
1508 // Additional Indices
1509 if (features.isRequired("splitidx")) {
1510 IndicesList::const_iterator iit = indiceslist().begin();
1511 IndicesList::const_iterator iend = indiceslist().end();
1512 for (; iit != iend; ++iit) {
1513 lyxpreamble += "\\newindex[";
1514 lyxpreamble += iit->index();
1515 lyxpreamble += "]{";
1516 lyxpreamble += iit->shortcut();
1517 lyxpreamble += "}\n";
1522 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1525 // * Hyperref manual: "Make sure it comes last of your loaded
1526 // packages, to give it a fighting chance of not being over-written,
1527 // since its job is to redefine many LaTeX commands."
1528 // * Email from Heiko Oberdiek: "It is usually better to load babel
1529 // before hyperref. Then hyperref has a chance to detect babel.
1530 // * Has to be loaded before the "LyX specific LaTeX commands" to
1531 // avoid errors with algorithm floats.
1532 // use hyperref explicitely when it is required
1533 if (features.isRequired("hyperref")) {
1534 odocstringstream oss;
1535 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1536 lyxpreamble += oss.str();
1539 // Will be surrounded by \makeatletter and \makeatother when not empty
1540 docstring atlyxpreamble;
1542 // Some macros LyX will need
1543 docstring tmppreamble(features.getMacros());
1545 if (!tmppreamble.empty())
1546 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1547 "LyX specific LaTeX commands.\n"
1548 + tmppreamble + '\n';
1550 // the text class specific preamble
1551 tmppreamble = features.getTClassPreamble();
1552 if (!tmppreamble.empty())
1553 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1554 "Textclass specific LaTeX commands.\n"
1555 + tmppreamble + '\n';
1557 // suppress date if selected
1558 // use \@ifundefined because we cannot be sure that every document class
1559 // has a \date command
1561 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1563 /* the user-defined preamble */
1564 if (!containsOnly(preamble, " \n\t"))
1566 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1567 "User specified LaTeX commands.\n"
1568 + from_utf8(preamble) + '\n';
1570 // subfig loads internally the LaTeX package "caption". As
1571 // caption is a very popular package, users will load it in
1572 // the preamble. Therefore we must load subfig behind the
1573 // user-defined preamble and check if the caption package was
1574 // loaded or not. For the case that caption is loaded before
1575 // subfig, there is the subfig option "caption=false". This
1576 // option also works when a koma-script class is used and
1577 // koma's own caption commands are used instead of caption. We
1578 // use \PassOptionsToPackage here because the user could have
1579 // already loaded subfig in the preamble.
1580 if (features.isRequired("subfig")) {
1581 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1582 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1583 "\\usepackage{subfig}\n";
1586 // Itemize bullet settings need to be last in case the user
1587 // defines their own bullets that use a package included
1588 // in the user-defined preamble -- ARRae
1589 // Actually it has to be done much later than that
1590 // since some packages like frenchb make modifications
1591 // at \begin{document} time -- JMarc
1592 docstring bullets_def;
1593 for (int i = 0; i < 4; ++i) {
1594 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1595 if (bullets_def.empty())
1596 bullets_def += "\\AtBeginDocument{\n";
1597 bullets_def += " \\def\\labelitemi";
1599 // `i' is one less than the item to modify
1606 bullets_def += "ii";
1612 bullets_def += '{' +
1613 user_defined_bullet(i).getText()
1618 if (!bullets_def.empty())
1619 atlyxpreamble += bullets_def + "}\n\n";
1621 if (!atlyxpreamble.empty())
1622 lyxpreamble += "\n\\makeatletter\n"
1623 + atlyxpreamble + "\\makeatother\n\n";
1625 // We try to load babel late, in case it interferes with other packages.
1626 // Jurabib and Hyperref have to be called after babel, though.
1627 if (use_babel && !features.isRequired("jurabib")
1628 && !features.isRequired("hyperref")
1629 && !features.isRequired("vietnamese")
1630 && !features.isRequired("japanese")) {
1632 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1633 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1636 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1637 if (!i18npreamble.empty())
1638 lyxpreamble += i18npreamble + '\n';
1641 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1642 for (int j = 0; j != nlines; ++j) {
1648 // these packages (xunicode, for that matter) need to be loaded at least
1649 // after amsmath, amssymb, esint and the other packages that provide
1652 os << "\\usepackage{xunicode}\n";
1654 os << "\\usepackage{xltxtra}\n";
1661 void BufferParams::useClassDefaults()
1663 DocumentClass const & tclass = documentClass();
1665 sides = tclass.sides();
1666 columns = tclass.columns();
1667 pagestyle = tclass.pagestyle();
1668 use_default_options = true;
1669 // Only if class has a ToC hierarchy
1670 if (tclass.hasTocLevels()) {
1671 secnumdepth = tclass.secnumdepth();
1672 tocdepth = tclass.tocdepth();
1677 bool BufferParams::hasClassDefaults() const
1679 DocumentClass const & tclass = documentClass();
1681 return sides == tclass.sides()
1682 && columns == tclass.columns()
1683 && pagestyle == tclass.pagestyle()
1684 && use_default_options
1685 && secnumdepth == tclass.secnumdepth()
1686 && tocdepth == tclass.tocdepth();
1690 DocumentClass const & BufferParams::documentClass() const
1696 DocumentClass const * BufferParams::documentClassPtr() const {
1701 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1702 // evil, but this function is evil
1703 doc_class_ = const_cast<DocumentClass *>(tc);
1707 bool BufferParams::setBaseClass(string const & classname)
1709 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1710 LayoutFileList & bcl = LayoutFileList::get();
1711 if (!bcl.haveClass(classname)) {
1713 bformat(_("The document class %1$s could not be found. "
1714 "A default textclass with default layouts will be used. "
1715 "LyX might not be able to produce output unless a correct "
1716 "textclass is selected from the document settings dialog."),
1717 from_utf8(classname));
1718 frontend::Alert::error(_("Document class not found"), s);
1719 bcl.addEmptyClass(classname);
1722 bool const success = bcl[classname].load();
1725 bformat(_("The document class %1$s could not be loaded."),
1726 from_utf8(classname));
1727 frontend::Alert::error(_("Could not load class"), s);
1731 pimpl_->baseClass_ = classname;
1732 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1737 LayoutFile const * BufferParams::baseClass() const
1739 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1740 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1746 LayoutFileIndex const & BufferParams::baseClassID() const
1748 return pimpl_->baseClass_;
1752 void BufferParams::makeDocumentClass()
1757 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1759 if (!local_layout.empty()) {
1760 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1761 docstring const msg = _("Error reading internal layout information");
1762 frontend::Alert::warning(_("Read Error"), msg);
1767 bool BufferParams::moduleCanBeAdded(string const & modName) const
1769 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1773 bool BufferParams::addLayoutModule(string const & modName)
1775 LayoutModuleList::const_iterator it = layoutModules_.begin();
1776 LayoutModuleList::const_iterator end = layoutModules_.end();
1777 for (; it != end; it++)
1780 layoutModules_.push_back(modName);
1785 Font const BufferParams::getFont() const
1787 FontInfo f = documentClass().defaultfont();
1788 if (fontsDefaultFamily == "rmdefault")
1789 f.setFamily(ROMAN_FAMILY);
1790 else if (fontsDefaultFamily == "sfdefault")
1791 f.setFamily(SANS_FAMILY);
1792 else if (fontsDefaultFamily == "ttdefault")
1793 f.setFamily(TYPEWRITER_FAMILY);
1794 return Font(f, language);
1798 void BufferParams::readPreamble(Lexer & lex)
1800 if (lex.getString() != "\\begin_preamble")
1801 lyxerr << "Error (BufferParams::readPreamble):"
1802 "consistency check failed." << endl;
1804 preamble = lex.getLongString("\\end_preamble");
1808 void BufferParams::readLocalLayout(Lexer & lex)
1810 if (lex.getString() != "\\begin_local_layout")
1811 lyxerr << "Error (BufferParams::readLocalLayout):"
1812 "consistency check failed." << endl;
1814 local_layout = lex.getLongString("\\end_local_layout");
1818 void BufferParams::readLanguage(Lexer & lex)
1820 if (!lex.next()) return;
1822 string const tmptok = lex.getString();
1824 // check if tmptok is part of tex_babel in tex-defs.h
1825 language = languages.getLanguage(tmptok);
1827 // Language tmptok was not found
1828 language = default_language;
1829 lyxerr << "Warning: Setting language `"
1830 << tmptok << "' to `" << language->lang()
1836 void BufferParams::readGraphicsDriver(Lexer & lex)
1841 string const tmptok = lex.getString();
1842 // check if tmptok is part of tex_graphics in tex_defs.h
1845 string const test = tex_graphics[n++];
1847 if (test == tmptok) {
1848 graphicsDriver = tmptok;
1853 "Warning: graphics driver `$$Token' not recognized!\n"
1854 " Setting graphics driver to `default'.\n");
1855 graphicsDriver = "default";
1862 void BufferParams::readBullets(Lexer & lex)
1867 int const index = lex.getInteger();
1869 int temp_int = lex.getInteger();
1870 user_defined_bullet(index).setFont(temp_int);
1871 temp_bullet(index).setFont(temp_int);
1873 user_defined_bullet(index).setCharacter(temp_int);
1874 temp_bullet(index).setCharacter(temp_int);
1876 user_defined_bullet(index).setSize(temp_int);
1877 temp_bullet(index).setSize(temp_int);
1881 void BufferParams::readBulletsLaTeX(Lexer & lex)
1883 // The bullet class should be able to read this.
1886 int const index = lex.getInteger();
1888 docstring const temp_str = lex.getDocString();
1890 user_defined_bullet(index).setText(temp_str);
1891 temp_bullet(index).setText(temp_str);
1895 void BufferParams::readModules(Lexer & lex)
1897 if (!lex.eatLine()) {
1898 lyxerr << "Error (BufferParams::readModules):"
1899 "Unexpected end of input." << endl;
1903 string mod = lex.getString();
1904 if (mod == "\\end_modules")
1906 addLayoutModule(mod);
1912 void BufferParams::readRemovedModules(Lexer & lex)
1914 if (!lex.eatLine()) {
1915 lyxerr << "Error (BufferParams::readRemovedModules):"
1916 "Unexpected end of input." << endl;
1920 string mod = lex.getString();
1921 if (mod == "\\end_removed_modules")
1923 removedModules_.push_back(mod);
1926 // now we want to remove any removed modules that were previously
1927 // added. normally, that will be because default modules were added in
1928 // setBaseClass(), which gets called when \textclass is read at the
1929 // start of the read.
1930 list<string>::const_iterator rit = removedModules_.begin();
1931 list<string>::const_iterator const ren = removedModules_.end();
1932 for (; rit != ren; rit++) {
1933 LayoutModuleList::iterator const mit = layoutModules_.begin();
1934 LayoutModuleList::iterator const men = layoutModules_.end();
1935 LayoutModuleList::iterator found = find(mit, men, *rit);
1938 layoutModules_.erase(found);
1943 void BufferParams::readIncludeonly(Lexer & lex)
1945 if (!lex.eatLine()) {
1946 lyxerr << "Error (BufferParams::readIncludeonly):"
1947 "Unexpected end of input." << endl;
1951 string child = lex.getString();
1952 if (child == "\\end_includeonly")
1954 includedChildren_.push_back(child);
1960 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1962 char real_papersize = papersize;
1963 if (real_papersize == PAPER_DEFAULT)
1964 real_papersize = lyxrc.default_papersize;
1966 switch (real_papersize) {
1968 // could be anything, so don't guess
1970 case PAPER_CUSTOM: {
1971 if (purpose == XDVI && !paperwidth.empty() &&
1972 !paperheight.empty()) {
1973 // heightxwidth<unit>
1974 string first = paperwidth;
1975 string second = paperheight;
1976 if (orientation == ORIENTATION_LANDSCAPE)
1979 return first.erase(first.length() - 2)
1991 // dvips and dvipdfm do not know this
1992 if (purpose == DVIPS || purpose == DVIPDFM)
1996 // dvipdfm does not know this
1997 if (purpose == DVIPDFM)
2001 // dvipdfm does not know this
2002 if (purpose == DVIPDFM)
2005 case PAPER_USEXECUTIVE:
2006 // dvipdfm does not know this
2007 if (purpose == DVIPDFM)
2012 case PAPER_USLETTER:
2014 if (purpose == XDVI)
2021 string const BufferParams::dvips_options() const
2026 && papersize == PAPER_CUSTOM
2027 && !lyxrc.print_paper_dimension_flag.empty()
2028 && !paperwidth.empty()
2029 && !paperheight.empty()) {
2030 // using a custom papersize
2031 result = lyxrc.print_paper_dimension_flag;
2032 result += ' ' + paperwidth;
2033 result += ',' + paperheight;
2035 string const paper_option = paperSizeName(DVIPS);
2036 if (!paper_option.empty() && (paper_option != "letter" ||
2037 orientation != ORIENTATION_LANDSCAPE)) {
2038 // dvips won't accept -t letter -t landscape.
2039 // In all other cases, include the paper size
2041 result = lyxrc.print_paper_flag;
2042 result += ' ' + paper_option;
2045 if (orientation == ORIENTATION_LANDSCAPE &&
2046 papersize != PAPER_CUSTOM)
2047 result += ' ' + lyxrc.print_landscape_flag;
2052 string const BufferParams::font_encoding() const
2054 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2058 string BufferParams::babelCall(string const & lang_opts) const
2060 string lang_pack = lyxrc.language_package;
2061 if (lang_pack != "\\usepackage{babel}")
2063 // suppress the babel call when there is no babel language defined
2064 // for the document language in the lib/languages file and if no
2065 // other languages are used (lang_opts is then empty)
2066 if (lang_opts.empty())
2068 // If Vietnamese is used, babel must directly be loaded with the
2069 // language options, see
2070 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2071 size_t viet = lang_opts.find("vietnam");
2072 // viet = string::npos when not found
2073 // the same is for all other languages that are not directly supported by
2074 // babel, but where LaTeX-packages add babel support.
2075 // this is currently the case for Latvian, Lithuanian, and Mongolian
2076 size_t latvian = lang_opts.find("latvian");
2077 size_t lithu = lang_opts.find("lithuanian");
2078 size_t mongo = lang_opts.find("mongolian");
2079 // If Japanese is used, babel must directly be loaded with the
2080 // language options, see
2081 // http://www.lyx.org/trac/ticket/4597#c4
2082 size_t japan = lang_opts.find("japanese");
2083 if (!lyxrc.language_global_options || viet != string::npos
2084 || japan != string::npos || latvian != string::npos
2085 || lithu != string::npos || mongo != string::npos)
2086 return "\\usepackage[" + lang_opts + "]{babel}";
2091 docstring BufferParams::getGraphicsDriver(string const & package) const
2095 if (package == "geometry") {
2096 if (graphicsDriver == "dvips"
2097 || graphicsDriver == "dvipdfm"
2098 || graphicsDriver == "pdftex"
2099 || graphicsDriver == "vtex")
2100 result = from_ascii(graphicsDriver);
2101 else if (graphicsDriver == "dvipdfmx")
2102 result = from_ascii("dvipdfm");
2109 void BufferParams::writeEncodingPreamble(odocstream & os,
2110 LaTeXFeatures & features, TexRow & texrow) const
2114 if (inputenc == "auto") {
2115 string const doc_encoding =
2116 language->encoding()->latexName();
2117 Encoding::Package const package =
2118 language->encoding()->package();
2120 // Create a list with all the input encodings used
2122 set<string> encodings =
2123 features.getEncodingSet(doc_encoding);
2125 // If the "japanese" package (i.e. pLaTeX) is used,
2126 // inputenc must be omitted.
2127 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2128 if (package == Encoding::japanese)
2129 features.require("japanese");
2131 if ((!encodings.empty() || package == Encoding::inputenc)
2132 && !features.isRequired("japanese")) {
2133 os << "\\usepackage[";
2134 set<string>::const_iterator it = encodings.begin();
2135 set<string>::const_iterator const end = encodings.end();
2137 os << from_ascii(*it);
2140 for (; it != end; ++it)
2141 os << ',' << from_ascii(*it);
2142 if (package == Encoding::inputenc) {
2143 if (!encodings.empty())
2145 os << from_ascii(doc_encoding);
2147 os << "]{inputenc}\n";
2150 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2151 if (language->encoding()->name() == "utf8-cjk"
2152 && LaTeXFeatures::isAvailable("CJKutf8"))
2153 os << "\\usepackage{CJKutf8}\n";
2155 os << "\\usepackage{CJK}\n";
2158 } else if (inputenc != "default") {
2159 switch (encoding().package()) {
2160 case Encoding::none:
2161 case Encoding::japanese:
2163 case Encoding::inputenc:
2164 // do not load inputenc if japanese is used
2165 if (features.isRequired("japanese"))
2167 os << "\\usepackage[" << from_ascii(inputenc)
2172 if (encoding().name() == "utf8-cjk"
2173 && LaTeXFeatures::isAvailable("CJKutf8"))
2174 os << "\\usepackage{CJKutf8}\n";
2176 os << "\\usepackage{CJK}\n";
2182 // The encoding "armscii8" (for Armenian) is only available when
2183 // the package "armtex" is loaded.
2184 if (language->encoding()->latexName() == "armscii8"
2185 || inputenc == "armscii8") {
2186 os << "\\usepackage{armtex}\n";
2192 string const BufferParams::parseFontName(string const & name) const
2194 string mangled = name;
2195 size_t const idx = mangled.find('[');
2196 if (idx == string::npos || idx == 0)
2199 return mangled.substr(0, idx - 1);
2203 string const BufferParams::loadFonts(string const & rm,
2204 string const & sf, string const & tt,
2205 bool const & sc, bool const & osf,
2206 int const & sfscale, int const & ttscale,
2207 bool const & xetex) const
2209 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2210 several packages have been replaced by others, that might not
2211 be installed on every system. We have to take care for that
2212 (see psnfss.pdf). We try to support all psnfss fonts as well
2213 as the fonts that have become de facto standard in the LaTeX
2214 world (e.g. Latin Modern). We do not support obsolete fonts
2215 (like PSLatex). In general, it should be possible to mix any
2216 rm font with any sf or tt font, respectively. (JSpitzm)
2218 -- separate math fonts.
2221 if (rm == "default" && sf == "default" && tt == "default")
2228 if (rm != "default")
2229 os << "\\setmainfont[Mapping=tex-text]{"
2230 << parseFontName(rm) << "}\n";
2231 if (sf != "default") {
2232 string const sans = parseFontName(sf);
2234 os << "\\setsansfont[Scale="
2235 << float(sfscale) / 100
2236 << ",Mapping=tex-text]{"
2239 os << "\\setsansfont[Mapping=tex-text]{"
2242 if (tt != "default") {
2243 string const mono = parseFontName(tt);
2245 os << "\\setmonofont[Scale="
2246 << float(sfscale) / 100
2250 os << "\\setmonofont[Mapping=tex-text]{"
2254 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2259 // Computer Modern (must be explicitely selectable -- there might be classes
2260 // that define a different default font!
2262 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2263 // osf for Computer Modern needs eco.sty
2265 os << "\\usepackage{eco}\n";
2267 // Latin Modern Roman
2268 else if (rm == "lmodern")
2269 os << "\\usepackage{lmodern}\n";
2271 else if (rm == "ae") {
2272 // not needed when using OT1 font encoding.
2273 if (font_encoding() != "default")
2274 os << "\\usepackage{ae,aecompl}\n";
2277 else if (rm == "times") {
2278 // try to load the best available package
2279 if (LaTeXFeatures::isAvailable("mathptmx"))
2280 os << "\\usepackage{mathptmx}\n";
2281 else if (LaTeXFeatures::isAvailable("mathptm"))
2282 os << "\\usepackage{mathptm}\n";
2284 os << "\\usepackage{times}\n";
2287 else if (rm == "palatino") {
2288 // try to load the best available package
2289 if (LaTeXFeatures::isAvailable("mathpazo")) {
2290 os << "\\usepackage";
2296 // "osf" includes "sc"!
2300 os << "{mathpazo}\n";
2302 else if (LaTeXFeatures::isAvailable("mathpple"))
2303 os << "\\usepackage{mathpple}\n";
2305 os << "\\usepackage{palatino}\n";
2308 else if (rm == "utopia") {
2309 // fourier supersedes utopia.sty, but does
2310 // not work with OT1 encoding.
2311 if (LaTeXFeatures::isAvailable("fourier")
2312 && font_encoding() != "default") {
2313 os << "\\usepackage";
2324 os << "{fourier}\n";
2327 os << "\\usepackage{utopia}\n";
2329 // Bera (complete fontset)
2330 else if (rm == "bera" && sf == "default" && tt == "default")
2331 os << "\\usepackage{bera}\n";
2333 else if (rm != "default")
2334 os << "\\usepackage" << "{" << rm << "}\n";
2337 // Helvetica, Bera Sans
2338 if (sf == "helvet" || sf == "berasans") {
2340 os << "\\usepackage[scaled=" << float(sfscale) / 100
2341 << "]{" << sf << "}\n";
2343 os << "\\usepackage{" << sf << "}\n";
2346 else if (sf == "avant")
2347 os << "\\usepackage{" << sf << "}\n";
2348 // Computer Modern, Latin Modern, CM Bright
2349 else if (sf != "default")
2350 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2352 // monospaced/typewriter
2353 // Courier, LuxiMono
2354 if (tt == "luximono" || tt == "beramono") {
2356 os << "\\usepackage[scaled=" << float(ttscale) / 100
2357 << "]{" << tt << "}\n";
2359 os << "\\usepackage{" << tt << "}\n";
2362 else if (tt == "courier" )
2363 os << "\\usepackage{" << tt << "}\n";
2364 // Computer Modern, Latin Modern, CM Bright
2365 else if (tt != "default")
2366 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2372 Encoding const & BufferParams::encoding() const
2375 return *(encodings.fromLaTeXName("utf8-plain"));
2376 if (inputenc == "auto" || inputenc == "default")
2377 return *language->encoding();
2378 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2381 LYXERR0("Unknown inputenc value `" << inputenc
2382 << "'. Using `auto' instead.");
2383 return *language->encoding();
2387 CiteEngine BufferParams::citeEngine() const
2389 // FIXME the class should provide the numerical/
2390 // authoryear choice
2391 if (documentClass().provides("natbib")
2392 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2393 return ENGINE_NATBIB_AUTHORYEAR;
2394 return cite_engine_;
2398 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2400 cite_engine_ = cite_engine;