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 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
76 "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
77 "b5paper", "b6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
82 static char const * const string_orientation[] = {
83 "portrait", "landscape", ""
87 static char const * const string_footnotekinds[] = {
88 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
92 static char const * const tex_graphics[] = {
93 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
94 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
95 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
96 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
107 // Paragraph separation
108 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
111 ParSepTranslator const init_parseptranslator()
113 ParSepTranslator translator
114 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
115 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
120 ParSepTranslator const & parseptranslator()
122 static ParSepTranslator translator = init_parseptranslator();
128 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
131 QuotesLangTranslator const init_quoteslangtranslator()
133 QuotesLangTranslator translator
134 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
135 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
136 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
137 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
138 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
139 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
144 QuotesLangTranslator const & quoteslangtranslator()
146 static QuotesLangTranslator translator = init_quoteslangtranslator();
152 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
155 static PaperSizeTranslator initPaperSizeTranslator()
157 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
158 translator.addPair(string_papersize[1], PAPER_CUSTOM);
159 translator.addPair(string_papersize[2], PAPER_USLETTER);
160 translator.addPair(string_papersize[3], PAPER_USLEGAL);
161 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
162 translator.addPair(string_papersize[5], PAPER_A0);
163 translator.addPair(string_papersize[6], PAPER_A1);
164 translator.addPair(string_papersize[7], PAPER_A2);
165 translator.addPair(string_papersize[8], PAPER_A3);
166 translator.addPair(string_papersize[9], PAPER_A4);
167 translator.addPair(string_papersize[10], PAPER_A5);
168 translator.addPair(string_papersize[11], PAPER_A6);
169 translator.addPair(string_papersize[12], PAPER_B0);
170 translator.addPair(string_papersize[13], PAPER_B1);
171 translator.addPair(string_papersize[14], PAPER_B2);
172 translator.addPair(string_papersize[15], PAPER_B3);
173 translator.addPair(string_papersize[16], PAPER_B4);
174 translator.addPair(string_papersize[17], PAPER_B5);
175 translator.addPair(string_papersize[18], PAPER_B6);
176 translator.addPair(string_papersize[19], PAPER_JISB0);
177 translator.addPair(string_papersize[20], PAPER_JISB1);
178 translator.addPair(string_papersize[21], PAPER_JISB2);
179 translator.addPair(string_papersize[22], PAPER_JISB3);
180 translator.addPair(string_papersize[23], PAPER_JISB4);
181 translator.addPair(string_papersize[24], PAPER_JISB5);
182 translator.addPair(string_papersize[25], PAPER_JISB6);
187 PaperSizeTranslator const & papersizetranslator()
189 static PaperSizeTranslator translator = initPaperSizeTranslator();
195 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
198 PaperOrientationTranslator const init_paperorientationtranslator()
200 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
201 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
206 PaperOrientationTranslator const & paperorientationtranslator()
208 static PaperOrientationTranslator translator = init_paperorientationtranslator();
214 typedef Translator<int, PageSides> SidesTranslator;
217 SidesTranslator const init_sidestranslator()
219 SidesTranslator translator(1, OneSide);
220 translator.addPair(2, TwoSides);
225 SidesTranslator const & sidestranslator()
227 static SidesTranslator translator = init_sidestranslator();
233 typedef Translator<int, BufferParams::Package> PackageTranslator;
236 PackageTranslator const init_packagetranslator()
238 PackageTranslator translator(0, BufferParams::package_off);
239 translator.addPair(1, BufferParams::package_auto);
240 translator.addPair(2, BufferParams::package_on);
245 PackageTranslator const & packagetranslator()
247 static PackageTranslator translator = init_packagetranslator();
253 typedef Translator<string, CiteEngine> CiteEngineTranslator;
256 CiteEngineTranslator const init_citeenginetranslator()
258 CiteEngineTranslator translator("basic", ENGINE_BASIC);
259 translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
260 translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
261 translator.addPair("jurabib", ENGINE_JURABIB);
266 CiteEngineTranslator const & citeenginetranslator()
268 static CiteEngineTranslator translator = init_citeenginetranslator();
274 typedef Translator<string, Spacing::Space> SpaceTranslator;
277 SpaceTranslator const init_spacetranslator()
279 SpaceTranslator translator("default", Spacing::Default);
280 translator.addPair("single", Spacing::Single);
281 translator.addPair("onehalf", Spacing::Onehalf);
282 translator.addPair("double", Spacing::Double);
283 translator.addPair("other", Spacing::Other);
288 SpaceTranslator const & spacetranslator()
290 static SpaceTranslator translator = init_spacetranslator();
297 class BufferParams::Impl
302 AuthorList authorlist;
303 BranchList branchlist;
304 Bullet temp_bullets[4];
305 Bullet user_defined_bullets[4];
306 IndicesList indiceslist;
308 /** This is the amount of space used for paragraph_separation "skip",
309 * and for detached paragraphs in "indented" documents.
313 PDFOptions pdfoptions;
314 LayoutFileIndex baseClass_;
318 BufferParams::Impl::Impl()
319 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
321 // set initial author
323 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
328 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
332 return new BufferParams::Impl(*ptr);
336 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
342 BufferParams::BufferParams()
345 setBaseClass(defaultBaseclass());
347 paragraph_separation = ParagraphIndentSeparation;
348 quotes_language = InsetQuotes::EnglishQuotes;
349 fontsize = "default";
352 papersize = PAPER_DEFAULT;
353 orientation = ORIENTATION_PORTRAIT;
354 use_geometry = false;
355 use_amsmath = package_auto;
356 use_esint = package_auto;
357 use_mhchem = package_auto;
358 cite_engine_ = ENGINE_BASIC;
359 use_bibtopic = false;
361 trackChanges = false;
362 outputChanges = false;
363 use_default_options = true;
364 maintain_unincluded_children = false;
367 language = default_language;
369 fontsRoman = "default";
370 fontsSans = "default";
371 fontsTypewriter = "default";
372 fontsDefaultFamily = "default";
376 fontsSansScale = 100;
377 fontsTypewriterScale = 100;
379 graphicsDriver = "default";
380 defaultOutputFormat = "default";
381 bibtex_command = "default";
382 index_command = "default";
385 listings_params = string();
386 pagestyle = "default";
387 suppress_date = false;
388 // no color is the default (white)
389 backgroundcolor = lyx::rgbFromHexName("#ffffff");
390 isbackgroundcolor = false;
391 // no color is the default (black)
392 fontcolor = lyx::rgbFromHexName("#000000");
394 // light gray is the default font color for greyed-out notes
395 notefontcolor = lyx::rgbFromHexName("#cccccc");
396 boxbgcolor = lyx::rgbFromHexName("#ff0000");
397 compressed = lyxrc.save_compressed;
398 for (int iter = 0; iter < 4; ++iter) {
399 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
400 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
403 indiceslist().addDefault(B_("Index"));
404 html_be_strict = false;
405 html_math_output = MathML;
406 html_math_img_scale = 1.0;
410 docstring BufferParams::B_(string const & l10n) const
412 LASSERT(language, /**/);
413 return getMessages(language->code()).get(l10n);
417 AuthorList & BufferParams::authors()
419 return pimpl_->authorlist;
423 AuthorList const & BufferParams::authors() const
425 return pimpl_->authorlist;
429 BranchList & BufferParams::branchlist()
431 return pimpl_->branchlist;
435 BranchList const & BufferParams::branchlist() const
437 return pimpl_->branchlist;
441 IndicesList & BufferParams::indiceslist()
443 return pimpl_->indiceslist;
447 IndicesList const & BufferParams::indiceslist() const
449 return pimpl_->indiceslist;
453 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
455 LASSERT(index < 4, /**/);
456 return pimpl_->temp_bullets[index];
460 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
462 LASSERT(index < 4, /**/);
463 return pimpl_->temp_bullets[index];
467 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
469 LASSERT(index < 4, /**/);
470 return pimpl_->user_defined_bullets[index];
474 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
476 LASSERT(index < 4, /**/);
477 return pimpl_->user_defined_bullets[index];
481 Spacing & BufferParams::spacing()
483 return pimpl_->spacing;
487 Spacing const & BufferParams::spacing() const
489 return pimpl_->spacing;
493 PDFOptions & BufferParams::pdfoptions()
495 return pimpl_->pdfoptions;
499 PDFOptions const & BufferParams::pdfoptions() const
501 return pimpl_->pdfoptions;
505 HSpace const & BufferParams::getIndentation() const
507 return pimpl_->indentation;
511 void BufferParams::setIndentation(HSpace const & indent)
513 pimpl_->indentation = indent;
517 VSpace const & BufferParams::getDefSkip() const
519 return pimpl_->defskip;
523 void BufferParams::setDefSkip(VSpace const & vs)
525 pimpl_->defskip = vs;
529 string BufferParams::readToken(Lexer & lex, string const & token,
530 FileName const & filepath)
532 if (token == "\\textclass") {
534 string const classname = lex.getString();
535 // if there exists a local layout file, ignore the system one
536 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
538 LayoutFileList & bcl = LayoutFileList::get();
539 if (tcp.empty() && !filepath.empty())
540 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
544 setBaseClass(classname);
545 // We assume that a tex class exists for local or unknown layouts so this warning
546 // will only be given for system layouts.
547 if (!baseClass()->isTeXClassAvailable()) {
549 translateIfPossible(from_utf8(baseClass()->description()));
550 docstring const msg =
551 bformat(_("The used document class\n"
553 "requires external files that are not available.\n"
554 "The document class can still be used, but LyX\n"
555 "will not be able to produce output until the\n"
556 "following prerequisites are installed:\n"
558 "See section 3.1.2.2 of the User's Guide for\n"
559 "more information."),
560 desc, from_utf8(baseClass()->prerequisites()));
561 frontend::Alert::warning(_("Document class not available"),
564 } else if (token == "\\begin_preamble") {
566 } else if (token == "\\begin_local_layout") {
567 readLocalLayout(lex);
568 } else if (token == "\\begin_modules") {
570 } else if (token == "\\begin_removed_modules") {
571 readRemovedModules(lex);
572 } else if (token == "\\begin_includeonly") {
573 readIncludeonly(lex);
574 } else if (token == "\\maintain_unincluded_children") {
575 lex >> maintain_unincluded_children;
576 } else if (token == "\\options") {
578 options = lex.getString();
579 } else if (token == "\\use_default_options") {
580 lex >> use_default_options;
581 } else if (token == "\\master") {
583 master = lex.getString();
584 } else if (token == "\\suppress_date") {
585 lex >> suppress_date;
586 } else if (token == "\\language") {
588 } else if (token == "\\inputencoding") {
590 } else if (token == "\\graphics") {
591 readGraphicsDriver(lex);
592 } else if (token == "\\default_output_format") {
593 lex >> defaultOutputFormat;
594 } else if (token == "\\bibtex_command") {
596 bibtex_command = lex.getString();
597 } else if (token == "\\index_command") {
599 index_command = lex.getString();
600 } else if (token == "\\fontencoding") {
602 fontenc = lex.getString();
603 } else if (token == "\\font_roman") {
605 fontsRoman = lex.getString();
606 } else if (token == "\\font_sans") {
608 fontsSans = lex.getString();
609 } else if (token == "\\font_typewriter") {
611 fontsTypewriter = lex.getString();
612 } else if (token == "\\font_default_family") {
613 lex >> fontsDefaultFamily;
614 } else if (token == "\\use_xetex") {
616 } else if (token == "\\font_sc") {
618 } else if (token == "\\font_osf") {
620 } else if (token == "\\font_sf_scale") {
621 lex >> fontsSansScale;
622 } else if (token == "\\font_tt_scale") {
623 lex >> fontsTypewriterScale;
624 } else if (token == "\\font_cjk") {
626 } else if (token == "\\paragraph_separation") {
629 paragraph_separation = parseptranslator().find(parsep);
630 } else if (token == "\\paragraph_indentation") {
632 string indentation = lex.getString();
633 pimpl_->indentation = HSpace(indentation);
634 } else if (token == "\\defskip") {
636 string defskip = lex.getString();
637 if (defskip == "defskip")
640 pimpl_->defskip = VSpace(defskip);
641 } else if (token == "\\quotes_language") {
644 quotes_language = quoteslangtranslator().find(quotes_lang);
645 } else if (token == "\\papersize") {
648 papersize = papersizetranslator().find(ppsize);
649 } else if (token == "\\use_geometry") {
651 } else if (token == "\\use_amsmath") {
654 use_amsmath = packagetranslator().find(use_ams);
655 } else if (token == "\\use_esint") {
658 use_esint = packagetranslator().find(useesint);
659 } else if (token == "\\use_mhchem") {
662 use_mhchem = packagetranslator().find(usemhchem);
663 } else if (token == "\\cite_engine") {
666 cite_engine_ = citeenginetranslator().find(engine);
667 } else if (token == "\\use_bibtopic") {
669 } else if (token == "\\use_indices") {
671 } else if (token == "\\tracking_changes") {
673 } else if (token == "\\output_changes") {
674 lex >> outputChanges;
675 } else if (token == "\\branch") {
677 docstring branch = lex.getDocString();
678 branchlist().add(branch);
681 string const tok = lex.getString();
682 if (tok == "\\end_branch")
684 Branch * branch_ptr = branchlist().find(branch);
685 if (tok == "\\selected") {
688 branch_ptr->setSelected(lex.getInteger());
690 if (tok == "\\filename_suffix") {
693 branch_ptr->setFileNameSuffix(lex.getInteger());
695 if (tok == "\\color") {
697 string color = lex.getString();
699 branch_ptr->setColor(color);
700 // Update also the Color table:
702 color = lcolor.getX11Name(Color_background);
704 lcolor.setColor(to_utf8(branch), color);
707 } else if (token == "\\index") {
709 docstring index = lex.getDocString();
711 indiceslist().add(index);
714 string const tok = lex.getString();
715 if (tok == "\\end_index")
717 Index * index_ptr = indiceslist().find(index);
718 if (tok == "\\shortcut") {
720 shortcut = lex.getDocString();
722 index_ptr->setShortcut(shortcut);
724 if (tok == "\\color") {
726 string color = lex.getString();
728 index_ptr->setColor(color);
729 // Update also the Color table:
731 color = lcolor.getX11Name(Color_background);
733 if (!shortcut.empty())
734 lcolor.setColor(to_utf8(shortcut), color);
737 } else if (token == "\\author") {
739 istringstream ss(lex.getString());
742 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
743 } else if (token == "\\paperorientation") {
746 orientation = paperorientationtranslator().find(orient);
747 } else if (token == "\\backgroundcolor") {
749 backgroundcolor = lyx::rgbFromHexName(lex.getString());
750 isbackgroundcolor = true;
751 } else if (token == "\\fontcolor") {
753 fontcolor = lyx::rgbFromHexName(lex.getString());
755 } else if (token == "\\notefontcolor") {
757 string color = lex.getString();
758 notefontcolor = lyx::rgbFromHexName(color);
759 } else if (token == "\\boxbgcolor") {
761 string color = lex.getString();
762 boxbgcolor = lyx::rgbFromHexName(color);
763 } else if (token == "\\paperwidth") {
765 } else if (token == "\\paperheight") {
767 } else if (token == "\\leftmargin") {
769 } else if (token == "\\topmargin") {
771 } else if (token == "\\rightmargin") {
773 } else if (token == "\\bottommargin") {
775 } else if (token == "\\headheight") {
777 } else if (token == "\\headsep") {
779 } else if (token == "\\footskip") {
781 } else if (token == "\\columnsep") {
783 } else if (token == "\\paperfontsize") {
785 } else if (token == "\\papercolumns") {
787 } else if (token == "\\listings_params") {
790 listings_params = InsetListingsParams(par).params();
791 } else if (token == "\\papersides") {
794 sides = sidestranslator().find(psides);
795 } else if (token == "\\paperpagestyle") {
797 } else if (token == "\\bullet") {
799 } else if (token == "\\bulletLaTeX") {
800 readBulletsLaTeX(lex);
801 } else if (token == "\\secnumdepth") {
803 } else if (token == "\\tocdepth") {
805 } else if (token == "\\spacing") {
809 if (nspacing == "other") {
812 spacing().set(spacetranslator().find(nspacing), tmp_val);
813 } else if (token == "\\float_placement") {
814 lex >> float_placement;
816 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
817 string toktmp = pdfoptions().readToken(lex, token);
818 if (!toktmp.empty()) {
819 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
823 } else if (token == "\\html_math_output") {
826 html_math_output = static_cast<MathOutput>(temp);
827 } else if (token == "\\html_be_strict") {
828 lex >> html_be_strict;
829 } else if (token == "\\html_math_img_scale") {
830 lex >> html_math_img_scale;
831 } else if (token == "\\html_latex_start") {
833 html_latex_start = lex.getString();
834 } else if (token == "\\html_latex_end") {
836 html_latex_end = lex.getString();
838 lyxerr << "BufferParams::readToken(): Unknown token: " <<
847 void BufferParams::writeFile(ostream & os) const
849 // The top of the file is written by the buffer.
850 // Prints out the buffer info into the .lyx file given by file
853 os << "\\textclass " << baseClass()->name() << '\n';
856 if (!preamble.empty()) {
857 // remove '\n' from the end of preamble
858 string const tmppreamble = rtrim(preamble, "\n");
859 os << "\\begin_preamble\n"
861 << "\n\\end_preamble\n";
865 if (!options.empty()) {
866 os << "\\options " << options << '\n';
869 // use the class options defined in the layout?
870 os << "\\use_default_options "
871 << convert<string>(use_default_options) << "\n";
873 // the master document
874 if (!master.empty()) {
875 os << "\\master " << master << '\n';
879 if (!removedModules_.empty()) {
880 os << "\\begin_removed_modules" << '\n';
881 list<string>::const_iterator it = removedModules_.begin();
882 list<string>::const_iterator en = removedModules_.end();
883 for (; it != en; it++)
885 os << "\\end_removed_modules" << '\n';
889 if (!layoutModules_.empty()) {
890 os << "\\begin_modules" << '\n';
891 LayoutModuleList::const_iterator it = layoutModules_.begin();
892 LayoutModuleList::const_iterator en = layoutModules_.end();
893 for (; it != en; it++)
895 os << "\\end_modules" << '\n';
899 if (!includedChildren_.empty()) {
900 os << "\\begin_includeonly" << '\n';
901 list<string>::const_iterator it = includedChildren_.begin();
902 list<string>::const_iterator en = includedChildren_.end();
903 for (; it != en; it++)
905 os << "\\end_includeonly" << '\n';
907 os << "\\maintain_unincluded_children "
908 << convert<string>(maintain_unincluded_children) << '\n';
910 // local layout information
911 if (!local_layout.empty()) {
912 // remove '\n' from the end
913 string const tmplocal = rtrim(local_layout, "\n");
914 os << "\\begin_local_layout\n"
916 << "\n\\end_local_layout\n";
919 // then the text parameters
920 if (language != ignore_language)
921 os << "\\language " << language->lang() << '\n';
922 os << "\\inputencoding " << inputenc
923 << "\n\\fontencoding " << fontenc
924 << "\n\\font_roman " << fontsRoman
925 << "\n\\font_sans " << fontsSans
926 << "\n\\font_typewriter " << fontsTypewriter
927 << "\n\\font_default_family " << fontsDefaultFamily
928 << "\n\\use_xetex " << convert<string>(useXetex)
929 << "\n\\font_sc " << convert<string>(fontsSC)
930 << "\n\\font_osf " << convert<string>(fontsOSF)
931 << "\n\\font_sf_scale " << fontsSansScale
932 << "\n\\font_tt_scale " << fontsTypewriterScale
934 if (!fontsCJK.empty()) {
935 os << "\\font_cjk " << fontsCJK << '\n';
937 os << "\n\\graphics " << graphicsDriver << '\n';
938 os << "\\default_output_format " << defaultOutputFormat << '\n';
939 os << "\\bibtex_command " << bibtex_command << '\n';
940 os << "\\index_command " << index_command << '\n';
942 if (!float_placement.empty()) {
943 os << "\\float_placement " << float_placement << '\n';
945 os << "\\paperfontsize " << fontsize << '\n';
947 spacing().writeFile(os);
948 pdfoptions().writeFile(os);
950 os << "\\papersize " << string_papersize[papersize]
951 << "\n\\use_geometry " << convert<string>(use_geometry)
952 << "\n\\use_amsmath " << use_amsmath
953 << "\n\\use_esint " << use_esint
954 << "\n\\use_mhchem " << use_mhchem
955 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
956 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
957 << "\n\\use_indices " << convert<string>(use_indices)
958 << "\n\\paperorientation " << string_orientation[orientation]
959 << "\n\\suppress_date " << convert<string>(suppress_date)
961 if (isbackgroundcolor == true)
962 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
963 if (isfontcolor == true)
964 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
965 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
966 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
967 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
968 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
970 BranchList::const_iterator it = branchlist().begin();
971 BranchList::const_iterator end = branchlist().end();
972 for (; it != end; ++it) {
973 os << "\\branch " << to_utf8(it->branch())
974 << "\n\\selected " << it->isSelected()
975 << "\n\\filename_suffix " << it->hasFileNameSuffix()
976 << "\n\\color " << lyx::X11hexname(it->color())
981 IndicesList::const_iterator iit = indiceslist().begin();
982 IndicesList::const_iterator iend = indiceslist().end();
983 for (; iit != iend; ++iit) {
984 os << "\\index " << to_utf8(iit->index())
985 << "\n\\shortcut " << to_utf8(iit->shortcut())
986 << "\n\\color " << lyx::X11hexname(iit->color())
991 if (!paperwidth.empty())
992 os << "\\paperwidth "
993 << VSpace(paperwidth).asLyXCommand() << '\n';
994 if (!paperheight.empty())
995 os << "\\paperheight "
996 << VSpace(paperheight).asLyXCommand() << '\n';
997 if (!leftmargin.empty())
998 os << "\\leftmargin "
999 << VSpace(leftmargin).asLyXCommand() << '\n';
1000 if (!topmargin.empty())
1001 os << "\\topmargin "
1002 << VSpace(topmargin).asLyXCommand() << '\n';
1003 if (!rightmargin.empty())
1004 os << "\\rightmargin "
1005 << VSpace(rightmargin).asLyXCommand() << '\n';
1006 if (!bottommargin.empty())
1007 os << "\\bottommargin "
1008 << VSpace(bottommargin).asLyXCommand() << '\n';
1009 if (!headheight.empty())
1010 os << "\\headheight "
1011 << VSpace(headheight).asLyXCommand() << '\n';
1012 if (!headsep.empty())
1014 << VSpace(headsep).asLyXCommand() << '\n';
1015 if (!footskip.empty())
1017 << VSpace(footskip).asLyXCommand() << '\n';
1018 if (!columnsep.empty())
1019 os << "\\columnsep "
1020 << VSpace(columnsep).asLyXCommand() << '\n';
1021 os << "\\secnumdepth " << secnumdepth
1022 << "\n\\tocdepth " << tocdepth
1023 << "\n\\paragraph_separation "
1024 << string_paragraph_separation[paragraph_separation];
1025 if (!paragraph_separation)
1026 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1028 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1029 os << "\n\\quotes_language "
1030 << string_quotes_language[quotes_language]
1031 << "\n\\papercolumns " << columns
1032 << "\n\\papersides " << sides
1033 << "\n\\paperpagestyle " << pagestyle << '\n';
1034 if (!listings_params.empty())
1035 os << "\\listings_params \"" <<
1036 InsetListingsParams(listings_params).encodedString() << "\"\n";
1037 for (int i = 0; i < 4; ++i) {
1038 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1039 if (user_defined_bullet(i).getFont() != -1) {
1040 os << "\\bullet " << i << " "
1041 << user_defined_bullet(i).getFont() << " "
1042 << user_defined_bullet(i).getCharacter() << " "
1043 << user_defined_bullet(i).getSize() << "\n";
1047 os << "\\bulletLaTeX " << i << " \""
1048 << lyx::to_ascii(user_defined_bullet(i).getText())
1054 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1055 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1056 << "\\html_math_output " << html_math_output << '\n'
1057 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1059 if (html_math_img_scale != 1.0)
1060 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1061 if (!html_latex_start.empty())
1062 os << "\\html_latex_start " << html_latex_start << '\n';
1063 if (!html_latex_end.empty())
1064 os << "\\html_latex_end " << html_latex_end << '\n';
1066 os << pimpl_->authorlist;
1070 void BufferParams::validate(LaTeXFeatures & features) const
1072 features.require(documentClass().requires());
1074 if (outputChanges) {
1075 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1076 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1077 LaTeXFeatures::isAvailable("xcolor");
1079 switch (features.runparams().flavor) {
1080 case OutputParams::LATEX:
1082 features.require("ct-dvipost");
1083 features.require("dvipost");
1084 } else if (xcolorulem) {
1085 features.require("ct-xcolor-ulem");
1086 features.require("ulem");
1087 features.require("xcolor");
1089 features.require("ct-none");
1092 case OutputParams::PDFLATEX:
1093 case OutputParams::XETEX:
1095 features.require("ct-xcolor-ulem");
1096 features.require("ulem");
1097 features.require("xcolor");
1098 // improves color handling in PDF output
1099 features.require("pdfcolmk");
1101 features.require("ct-none");
1109 // Floats with 'Here definitely' as default setting.
1110 if (float_placement.find('H') != string::npos)
1111 features.require("float");
1113 // AMS Style is at document level
1114 if (use_amsmath == package_on
1115 || documentClass().provides("amsmath"))
1116 features.require("amsmath");
1117 if (use_esint == package_on)
1118 features.require("esint");
1119 if (use_mhchem == package_on)
1120 features.require("mhchem");
1122 // Document-level line spacing
1123 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1124 features.require("setspace");
1126 // the bullet shapes are buffer level not paragraph level
1127 // so they are tested here
1128 for (int i = 0; i < 4; ++i) {
1129 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1131 int const font = user_defined_bullet(i).getFont();
1133 int const c = user_defined_bullet(i).getCharacter();
1139 features.require("latexsym");
1141 } else if (font == 1) {
1142 features.require("amssymb");
1143 } else if (font >= 2 && font <= 5) {
1144 features.require("pifont");
1148 if (pdfoptions().use_hyperref) {
1149 features.require("hyperref");
1150 // due to interferences with babel and hyperref, the color package has to
1151 // be loaded after hyperref when hyperref is used with the colorlinks
1152 // option, see http://www.lyx.org/trac/ticket/5291
1153 if (pdfoptions().colorlinks)
1154 features.require("color");
1158 features.require("xetex");
1160 if (language->lang() == "vietnamese")
1161 features.require("vietnamese");
1162 else if (language->lang() == "japanese")
1163 features.require("japanese");
1167 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1168 TexRow & texrow, FileName const & filepath) const
1170 os << "\\documentclass";
1172 DocumentClass const & tclass = documentClass();
1174 ostringstream clsoptions; // the document class options.
1176 if (tokenPos(tclass.opt_fontsize(),
1177 '|', fontsize) >= 0) {
1178 // only write if existing in list (and not default)
1179 clsoptions << fontsize << "pt,";
1182 // all paper sizes except of A4, A5, B5 and the US sizes need the
1184 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1185 && papersize != PAPER_USLETTER
1186 && papersize != PAPER_USLEGAL
1187 && papersize != PAPER_USEXECUTIVE
1188 && papersize != PAPER_A4
1189 && papersize != PAPER_A5
1190 && papersize != PAPER_B5;
1192 if (!use_geometry) {
1193 switch (papersize) {
1195 clsoptions << "a4paper,";
1197 case PAPER_USLETTER:
1198 clsoptions << "letterpaper,";
1201 clsoptions << "a5paper,";
1204 clsoptions << "b5paper,";
1206 case PAPER_USEXECUTIVE:
1207 clsoptions << "executivepaper,";
1210 clsoptions << "legalpaper,";
1237 if (sides != tclass.sides()) {
1240 clsoptions << "oneside,";
1243 clsoptions << "twoside,";
1249 if (columns != tclass.columns()) {
1251 clsoptions << "twocolumn,";
1253 clsoptions << "onecolumn,";
1257 && orientation == ORIENTATION_LANDSCAPE)
1258 clsoptions << "landscape,";
1260 // language should be a parameter to \documentclass
1261 if (language->babel() == "hebrew"
1262 && default_language->babel() != "hebrew")
1263 // This seems necessary
1264 features.useLanguage(default_language);
1266 ostringstream language_options;
1267 bool const use_babel = features.useBabel();
1269 language_options << features.getLanguages();
1270 if (!language->babel().empty()) {
1271 if (!language_options.str().empty())
1272 language_options << ',';
1273 language_options << language->babel();
1275 // if Vietnamese is used, babel must directly be loaded
1276 // with language options, not in the class options, see
1277 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1278 size_t viet = language_options.str().find("vietnam");
1279 // viet = string::npos when not found
1280 // the same is for all other languages that are not directly supported by
1281 // babel, but where LaTeX-packages add babel support.
1282 // this is currently the case for Latvian, Lithuanian, Mongolian
1284 size_t latvian = language_options.str().find("latvian");
1285 size_t lithu = language_options.str().find("lithuanian");
1286 size_t mongo = language_options.str().find("mongolian");
1287 size_t turkmen = language_options.str().find("turkmen");
1288 // if Japanese is used, babel must directly be loaded
1289 // with language options, not in the class options, see
1290 // http://www.lyx.org/trac/ticket/4597#c4
1291 size_t japan = language_options.str().find("japanese");
1292 if (lyxrc.language_global_options && !language_options.str().empty()
1293 && viet == string::npos && japan == string::npos
1294 && latvian == string::npos && lithu == string::npos
1295 && mongo == string::npos && turkmen == string::npos)
1296 clsoptions << language_options.str() << ',';
1299 // the predefined options from the layout
1300 if (use_default_options && !tclass.options().empty())
1301 clsoptions << tclass.options() << ',';
1303 // the user-defined options
1304 if (!options.empty()) {
1305 clsoptions << options << ',';
1308 string strOptions(clsoptions.str());
1309 if (!strOptions.empty()) {
1310 strOptions = rtrim(strOptions, ",");
1312 os << '[' << from_utf8(strOptions) << ']';
1315 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1317 // end of \documentclass defs
1320 os << "\\usepackage{fontspec}\n";
1324 // font selection must be done before loading fontenc.sty
1325 string const fonts =
1326 loadFonts(fontsRoman, fontsSans,
1327 fontsTypewriter, fontsSC, fontsOSF,
1328 fontsSansScale, fontsTypewriterScale, useXetex);
1329 if (!fonts.empty()) {
1330 os << from_ascii(fonts);
1333 if (fontsDefaultFamily != "default")
1334 os << "\\renewcommand{\\familydefault}{\\"
1335 << from_ascii(fontsDefaultFamily) << "}\n";
1337 // set font encoding
1338 // for arabic_arabi and farsi we also need to load the LAE and
1340 // XeTeX works without fontenc
1341 if (font_encoding() != "default" && language->lang() != "japanese"
1343 size_t fars = language_options.str().find("farsi");
1344 size_t arab = language_options.str().find("arabic");
1345 if (language->lang() == "arabic_arabi"
1346 || language->lang() == "farsi" || fars != string::npos
1347 || arab != string::npos) {
1348 os << "\\usepackage[" << from_ascii(font_encoding())
1349 << ",LFE,LAE]{fontenc}\n";
1352 os << "\\usepackage[" << from_ascii(font_encoding())
1358 // handle inputenc etc.
1359 writeEncodingPreamble(os, features, texrow);
1362 if (!features.runparams().includeall && !includedChildren_.empty()) {
1363 os << "\\includeonly{";
1364 list<string>::const_iterator it = includedChildren_.begin();
1366 for (; it != includedChildren_.end() ; ++it) {
1367 string incfile = *it;
1368 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1369 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1371 if (!features.runparams().nice)
1373 // \includeonly doesn't want an extension
1374 incfile = changeExtension(incfile, string());
1375 incfile = support::latex_path(incfile);
1376 if (!incfile.empty()) {
1379 os << from_utf8(incfile);
1386 if (!listings_params.empty() || features.isRequired("listings")) {
1387 os << "\\usepackage{listings}\n";
1390 if (!listings_params.empty()) {
1392 // do not test validity because listings_params is
1393 // supposed to be valid
1395 InsetListingsParams(listings_params).separatedParams(true);
1396 // we can't support all packages, but we should load the color package
1397 if (par.find("\\color", 0) != string::npos)
1398 features.require("color");
1399 os << from_utf8(par);
1400 // count the number of newlines
1401 for (size_t i = 0; i < par.size(); ++i)
1407 if (!tclass.provides("geometry")
1408 && (use_geometry || nonstandard_papersize)) {
1409 odocstringstream ods;
1410 if (!getGraphicsDriver("geometry").empty())
1411 ods << getGraphicsDriver("geometry");
1412 if (orientation == ORIENTATION_LANDSCAPE)
1413 ods << ",landscape";
1414 switch (papersize) {
1416 if (!paperwidth.empty())
1417 ods << ",paperwidth="
1418 << from_ascii(paperwidth);
1419 if (!paperheight.empty())
1420 ods << ",paperheight="
1421 << from_ascii(paperheight);
1423 case PAPER_USLETTER:
1424 ods << ",letterpaper";
1427 ods << ",legalpaper";
1429 case PAPER_USEXECUTIVE:
1430 ods << ",executivepaper";
1496 // default papersize ie PAPER_DEFAULT
1497 switch (lyxrc.default_papersize) {
1498 case PAPER_DEFAULT: // keep compiler happy
1499 case PAPER_USLETTER:
1500 ods << ",letterpaper";
1503 ods << ",legalpaper";
1505 case PAPER_USEXECUTIVE:
1506 ods << ",executivepaper";
1541 docstring const g_options = trim(ods.str(), ",");
1542 os << "\\usepackage";
1543 if (!g_options.empty())
1544 os << '[' << g_options << ']';
1545 os << "{geometry}\n";
1547 // output this if only use_geometry is true
1549 os << "\\geometry{verbose";
1550 if (!topmargin.empty())
1551 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1552 if (!bottommargin.empty())
1553 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1554 if (!leftmargin.empty())
1555 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1556 if (!rightmargin.empty())
1557 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1558 if (!headheight.empty())
1559 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1560 if (!headsep.empty())
1561 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1562 if (!footskip.empty())
1563 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1564 if (!columnsep.empty())
1565 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1569 } else if (orientation == ORIENTATION_LANDSCAPE
1570 || papersize != PAPER_DEFAULT) {
1571 features.require("papersize");
1574 if (tokenPos(tclass.opt_pagestyle(),
1575 '|', pagestyle) >= 0) {
1576 if (pagestyle == "fancy") {
1577 os << "\\usepackage{fancyhdr}\n";
1580 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1584 // only output when the background color is not default
1585 if (isbackgroundcolor == true) {
1586 // only require color here, the background color will be defined
1587 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1589 features.require("color");
1590 features.require("pagecolor");
1593 // only output when the font color is not default
1594 if (isfontcolor == true) {
1595 // only require color here, the font color will be defined
1596 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1598 features.require("color");
1599 features.require("fontcolor");
1602 // Only if class has a ToC hierarchy
1603 if (tclass.hasTocLevels()) {
1604 if (secnumdepth != tclass.secnumdepth()) {
1605 os << "\\setcounter{secnumdepth}{"
1610 if (tocdepth != tclass.tocdepth()) {
1611 os << "\\setcounter{tocdepth}{"
1618 if (paragraph_separation) {
1619 // when skip separation
1620 switch (getDefSkip().kind()) {
1621 case VSpace::SMALLSKIP:
1622 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1624 case VSpace::MEDSKIP:
1625 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1627 case VSpace::BIGSKIP:
1628 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1630 case VSpace::LENGTH:
1631 os << "\\setlength{\\parskip}{"
1632 << from_utf8(getDefSkip().length().asLatexString())
1635 default: // should never happen // Then delete it.
1636 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1640 os << "\\setlength{\\parindent}{0pt}\n";
1643 // when separation by indentation
1644 // only output something when a width is given
1645 if (getIndentation().asLyXCommand() != "default") {
1646 os << "\\setlength{\\parindent}{"
1647 << from_utf8(getIndentation().asLatexCommand())
1653 // Now insert the LyX specific LaTeX commands...
1654 docstring lyxpreamble;
1656 // due to interferences with babel and hyperref, the color package has to
1657 // be loaded (when it is not already loaded) before babel when hyperref
1658 // is used with the colorlinks option, see
1659 // http://www.lyx.org/trac/ticket/5291
1660 // we decided therefore to load color always before babel, see
1661 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1662 lyxpreamble += from_ascii(features.getColorOptions());
1664 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1666 && (features.isRequired("jurabib")
1667 || features.isRequired("hyperref")
1668 || features.isRequired("vietnamese")
1669 || features.isRequired("japanese") ) ) {
1671 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1672 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1675 // The optional packages;
1676 lyxpreamble += from_ascii(features.getPackages());
1678 // Additional Indices
1679 if (features.isRequired("splitidx")) {
1680 IndicesList::const_iterator iit = indiceslist().begin();
1681 IndicesList::const_iterator iend = indiceslist().end();
1682 for (; iit != iend; ++iit) {
1683 lyxpreamble += "\\newindex[";
1684 lyxpreamble += iit->index();
1685 lyxpreamble += "]{";
1686 lyxpreamble += iit->shortcut();
1687 lyxpreamble += "}\n";
1692 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1695 // * Hyperref manual: "Make sure it comes last of your loaded
1696 // packages, to give it a fighting chance of not being over-written,
1697 // since its job is to redefine many LaTeX commands."
1698 // * Email from Heiko Oberdiek: "It is usually better to load babel
1699 // before hyperref. Then hyperref has a chance to detect babel.
1700 // * Has to be loaded before the "LyX specific LaTeX commands" to
1701 // avoid errors with algorithm floats.
1702 // use hyperref explicitly if it is required
1703 if (features.isRequired("hyperref")) {
1704 // pass what we have to stream here, since we need
1705 // to access the stream itself in PDFOptions.
1709 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1711 OutputParams tmp_params = features.runparams();
1712 lines += pdfoptions().writeLaTeX(tmp_params, os,
1713 documentClass().provides("hyperref"));
1714 texrow.newlines(lines);
1715 // set back for the rest
1716 lyxpreamble.clear();
1719 // Will be surrounded by \makeatletter and \makeatother when not empty
1720 docstring atlyxpreamble;
1722 // Some macros LyX will need
1723 docstring tmppreamble(features.getMacros());
1725 if (!tmppreamble.empty())
1726 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1727 "LyX specific LaTeX commands.\n"
1728 + tmppreamble + '\n';
1730 // the text class specific preamble
1731 tmppreamble = features.getTClassPreamble();
1732 if (!tmppreamble.empty())
1733 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1734 "Textclass specific LaTeX commands.\n"
1735 + tmppreamble + '\n';
1737 // suppress date if selected
1738 // use \@ifundefined because we cannot be sure that every document class
1739 // has a \date command
1741 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1743 /* the user-defined preamble */
1744 if (!containsOnly(preamble, " \n\t"))
1746 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1747 "User specified LaTeX commands.\n"
1748 + from_utf8(preamble) + '\n';
1750 // subfig loads internally the LaTeX package "caption". As
1751 // caption is a very popular package, users will load it in
1752 // the preamble. Therefore we must load subfig behind the
1753 // user-defined preamble and check if the caption package was
1754 // loaded or not. For the case that caption is loaded before
1755 // subfig, there is the subfig option "caption=false". This
1756 // option also works when a koma-script class is used and
1757 // koma's own caption commands are used instead of caption. We
1758 // use \PassOptionsToPackage here because the user could have
1759 // already loaded subfig in the preamble.
1760 if (features.isRequired("subfig")) {
1761 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1762 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1763 "\\usepackage{subfig}\n";
1766 // Itemize bullet settings need to be last in case the user
1767 // defines their own bullets that use a package included
1768 // in the user-defined preamble -- ARRae
1769 // Actually it has to be done much later than that
1770 // since some packages like frenchb make modifications
1771 // at \begin{document} time -- JMarc
1772 docstring bullets_def;
1773 for (int i = 0; i < 4; ++i) {
1774 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1775 if (bullets_def.empty())
1776 bullets_def += "\\AtBeginDocument{\n";
1777 bullets_def += " \\def\\labelitemi";
1779 // `i' is one less than the item to modify
1786 bullets_def += "ii";
1792 bullets_def += '{' +
1793 user_defined_bullet(i).getText()
1798 if (!bullets_def.empty())
1799 atlyxpreamble += bullets_def + "}\n\n";
1801 if (!atlyxpreamble.empty())
1802 lyxpreamble += "\n\\makeatletter\n"
1803 + atlyxpreamble + "\\makeatother\n\n";
1805 // We try to load babel late, in case it interferes with other packages.
1806 // Jurabib and Hyperref have to be called after babel, though.
1807 if (use_babel && !features.isRequired("jurabib")
1808 && !features.isRequired("hyperref")
1809 && !features.isRequired("vietnamese")
1810 && !features.isRequired("japanese")) {
1812 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1813 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1816 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1817 if (!i18npreamble.empty())
1818 lyxpreamble += i18npreamble + '\n';
1821 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1822 texrow.newlines(nlines);
1826 // these packages (xunicode, for that matter) need to be loaded at least
1827 // after amsmath, amssymb, esint and the other packages that provide
1830 os << "\\usepackage{xunicode}\n";
1832 os << "\\usepackage{xltxtra}\n";
1839 void BufferParams::useClassDefaults()
1841 DocumentClass const & tclass = documentClass();
1843 sides = tclass.sides();
1844 columns = tclass.columns();
1845 pagestyle = tclass.pagestyle();
1846 use_default_options = true;
1847 // Only if class has a ToC hierarchy
1848 if (tclass.hasTocLevels()) {
1849 secnumdepth = tclass.secnumdepth();
1850 tocdepth = tclass.tocdepth();
1855 bool BufferParams::hasClassDefaults() const
1857 DocumentClass const & tclass = documentClass();
1859 return sides == tclass.sides()
1860 && columns == tclass.columns()
1861 && pagestyle == tclass.pagestyle()
1862 && use_default_options
1863 && secnumdepth == tclass.secnumdepth()
1864 && tocdepth == tclass.tocdepth();
1868 DocumentClass const & BufferParams::documentClass() const
1874 DocumentClass const * BufferParams::documentClassPtr() const {
1879 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1880 // evil, but this function is evil
1881 doc_class_ = const_cast<DocumentClass *>(tc);
1885 bool BufferParams::setBaseClass(string const & classname)
1887 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1888 LayoutFileList & bcl = LayoutFileList::get();
1889 if (!bcl.haveClass(classname)) {
1891 bformat(_("The layout file:\n"
1893 "could not be found. A default textclass with default\n"
1894 "layouts will be used. LyX will not be able to produce\n"
1896 from_utf8(classname));
1897 frontend::Alert::error(_("Document class not found"), s);
1898 bcl.addEmptyClass(classname);
1901 bool const success = bcl[classname].load();
1904 bformat(_("Due to some error in it, the layout file:\n"
1906 "could not be loaded. A default textclass with default\n"
1907 "layouts will be used. LyX will not be able to produce\n"
1909 from_utf8(classname));
1910 frontend::Alert::error(_("Could not load class"), s);
1911 bcl.addEmptyClass(classname);
1914 pimpl_->baseClass_ = classname;
1915 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1920 LayoutFile const * BufferParams::baseClass() const
1922 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1923 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1929 LayoutFileIndex const & BufferParams::baseClassID() const
1931 return pimpl_->baseClass_;
1935 void BufferParams::makeDocumentClass()
1940 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1942 if (!local_layout.empty()) {
1943 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1944 docstring const msg = _("Error reading internal layout information");
1945 frontend::Alert::warning(_("Read Error"), msg);
1951 bool BufferParams::moduleCanBeAdded(string const & modName) const
1953 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1957 bool BufferParams::addLayoutModule(string const & modName)
1959 LayoutModuleList::const_iterator it = layoutModules_.begin();
1960 LayoutModuleList::const_iterator end = layoutModules_.end();
1961 for (; it != end; it++)
1964 layoutModules_.push_back(modName);
1969 Font const BufferParams::getFont() const
1971 FontInfo f = documentClass().defaultfont();
1972 if (fontsDefaultFamily == "rmdefault")
1973 f.setFamily(ROMAN_FAMILY);
1974 else if (fontsDefaultFamily == "sfdefault")
1975 f.setFamily(SANS_FAMILY);
1976 else if (fontsDefaultFamily == "ttdefault")
1977 f.setFamily(TYPEWRITER_FAMILY);
1978 return Font(f, language);
1982 void BufferParams::readPreamble(Lexer & lex)
1984 if (lex.getString() != "\\begin_preamble")
1985 lyxerr << "Error (BufferParams::readPreamble):"
1986 "consistency check failed." << endl;
1988 preamble = lex.getLongString("\\end_preamble");
1992 void BufferParams::readLocalLayout(Lexer & lex)
1994 if (lex.getString() != "\\begin_local_layout")
1995 lyxerr << "Error (BufferParams::readLocalLayout):"
1996 "consistency check failed." << endl;
1998 local_layout = lex.getLongString("\\end_local_layout");
2002 void BufferParams::readLanguage(Lexer & lex)
2004 if (!lex.next()) return;
2006 string const tmptok = lex.getString();
2008 // check if tmptok is part of tex_babel in tex-defs.h
2009 language = languages.getLanguage(tmptok);
2011 // Language tmptok was not found
2012 language = default_language;
2013 lyxerr << "Warning: Setting language `"
2014 << tmptok << "' to `" << language->lang()
2020 void BufferParams::readGraphicsDriver(Lexer & lex)
2025 string const tmptok = lex.getString();
2026 // check if tmptok is part of tex_graphics in tex_defs.h
2029 string const test = tex_graphics[n++];
2031 if (test == tmptok) {
2032 graphicsDriver = tmptok;
2037 "Warning: graphics driver `$$Token' not recognized!\n"
2038 " Setting graphics driver to `default'.\n");
2039 graphicsDriver = "default";
2046 void BufferParams::readBullets(Lexer & lex)
2051 int const index = lex.getInteger();
2053 int temp_int = lex.getInteger();
2054 user_defined_bullet(index).setFont(temp_int);
2055 temp_bullet(index).setFont(temp_int);
2057 user_defined_bullet(index).setCharacter(temp_int);
2058 temp_bullet(index).setCharacter(temp_int);
2060 user_defined_bullet(index).setSize(temp_int);
2061 temp_bullet(index).setSize(temp_int);
2065 void BufferParams::readBulletsLaTeX(Lexer & lex)
2067 // The bullet class should be able to read this.
2070 int const index = lex.getInteger();
2072 docstring const temp_str = lex.getDocString();
2074 user_defined_bullet(index).setText(temp_str);
2075 temp_bullet(index).setText(temp_str);
2079 void BufferParams::readModules(Lexer & lex)
2081 if (!lex.eatLine()) {
2082 lyxerr << "Error (BufferParams::readModules):"
2083 "Unexpected end of input." << endl;
2087 string mod = lex.getString();
2088 if (mod == "\\end_modules")
2090 addLayoutModule(mod);
2096 void BufferParams::readRemovedModules(Lexer & lex)
2098 if (!lex.eatLine()) {
2099 lyxerr << "Error (BufferParams::readRemovedModules):"
2100 "Unexpected end of input." << endl;
2104 string mod = lex.getString();
2105 if (mod == "\\end_removed_modules")
2107 removedModules_.push_back(mod);
2110 // now we want to remove any removed modules that were previously
2111 // added. normally, that will be because default modules were added in
2112 // setBaseClass(), which gets called when \textclass is read at the
2113 // start of the read.
2114 list<string>::const_iterator rit = removedModules_.begin();
2115 list<string>::const_iterator const ren = removedModules_.end();
2116 for (; rit != ren; rit++) {
2117 LayoutModuleList::iterator const mit = layoutModules_.begin();
2118 LayoutModuleList::iterator const men = layoutModules_.end();
2119 LayoutModuleList::iterator found = find(mit, men, *rit);
2122 layoutModules_.erase(found);
2127 void BufferParams::readIncludeonly(Lexer & lex)
2129 if (!lex.eatLine()) {
2130 lyxerr << "Error (BufferParams::readIncludeonly):"
2131 "Unexpected end of input." << endl;
2135 string child = lex.getString();
2136 if (child == "\\end_includeonly")
2138 includedChildren_.push_back(child);
2144 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2146 char real_papersize = papersize;
2147 if (real_papersize == PAPER_DEFAULT)
2148 real_papersize = lyxrc.default_papersize;
2150 switch (real_papersize) {
2152 // could be anything, so don't guess
2154 case PAPER_CUSTOM: {
2155 if (purpose == XDVI && !paperwidth.empty() &&
2156 !paperheight.empty()) {
2157 // heightxwidth<unit>
2158 string first = paperwidth;
2159 string second = paperheight;
2160 if (orientation == ORIENTATION_LANDSCAPE)
2163 return first.erase(first.length() - 2)
2169 // dvips and dvipdfm do not know this
2170 if (purpose == DVIPS || purpose == DVIPDFM)
2174 if (purpose == DVIPS || purpose == DVIPDFM)
2178 if (purpose == DVIPS || purpose == DVIPDFM)
2188 if (purpose == DVIPS || purpose == DVIPDFM)
2192 if (purpose == DVIPS || purpose == DVIPDFM)
2196 if (purpose == DVIPS || purpose == DVIPDFM)
2200 if (purpose == DVIPS || purpose == DVIPDFM)
2204 if (purpose == DVIPS || purpose == DVIPDFM)
2208 // dvipdfm does not know this
2209 if (purpose == DVIPDFM)
2213 if (purpose == DVIPDFM)
2217 if (purpose == DVIPS || purpose == DVIPDFM)
2221 if (purpose == DVIPS || purpose == DVIPDFM)
2225 if (purpose == DVIPS || purpose == DVIPDFM)
2229 if (purpose == DVIPS || purpose == DVIPDFM)
2233 if (purpose == DVIPS || purpose == DVIPDFM)
2237 if (purpose == DVIPS || purpose == DVIPDFM)
2241 if (purpose == DVIPS || purpose == DVIPDFM)
2245 if (purpose == DVIPS || purpose == DVIPDFM)
2248 case PAPER_USEXECUTIVE:
2249 // dvipdfm does not know this
2250 if (purpose == DVIPDFM)
2255 case PAPER_USLETTER:
2257 if (purpose == XDVI)
2264 string const BufferParams::dvips_options() const
2269 && papersize == PAPER_CUSTOM
2270 && !lyxrc.print_paper_dimension_flag.empty()
2271 && !paperwidth.empty()
2272 && !paperheight.empty()) {
2273 // using a custom papersize
2274 result = lyxrc.print_paper_dimension_flag;
2275 result += ' ' + paperwidth;
2276 result += ',' + paperheight;
2278 string const paper_option = paperSizeName(DVIPS);
2279 if (!paper_option.empty() && (paper_option != "letter" ||
2280 orientation != ORIENTATION_LANDSCAPE)) {
2281 // dvips won't accept -t letter -t landscape.
2282 // In all other cases, include the paper size
2284 result = lyxrc.print_paper_flag;
2285 result += ' ' + paper_option;
2288 if (orientation == ORIENTATION_LANDSCAPE &&
2289 papersize != PAPER_CUSTOM)
2290 result += ' ' + lyxrc.print_landscape_flag;
2295 string const BufferParams::font_encoding() const
2297 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2301 string BufferParams::babelCall(string const & lang_opts) const
2303 string lang_pack = lyxrc.language_package;
2304 if (lang_pack != "\\usepackage{babel}")
2306 // suppress the babel call when there is no babel language defined
2307 // for the document language in the lib/languages file and if no
2308 // other languages are used (lang_opts is then empty)
2309 if (lang_opts.empty())
2311 // If Vietnamese is used, babel must directly be loaded with the
2312 // language options, see
2313 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2314 size_t viet = lang_opts.find("vietnam");
2315 // viet = string::npos when not found
2316 // the same is for all other languages that are not directly supported by
2317 // babel, but where LaTeX-packages add babel support.
2318 // this is currently the case for Latvian, Lithuanian, Mongolian
2320 size_t latvian = lang_opts.find("latvian");
2321 size_t lithu = lang_opts.find("lithuanian");
2322 size_t mongo = lang_opts.find("mongolian");
2323 size_t turkmen = lang_opts.find("turkmen");
2324 // If Japanese is used, babel must directly be loaded with the
2325 // language options, see
2326 // http://www.lyx.org/trac/ticket/4597#c4
2327 size_t japan = lang_opts.find("japanese");
2328 if (!lyxrc.language_global_options || viet != string::npos
2329 || japan != string::npos || latvian != string::npos
2330 || lithu != string::npos || mongo != string::npos
2331 || turkmen != string::npos)
2332 return "\\usepackage[" + lang_opts + "]{babel}";
2337 docstring BufferParams::getGraphicsDriver(string const & package) const
2341 if (package == "geometry") {
2342 if (graphicsDriver == "dvips"
2343 || graphicsDriver == "dvipdfm"
2344 || graphicsDriver == "pdftex"
2345 || graphicsDriver == "vtex")
2346 result = from_ascii(graphicsDriver);
2347 else if (graphicsDriver == "dvipdfmx")
2348 result = from_ascii("dvipdfm");
2355 void BufferParams::writeEncodingPreamble(odocstream & os,
2356 LaTeXFeatures & features, TexRow & texrow) const
2360 if (inputenc == "auto") {
2361 string const doc_encoding =
2362 language->encoding()->latexName();
2363 Encoding::Package const package =
2364 language->encoding()->package();
2366 // Create a list with all the input encodings used
2368 set<string> encodings =
2369 features.getEncodingSet(doc_encoding);
2371 // If the "japanese" package (i.e. pLaTeX) is used,
2372 // inputenc must be omitted.
2373 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2374 if (package == Encoding::japanese)
2375 features.require("japanese");
2377 if ((!encodings.empty() || package == Encoding::inputenc)
2378 && !features.isRequired("japanese")) {
2379 os << "\\usepackage[";
2380 set<string>::const_iterator it = encodings.begin();
2381 set<string>::const_iterator const end = encodings.end();
2383 os << from_ascii(*it);
2386 for (; it != end; ++it)
2387 os << ',' << from_ascii(*it);
2388 if (package == Encoding::inputenc) {
2389 if (!encodings.empty())
2391 os << from_ascii(doc_encoding);
2393 os << "]{inputenc}\n";
2396 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2397 if (language->encoding()->name() == "utf8-cjk"
2398 && LaTeXFeatures::isAvailable("CJKutf8"))
2399 os << "\\usepackage{CJKutf8}\n";
2401 os << "\\usepackage{CJK}\n";
2404 } else if (inputenc != "default") {
2405 switch (encoding().package()) {
2406 case Encoding::none:
2407 case Encoding::japanese:
2409 case Encoding::inputenc:
2410 // do not load inputenc if japanese is used
2411 if (features.isRequired("japanese"))
2413 os << "\\usepackage[" << from_ascii(inputenc)
2418 if (encoding().name() == "utf8-cjk"
2419 && LaTeXFeatures::isAvailable("CJKutf8"))
2420 os << "\\usepackage{CJKutf8}\n";
2422 os << "\\usepackage{CJK}\n";
2428 // The encoding "armscii8" (for Armenian) is only available when
2429 // the package "armtex" is loaded.
2430 if (language->encoding()->latexName() == "armscii8"
2431 || inputenc == "armscii8") {
2432 os << "\\usepackage{armtex}\n";
2438 string const BufferParams::parseFontName(string const & name) const
2440 string mangled = name;
2441 size_t const idx = mangled.find('[');
2442 if (idx == string::npos || idx == 0)
2445 return mangled.substr(0, idx - 1);
2449 string const BufferParams::loadFonts(string const & rm,
2450 string const & sf, string const & tt,
2451 bool const & sc, bool const & osf,
2452 int const & sfscale, int const & ttscale,
2453 bool const & xetex) const
2455 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2456 several packages have been replaced by others, that might not
2457 be installed on every system. We have to take care for that
2458 (see psnfss.pdf). We try to support all psnfss fonts as well
2459 as the fonts that have become de facto standard in the LaTeX
2460 world (e.g. Latin Modern). We do not support obsolete fonts
2461 (like PSLatex). In general, it should be possible to mix any
2462 rm font with any sf or tt font, respectively. (JSpitzm)
2464 -- separate math fonts.
2467 if (rm == "default" && sf == "default" && tt == "default")
2474 if (rm != "default")
2475 os << "\\setmainfont[Mapping=tex-text]{"
2476 << parseFontName(rm) << "}\n";
2477 if (sf != "default") {
2478 string const sans = parseFontName(sf);
2480 os << "\\setsansfont[Scale="
2481 << float(sfscale) / 100
2482 << ",Mapping=tex-text]{"
2485 os << "\\setsansfont[Mapping=tex-text]{"
2488 if (tt != "default") {
2489 string const mono = parseFontName(tt);
2491 os << "\\setmonofont[Scale="
2492 << float(sfscale) / 100
2496 os << "\\setmonofont[Mapping=tex-text]{"
2500 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2505 // Computer Modern (must be explicitly selectable -- there might be classes
2506 // that define a different default font!
2508 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2509 // osf for Computer Modern needs eco.sty
2511 os << "\\usepackage{eco}\n";
2513 // Latin Modern Roman
2514 else if (rm == "lmodern")
2515 os << "\\usepackage{lmodern}\n";
2517 else if (rm == "ae") {
2518 // not needed when using OT1 font encoding.
2519 if (font_encoding() != "default")
2520 os << "\\usepackage{ae,aecompl}\n";
2523 else if (rm == "times") {
2524 // try to load the best available package
2525 if (LaTeXFeatures::isAvailable("mathptmx"))
2526 os << "\\usepackage{mathptmx}\n";
2527 else if (LaTeXFeatures::isAvailable("mathptm"))
2528 os << "\\usepackage{mathptm}\n";
2530 os << "\\usepackage{times}\n";
2533 else if (rm == "palatino") {
2534 // try to load the best available package
2535 if (LaTeXFeatures::isAvailable("mathpazo")) {
2536 os << "\\usepackage";
2542 // "osf" includes "sc"!
2546 os << "{mathpazo}\n";
2548 else if (LaTeXFeatures::isAvailable("mathpple"))
2549 os << "\\usepackage{mathpple}\n";
2551 os << "\\usepackage{palatino}\n";
2554 else if (rm == "utopia") {
2555 // fourier supersedes utopia.sty, but does
2556 // not work with OT1 encoding.
2557 if (LaTeXFeatures::isAvailable("fourier")
2558 && font_encoding() != "default") {
2559 os << "\\usepackage";
2570 os << "{fourier}\n";
2573 os << "\\usepackage{utopia}\n";
2575 // Bera (complete fontset)
2576 else if (rm == "bera" && sf == "default" && tt == "default")
2577 os << "\\usepackage{bera}\n";
2579 else if (rm != "default")
2580 os << "\\usepackage" << "{" << rm << "}\n";
2583 // Helvetica, Bera Sans
2584 if (sf == "helvet" || sf == "berasans") {
2586 os << "\\usepackage[scaled=" << float(sfscale) / 100
2587 << "]{" << sf << "}\n";
2589 os << "\\usepackage{" << sf << "}\n";
2592 else if (sf == "avant")
2593 os << "\\usepackage{" << sf << "}\n";
2594 // Computer Modern, Latin Modern, CM Bright
2595 else if (sf != "default")
2596 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2598 // monospaced/typewriter
2599 // Courier, LuxiMono
2600 if (tt == "luximono" || tt == "beramono") {
2602 os << "\\usepackage[scaled=" << float(ttscale) / 100
2603 << "]{" << tt << "}\n";
2605 os << "\\usepackage{" << tt << "}\n";
2608 else if (tt == "courier" )
2609 os << "\\usepackage{" << tt << "}\n";
2610 // Computer Modern, Latin Modern, CM Bright
2611 else if (tt != "default")
2612 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2618 Encoding const & BufferParams::encoding() const
2621 return *(encodings.fromLaTeXName("utf8-plain"));
2622 if (inputenc == "auto" || inputenc == "default")
2623 return *language->encoding();
2624 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2627 LYXERR0("Unknown inputenc value `" << inputenc
2628 << "'. Using `auto' instead.");
2629 return *language->encoding();
2633 CiteEngine BufferParams::citeEngine() const
2635 // FIXME the class should provide the numerical/
2636 // authoryear choice
2637 if (documentClass().provides("natbib")
2638 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2639 return ENGINE_NATBIB_AUTHORYEAR;
2640 return cite_engine_;
2644 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2646 cite_engine_ = cite_engine;