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;
407 html_latex_start = "<span class='latex'>";
408 html_latex_end = "</span>";
412 docstring BufferParams::B_(string const & l10n) const
414 LASSERT(language, /**/);
415 return getMessages(language->code()).get(l10n);
419 AuthorList & BufferParams::authors()
421 return pimpl_->authorlist;
425 AuthorList const & BufferParams::authors() const
427 return pimpl_->authorlist;
431 BranchList & BufferParams::branchlist()
433 return pimpl_->branchlist;
437 BranchList const & BufferParams::branchlist() const
439 return pimpl_->branchlist;
443 IndicesList & BufferParams::indiceslist()
445 return pimpl_->indiceslist;
449 IndicesList const & BufferParams::indiceslist() const
451 return pimpl_->indiceslist;
455 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
457 LASSERT(index < 4, /**/);
458 return pimpl_->temp_bullets[index];
462 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
464 LASSERT(index < 4, /**/);
465 return pimpl_->temp_bullets[index];
469 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
471 LASSERT(index < 4, /**/);
472 return pimpl_->user_defined_bullets[index];
476 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
478 LASSERT(index < 4, /**/);
479 return pimpl_->user_defined_bullets[index];
483 Spacing & BufferParams::spacing()
485 return pimpl_->spacing;
489 Spacing const & BufferParams::spacing() const
491 return pimpl_->spacing;
495 PDFOptions & BufferParams::pdfoptions()
497 return pimpl_->pdfoptions;
501 PDFOptions const & BufferParams::pdfoptions() const
503 return pimpl_->pdfoptions;
507 HSpace const & BufferParams::getIndentation() const
509 return pimpl_->indentation;
513 void BufferParams::setIndentation(HSpace const & indent)
515 pimpl_->indentation = indent;
519 VSpace const & BufferParams::getDefSkip() const
521 return pimpl_->defskip;
525 void BufferParams::setDefSkip(VSpace const & vs)
527 pimpl_->defskip = vs;
531 string BufferParams::readToken(Lexer & lex, string const & token,
532 FileName const & filepath)
534 if (token == "\\textclass") {
536 string const classname = lex.getString();
537 // if there exists a local layout file, ignore the system one
538 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
540 LayoutFileList & bcl = LayoutFileList::get();
541 if (tcp.empty() && !filepath.empty())
542 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
546 setBaseClass(classname);
547 // We assume that a tex class exists for local or unknown layouts so this warning
548 // will only be given for system layouts.
549 if (!baseClass()->isTeXClassAvailable()) {
551 translateIfPossible(from_utf8(baseClass()->description()));
552 docstring const msg =
553 bformat(_("The used document class\n"
555 "requires external files that are not available.\n"
556 "The document class can still be used, but LyX\n"
557 "will not be able to produce output until the\n"
558 "following prerequisites are installed:\n"
560 "See section 3.1.2.2 of the User's Guide for\n"
561 "more information."),
562 desc, from_utf8(baseClass()->prerequisites()));
563 frontend::Alert::warning(_("Document class not available"),
566 } else if (token == "\\begin_preamble") {
568 } else if (token == "\\begin_local_layout") {
569 readLocalLayout(lex);
570 } else if (token == "\\begin_modules") {
572 } else if (token == "\\begin_removed_modules") {
573 readRemovedModules(lex);
574 } else if (token == "\\begin_includeonly") {
575 readIncludeonly(lex);
576 } else if (token == "\\maintain_unincluded_children") {
577 lex >> maintain_unincluded_children;
578 } else if (token == "\\options") {
580 options = lex.getString();
581 } else if (token == "\\use_default_options") {
582 lex >> use_default_options;
583 } else if (token == "\\master") {
585 master = lex.getString();
586 } else if (token == "\\suppress_date") {
587 lex >> suppress_date;
588 } else if (token == "\\language") {
590 } else if (token == "\\inputencoding") {
592 } else if (token == "\\graphics") {
593 readGraphicsDriver(lex);
594 } else if (token == "\\default_output_format") {
595 lex >> defaultOutputFormat;
596 } else if (token == "\\bibtex_command") {
598 bibtex_command = lex.getString();
599 } else if (token == "\\index_command") {
601 index_command = lex.getString();
602 } else if (token == "\\fontencoding") {
604 fontenc = lex.getString();
605 } else if (token == "\\font_roman") {
607 fontsRoman = lex.getString();
608 } else if (token == "\\font_sans") {
610 fontsSans = lex.getString();
611 } else if (token == "\\font_typewriter") {
613 fontsTypewriter = lex.getString();
614 } else if (token == "\\font_default_family") {
615 lex >> fontsDefaultFamily;
616 } else if (token == "\\use_xetex") {
618 } else if (token == "\\font_sc") {
620 } else if (token == "\\font_osf") {
622 } else if (token == "\\font_sf_scale") {
623 lex >> fontsSansScale;
624 } else if (token == "\\font_tt_scale") {
625 lex >> fontsTypewriterScale;
626 } else if (token == "\\font_cjk") {
628 } else if (token == "\\paragraph_separation") {
631 paragraph_separation = parseptranslator().find(parsep);
632 } else if (token == "\\paragraph_indentation") {
634 string indentation = lex.getString();
635 pimpl_->indentation = HSpace(indentation);
636 } else if (token == "\\defskip") {
638 string defskip = lex.getString();
639 if (defskip == "defskip")
642 pimpl_->defskip = VSpace(defskip);
643 } else if (token == "\\quotes_language") {
646 quotes_language = quoteslangtranslator().find(quotes_lang);
647 } else if (token == "\\papersize") {
650 papersize = papersizetranslator().find(ppsize);
651 } else if (token == "\\use_geometry") {
653 } else if (token == "\\use_amsmath") {
656 use_amsmath = packagetranslator().find(use_ams);
657 } else if (token == "\\use_esint") {
660 use_esint = packagetranslator().find(useesint);
661 } else if (token == "\\use_mhchem") {
664 use_mhchem = packagetranslator().find(usemhchem);
665 } else if (token == "\\cite_engine") {
668 cite_engine_ = citeenginetranslator().find(engine);
669 } else if (token == "\\use_bibtopic") {
671 } else if (token == "\\use_indices") {
673 } else if (token == "\\tracking_changes") {
675 } else if (token == "\\output_changes") {
676 lex >> outputChanges;
677 } else if (token == "\\branch") {
679 docstring branch = lex.getDocString();
680 branchlist().add(branch);
683 string const tok = lex.getString();
684 if (tok == "\\end_branch")
686 Branch * branch_ptr = branchlist().find(branch);
687 if (tok == "\\selected") {
690 branch_ptr->setSelected(lex.getInteger());
692 if (tok == "\\filename_suffix") {
695 branch_ptr->setFileNameSuffix(lex.getInteger());
697 if (tok == "\\color") {
699 string color = lex.getString();
701 branch_ptr->setColor(color);
702 // Update also the Color table:
704 color = lcolor.getX11Name(Color_background);
706 lcolor.setColor(to_utf8(branch), color);
709 } else if (token == "\\index") {
711 docstring index = lex.getDocString();
713 indiceslist().add(index);
716 string const tok = lex.getString();
717 if (tok == "\\end_index")
719 Index * index_ptr = indiceslist().find(index);
720 if (tok == "\\shortcut") {
722 shortcut = lex.getDocString();
724 index_ptr->setShortcut(shortcut);
726 if (tok == "\\color") {
728 string color = lex.getString();
730 index_ptr->setColor(color);
731 // Update also the Color table:
733 color = lcolor.getX11Name(Color_background);
735 if (!shortcut.empty())
736 lcolor.setColor(to_utf8(shortcut), color);
739 } else if (token == "\\author") {
741 istringstream ss(lex.getString());
744 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
745 } else if (token == "\\paperorientation") {
748 orientation = paperorientationtranslator().find(orient);
749 } else if (token == "\\backgroundcolor") {
751 backgroundcolor = lyx::rgbFromHexName(lex.getString());
752 isbackgroundcolor = true;
753 } else if (token == "\\fontcolor") {
755 fontcolor = lyx::rgbFromHexName(lex.getString());
757 } else if (token == "\\notefontcolor") {
759 string color = lex.getString();
760 notefontcolor = lyx::rgbFromHexName(color);
761 } else if (token == "\\boxbgcolor") {
763 string color = lex.getString();
764 boxbgcolor = lyx::rgbFromHexName(color);
765 } else if (token == "\\paperwidth") {
767 } else if (token == "\\paperheight") {
769 } else if (token == "\\leftmargin") {
771 } else if (token == "\\topmargin") {
773 } else if (token == "\\rightmargin") {
775 } else if (token == "\\bottommargin") {
777 } else if (token == "\\headheight") {
779 } else if (token == "\\headsep") {
781 } else if (token == "\\footskip") {
783 } else if (token == "\\columnsep") {
785 } else if (token == "\\paperfontsize") {
787 } else if (token == "\\papercolumns") {
789 } else if (token == "\\listings_params") {
792 listings_params = InsetListingsParams(par).params();
793 } else if (token == "\\papersides") {
796 sides = sidestranslator().find(psides);
797 } else if (token == "\\paperpagestyle") {
799 } else if (token == "\\bullet") {
801 } else if (token == "\\bulletLaTeX") {
802 readBulletsLaTeX(lex);
803 } else if (token == "\\secnumdepth") {
805 } else if (token == "\\tocdepth") {
807 } else if (token == "\\spacing") {
811 if (nspacing == "other") {
814 spacing().set(spacetranslator().find(nspacing), tmp_val);
815 } else if (token == "\\float_placement") {
816 lex >> float_placement;
818 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
819 string toktmp = pdfoptions().readToken(lex, token);
820 if (!toktmp.empty()) {
821 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
825 } else if (token == "\\html_math_output") {
828 html_math_output = static_cast<MathOutput>(temp);
829 } else if (token == "\\html_be_strict") {
830 lex >> html_be_strict;
831 } else if (token == "\\html_math_img_scale") {
832 lex >> html_math_img_scale;
833 } else if (token == "\\html_latex_start") {
834 lex >> html_latex_start;
835 } else if (token == "\\html_latex_end") {
836 lex >> html_latex_end;
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'
1058 << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n'
1059 << "\\html_latex_start \"" << html_latex_start << "\"\n"
1060 << "\\html_latex_end \"" << html_latex_end << "\"\n";
1062 os << pimpl_->authorlist;
1066 void BufferParams::validate(LaTeXFeatures & features) const
1068 features.require(documentClass().requires());
1070 if (outputChanges) {
1071 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1072 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1073 LaTeXFeatures::isAvailable("xcolor");
1075 switch (features.runparams().flavor) {
1076 case OutputParams::LATEX:
1078 features.require("ct-dvipost");
1079 features.require("dvipost");
1080 } else if (xcolorulem) {
1081 features.require("ct-xcolor-ulem");
1082 features.require("ulem");
1083 features.require("xcolor");
1085 features.require("ct-none");
1088 case OutputParams::PDFLATEX:
1089 case OutputParams::XETEX:
1091 features.require("ct-xcolor-ulem");
1092 features.require("ulem");
1093 features.require("xcolor");
1094 // improves color handling in PDF output
1095 features.require("pdfcolmk");
1097 features.require("ct-none");
1105 // Floats with 'Here definitely' as default setting.
1106 if (float_placement.find('H') != string::npos)
1107 features.require("float");
1109 // AMS Style is at document level
1110 if (use_amsmath == package_on
1111 || documentClass().provides("amsmath"))
1112 features.require("amsmath");
1113 if (use_esint == package_on)
1114 features.require("esint");
1115 if (use_mhchem == package_on)
1116 features.require("mhchem");
1118 // Document-level line spacing
1119 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1120 features.require("setspace");
1122 // the bullet shapes are buffer level not paragraph level
1123 // so they are tested here
1124 for (int i = 0; i < 4; ++i) {
1125 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1127 int const font = user_defined_bullet(i).getFont();
1129 int const c = user_defined_bullet(i).getCharacter();
1135 features.require("latexsym");
1137 } else if (font == 1) {
1138 features.require("amssymb");
1139 } else if (font >= 2 && font <= 5) {
1140 features.require("pifont");
1144 if (pdfoptions().use_hyperref) {
1145 features.require("hyperref");
1146 // due to interferences with babel and hyperref, the color package has to
1147 // be loaded after hyperref when hyperref is used with the colorlinks
1148 // option, see http://www.lyx.org/trac/ticket/5291
1149 if (pdfoptions().colorlinks)
1150 features.require("color");
1154 features.require("xetex");
1156 if (language->lang() == "vietnamese")
1157 features.require("vietnamese");
1158 else if (language->lang() == "japanese")
1159 features.require("japanese");
1163 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1164 TexRow & texrow, FileName const & filepath) const
1166 os << "\\documentclass";
1168 DocumentClass const & tclass = documentClass();
1170 ostringstream clsoptions; // the document class options.
1172 if (tokenPos(tclass.opt_fontsize(),
1173 '|', fontsize) >= 0) {
1174 // only write if existing in list (and not default)
1175 clsoptions << fontsize << "pt,";
1178 // all paper sizes except of A4, A5, B5 and the US sizes need the
1180 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1181 && papersize != PAPER_USLETTER
1182 && papersize != PAPER_USLEGAL
1183 && papersize != PAPER_USEXECUTIVE
1184 && papersize != PAPER_A4
1185 && papersize != PAPER_A5
1186 && papersize != PAPER_B5;
1188 if (!use_geometry) {
1189 switch (papersize) {
1191 clsoptions << "a4paper,";
1193 case PAPER_USLETTER:
1194 clsoptions << "letterpaper,";
1197 clsoptions << "a5paper,";
1200 clsoptions << "b5paper,";
1202 case PAPER_USEXECUTIVE:
1203 clsoptions << "executivepaper,";
1206 clsoptions << "legalpaper,";
1233 if (sides != tclass.sides()) {
1236 clsoptions << "oneside,";
1239 clsoptions << "twoside,";
1245 if (columns != tclass.columns()) {
1247 clsoptions << "twocolumn,";
1249 clsoptions << "onecolumn,";
1253 && orientation == ORIENTATION_LANDSCAPE)
1254 clsoptions << "landscape,";
1256 // language should be a parameter to \documentclass
1257 if (language->babel() == "hebrew"
1258 && default_language->babel() != "hebrew")
1259 // This seems necessary
1260 features.useLanguage(default_language);
1262 ostringstream language_options;
1263 bool const use_babel = features.useBabel();
1265 language_options << features.getLanguages();
1266 if (!language->babel().empty()) {
1267 if (!language_options.str().empty())
1268 language_options << ',';
1269 language_options << language->babel();
1271 // if Vietnamese is used, babel must directly be loaded
1272 // with language options, not in the class options, see
1273 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1274 size_t viet = language_options.str().find("vietnam");
1275 // viet = string::npos when not found
1276 // the same is for all other languages that are not directly supported by
1277 // babel, but where LaTeX-packages add babel support.
1278 // this is currently the case for Latvian, Lithuanian, Mongolian
1280 size_t latvian = language_options.str().find("latvian");
1281 size_t lithu = language_options.str().find("lithuanian");
1282 size_t mongo = language_options.str().find("mongolian");
1283 size_t turkmen = language_options.str().find("turkmen");
1284 // if Japanese is used, babel must directly be loaded
1285 // with language options, not in the class options, see
1286 // http://www.lyx.org/trac/ticket/4597#c4
1287 size_t japan = language_options.str().find("japanese");
1288 if (lyxrc.language_global_options && !language_options.str().empty()
1289 && viet == string::npos && japan == string::npos
1290 && latvian == string::npos && lithu == string::npos
1291 && mongo == string::npos && turkmen == string::npos)
1292 clsoptions << language_options.str() << ',';
1295 // the predefined options from the layout
1296 if (use_default_options && !tclass.options().empty())
1297 clsoptions << tclass.options() << ',';
1299 // the user-defined options
1300 if (!options.empty()) {
1301 clsoptions << options << ',';
1304 string strOptions(clsoptions.str());
1305 if (!strOptions.empty()) {
1306 strOptions = rtrim(strOptions, ",");
1308 os << '[' << from_utf8(strOptions) << ']';
1311 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1313 // end of \documentclass defs
1316 os << "\\usepackage{fontspec}\n";
1320 // font selection must be done before loading fontenc.sty
1321 string const fonts =
1322 loadFonts(fontsRoman, fontsSans,
1323 fontsTypewriter, fontsSC, fontsOSF,
1324 fontsSansScale, fontsTypewriterScale, useXetex);
1325 if (!fonts.empty()) {
1326 os << from_ascii(fonts);
1329 if (fontsDefaultFamily != "default")
1330 os << "\\renewcommand{\\familydefault}{\\"
1331 << from_ascii(fontsDefaultFamily) << "}\n";
1333 // set font encoding
1334 // for arabic_arabi and farsi we also need to load the LAE and
1336 // XeTeX works without fontenc
1337 if (font_encoding() != "default" && language->lang() != "japanese"
1339 size_t fars = language_options.str().find("farsi");
1340 size_t arab = language_options.str().find("arabic");
1341 if (language->lang() == "arabic_arabi"
1342 || language->lang() == "farsi" || fars != string::npos
1343 || arab != string::npos) {
1344 os << "\\usepackage[" << from_ascii(font_encoding())
1345 << ",LFE,LAE]{fontenc}\n";
1348 os << "\\usepackage[" << from_ascii(font_encoding())
1354 // handle inputenc etc.
1355 writeEncodingPreamble(os, features, texrow);
1358 if (!features.runparams().includeall && !includedChildren_.empty()) {
1359 os << "\\includeonly{";
1360 list<string>::const_iterator it = includedChildren_.begin();
1362 for (; it != includedChildren_.end() ; ++it) {
1363 string incfile = *it;
1364 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1365 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1367 if (!features.runparams().nice)
1369 // \includeonly doesn't want an extension
1370 incfile = changeExtension(incfile, string());
1371 incfile = support::latex_path(incfile);
1372 if (!incfile.empty()) {
1375 os << from_utf8(incfile);
1382 if (!listings_params.empty() || features.isRequired("listings")) {
1383 os << "\\usepackage{listings}\n";
1386 if (!listings_params.empty()) {
1388 // do not test validity because listings_params is
1389 // supposed to be valid
1391 InsetListingsParams(listings_params).separatedParams(true);
1392 // we can't support all packages, but we should load the color package
1393 if (par.find("\\color", 0) != string::npos)
1394 features.require("color");
1395 os << from_utf8(par);
1396 // count the number of newlines
1397 for (size_t i = 0; i < par.size(); ++i)
1403 if (!tclass.provides("geometry")
1404 && (use_geometry || nonstandard_papersize)) {
1405 odocstringstream ods;
1406 if (!getGraphicsDriver("geometry").empty())
1407 ods << getGraphicsDriver("geometry");
1408 if (orientation == ORIENTATION_LANDSCAPE)
1409 ods << ",landscape";
1410 switch (papersize) {
1412 if (!paperwidth.empty())
1413 ods << ",paperwidth="
1414 << from_ascii(paperwidth);
1415 if (!paperheight.empty())
1416 ods << ",paperheight="
1417 << from_ascii(paperheight);
1419 case PAPER_USLETTER:
1420 ods << ",letterpaper";
1423 ods << ",legalpaper";
1425 case PAPER_USEXECUTIVE:
1426 ods << ",executivepaper";
1492 // default papersize ie PAPER_DEFAULT
1493 switch (lyxrc.default_papersize) {
1494 case PAPER_DEFAULT: // keep compiler happy
1495 case PAPER_USLETTER:
1496 ods << ",letterpaper";
1499 ods << ",legalpaper";
1501 case PAPER_USEXECUTIVE:
1502 ods << ",executivepaper";
1537 docstring const g_options = trim(ods.str(), ",");
1538 os << "\\usepackage";
1539 if (!g_options.empty())
1540 os << '[' << g_options << ']';
1541 os << "{geometry}\n";
1543 // output this if only use_geometry is true
1545 os << "\\geometry{verbose";
1546 if (!topmargin.empty())
1547 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1548 if (!bottommargin.empty())
1549 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1550 if (!leftmargin.empty())
1551 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1552 if (!rightmargin.empty())
1553 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1554 if (!headheight.empty())
1555 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1556 if (!headsep.empty())
1557 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1558 if (!footskip.empty())
1559 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1560 if (!columnsep.empty())
1561 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1565 } else if (orientation == ORIENTATION_LANDSCAPE
1566 || papersize != PAPER_DEFAULT) {
1567 features.require("papersize");
1570 if (tokenPos(tclass.opt_pagestyle(),
1571 '|', pagestyle) >= 0) {
1572 if (pagestyle == "fancy") {
1573 os << "\\usepackage{fancyhdr}\n";
1576 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1580 // only output when the background color is not default
1581 if (isbackgroundcolor == true) {
1582 // only require color here, the background color will be defined
1583 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1585 features.require("color");
1586 features.require("pagecolor");
1589 // only output when the font color is not default
1590 if (isfontcolor == true) {
1591 // only require color here, the font color will be defined
1592 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1594 features.require("color");
1595 features.require("fontcolor");
1598 // Only if class has a ToC hierarchy
1599 if (tclass.hasTocLevels()) {
1600 if (secnumdepth != tclass.secnumdepth()) {
1601 os << "\\setcounter{secnumdepth}{"
1606 if (tocdepth != tclass.tocdepth()) {
1607 os << "\\setcounter{tocdepth}{"
1614 if (paragraph_separation) {
1615 // when skip separation
1616 switch (getDefSkip().kind()) {
1617 case VSpace::SMALLSKIP:
1618 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1620 case VSpace::MEDSKIP:
1621 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1623 case VSpace::BIGSKIP:
1624 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1626 case VSpace::LENGTH:
1627 os << "\\setlength{\\parskip}{"
1628 << from_utf8(getDefSkip().length().asLatexString())
1631 default: // should never happen // Then delete it.
1632 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1636 os << "\\setlength{\\parindent}{0pt}\n";
1639 // when separation by indentation
1640 // only output something when a width is given
1641 if (getIndentation().asLyXCommand() != "default") {
1642 os << "\\setlength{\\parindent}{"
1643 << from_utf8(getIndentation().asLatexCommand())
1649 // Now insert the LyX specific LaTeX commands...
1650 docstring lyxpreamble;
1652 // due to interferences with babel and hyperref, the color package has to
1653 // be loaded (when it is not already loaded) before babel when hyperref
1654 // is used with the colorlinks option, see
1655 // http://www.lyx.org/trac/ticket/5291
1656 // we decided therefore to load color always before babel, see
1657 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1658 lyxpreamble += from_ascii(features.getColorOptions());
1660 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1662 && (features.isRequired("jurabib")
1663 || features.isRequired("hyperref")
1664 || features.isRequired("vietnamese")
1665 || features.isRequired("japanese") ) ) {
1667 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1668 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1671 // The optional packages;
1672 lyxpreamble += from_ascii(features.getPackages());
1674 // Additional Indices
1675 if (features.isRequired("splitidx")) {
1676 IndicesList::const_iterator iit = indiceslist().begin();
1677 IndicesList::const_iterator iend = indiceslist().end();
1678 for (; iit != iend; ++iit) {
1679 lyxpreamble += "\\newindex[";
1680 lyxpreamble += iit->index();
1681 lyxpreamble += "]{";
1682 lyxpreamble += iit->shortcut();
1683 lyxpreamble += "}\n";
1688 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1691 // * Hyperref manual: "Make sure it comes last of your loaded
1692 // packages, to give it a fighting chance of not being over-written,
1693 // since its job is to redefine many LaTeX commands."
1694 // * Email from Heiko Oberdiek: "It is usually better to load babel
1695 // before hyperref. Then hyperref has a chance to detect babel.
1696 // * Has to be loaded before the "LyX specific LaTeX commands" to
1697 // avoid errors with algorithm floats.
1698 // use hyperref explicitly if it is required
1699 if (features.isRequired("hyperref")) {
1700 // pass what we have to stream here, since we need
1701 // to access the stream itself in PDFOptions.
1705 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1707 OutputParams tmp_params = features.runparams();
1708 lines += pdfoptions().writeLaTeX(tmp_params, os,
1709 documentClass().provides("hyperref"));
1710 texrow.newlines(lines);
1711 // set back for the rest
1712 lyxpreamble.clear();
1715 // Will be surrounded by \makeatletter and \makeatother when not empty
1716 docstring atlyxpreamble;
1718 // Some macros LyX will need
1719 docstring tmppreamble(features.getMacros());
1721 if (!tmppreamble.empty())
1722 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1723 "LyX specific LaTeX commands.\n"
1724 + tmppreamble + '\n';
1726 // the text class specific preamble
1727 tmppreamble = features.getTClassPreamble();
1728 if (!tmppreamble.empty())
1729 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1730 "Textclass specific LaTeX commands.\n"
1731 + tmppreamble + '\n';
1733 // suppress date if selected
1734 // use \@ifundefined because we cannot be sure that every document class
1735 // has a \date command
1737 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1739 /* the user-defined preamble */
1740 if (!containsOnly(preamble, " \n\t"))
1742 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1743 "User specified LaTeX commands.\n"
1744 + from_utf8(preamble) + '\n';
1746 // subfig loads internally the LaTeX package "caption". As
1747 // caption is a very popular package, users will load it in
1748 // the preamble. Therefore we must load subfig behind the
1749 // user-defined preamble and check if the caption package was
1750 // loaded or not. For the case that caption is loaded before
1751 // subfig, there is the subfig option "caption=false". This
1752 // option also works when a koma-script class is used and
1753 // koma's own caption commands are used instead of caption. We
1754 // use \PassOptionsToPackage here because the user could have
1755 // already loaded subfig in the preamble.
1756 if (features.isRequired("subfig")) {
1757 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1758 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1759 "\\usepackage{subfig}\n";
1762 // Itemize bullet settings need to be last in case the user
1763 // defines their own bullets that use a package included
1764 // in the user-defined preamble -- ARRae
1765 // Actually it has to be done much later than that
1766 // since some packages like frenchb make modifications
1767 // at \begin{document} time -- JMarc
1768 docstring bullets_def;
1769 for (int i = 0; i < 4; ++i) {
1770 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1771 if (bullets_def.empty())
1772 bullets_def += "\\AtBeginDocument{\n";
1773 bullets_def += " \\def\\labelitemi";
1775 // `i' is one less than the item to modify
1782 bullets_def += "ii";
1788 bullets_def += '{' +
1789 user_defined_bullet(i).getText()
1794 if (!bullets_def.empty())
1795 atlyxpreamble += bullets_def + "}\n\n";
1797 if (!atlyxpreamble.empty())
1798 lyxpreamble += "\n\\makeatletter\n"
1799 + atlyxpreamble + "\\makeatother\n\n";
1801 // We try to load babel late, in case it interferes with other packages.
1802 // Jurabib and Hyperref have to be called after babel, though.
1803 if (use_babel && !features.isRequired("jurabib")
1804 && !features.isRequired("hyperref")
1805 && !features.isRequired("vietnamese")
1806 && !features.isRequired("japanese")) {
1808 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1809 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1812 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1813 if (!i18npreamble.empty())
1814 lyxpreamble += i18npreamble + '\n';
1817 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1818 texrow.newlines(nlines);
1822 // these packages (xunicode, for that matter) need to be loaded at least
1823 // after amsmath, amssymb, esint and the other packages that provide
1826 os << "\\usepackage{xunicode}\n";
1828 os << "\\usepackage{xltxtra}\n";
1835 void BufferParams::useClassDefaults()
1837 DocumentClass const & tclass = documentClass();
1839 sides = tclass.sides();
1840 columns = tclass.columns();
1841 pagestyle = tclass.pagestyle();
1842 use_default_options = true;
1843 // Only if class has a ToC hierarchy
1844 if (tclass.hasTocLevels()) {
1845 secnumdepth = tclass.secnumdepth();
1846 tocdepth = tclass.tocdepth();
1851 bool BufferParams::hasClassDefaults() const
1853 DocumentClass const & tclass = documentClass();
1855 return sides == tclass.sides()
1856 && columns == tclass.columns()
1857 && pagestyle == tclass.pagestyle()
1858 && use_default_options
1859 && secnumdepth == tclass.secnumdepth()
1860 && tocdepth == tclass.tocdepth();
1864 DocumentClass const & BufferParams::documentClass() const
1870 DocumentClass const * BufferParams::documentClassPtr() const {
1875 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1876 // evil, but this function is evil
1877 doc_class_ = const_cast<DocumentClass *>(tc);
1881 bool BufferParams::setBaseClass(string const & classname)
1883 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1884 LayoutFileList & bcl = LayoutFileList::get();
1885 if (!bcl.haveClass(classname)) {
1887 bformat(_("The layout file:\n"
1889 "could not be found. A default textclass with default\n"
1890 "layouts will be used. LyX will not be able to produce\n"
1892 from_utf8(classname));
1893 frontend::Alert::error(_("Document class not found"), s);
1894 bcl.addEmptyClass(classname);
1897 bool const success = bcl[classname].load();
1900 bformat(_("Due to some error in it, the layout file:\n"
1902 "could not be loaded. A default textclass with default\n"
1903 "layouts will be used. LyX will not be able to produce\n"
1905 from_utf8(classname));
1906 frontend::Alert::error(_("Could not load class"), s);
1907 bcl.addEmptyClass(classname);
1910 pimpl_->baseClass_ = classname;
1911 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1916 LayoutFile const * BufferParams::baseClass() const
1918 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1919 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1925 LayoutFileIndex const & BufferParams::baseClassID() const
1927 return pimpl_->baseClass_;
1931 void BufferParams::makeDocumentClass()
1936 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1938 if (!local_layout.empty()) {
1939 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1940 docstring const msg = _("Error reading internal layout information");
1941 frontend::Alert::warning(_("Read Error"), msg);
1947 bool BufferParams::moduleCanBeAdded(string const & modName) const
1949 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1953 bool BufferParams::addLayoutModule(string const & modName)
1955 LayoutModuleList::const_iterator it = layoutModules_.begin();
1956 LayoutModuleList::const_iterator end = layoutModules_.end();
1957 for (; it != end; it++)
1960 layoutModules_.push_back(modName);
1965 Font const BufferParams::getFont() const
1967 FontInfo f = documentClass().defaultfont();
1968 if (fontsDefaultFamily == "rmdefault")
1969 f.setFamily(ROMAN_FAMILY);
1970 else if (fontsDefaultFamily == "sfdefault")
1971 f.setFamily(SANS_FAMILY);
1972 else if (fontsDefaultFamily == "ttdefault")
1973 f.setFamily(TYPEWRITER_FAMILY);
1974 return Font(f, language);
1978 void BufferParams::readPreamble(Lexer & lex)
1980 if (lex.getString() != "\\begin_preamble")
1981 lyxerr << "Error (BufferParams::readPreamble):"
1982 "consistency check failed." << endl;
1984 preamble = lex.getLongString("\\end_preamble");
1988 void BufferParams::readLocalLayout(Lexer & lex)
1990 if (lex.getString() != "\\begin_local_layout")
1991 lyxerr << "Error (BufferParams::readLocalLayout):"
1992 "consistency check failed." << endl;
1994 local_layout = lex.getLongString("\\end_local_layout");
1998 void BufferParams::readLanguage(Lexer & lex)
2000 if (!lex.next()) return;
2002 string const tmptok = lex.getString();
2004 // check if tmptok is part of tex_babel in tex-defs.h
2005 language = languages.getLanguage(tmptok);
2007 // Language tmptok was not found
2008 language = default_language;
2009 lyxerr << "Warning: Setting language `"
2010 << tmptok << "' to `" << language->lang()
2016 void BufferParams::readGraphicsDriver(Lexer & lex)
2021 string const tmptok = lex.getString();
2022 // check if tmptok is part of tex_graphics in tex_defs.h
2025 string const test = tex_graphics[n++];
2027 if (test == tmptok) {
2028 graphicsDriver = tmptok;
2033 "Warning: graphics driver `$$Token' not recognized!\n"
2034 " Setting graphics driver to `default'.\n");
2035 graphicsDriver = "default";
2042 void BufferParams::readBullets(Lexer & lex)
2047 int const index = lex.getInteger();
2049 int temp_int = lex.getInteger();
2050 user_defined_bullet(index).setFont(temp_int);
2051 temp_bullet(index).setFont(temp_int);
2053 user_defined_bullet(index).setCharacter(temp_int);
2054 temp_bullet(index).setCharacter(temp_int);
2056 user_defined_bullet(index).setSize(temp_int);
2057 temp_bullet(index).setSize(temp_int);
2061 void BufferParams::readBulletsLaTeX(Lexer & lex)
2063 // The bullet class should be able to read this.
2066 int const index = lex.getInteger();
2068 docstring const temp_str = lex.getDocString();
2070 user_defined_bullet(index).setText(temp_str);
2071 temp_bullet(index).setText(temp_str);
2075 void BufferParams::readModules(Lexer & lex)
2077 if (!lex.eatLine()) {
2078 lyxerr << "Error (BufferParams::readModules):"
2079 "Unexpected end of input." << endl;
2083 string mod = lex.getString();
2084 if (mod == "\\end_modules")
2086 addLayoutModule(mod);
2092 void BufferParams::readRemovedModules(Lexer & lex)
2094 if (!lex.eatLine()) {
2095 lyxerr << "Error (BufferParams::readRemovedModules):"
2096 "Unexpected end of input." << endl;
2100 string mod = lex.getString();
2101 if (mod == "\\end_removed_modules")
2103 removedModules_.push_back(mod);
2106 // now we want to remove any removed modules that were previously
2107 // added. normally, that will be because default modules were added in
2108 // setBaseClass(), which gets called when \textclass is read at the
2109 // start of the read.
2110 list<string>::const_iterator rit = removedModules_.begin();
2111 list<string>::const_iterator const ren = removedModules_.end();
2112 for (; rit != ren; rit++) {
2113 LayoutModuleList::iterator const mit = layoutModules_.begin();
2114 LayoutModuleList::iterator const men = layoutModules_.end();
2115 LayoutModuleList::iterator found = find(mit, men, *rit);
2118 layoutModules_.erase(found);
2123 void BufferParams::readIncludeonly(Lexer & lex)
2125 if (!lex.eatLine()) {
2126 lyxerr << "Error (BufferParams::readIncludeonly):"
2127 "Unexpected end of input." << endl;
2131 string child = lex.getString();
2132 if (child == "\\end_includeonly")
2134 includedChildren_.push_back(child);
2140 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2142 char real_papersize = papersize;
2143 if (real_papersize == PAPER_DEFAULT)
2144 real_papersize = lyxrc.default_papersize;
2146 switch (real_papersize) {
2148 // could be anything, so don't guess
2150 case PAPER_CUSTOM: {
2151 if (purpose == XDVI && !paperwidth.empty() &&
2152 !paperheight.empty()) {
2153 // heightxwidth<unit>
2154 string first = paperwidth;
2155 string second = paperheight;
2156 if (orientation == ORIENTATION_LANDSCAPE)
2159 return first.erase(first.length() - 2)
2165 // dvips and dvipdfm do not know this
2166 if (purpose == DVIPS || purpose == DVIPDFM)
2170 if (purpose == DVIPS || purpose == DVIPDFM)
2174 if (purpose == DVIPS || purpose == DVIPDFM)
2184 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 // dvipdfm does not know this
2205 if (purpose == DVIPDFM)
2209 if (purpose == DVIPDFM)
2213 if (purpose == DVIPS || 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)
2244 case PAPER_USEXECUTIVE:
2245 // dvipdfm does not know this
2246 if (purpose == DVIPDFM)
2251 case PAPER_USLETTER:
2253 if (purpose == XDVI)
2260 string const BufferParams::dvips_options() const
2265 && papersize == PAPER_CUSTOM
2266 && !lyxrc.print_paper_dimension_flag.empty()
2267 && !paperwidth.empty()
2268 && !paperheight.empty()) {
2269 // using a custom papersize
2270 result = lyxrc.print_paper_dimension_flag;
2271 result += ' ' + paperwidth;
2272 result += ',' + paperheight;
2274 string const paper_option = paperSizeName(DVIPS);
2275 if (!paper_option.empty() && (paper_option != "letter" ||
2276 orientation != ORIENTATION_LANDSCAPE)) {
2277 // dvips won't accept -t letter -t landscape.
2278 // In all other cases, include the paper size
2280 result = lyxrc.print_paper_flag;
2281 result += ' ' + paper_option;
2284 if (orientation == ORIENTATION_LANDSCAPE &&
2285 papersize != PAPER_CUSTOM)
2286 result += ' ' + lyxrc.print_landscape_flag;
2291 string const BufferParams::font_encoding() const
2293 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2297 string BufferParams::babelCall(string const & lang_opts) const
2299 string lang_pack = lyxrc.language_package;
2300 if (lang_pack != "\\usepackage{babel}")
2302 // suppress the babel call when there is no babel language defined
2303 // for the document language in the lib/languages file and if no
2304 // other languages are used (lang_opts is then empty)
2305 if (lang_opts.empty())
2307 // If Vietnamese is used, babel must directly be loaded with the
2308 // language options, see
2309 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2310 size_t viet = lang_opts.find("vietnam");
2311 // viet = string::npos when not found
2312 // the same is for all other languages that are not directly supported by
2313 // babel, but where LaTeX-packages add babel support.
2314 // this is currently the case for Latvian, Lithuanian, Mongolian
2316 size_t latvian = lang_opts.find("latvian");
2317 size_t lithu = lang_opts.find("lithuanian");
2318 size_t mongo = lang_opts.find("mongolian");
2319 size_t turkmen = lang_opts.find("turkmen");
2320 // If Japanese is used, babel must directly be loaded with the
2321 // language options, see
2322 // http://www.lyx.org/trac/ticket/4597#c4
2323 size_t japan = lang_opts.find("japanese");
2324 if (!lyxrc.language_global_options || viet != string::npos
2325 || japan != string::npos || latvian != string::npos
2326 || lithu != string::npos || mongo != string::npos
2327 || turkmen != string::npos)
2328 return "\\usepackage[" + lang_opts + "]{babel}";
2333 docstring BufferParams::getGraphicsDriver(string const & package) const
2337 if (package == "geometry") {
2338 if (graphicsDriver == "dvips"
2339 || graphicsDriver == "dvipdfm"
2340 || graphicsDriver == "pdftex"
2341 || graphicsDriver == "vtex")
2342 result = from_ascii(graphicsDriver);
2343 else if (graphicsDriver == "dvipdfmx")
2344 result = from_ascii("dvipdfm");
2351 void BufferParams::writeEncodingPreamble(odocstream & os,
2352 LaTeXFeatures & features, TexRow & texrow) const
2356 if (inputenc == "auto") {
2357 string const doc_encoding =
2358 language->encoding()->latexName();
2359 Encoding::Package const package =
2360 language->encoding()->package();
2362 // Create a list with all the input encodings used
2364 set<string> encodings =
2365 features.getEncodingSet(doc_encoding);
2367 // If the "japanese" package (i.e. pLaTeX) is used,
2368 // inputenc must be omitted.
2369 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2370 if (package == Encoding::japanese)
2371 features.require("japanese");
2373 if ((!encodings.empty() || package == Encoding::inputenc)
2374 && !features.isRequired("japanese")) {
2375 os << "\\usepackage[";
2376 set<string>::const_iterator it = encodings.begin();
2377 set<string>::const_iterator const end = encodings.end();
2379 os << from_ascii(*it);
2382 for (; it != end; ++it)
2383 os << ',' << from_ascii(*it);
2384 if (package == Encoding::inputenc) {
2385 if (!encodings.empty())
2387 os << from_ascii(doc_encoding);
2389 os << "]{inputenc}\n";
2392 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2393 if (language->encoding()->name() == "utf8-cjk"
2394 && LaTeXFeatures::isAvailable("CJKutf8"))
2395 os << "\\usepackage{CJKutf8}\n";
2397 os << "\\usepackage{CJK}\n";
2400 } else if (inputenc != "default") {
2401 switch (encoding().package()) {
2402 case Encoding::none:
2403 case Encoding::japanese:
2405 case Encoding::inputenc:
2406 // do not load inputenc if japanese is used
2407 if (features.isRequired("japanese"))
2409 os << "\\usepackage[" << from_ascii(inputenc)
2414 if (encoding().name() == "utf8-cjk"
2415 && LaTeXFeatures::isAvailable("CJKutf8"))
2416 os << "\\usepackage{CJKutf8}\n";
2418 os << "\\usepackage{CJK}\n";
2424 // The encoding "armscii8" (for Armenian) is only available when
2425 // the package "armtex" is loaded.
2426 if (language->encoding()->latexName() == "armscii8"
2427 || inputenc == "armscii8") {
2428 os << "\\usepackage{armtex}\n";
2434 string const BufferParams::parseFontName(string const & name) const
2436 string mangled = name;
2437 size_t const idx = mangled.find('[');
2438 if (idx == string::npos || idx == 0)
2441 return mangled.substr(0, idx - 1);
2445 string const BufferParams::loadFonts(string const & rm,
2446 string const & sf, string const & tt,
2447 bool const & sc, bool const & osf,
2448 int const & sfscale, int const & ttscale,
2449 bool const & xetex) const
2451 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2452 several packages have been replaced by others, that might not
2453 be installed on every system. We have to take care for that
2454 (see psnfss.pdf). We try to support all psnfss fonts as well
2455 as the fonts that have become de facto standard in the LaTeX
2456 world (e.g. Latin Modern). We do not support obsolete fonts
2457 (like PSLatex). In general, it should be possible to mix any
2458 rm font with any sf or tt font, respectively. (JSpitzm)
2460 -- separate math fonts.
2463 if (rm == "default" && sf == "default" && tt == "default")
2470 if (rm != "default")
2471 os << "\\setmainfont[Mapping=tex-text]{"
2472 << parseFontName(rm) << "}\n";
2473 if (sf != "default") {
2474 string const sans = parseFontName(sf);
2476 os << "\\setsansfont[Scale="
2477 << float(sfscale) / 100
2478 << ",Mapping=tex-text]{"
2481 os << "\\setsansfont[Mapping=tex-text]{"
2484 if (tt != "default") {
2485 string const mono = parseFontName(tt);
2487 os << "\\setmonofont[Scale="
2488 << float(sfscale) / 100
2492 os << "\\setmonofont[Mapping=tex-text]{"
2496 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2501 // Computer Modern (must be explicitly selectable -- there might be classes
2502 // that define a different default font!
2504 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2505 // osf for Computer Modern needs eco.sty
2507 os << "\\usepackage{eco}\n";
2509 // Latin Modern Roman
2510 else if (rm == "lmodern")
2511 os << "\\usepackage{lmodern}\n";
2513 else if (rm == "ae") {
2514 // not needed when using OT1 font encoding.
2515 if (font_encoding() != "default")
2516 os << "\\usepackage{ae,aecompl}\n";
2519 else if (rm == "times") {
2520 // try to load the best available package
2521 if (LaTeXFeatures::isAvailable("mathptmx"))
2522 os << "\\usepackage{mathptmx}\n";
2523 else if (LaTeXFeatures::isAvailable("mathptm"))
2524 os << "\\usepackage{mathptm}\n";
2526 os << "\\usepackage{times}\n";
2529 else if (rm == "palatino") {
2530 // try to load the best available package
2531 if (LaTeXFeatures::isAvailable("mathpazo")) {
2532 os << "\\usepackage";
2538 // "osf" includes "sc"!
2542 os << "{mathpazo}\n";
2544 else if (LaTeXFeatures::isAvailable("mathpple"))
2545 os << "\\usepackage{mathpple}\n";
2547 os << "\\usepackage{palatino}\n";
2550 else if (rm == "utopia") {
2551 // fourier supersedes utopia.sty, but does
2552 // not work with OT1 encoding.
2553 if (LaTeXFeatures::isAvailable("fourier")
2554 && font_encoding() != "default") {
2555 os << "\\usepackage";
2566 os << "{fourier}\n";
2569 os << "\\usepackage{utopia}\n";
2571 // Bera (complete fontset)
2572 else if (rm == "bera" && sf == "default" && tt == "default")
2573 os << "\\usepackage{bera}\n";
2575 else if (rm != "default")
2576 os << "\\usepackage" << "{" << rm << "}\n";
2579 // Helvetica, Bera Sans
2580 if (sf == "helvet" || sf == "berasans") {
2582 os << "\\usepackage[scaled=" << float(sfscale) / 100
2583 << "]{" << sf << "}\n";
2585 os << "\\usepackage{" << sf << "}\n";
2588 else if (sf == "avant")
2589 os << "\\usepackage{" << sf << "}\n";
2590 // Computer Modern, Latin Modern, CM Bright
2591 else if (sf != "default")
2592 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2594 // monospaced/typewriter
2595 // Courier, LuxiMono
2596 if (tt == "luximono" || tt == "beramono") {
2598 os << "\\usepackage[scaled=" << float(ttscale) / 100
2599 << "]{" << tt << "}\n";
2601 os << "\\usepackage{" << tt << "}\n";
2604 else if (tt == "courier" )
2605 os << "\\usepackage{" << tt << "}\n";
2606 // Computer Modern, Latin Modern, CM Bright
2607 else if (tt != "default")
2608 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2614 Encoding const & BufferParams::encoding() const
2617 return *(encodings.fromLaTeXName("utf8-plain"));
2618 if (inputenc == "auto" || inputenc == "default")
2619 return *language->encoding();
2620 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2623 LYXERR0("Unknown inputenc value `" << inputenc
2624 << "'. Using `auto' instead.");
2625 return *language->encoding();
2629 CiteEngine BufferParams::citeEngine() const
2631 // FIXME the class should provide the numerical/
2632 // authoryear choice
2633 if (documentClass().provides("natbib")
2634 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2635 return ENGINE_NATBIB_AUTHORYEAR;
2636 return cite_engine_;
2640 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2642 cite_engine_ = cite_engine;