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") {
835 html_latex_start = lex.getString();
836 } else if (token == "\\html_latex_end") {
838 html_latex_end = lex.getString();
840 lyxerr << "BufferParams::readToken(): Unknown token: " <<
849 void BufferParams::writeFile(ostream & os) const
851 // The top of the file is written by the buffer.
852 // Prints out the buffer info into the .lyx file given by file
855 os << "\\textclass " << baseClass()->name() << '\n';
858 if (!preamble.empty()) {
859 // remove '\n' from the end of preamble
860 string const tmppreamble = rtrim(preamble, "\n");
861 os << "\\begin_preamble\n"
863 << "\n\\end_preamble\n";
867 if (!options.empty()) {
868 os << "\\options " << options << '\n';
871 // use the class options defined in the layout?
872 os << "\\use_default_options "
873 << convert<string>(use_default_options) << "\n";
875 // the master document
876 if (!master.empty()) {
877 os << "\\master " << master << '\n';
881 if (!removedModules_.empty()) {
882 os << "\\begin_removed_modules" << '\n';
883 list<string>::const_iterator it = removedModules_.begin();
884 list<string>::const_iterator en = removedModules_.end();
885 for (; it != en; it++)
887 os << "\\end_removed_modules" << '\n';
891 if (!layoutModules_.empty()) {
892 os << "\\begin_modules" << '\n';
893 LayoutModuleList::const_iterator it = layoutModules_.begin();
894 LayoutModuleList::const_iterator en = layoutModules_.end();
895 for (; it != en; it++)
897 os << "\\end_modules" << '\n';
901 if (!includedChildren_.empty()) {
902 os << "\\begin_includeonly" << '\n';
903 list<string>::const_iterator it = includedChildren_.begin();
904 list<string>::const_iterator en = includedChildren_.end();
905 for (; it != en; it++)
907 os << "\\end_includeonly" << '\n';
909 os << "\\maintain_unincluded_children "
910 << convert<string>(maintain_unincluded_children) << '\n';
912 // local layout information
913 if (!local_layout.empty()) {
914 // remove '\n' from the end
915 string const tmplocal = rtrim(local_layout, "\n");
916 os << "\\begin_local_layout\n"
918 << "\n\\end_local_layout\n";
921 // then the text parameters
922 if (language != ignore_language)
923 os << "\\language " << language->lang() << '\n';
924 os << "\\inputencoding " << inputenc
925 << "\n\\fontencoding " << fontenc
926 << "\n\\font_roman " << fontsRoman
927 << "\n\\font_sans " << fontsSans
928 << "\n\\font_typewriter " << fontsTypewriter
929 << "\n\\font_default_family " << fontsDefaultFamily
930 << "\n\\use_xetex " << convert<string>(useXetex)
931 << "\n\\font_sc " << convert<string>(fontsSC)
932 << "\n\\font_osf " << convert<string>(fontsOSF)
933 << "\n\\font_sf_scale " << fontsSansScale
934 << "\n\\font_tt_scale " << fontsTypewriterScale
936 if (!fontsCJK.empty()) {
937 os << "\\font_cjk " << fontsCJK << '\n';
939 os << "\n\\graphics " << graphicsDriver << '\n';
940 os << "\\default_output_format " << defaultOutputFormat << '\n';
941 os << "\\bibtex_command " << bibtex_command << '\n';
942 os << "\\index_command " << index_command << '\n';
944 if (!float_placement.empty()) {
945 os << "\\float_placement " << float_placement << '\n';
947 os << "\\paperfontsize " << fontsize << '\n';
949 spacing().writeFile(os);
950 pdfoptions().writeFile(os);
952 os << "\\papersize " << string_papersize[papersize]
953 << "\n\\use_geometry " << convert<string>(use_geometry)
954 << "\n\\use_amsmath " << use_amsmath
955 << "\n\\use_esint " << use_esint
956 << "\n\\use_mhchem " << use_mhchem
957 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
958 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
959 << "\n\\use_indices " << convert<string>(use_indices)
960 << "\n\\paperorientation " << string_orientation[orientation]
961 << "\n\\suppress_date " << convert<string>(suppress_date)
963 if (isbackgroundcolor == true)
964 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
965 if (isfontcolor == true)
966 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
967 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
968 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
969 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
970 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
972 BranchList::const_iterator it = branchlist().begin();
973 BranchList::const_iterator end = branchlist().end();
974 for (; it != end; ++it) {
975 os << "\\branch " << to_utf8(it->branch())
976 << "\n\\selected " << it->isSelected()
977 << "\n\\filename_suffix " << it->hasFileNameSuffix()
978 << "\n\\color " << lyx::X11hexname(it->color())
983 IndicesList::const_iterator iit = indiceslist().begin();
984 IndicesList::const_iterator iend = indiceslist().end();
985 for (; iit != iend; ++iit) {
986 os << "\\index " << to_utf8(iit->index())
987 << "\n\\shortcut " << to_utf8(iit->shortcut())
988 << "\n\\color " << lyx::X11hexname(iit->color())
993 if (!paperwidth.empty())
994 os << "\\paperwidth "
995 << VSpace(paperwidth).asLyXCommand() << '\n';
996 if (!paperheight.empty())
997 os << "\\paperheight "
998 << VSpace(paperheight).asLyXCommand() << '\n';
999 if (!leftmargin.empty())
1000 os << "\\leftmargin "
1001 << VSpace(leftmargin).asLyXCommand() << '\n';
1002 if (!topmargin.empty())
1003 os << "\\topmargin "
1004 << VSpace(topmargin).asLyXCommand() << '\n';
1005 if (!rightmargin.empty())
1006 os << "\\rightmargin "
1007 << VSpace(rightmargin).asLyXCommand() << '\n';
1008 if (!bottommargin.empty())
1009 os << "\\bottommargin "
1010 << VSpace(bottommargin).asLyXCommand() << '\n';
1011 if (!headheight.empty())
1012 os << "\\headheight "
1013 << VSpace(headheight).asLyXCommand() << '\n';
1014 if (!headsep.empty())
1016 << VSpace(headsep).asLyXCommand() << '\n';
1017 if (!footskip.empty())
1019 << VSpace(footskip).asLyXCommand() << '\n';
1020 if (!columnsep.empty())
1021 os << "\\columnsep "
1022 << VSpace(columnsep).asLyXCommand() << '\n';
1023 os << "\\secnumdepth " << secnumdepth
1024 << "\n\\tocdepth " << tocdepth
1025 << "\n\\paragraph_separation "
1026 << string_paragraph_separation[paragraph_separation];
1027 if (!paragraph_separation)
1028 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1030 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1031 os << "\n\\quotes_language "
1032 << string_quotes_language[quotes_language]
1033 << "\n\\papercolumns " << columns
1034 << "\n\\papersides " << sides
1035 << "\n\\paperpagestyle " << pagestyle << '\n';
1036 if (!listings_params.empty())
1037 os << "\\listings_params \"" <<
1038 InsetListingsParams(listings_params).encodedString() << "\"\n";
1039 for (int i = 0; i < 4; ++i) {
1040 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1041 if (user_defined_bullet(i).getFont() != -1) {
1042 os << "\\bullet " << i << " "
1043 << user_defined_bullet(i).getFont() << " "
1044 << user_defined_bullet(i).getCharacter() << " "
1045 << user_defined_bullet(i).getSize() << "\n";
1049 os << "\\bulletLaTeX " << i << " \""
1050 << lyx::to_ascii(user_defined_bullet(i).getText())
1056 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1057 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1058 << "\\html_math_output " << html_math_output << '\n'
1059 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n'
1060 << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n'
1061 << "\\html_latex_start " << html_latex_start << "\n"
1062 << "\\html_latex_end " << html_latex_end << "\n";
1064 os << pimpl_->authorlist;
1068 void BufferParams::validate(LaTeXFeatures & features) const
1070 features.require(documentClass().requires());
1072 if (outputChanges) {
1073 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1074 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1075 LaTeXFeatures::isAvailable("xcolor");
1077 switch (features.runparams().flavor) {
1078 case OutputParams::LATEX:
1080 features.require("ct-dvipost");
1081 features.require("dvipost");
1082 } else if (xcolorulem) {
1083 features.require("ct-xcolor-ulem");
1084 features.require("ulem");
1085 features.require("xcolor");
1087 features.require("ct-none");
1090 case OutputParams::PDFLATEX:
1091 case OutputParams::XETEX:
1093 features.require("ct-xcolor-ulem");
1094 features.require("ulem");
1095 features.require("xcolor");
1096 // improves color handling in PDF output
1097 features.require("pdfcolmk");
1099 features.require("ct-none");
1107 // Floats with 'Here definitely' as default setting.
1108 if (float_placement.find('H') != string::npos)
1109 features.require("float");
1111 // AMS Style is at document level
1112 if (use_amsmath == package_on
1113 || documentClass().provides("amsmath"))
1114 features.require("amsmath");
1115 if (use_esint == package_on)
1116 features.require("esint");
1117 if (use_mhchem == package_on)
1118 features.require("mhchem");
1120 // Document-level line spacing
1121 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1122 features.require("setspace");
1124 // the bullet shapes are buffer level not paragraph level
1125 // so they are tested here
1126 for (int i = 0; i < 4; ++i) {
1127 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1129 int const font = user_defined_bullet(i).getFont();
1131 int const c = user_defined_bullet(i).getCharacter();
1137 features.require("latexsym");
1139 } else if (font == 1) {
1140 features.require("amssymb");
1141 } else if (font >= 2 && font <= 5) {
1142 features.require("pifont");
1146 if (pdfoptions().use_hyperref) {
1147 features.require("hyperref");
1148 // due to interferences with babel and hyperref, the color package has to
1149 // be loaded after hyperref when hyperref is used with the colorlinks
1150 // option, see http://www.lyx.org/trac/ticket/5291
1151 if (pdfoptions().colorlinks)
1152 features.require("color");
1156 features.require("xetex");
1158 if (language->lang() == "vietnamese")
1159 features.require("vietnamese");
1160 else if (language->lang() == "japanese")
1161 features.require("japanese");
1165 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1166 TexRow & texrow, FileName const & filepath) const
1168 os << "\\documentclass";
1170 DocumentClass const & tclass = documentClass();
1172 ostringstream clsoptions; // the document class options.
1174 if (tokenPos(tclass.opt_fontsize(),
1175 '|', fontsize) >= 0) {
1176 // only write if existing in list (and not default)
1177 clsoptions << fontsize << "pt,";
1180 // all paper sizes except of A4, A5, B5 and the US sizes need the
1182 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1183 && papersize != PAPER_USLETTER
1184 && papersize != PAPER_USLEGAL
1185 && papersize != PAPER_USEXECUTIVE
1186 && papersize != PAPER_A4
1187 && papersize != PAPER_A5
1188 && papersize != PAPER_B5;
1190 if (!use_geometry) {
1191 switch (papersize) {
1193 clsoptions << "a4paper,";
1195 case PAPER_USLETTER:
1196 clsoptions << "letterpaper,";
1199 clsoptions << "a5paper,";
1202 clsoptions << "b5paper,";
1204 case PAPER_USEXECUTIVE:
1205 clsoptions << "executivepaper,";
1208 clsoptions << "legalpaper,";
1235 if (sides != tclass.sides()) {
1238 clsoptions << "oneside,";
1241 clsoptions << "twoside,";
1247 if (columns != tclass.columns()) {
1249 clsoptions << "twocolumn,";
1251 clsoptions << "onecolumn,";
1255 && orientation == ORIENTATION_LANDSCAPE)
1256 clsoptions << "landscape,";
1258 // language should be a parameter to \documentclass
1259 if (language->babel() == "hebrew"
1260 && default_language->babel() != "hebrew")
1261 // This seems necessary
1262 features.useLanguage(default_language);
1264 ostringstream language_options;
1265 bool const use_babel = features.useBabel();
1267 language_options << features.getLanguages();
1268 if (!language->babel().empty()) {
1269 if (!language_options.str().empty())
1270 language_options << ',';
1271 language_options << language->babel();
1273 // if Vietnamese is used, babel must directly be loaded
1274 // with language options, not in the class options, see
1275 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1276 size_t viet = language_options.str().find("vietnam");
1277 // viet = string::npos when not found
1278 // the same is for all other languages that are not directly supported by
1279 // babel, but where LaTeX-packages add babel support.
1280 // this is currently the case for Latvian, Lithuanian, Mongolian
1282 size_t latvian = language_options.str().find("latvian");
1283 size_t lithu = language_options.str().find("lithuanian");
1284 size_t mongo = language_options.str().find("mongolian");
1285 size_t turkmen = language_options.str().find("turkmen");
1286 // if Japanese is used, babel must directly be loaded
1287 // with language options, not in the class options, see
1288 // http://www.lyx.org/trac/ticket/4597#c4
1289 size_t japan = language_options.str().find("japanese");
1290 if (lyxrc.language_global_options && !language_options.str().empty()
1291 && viet == string::npos && japan == string::npos
1292 && latvian == string::npos && lithu == string::npos
1293 && mongo == string::npos && turkmen == string::npos)
1294 clsoptions << language_options.str() << ',';
1297 // the predefined options from the layout
1298 if (use_default_options && !tclass.options().empty())
1299 clsoptions << tclass.options() << ',';
1301 // the user-defined options
1302 if (!options.empty()) {
1303 clsoptions << options << ',';
1306 string strOptions(clsoptions.str());
1307 if (!strOptions.empty()) {
1308 strOptions = rtrim(strOptions, ",");
1310 os << '[' << from_utf8(strOptions) << ']';
1313 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1315 // end of \documentclass defs
1318 os << "\\usepackage{fontspec}\n";
1322 // font selection must be done before loading fontenc.sty
1323 string const fonts =
1324 loadFonts(fontsRoman, fontsSans,
1325 fontsTypewriter, fontsSC, fontsOSF,
1326 fontsSansScale, fontsTypewriterScale, useXetex);
1327 if (!fonts.empty()) {
1328 os << from_ascii(fonts);
1331 if (fontsDefaultFamily != "default")
1332 os << "\\renewcommand{\\familydefault}{\\"
1333 << from_ascii(fontsDefaultFamily) << "}\n";
1335 // set font encoding
1336 // for arabic_arabi and farsi we also need to load the LAE and
1338 // XeTeX works without fontenc
1339 if (font_encoding() != "default" && language->lang() != "japanese"
1341 size_t fars = language_options.str().find("farsi");
1342 size_t arab = language_options.str().find("arabic");
1343 if (language->lang() == "arabic_arabi"
1344 || language->lang() == "farsi" || fars != string::npos
1345 || arab != string::npos) {
1346 os << "\\usepackage[" << from_ascii(font_encoding())
1347 << ",LFE,LAE]{fontenc}\n";
1350 os << "\\usepackage[" << from_ascii(font_encoding())
1356 // handle inputenc etc.
1357 writeEncodingPreamble(os, features, texrow);
1360 if (!features.runparams().includeall && !includedChildren_.empty()) {
1361 os << "\\includeonly{";
1362 list<string>::const_iterator it = includedChildren_.begin();
1364 for (; it != includedChildren_.end() ; ++it) {
1365 string incfile = *it;
1366 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1367 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1369 if (!features.runparams().nice)
1371 // \includeonly doesn't want an extension
1372 incfile = changeExtension(incfile, string());
1373 incfile = support::latex_path(incfile);
1374 if (!incfile.empty()) {
1377 os << from_utf8(incfile);
1384 if (!listings_params.empty() || features.isRequired("listings")) {
1385 os << "\\usepackage{listings}\n";
1388 if (!listings_params.empty()) {
1390 // do not test validity because listings_params is
1391 // supposed to be valid
1393 InsetListingsParams(listings_params).separatedParams(true);
1394 // we can't support all packages, but we should load the color package
1395 if (par.find("\\color", 0) != string::npos)
1396 features.require("color");
1397 os << from_utf8(par);
1398 // count the number of newlines
1399 for (size_t i = 0; i < par.size(); ++i)
1405 if (!tclass.provides("geometry")
1406 && (use_geometry || nonstandard_papersize)) {
1407 odocstringstream ods;
1408 if (!getGraphicsDriver("geometry").empty())
1409 ods << getGraphicsDriver("geometry");
1410 if (orientation == ORIENTATION_LANDSCAPE)
1411 ods << ",landscape";
1412 switch (papersize) {
1414 if (!paperwidth.empty())
1415 ods << ",paperwidth="
1416 << from_ascii(paperwidth);
1417 if (!paperheight.empty())
1418 ods << ",paperheight="
1419 << from_ascii(paperheight);
1421 case PAPER_USLETTER:
1422 ods << ",letterpaper";
1425 ods << ",legalpaper";
1427 case PAPER_USEXECUTIVE:
1428 ods << ",executivepaper";
1494 // default papersize ie PAPER_DEFAULT
1495 switch (lyxrc.default_papersize) {
1496 case PAPER_DEFAULT: // keep compiler happy
1497 case PAPER_USLETTER:
1498 ods << ",letterpaper";
1501 ods << ",legalpaper";
1503 case PAPER_USEXECUTIVE:
1504 ods << ",executivepaper";
1539 docstring const g_options = trim(ods.str(), ",");
1540 os << "\\usepackage";
1541 if (!g_options.empty())
1542 os << '[' << g_options << ']';
1543 os << "{geometry}\n";
1545 // output this if only use_geometry is true
1547 os << "\\geometry{verbose";
1548 if (!topmargin.empty())
1549 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1550 if (!bottommargin.empty())
1551 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1552 if (!leftmargin.empty())
1553 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1554 if (!rightmargin.empty())
1555 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1556 if (!headheight.empty())
1557 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1558 if (!headsep.empty())
1559 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1560 if (!footskip.empty())
1561 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1562 if (!columnsep.empty())
1563 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1567 } else if (orientation == ORIENTATION_LANDSCAPE
1568 || papersize != PAPER_DEFAULT) {
1569 features.require("papersize");
1572 if (tokenPos(tclass.opt_pagestyle(),
1573 '|', pagestyle) >= 0) {
1574 if (pagestyle == "fancy") {
1575 os << "\\usepackage{fancyhdr}\n";
1578 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1582 // only output when the background color is not default
1583 if (isbackgroundcolor == true) {
1584 // only require color here, the background color will be defined
1585 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1587 features.require("color");
1588 features.require("pagecolor");
1591 // only output when the font color is not default
1592 if (isfontcolor == true) {
1593 // only require color here, the font color will be defined
1594 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1596 features.require("color");
1597 features.require("fontcolor");
1600 // Only if class has a ToC hierarchy
1601 if (tclass.hasTocLevels()) {
1602 if (secnumdepth != tclass.secnumdepth()) {
1603 os << "\\setcounter{secnumdepth}{"
1608 if (tocdepth != tclass.tocdepth()) {
1609 os << "\\setcounter{tocdepth}{"
1616 if (paragraph_separation) {
1617 // when skip separation
1618 switch (getDefSkip().kind()) {
1619 case VSpace::SMALLSKIP:
1620 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1622 case VSpace::MEDSKIP:
1623 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1625 case VSpace::BIGSKIP:
1626 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1628 case VSpace::LENGTH:
1629 os << "\\setlength{\\parskip}{"
1630 << from_utf8(getDefSkip().length().asLatexString())
1633 default: // should never happen // Then delete it.
1634 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1638 os << "\\setlength{\\parindent}{0pt}\n";
1641 // when separation by indentation
1642 // only output something when a width is given
1643 if (getIndentation().asLyXCommand() != "default") {
1644 os << "\\setlength{\\parindent}{"
1645 << from_utf8(getIndentation().asLatexCommand())
1651 // Now insert the LyX specific LaTeX commands...
1652 docstring lyxpreamble;
1654 // due to interferences with babel and hyperref, the color package has to
1655 // be loaded (when it is not already loaded) before babel when hyperref
1656 // is used with the colorlinks option, see
1657 // http://www.lyx.org/trac/ticket/5291
1658 // we decided therefore to load color always before babel, see
1659 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1660 lyxpreamble += from_ascii(features.getColorOptions());
1662 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1664 && (features.isRequired("jurabib")
1665 || features.isRequired("hyperref")
1666 || features.isRequired("vietnamese")
1667 || features.isRequired("japanese") ) ) {
1669 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1670 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1673 // The optional packages;
1674 lyxpreamble += from_ascii(features.getPackages());
1676 // Additional Indices
1677 if (features.isRequired("splitidx")) {
1678 IndicesList::const_iterator iit = indiceslist().begin();
1679 IndicesList::const_iterator iend = indiceslist().end();
1680 for (; iit != iend; ++iit) {
1681 lyxpreamble += "\\newindex[";
1682 lyxpreamble += iit->index();
1683 lyxpreamble += "]{";
1684 lyxpreamble += iit->shortcut();
1685 lyxpreamble += "}\n";
1690 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1693 // * Hyperref manual: "Make sure it comes last of your loaded
1694 // packages, to give it a fighting chance of not being over-written,
1695 // since its job is to redefine many LaTeX commands."
1696 // * Email from Heiko Oberdiek: "It is usually better to load babel
1697 // before hyperref. Then hyperref has a chance to detect babel.
1698 // * Has to be loaded before the "LyX specific LaTeX commands" to
1699 // avoid errors with algorithm floats.
1700 // use hyperref explicitly if it is required
1701 if (features.isRequired("hyperref")) {
1702 // pass what we have to stream here, since we need
1703 // to access the stream itself in PDFOptions.
1707 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1709 OutputParams tmp_params = features.runparams();
1710 lines += pdfoptions().writeLaTeX(tmp_params, os,
1711 documentClass().provides("hyperref"));
1712 texrow.newlines(lines);
1713 // set back for the rest
1714 lyxpreamble.clear();
1717 // Will be surrounded by \makeatletter and \makeatother when not empty
1718 docstring atlyxpreamble;
1720 // Some macros LyX will need
1721 docstring tmppreamble(features.getMacros());
1723 if (!tmppreamble.empty())
1724 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1725 "LyX specific LaTeX commands.\n"
1726 + tmppreamble + '\n';
1728 // the text class specific preamble
1729 tmppreamble = features.getTClassPreamble();
1730 if (!tmppreamble.empty())
1731 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1732 "Textclass specific LaTeX commands.\n"
1733 + tmppreamble + '\n';
1735 // suppress date if selected
1736 // use \@ifundefined because we cannot be sure that every document class
1737 // has a \date command
1739 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1741 /* the user-defined preamble */
1742 if (!containsOnly(preamble, " \n\t"))
1744 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1745 "User specified LaTeX commands.\n"
1746 + from_utf8(preamble) + '\n';
1748 // subfig loads internally the LaTeX package "caption". As
1749 // caption is a very popular package, users will load it in
1750 // the preamble. Therefore we must load subfig behind the
1751 // user-defined preamble and check if the caption package was
1752 // loaded or not. For the case that caption is loaded before
1753 // subfig, there is the subfig option "caption=false". This
1754 // option also works when a koma-script class is used and
1755 // koma's own caption commands are used instead of caption. We
1756 // use \PassOptionsToPackage here because the user could have
1757 // already loaded subfig in the preamble.
1758 if (features.isRequired("subfig")) {
1759 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1760 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1761 "\\usepackage{subfig}\n";
1764 // Itemize bullet settings need to be last in case the user
1765 // defines their own bullets that use a package included
1766 // in the user-defined preamble -- ARRae
1767 // Actually it has to be done much later than that
1768 // since some packages like frenchb make modifications
1769 // at \begin{document} time -- JMarc
1770 docstring bullets_def;
1771 for (int i = 0; i < 4; ++i) {
1772 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1773 if (bullets_def.empty())
1774 bullets_def += "\\AtBeginDocument{\n";
1775 bullets_def += " \\def\\labelitemi";
1777 // `i' is one less than the item to modify
1784 bullets_def += "ii";
1790 bullets_def += '{' +
1791 user_defined_bullet(i).getText()
1796 if (!bullets_def.empty())
1797 atlyxpreamble += bullets_def + "}\n\n";
1799 if (!atlyxpreamble.empty())
1800 lyxpreamble += "\n\\makeatletter\n"
1801 + atlyxpreamble + "\\makeatother\n\n";
1803 // We try to load babel late, in case it interferes with other packages.
1804 // Jurabib and Hyperref have to be called after babel, though.
1805 if (use_babel && !features.isRequired("jurabib")
1806 && !features.isRequired("hyperref")
1807 && !features.isRequired("vietnamese")
1808 && !features.isRequired("japanese")) {
1810 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1811 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1814 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1815 if (!i18npreamble.empty())
1816 lyxpreamble += i18npreamble + '\n';
1819 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1820 texrow.newlines(nlines);
1824 // these packages (xunicode, for that matter) need to be loaded at least
1825 // after amsmath, amssymb, esint and the other packages that provide
1828 os << "\\usepackage{xunicode}\n";
1830 os << "\\usepackage{xltxtra}\n";
1837 void BufferParams::useClassDefaults()
1839 DocumentClass const & tclass = documentClass();
1841 sides = tclass.sides();
1842 columns = tclass.columns();
1843 pagestyle = tclass.pagestyle();
1844 use_default_options = true;
1845 // Only if class has a ToC hierarchy
1846 if (tclass.hasTocLevels()) {
1847 secnumdepth = tclass.secnumdepth();
1848 tocdepth = tclass.tocdepth();
1853 bool BufferParams::hasClassDefaults() const
1855 DocumentClass const & tclass = documentClass();
1857 return sides == tclass.sides()
1858 && columns == tclass.columns()
1859 && pagestyle == tclass.pagestyle()
1860 && use_default_options
1861 && secnumdepth == tclass.secnumdepth()
1862 && tocdepth == tclass.tocdepth();
1866 DocumentClass const & BufferParams::documentClass() const
1872 DocumentClass const * BufferParams::documentClassPtr() const {
1877 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1878 // evil, but this function is evil
1879 doc_class_ = const_cast<DocumentClass *>(tc);
1883 bool BufferParams::setBaseClass(string const & classname)
1885 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1886 LayoutFileList & bcl = LayoutFileList::get();
1887 if (!bcl.haveClass(classname)) {
1889 bformat(_("The layout file:\n"
1891 "could not be found. A default textclass with default\n"
1892 "layouts will be used. LyX will not be able to produce\n"
1894 from_utf8(classname));
1895 frontend::Alert::error(_("Document class not found"), s);
1896 bcl.addEmptyClass(classname);
1899 bool const success = bcl[classname].load();
1902 bformat(_("Due to some error in it, the layout file:\n"
1904 "could not be loaded. A default textclass with default\n"
1905 "layouts will be used. LyX will not be able to produce\n"
1907 from_utf8(classname));
1908 frontend::Alert::error(_("Could not load class"), s);
1909 bcl.addEmptyClass(classname);
1912 pimpl_->baseClass_ = classname;
1913 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1918 LayoutFile const * BufferParams::baseClass() const
1920 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1921 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1927 LayoutFileIndex const & BufferParams::baseClassID() const
1929 return pimpl_->baseClass_;
1933 void BufferParams::makeDocumentClass()
1938 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1940 if (!local_layout.empty()) {
1941 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1942 docstring const msg = _("Error reading internal layout information");
1943 frontend::Alert::warning(_("Read Error"), msg);
1949 bool BufferParams::moduleCanBeAdded(string const & modName) const
1951 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1955 bool BufferParams::addLayoutModule(string const & modName)
1957 LayoutModuleList::const_iterator it = layoutModules_.begin();
1958 LayoutModuleList::const_iterator end = layoutModules_.end();
1959 for (; it != end; it++)
1962 layoutModules_.push_back(modName);
1967 Font const BufferParams::getFont() const
1969 FontInfo f = documentClass().defaultfont();
1970 if (fontsDefaultFamily == "rmdefault")
1971 f.setFamily(ROMAN_FAMILY);
1972 else if (fontsDefaultFamily == "sfdefault")
1973 f.setFamily(SANS_FAMILY);
1974 else if (fontsDefaultFamily == "ttdefault")
1975 f.setFamily(TYPEWRITER_FAMILY);
1976 return Font(f, language);
1980 void BufferParams::readPreamble(Lexer & lex)
1982 if (lex.getString() != "\\begin_preamble")
1983 lyxerr << "Error (BufferParams::readPreamble):"
1984 "consistency check failed." << endl;
1986 preamble = lex.getLongString("\\end_preamble");
1990 void BufferParams::readLocalLayout(Lexer & lex)
1992 if (lex.getString() != "\\begin_local_layout")
1993 lyxerr << "Error (BufferParams::readLocalLayout):"
1994 "consistency check failed." << endl;
1996 local_layout = lex.getLongString("\\end_local_layout");
2000 void BufferParams::readLanguage(Lexer & lex)
2002 if (!lex.next()) return;
2004 string const tmptok = lex.getString();
2006 // check if tmptok is part of tex_babel in tex-defs.h
2007 language = languages.getLanguage(tmptok);
2009 // Language tmptok was not found
2010 language = default_language;
2011 lyxerr << "Warning: Setting language `"
2012 << tmptok << "' to `" << language->lang()
2018 void BufferParams::readGraphicsDriver(Lexer & lex)
2023 string const tmptok = lex.getString();
2024 // check if tmptok is part of tex_graphics in tex_defs.h
2027 string const test = tex_graphics[n++];
2029 if (test == tmptok) {
2030 graphicsDriver = tmptok;
2035 "Warning: graphics driver `$$Token' not recognized!\n"
2036 " Setting graphics driver to `default'.\n");
2037 graphicsDriver = "default";
2044 void BufferParams::readBullets(Lexer & lex)
2049 int const index = lex.getInteger();
2051 int temp_int = lex.getInteger();
2052 user_defined_bullet(index).setFont(temp_int);
2053 temp_bullet(index).setFont(temp_int);
2055 user_defined_bullet(index).setCharacter(temp_int);
2056 temp_bullet(index).setCharacter(temp_int);
2058 user_defined_bullet(index).setSize(temp_int);
2059 temp_bullet(index).setSize(temp_int);
2063 void BufferParams::readBulletsLaTeX(Lexer & lex)
2065 // The bullet class should be able to read this.
2068 int const index = lex.getInteger();
2070 docstring const temp_str = lex.getDocString();
2072 user_defined_bullet(index).setText(temp_str);
2073 temp_bullet(index).setText(temp_str);
2077 void BufferParams::readModules(Lexer & lex)
2079 if (!lex.eatLine()) {
2080 lyxerr << "Error (BufferParams::readModules):"
2081 "Unexpected end of input." << endl;
2085 string mod = lex.getString();
2086 if (mod == "\\end_modules")
2088 addLayoutModule(mod);
2094 void BufferParams::readRemovedModules(Lexer & lex)
2096 if (!lex.eatLine()) {
2097 lyxerr << "Error (BufferParams::readRemovedModules):"
2098 "Unexpected end of input." << endl;
2102 string mod = lex.getString();
2103 if (mod == "\\end_removed_modules")
2105 removedModules_.push_back(mod);
2108 // now we want to remove any removed modules that were previously
2109 // added. normally, that will be because default modules were added in
2110 // setBaseClass(), which gets called when \textclass is read at the
2111 // start of the read.
2112 list<string>::const_iterator rit = removedModules_.begin();
2113 list<string>::const_iterator const ren = removedModules_.end();
2114 for (; rit != ren; rit++) {
2115 LayoutModuleList::iterator const mit = layoutModules_.begin();
2116 LayoutModuleList::iterator const men = layoutModules_.end();
2117 LayoutModuleList::iterator found = find(mit, men, *rit);
2120 layoutModules_.erase(found);
2125 void BufferParams::readIncludeonly(Lexer & lex)
2127 if (!lex.eatLine()) {
2128 lyxerr << "Error (BufferParams::readIncludeonly):"
2129 "Unexpected end of input." << endl;
2133 string child = lex.getString();
2134 if (child == "\\end_includeonly")
2136 includedChildren_.push_back(child);
2142 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2144 char real_papersize = papersize;
2145 if (real_papersize == PAPER_DEFAULT)
2146 real_papersize = lyxrc.default_papersize;
2148 switch (real_papersize) {
2150 // could be anything, so don't guess
2152 case PAPER_CUSTOM: {
2153 if (purpose == XDVI && !paperwidth.empty() &&
2154 !paperheight.empty()) {
2155 // heightxwidth<unit>
2156 string first = paperwidth;
2157 string second = paperheight;
2158 if (orientation == ORIENTATION_LANDSCAPE)
2161 return first.erase(first.length() - 2)
2167 // dvips and dvipdfm do not know this
2168 if (purpose == DVIPS || purpose == DVIPDFM)
2172 if (purpose == DVIPS || purpose == DVIPDFM)
2176 if (purpose == DVIPS || purpose == DVIPDFM)
2186 if (purpose == DVIPS || purpose == DVIPDFM)
2190 if (purpose == DVIPS || purpose == DVIPDFM)
2194 if (purpose == DVIPS || purpose == DVIPDFM)
2198 if (purpose == DVIPS || purpose == DVIPDFM)
2202 if (purpose == DVIPS || purpose == DVIPDFM)
2206 // dvipdfm does not know this
2207 if (purpose == DVIPDFM)
2211 if (purpose == DVIPDFM)
2215 if (purpose == DVIPS || purpose == DVIPDFM)
2219 if (purpose == DVIPS || purpose == DVIPDFM)
2223 if (purpose == DVIPS || purpose == DVIPDFM)
2227 if (purpose == DVIPS || purpose == DVIPDFM)
2231 if (purpose == DVIPS || purpose == DVIPDFM)
2235 if (purpose == DVIPS || purpose == DVIPDFM)
2239 if (purpose == DVIPS || purpose == DVIPDFM)
2243 if (purpose == DVIPS || purpose == DVIPDFM)
2246 case PAPER_USEXECUTIVE:
2247 // dvipdfm does not know this
2248 if (purpose == DVIPDFM)
2253 case PAPER_USLETTER:
2255 if (purpose == XDVI)
2262 string const BufferParams::dvips_options() const
2267 && papersize == PAPER_CUSTOM
2268 && !lyxrc.print_paper_dimension_flag.empty()
2269 && !paperwidth.empty()
2270 && !paperheight.empty()) {
2271 // using a custom papersize
2272 result = lyxrc.print_paper_dimension_flag;
2273 result += ' ' + paperwidth;
2274 result += ',' + paperheight;
2276 string const paper_option = paperSizeName(DVIPS);
2277 if (!paper_option.empty() && (paper_option != "letter" ||
2278 orientation != ORIENTATION_LANDSCAPE)) {
2279 // dvips won't accept -t letter -t landscape.
2280 // In all other cases, include the paper size
2282 result = lyxrc.print_paper_flag;
2283 result += ' ' + paper_option;
2286 if (orientation == ORIENTATION_LANDSCAPE &&
2287 papersize != PAPER_CUSTOM)
2288 result += ' ' + lyxrc.print_landscape_flag;
2293 string const BufferParams::font_encoding() const
2295 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2299 string BufferParams::babelCall(string const & lang_opts) const
2301 string lang_pack = lyxrc.language_package;
2302 if (lang_pack != "\\usepackage{babel}")
2304 // suppress the babel call when there is no babel language defined
2305 // for the document language in the lib/languages file and if no
2306 // other languages are used (lang_opts is then empty)
2307 if (lang_opts.empty())
2309 // If Vietnamese is used, babel must directly be loaded with the
2310 // language options, see
2311 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2312 size_t viet = lang_opts.find("vietnam");
2313 // viet = string::npos when not found
2314 // the same is for all other languages that are not directly supported by
2315 // babel, but where LaTeX-packages add babel support.
2316 // this is currently the case for Latvian, Lithuanian, Mongolian
2318 size_t latvian = lang_opts.find("latvian");
2319 size_t lithu = lang_opts.find("lithuanian");
2320 size_t mongo = lang_opts.find("mongolian");
2321 size_t turkmen = lang_opts.find("turkmen");
2322 // If Japanese is used, babel must directly be loaded with the
2323 // language options, see
2324 // http://www.lyx.org/trac/ticket/4597#c4
2325 size_t japan = lang_opts.find("japanese");
2326 if (!lyxrc.language_global_options || viet != string::npos
2327 || japan != string::npos || latvian != string::npos
2328 || lithu != string::npos || mongo != string::npos
2329 || turkmen != string::npos)
2330 return "\\usepackage[" + lang_opts + "]{babel}";
2335 docstring BufferParams::getGraphicsDriver(string const & package) const
2339 if (package == "geometry") {
2340 if (graphicsDriver == "dvips"
2341 || graphicsDriver == "dvipdfm"
2342 || graphicsDriver == "pdftex"
2343 || graphicsDriver == "vtex")
2344 result = from_ascii(graphicsDriver);
2345 else if (graphicsDriver == "dvipdfmx")
2346 result = from_ascii("dvipdfm");
2353 void BufferParams::writeEncodingPreamble(odocstream & os,
2354 LaTeXFeatures & features, TexRow & texrow) const
2358 if (inputenc == "auto") {
2359 string const doc_encoding =
2360 language->encoding()->latexName();
2361 Encoding::Package const package =
2362 language->encoding()->package();
2364 // Create a list with all the input encodings used
2366 set<string> encodings =
2367 features.getEncodingSet(doc_encoding);
2369 // If the "japanese" package (i.e. pLaTeX) is used,
2370 // inputenc must be omitted.
2371 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2372 if (package == Encoding::japanese)
2373 features.require("japanese");
2375 if ((!encodings.empty() || package == Encoding::inputenc)
2376 && !features.isRequired("japanese")) {
2377 os << "\\usepackage[";
2378 set<string>::const_iterator it = encodings.begin();
2379 set<string>::const_iterator const end = encodings.end();
2381 os << from_ascii(*it);
2384 for (; it != end; ++it)
2385 os << ',' << from_ascii(*it);
2386 if (package == Encoding::inputenc) {
2387 if (!encodings.empty())
2389 os << from_ascii(doc_encoding);
2391 os << "]{inputenc}\n";
2394 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2395 if (language->encoding()->name() == "utf8-cjk"
2396 && LaTeXFeatures::isAvailable("CJKutf8"))
2397 os << "\\usepackage{CJKutf8}\n";
2399 os << "\\usepackage{CJK}\n";
2402 } else if (inputenc != "default") {
2403 switch (encoding().package()) {
2404 case Encoding::none:
2405 case Encoding::japanese:
2407 case Encoding::inputenc:
2408 // do not load inputenc if japanese is used
2409 if (features.isRequired("japanese"))
2411 os << "\\usepackage[" << from_ascii(inputenc)
2416 if (encoding().name() == "utf8-cjk"
2417 && LaTeXFeatures::isAvailable("CJKutf8"))
2418 os << "\\usepackage{CJKutf8}\n";
2420 os << "\\usepackage{CJK}\n";
2426 // The encoding "armscii8" (for Armenian) is only available when
2427 // the package "armtex" is loaded.
2428 if (language->encoding()->latexName() == "armscii8"
2429 || inputenc == "armscii8") {
2430 os << "\\usepackage{armtex}\n";
2436 string const BufferParams::parseFontName(string const & name) const
2438 string mangled = name;
2439 size_t const idx = mangled.find('[');
2440 if (idx == string::npos || idx == 0)
2443 return mangled.substr(0, idx - 1);
2447 string const BufferParams::loadFonts(string const & rm,
2448 string const & sf, string const & tt,
2449 bool const & sc, bool const & osf,
2450 int const & sfscale, int const & ttscale,
2451 bool const & xetex) const
2453 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2454 several packages have been replaced by others, that might not
2455 be installed on every system. We have to take care for that
2456 (see psnfss.pdf). We try to support all psnfss fonts as well
2457 as the fonts that have become de facto standard in the LaTeX
2458 world (e.g. Latin Modern). We do not support obsolete fonts
2459 (like PSLatex). In general, it should be possible to mix any
2460 rm font with any sf or tt font, respectively. (JSpitzm)
2462 -- separate math fonts.
2465 if (rm == "default" && sf == "default" && tt == "default")
2472 if (rm != "default")
2473 os << "\\setmainfont[Mapping=tex-text]{"
2474 << parseFontName(rm) << "}\n";
2475 if (sf != "default") {
2476 string const sans = parseFontName(sf);
2478 os << "\\setsansfont[Scale="
2479 << float(sfscale) / 100
2480 << ",Mapping=tex-text]{"
2483 os << "\\setsansfont[Mapping=tex-text]{"
2486 if (tt != "default") {
2487 string const mono = parseFontName(tt);
2489 os << "\\setmonofont[Scale="
2490 << float(sfscale) / 100
2494 os << "\\setmonofont[Mapping=tex-text]{"
2498 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2503 // Computer Modern (must be explicitly selectable -- there might be classes
2504 // that define a different default font!
2506 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2507 // osf for Computer Modern needs eco.sty
2509 os << "\\usepackage{eco}\n";
2511 // Latin Modern Roman
2512 else if (rm == "lmodern")
2513 os << "\\usepackage{lmodern}\n";
2515 else if (rm == "ae") {
2516 // not needed when using OT1 font encoding.
2517 if (font_encoding() != "default")
2518 os << "\\usepackage{ae,aecompl}\n";
2521 else if (rm == "times") {
2522 // try to load the best available package
2523 if (LaTeXFeatures::isAvailable("mathptmx"))
2524 os << "\\usepackage{mathptmx}\n";
2525 else if (LaTeXFeatures::isAvailable("mathptm"))
2526 os << "\\usepackage{mathptm}\n";
2528 os << "\\usepackage{times}\n";
2531 else if (rm == "palatino") {
2532 // try to load the best available package
2533 if (LaTeXFeatures::isAvailable("mathpazo")) {
2534 os << "\\usepackage";
2540 // "osf" includes "sc"!
2544 os << "{mathpazo}\n";
2546 else if (LaTeXFeatures::isAvailable("mathpple"))
2547 os << "\\usepackage{mathpple}\n";
2549 os << "\\usepackage{palatino}\n";
2552 else if (rm == "utopia") {
2553 // fourier supersedes utopia.sty, but does
2554 // not work with OT1 encoding.
2555 if (LaTeXFeatures::isAvailable("fourier")
2556 && font_encoding() != "default") {
2557 os << "\\usepackage";
2568 os << "{fourier}\n";
2571 os << "\\usepackage{utopia}\n";
2573 // Bera (complete fontset)
2574 else if (rm == "bera" && sf == "default" && tt == "default")
2575 os << "\\usepackage{bera}\n";
2577 else if (rm != "default")
2578 os << "\\usepackage" << "{" << rm << "}\n";
2581 // Helvetica, Bera Sans
2582 if (sf == "helvet" || sf == "berasans") {
2584 os << "\\usepackage[scaled=" << float(sfscale) / 100
2585 << "]{" << sf << "}\n";
2587 os << "\\usepackage{" << sf << "}\n";
2590 else if (sf == "avant")
2591 os << "\\usepackage{" << sf << "}\n";
2592 // Computer Modern, Latin Modern, CM Bright
2593 else if (sf != "default")
2594 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2596 // monospaced/typewriter
2597 // Courier, LuxiMono
2598 if (tt == "luximono" || tt == "beramono") {
2600 os << "\\usepackage[scaled=" << float(ttscale) / 100
2601 << "]{" << tt << "}\n";
2603 os << "\\usepackage{" << tt << "}\n";
2606 else if (tt == "courier" )
2607 os << "\\usepackage{" << tt << "}\n";
2608 // Computer Modern, Latin Modern, CM Bright
2609 else if (tt != "default")
2610 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2616 Encoding const & BufferParams::encoding() const
2619 return *(encodings.fromLaTeXName("utf8-plain"));
2620 if (inputenc == "auto" || inputenc == "default")
2621 return *language->encoding();
2622 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2625 LYXERR0("Unknown inputenc value `" << inputenc
2626 << "'. Using `auto' instead.");
2627 return *language->encoding();
2631 CiteEngine BufferParams::citeEngine() const
2633 // FIXME the class should provide the numerical/
2634 // authoryear choice
2635 if (documentClass().provides("natbib")
2636 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2637 return ENGINE_NATBIB_AUTHORYEAR;
2638 return cite_engine_;
2642 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2644 cite_engine_ = cite_engine;