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"
27 #include "Converter.h"
30 #include "IndicesList.h"
32 #include "LaTeXFeatures.h"
33 #include "LaTeXFonts.h"
34 #include "ModuleList.h"
38 #include "OutputParams.h"
42 #include "PDFOptions.h"
44 #include "frontends/alert.h"
46 #include "insets/InsetListingsParams.h"
48 #include "support/convert.h"
49 #include "support/debug.h"
50 #include "support/docstream.h"
51 #include "support/FileName.h"
52 #include "support/filetools.h"
53 #include "support/gettext.h"
54 #include "support/Messages.h"
55 #include "support/Translator.h"
56 #include "support/lstrings.h"
62 using namespace lyx::support;
65 static char const * const string_paragraph_separation[] = {
70 static char const * const string_quotes_language[] = {
71 "english", "swedish", "german", "polish", "french", "danish", ""
75 static char const * const string_papersize[] = {
76 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
77 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
78 "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
79 "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
80 "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
85 static char const * const string_orientation[] = {
86 "portrait", "landscape", ""
90 static char const * const string_footnotekinds[] = {
91 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
95 static char const * const tex_graphics[] = {
96 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
97 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
98 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
99 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
110 // Paragraph separation
111 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
114 ParSepTranslator const init_parseptranslator()
116 ParSepTranslator translator
117 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
118 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
123 ParSepTranslator const & parseptranslator()
125 static ParSepTranslator translator = init_parseptranslator();
131 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
134 QuotesLangTranslator const init_quoteslangtranslator()
136 QuotesLangTranslator translator
137 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
138 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
139 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
140 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
141 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
142 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
147 QuotesLangTranslator const & quoteslangtranslator()
149 static QuotesLangTranslator translator = init_quoteslangtranslator();
155 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
158 static PaperSizeTranslator initPaperSizeTranslator()
160 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
161 translator.addPair(string_papersize[1], PAPER_CUSTOM);
162 translator.addPair(string_papersize[2], PAPER_USLETTER);
163 translator.addPair(string_papersize[3], PAPER_USLEGAL);
164 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
165 translator.addPair(string_papersize[5], PAPER_A0);
166 translator.addPair(string_papersize[6], PAPER_A1);
167 translator.addPair(string_papersize[7], PAPER_A2);
168 translator.addPair(string_papersize[8], PAPER_A3);
169 translator.addPair(string_papersize[9], PAPER_A4);
170 translator.addPair(string_papersize[10], PAPER_A5);
171 translator.addPair(string_papersize[11], PAPER_A6);
172 translator.addPair(string_papersize[12], PAPER_B0);
173 translator.addPair(string_papersize[13], PAPER_B1);
174 translator.addPair(string_papersize[14], PAPER_B2);
175 translator.addPair(string_papersize[15], PAPER_B3);
176 translator.addPair(string_papersize[16], PAPER_B4);
177 translator.addPair(string_papersize[17], PAPER_B5);
178 translator.addPair(string_papersize[18], PAPER_B6);
179 translator.addPair(string_papersize[19], PAPER_C0);
180 translator.addPair(string_papersize[20], PAPER_C1);
181 translator.addPair(string_papersize[21], PAPER_C2);
182 translator.addPair(string_papersize[22], PAPER_C3);
183 translator.addPair(string_papersize[23], PAPER_C4);
184 translator.addPair(string_papersize[24], PAPER_C5);
185 translator.addPair(string_papersize[25], PAPER_C6);
186 translator.addPair(string_papersize[26], PAPER_JISB0);
187 translator.addPair(string_papersize[27], PAPER_JISB1);
188 translator.addPair(string_papersize[28], PAPER_JISB2);
189 translator.addPair(string_papersize[29], PAPER_JISB3);
190 translator.addPair(string_papersize[30], PAPER_JISB4);
191 translator.addPair(string_papersize[31], PAPER_JISB5);
192 translator.addPair(string_papersize[32], PAPER_JISB6);
197 PaperSizeTranslator const & papersizetranslator()
199 static PaperSizeTranslator translator = initPaperSizeTranslator();
205 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
208 PaperOrientationTranslator const init_paperorientationtranslator()
210 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
211 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
216 PaperOrientationTranslator const & paperorientationtranslator()
218 static PaperOrientationTranslator translator = init_paperorientationtranslator();
224 typedef Translator<int, PageSides> SidesTranslator;
227 SidesTranslator const init_sidestranslator()
229 SidesTranslator translator(1, OneSide);
230 translator.addPair(2, TwoSides);
235 SidesTranslator const & sidestranslator()
237 static SidesTranslator translator = init_sidestranslator();
243 typedef Translator<int, BufferParams::Package> PackageTranslator;
246 PackageTranslator const init_packagetranslator()
248 PackageTranslator translator(0, BufferParams::package_off);
249 translator.addPair(1, BufferParams::package_auto);
250 translator.addPair(2, BufferParams::package_on);
255 PackageTranslator const & packagetranslator()
257 static PackageTranslator translator = init_packagetranslator();
263 typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator;
266 CiteEngineTypeTranslator const init_citeenginetypetranslator()
268 CiteEngineTypeTranslator translator("authoryear", ENGINE_TYPE_AUTHORYEAR);
269 translator.addPair("numerical", ENGINE_TYPE_NUMERICAL);
274 CiteEngineTypeTranslator const & citeenginetypetranslator()
276 static CiteEngineTypeTranslator translator = init_citeenginetypetranslator();
282 typedef Translator<string, Spacing::Space> SpaceTranslator;
285 SpaceTranslator const init_spacetranslator()
287 SpaceTranslator translator("default", Spacing::Default);
288 translator.addPair("single", Spacing::Single);
289 translator.addPair("onehalf", Spacing::Onehalf);
290 translator.addPair("double", Spacing::Double);
291 translator.addPair("other", Spacing::Other);
296 SpaceTranslator const & spacetranslator()
298 static SpaceTranslator translator = init_spacetranslator();
305 class BufferParams::Impl
310 AuthorList authorlist;
311 BranchList branchlist;
312 Bullet temp_bullets[4];
313 Bullet user_defined_bullets[4];
314 IndicesList indiceslist;
316 /** This is the amount of space used for paragraph_separation "skip",
317 * and for detached paragraphs in "indented" documents.
321 PDFOptions pdfoptions;
322 LayoutFileIndex baseClass_;
326 BufferParams::Impl::Impl()
327 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
329 // set initial author
331 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
336 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
340 return new BufferParams::Impl(*ptr);
344 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
350 BufferParams::BufferParams()
353 setBaseClass(defaultBaseclass());
355 paragraph_separation = ParagraphIndentSeparation;
356 quotes_language = InsetQuotes::EnglishQuotes;
357 fontsize = "default";
360 papersize = PAPER_DEFAULT;
361 orientation = ORIENTATION_PORTRAIT;
362 use_geometry = false;
363 cite_engine_.push_back("basic");
364 cite_engine_type_ = ENGINE_TYPE_NUMERICAL;
365 biblio_style = "plain";
366 use_bibtopic = false;
368 trackChanges = false;
369 outputChanges = false;
370 use_default_options = true;
371 maintain_unincluded_children = false;
374 language = default_language;
376 fonts_roman = "default";
377 fonts_sans = "default";
378 fonts_typewriter = "default";
380 fonts_default_family = "default";
381 useNonTeXFonts = false;
382 fonts_expert_sc = false;
383 fonts_old_figures = false;
384 fonts_sans_scale = 100;
385 fonts_typewriter_scale = 100;
387 lang_package = "default";
388 graphics_driver = "default";
389 default_output_format = "default";
390 bibtex_command = "default";
391 index_command = "default";
394 listings_params = string();
395 pagestyle = "default";
396 suppress_date = false;
397 justification = true;
398 // no color is the default (white)
399 backgroundcolor = lyx::rgbFromHexName("#ffffff");
400 isbackgroundcolor = false;
401 // no color is the default (black)
402 fontcolor = lyx::rgbFromHexName("#000000");
404 // light gray is the default font color for greyed-out notes
405 notefontcolor = lyx::rgbFromHexName("#cccccc");
406 boxbgcolor = lyx::rgbFromHexName("#ff0000");
407 compressed = lyxrc.save_compressed;
408 for (int iter = 0; iter < 4; ++iter) {
409 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
410 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
413 indiceslist().addDefault(B_("Index"));
414 html_be_strict = false;
415 html_math_output = MathML;
416 html_math_img_scale = 1.0;
417 html_css_as_file = false;
424 docstring BufferParams::B_(string const & l10n) const
426 LASSERT(language, /**/);
427 return getMessages(language->code()).get(l10n);
431 BufferParams::Package BufferParams::use_package(std::string const & p) const
433 PackageMap::const_iterator it = use_packages.find(p);
434 if (it == use_packages.end())
440 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
446 vector<string> const & BufferParams::auto_packages()
448 static vector<string> packages;
449 if (packages.empty()) {
450 // adding a package here implies a file format change!
451 packages.push_back("amsmath");
452 packages.push_back("amssymb");
453 packages.push_back("esint");
454 packages.push_back("mathdots");
455 packages.push_back("mathtools");
456 packages.push_back("mhchem");
457 packages.push_back("stackrel");
458 packages.push_back("stmaryrd");
459 packages.push_back("undertilde");
465 AuthorList & BufferParams::authors()
467 return pimpl_->authorlist;
471 AuthorList const & BufferParams::authors() const
473 return pimpl_->authorlist;
477 BranchList & BufferParams::branchlist()
479 return pimpl_->branchlist;
483 BranchList const & BufferParams::branchlist() const
485 return pimpl_->branchlist;
489 IndicesList & BufferParams::indiceslist()
491 return pimpl_->indiceslist;
495 IndicesList const & BufferParams::indiceslist() const
497 return pimpl_->indiceslist;
501 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
503 LASSERT(index < 4, /**/);
504 return pimpl_->temp_bullets[index];
508 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
510 LASSERT(index < 4, /**/);
511 return pimpl_->temp_bullets[index];
515 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
517 LASSERT(index < 4, /**/);
518 return pimpl_->user_defined_bullets[index];
522 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
524 LASSERT(index < 4, /**/);
525 return pimpl_->user_defined_bullets[index];
529 Spacing & BufferParams::spacing()
531 return pimpl_->spacing;
535 Spacing const & BufferParams::spacing() const
537 return pimpl_->spacing;
541 PDFOptions & BufferParams::pdfoptions()
543 return pimpl_->pdfoptions;
547 PDFOptions const & BufferParams::pdfoptions() const
549 return pimpl_->pdfoptions;
553 HSpace const & BufferParams::getIndentation() const
555 return pimpl_->indentation;
559 void BufferParams::setIndentation(HSpace const & indent)
561 pimpl_->indentation = indent;
565 VSpace const & BufferParams::getDefSkip() const
567 return pimpl_->defskip;
571 void BufferParams::setDefSkip(VSpace const & vs)
573 // DEFSKIP will cause an infinite loop
574 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
575 pimpl_->defskip = vs;
579 string BufferParams::readToken(Lexer & lex, string const & token,
580 FileName const & filepath)
582 if (token == "\\textclass") {
584 string const classname = lex.getString();
585 // if there exists a local layout file, ignore the system one
586 // NOTE: in this case, the textclass (.cls file) is assumed to
589 LayoutFileList & bcl = LayoutFileList::get();
590 if (tcp.empty() && !filepath.empty())
591 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
595 setBaseClass(classname);
596 // We assume that a tex class exists for local or unknown
597 // layouts so this warning, will only be given for system layouts.
598 if (!baseClass()->isTeXClassAvailable()) {
599 docstring const desc =
600 translateIfPossible(from_utf8(baseClass()->description()));
601 docstring const prereqs =
602 from_utf8(baseClass()->prerequisites());
603 docstring const msg =
604 bformat(_("The selected document class\n"
606 "requires external files that are not available.\n"
607 "The document class can still be used, but the\n"
608 "document cannot be compiled until the following\n"
609 "prerequisites are installed:\n"
611 "See section 3.1.2.2 (Class Availability) of the\n"
612 "User's Guide for more information."), desc, prereqs);
613 frontend::Alert::warning(_("Document class not available"),
616 } else if (token == "\\begin_preamble") {
618 } else if (token == "\\begin_local_layout") {
619 readLocalLayout(lex);
620 } else if (token == "\\begin_modules") {
622 } else if (token == "\\begin_removed_modules") {
623 readRemovedModules(lex);
624 } else if (token == "\\begin_includeonly") {
625 readIncludeonly(lex);
626 } else if (token == "\\maintain_unincluded_children") {
627 lex >> maintain_unincluded_children;
628 } else if (token == "\\options") {
630 options = lex.getString();
631 } else if (token == "\\use_default_options") {
632 lex >> use_default_options;
633 } else if (token == "\\master") {
635 master = lex.getString();
636 } else if (token == "\\suppress_date") {
637 lex >> suppress_date;
638 } else if (token == "\\justification") {
639 lex >> justification;
640 } else if (token == "\\language") {
642 } else if (token == "\\language_package") {
644 lang_package = lex.getString();
645 } else if (token == "\\inputencoding") {
647 } else if (token == "\\graphics") {
648 readGraphicsDriver(lex);
649 } else if (token == "\\default_output_format") {
650 lex >> default_output_format;
651 } else if (token == "\\bibtex_command") {
653 bibtex_command = lex.getString();
654 } else if (token == "\\index_command") {
656 index_command = lex.getString();
657 } else if (token == "\\fontencoding") {
659 fontenc = lex.getString();
660 } else if (token == "\\font_roman") {
662 fonts_roman = lex.getString();
663 } else if (token == "\\font_sans") {
665 fonts_sans = lex.getString();
666 } else if (token == "\\font_typewriter") {
668 fonts_typewriter = lex.getString();
669 } else if (token == "\\font_math") {
671 fonts_math = lex.getString();
672 } else if (token == "\\font_default_family") {
673 lex >> fonts_default_family;
674 } else if (token == "\\use_non_tex_fonts") {
675 lex >> useNonTeXFonts;
676 } else if (token == "\\font_sc") {
677 lex >> fonts_expert_sc;
678 } else if (token == "\\font_osf") {
679 lex >> fonts_old_figures;
680 } else if (token == "\\font_sf_scale") {
681 lex >> fonts_sans_scale;
682 } else if (token == "\\font_tt_scale") {
683 lex >> fonts_typewriter_scale;
684 } else if (token == "\\font_cjk") {
686 } else if (token == "\\paragraph_separation") {
689 paragraph_separation = parseptranslator().find(parsep);
690 } else if (token == "\\paragraph_indentation") {
692 string indentation = lex.getString();
693 pimpl_->indentation = HSpace(indentation);
694 } else if (token == "\\defskip") {
696 string const defskip = lex.getString();
697 pimpl_->defskip = VSpace(defskip);
698 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
700 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
701 } else if (token == "\\quotes_language") {
704 quotes_language = quoteslangtranslator().find(quotes_lang);
705 } else if (token == "\\papersize") {
708 papersize = papersizetranslator().find(ppsize);
709 } else if (token == "\\use_geometry") {
711 } else if (token == "\\use_package") {
716 use_package(package, packagetranslator().find(use));
717 } else if (token == "\\cite_engine") {
719 vector<string> engine = getVectorFromString(lex.getString());
720 setCiteEngine(engine);
721 } else if (token == "\\cite_engine_type") {
724 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
725 } else if (token == "\\biblio_style") {
727 biblio_style = lex.getString();
728 } else if (token == "\\use_bibtopic") {
730 } else if (token == "\\use_indices") {
732 } else if (token == "\\tracking_changes") {
734 } else if (token == "\\output_changes") {
735 lex >> outputChanges;
736 } else if (token == "\\branch") {
738 docstring branch = lex.getDocString();
739 branchlist().add(branch);
742 string const tok = lex.getString();
743 if (tok == "\\end_branch")
745 Branch * branch_ptr = branchlist().find(branch);
746 if (tok == "\\selected") {
749 branch_ptr->setSelected(lex.getInteger());
751 if (tok == "\\filename_suffix") {
754 branch_ptr->setFileNameSuffix(lex.getInteger());
756 if (tok == "\\color") {
758 string color = lex.getString();
760 branch_ptr->setColor(color);
761 // Update also the Color table:
763 color = lcolor.getX11Name(Color_background);
765 lcolor.setColor(to_utf8(branch), color);
768 } else if (token == "\\index") {
770 docstring index = lex.getDocString();
772 indiceslist().add(index);
775 string const tok = lex.getString();
776 if (tok == "\\end_index")
778 Index * index_ptr = indiceslist().find(index);
779 if (tok == "\\shortcut") {
781 shortcut = lex.getDocString();
783 index_ptr->setShortcut(shortcut);
785 if (tok == "\\color") {
787 string color = lex.getString();
789 index_ptr->setColor(color);
790 // Update also the Color table:
792 color = lcolor.getX11Name(Color_background);
794 if (!shortcut.empty())
795 lcolor.setColor(to_utf8(shortcut), color);
798 } else if (token == "\\author") {
800 istringstream ss(lex.getString());
803 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
804 } else if (token == "\\paperorientation") {
807 orientation = paperorientationtranslator().find(orient);
808 } else if (token == "\\backgroundcolor") {
810 backgroundcolor = lyx::rgbFromHexName(lex.getString());
811 isbackgroundcolor = true;
812 } else if (token == "\\fontcolor") {
814 fontcolor = lyx::rgbFromHexName(lex.getString());
816 } else if (token == "\\notefontcolor") {
818 string color = lex.getString();
819 notefontcolor = lyx::rgbFromHexName(color);
820 lcolor.setColor("notefontcolor", color);
821 } else if (token == "\\boxbgcolor") {
823 string color = lex.getString();
824 boxbgcolor = lyx::rgbFromHexName(color);
825 lcolor.setColor("boxbgcolor", color);
826 } else if (token == "\\paperwidth") {
828 } else if (token == "\\paperheight") {
830 } else if (token == "\\leftmargin") {
832 } else if (token == "\\topmargin") {
834 } else if (token == "\\rightmargin") {
836 } else if (token == "\\bottommargin") {
838 } else if (token == "\\headheight") {
840 } else if (token == "\\headsep") {
842 } else if (token == "\\footskip") {
844 } else if (token == "\\columnsep") {
846 } else if (token == "\\paperfontsize") {
848 } else if (token == "\\papercolumns") {
850 } else if (token == "\\listings_params") {
853 listings_params = InsetListingsParams(par).params();
854 } else if (token == "\\papersides") {
857 sides = sidestranslator().find(psides);
858 } else if (token == "\\paperpagestyle") {
860 } else if (token == "\\bullet") {
862 } else if (token == "\\bulletLaTeX") {
863 readBulletsLaTeX(lex);
864 } else if (token == "\\secnumdepth") {
866 } else if (token == "\\tocdepth") {
868 } else if (token == "\\spacing") {
872 if (nspacing == "other") {
875 spacing().set(spacetranslator().find(nspacing), tmp_val);
876 } else if (token == "\\float_placement") {
877 lex >> float_placement;
879 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
880 string toktmp = pdfoptions().readToken(lex, token);
881 if (!toktmp.empty()) {
882 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
886 } else if (token == "\\html_math_output") {
889 html_math_output = static_cast<MathOutput>(temp);
890 } else if (token == "\\html_be_strict") {
891 lex >> html_be_strict;
892 } else if (token == "\\html_css_as_file") {
893 lex >> html_css_as_file;
894 } else if (token == "\\html_math_img_scale") {
895 lex >> html_math_img_scale;
896 } else if (token == "\\html_latex_start") {
898 html_latex_start = lex.getString();
899 } else if (token == "\\html_latex_end") {
901 html_latex_end = lex.getString();
902 } else if (token == "\\output_sync") {
904 } else if (token == "\\output_sync_macro") {
905 lex >> output_sync_macro;
906 } else if (token == "\\use_refstyle") {
909 lyxerr << "BufferParams::readToken(): Unknown token: " <<
918 void BufferParams::writeFile(ostream & os) const
920 // The top of the file is written by the buffer.
921 // Prints out the buffer info into the .lyx file given by file
924 os << "\\textclass " << baseClass()->name() << '\n';
927 if (!preamble.empty()) {
928 // remove '\n' from the end of preamble
929 string const tmppreamble = rtrim(preamble, "\n");
930 os << "\\begin_preamble\n"
932 << "\n\\end_preamble\n";
936 if (!options.empty()) {
937 os << "\\options " << options << '\n';
940 // use the class options defined in the layout?
941 os << "\\use_default_options "
942 << convert<string>(use_default_options) << "\n";
944 // the master document
945 if (!master.empty()) {
946 os << "\\master " << master << '\n';
950 if (!removed_modules_.empty()) {
951 os << "\\begin_removed_modules" << '\n';
952 list<string>::const_iterator it = removed_modules_.begin();
953 list<string>::const_iterator en = removed_modules_.end();
954 for (; it != en; ++it)
956 os << "\\end_removed_modules" << '\n';
960 if (!layout_modules_.empty()) {
961 os << "\\begin_modules" << '\n';
962 LayoutModuleList::const_iterator it = layout_modules_.begin();
963 LayoutModuleList::const_iterator en = layout_modules_.end();
964 for (; it != en; ++it)
966 os << "\\end_modules" << '\n';
970 if (!included_children_.empty()) {
971 os << "\\begin_includeonly" << '\n';
972 list<string>::const_iterator it = included_children_.begin();
973 list<string>::const_iterator en = included_children_.end();
974 for (; it != en; ++it)
976 os << "\\end_includeonly" << '\n';
978 os << "\\maintain_unincluded_children "
979 << convert<string>(maintain_unincluded_children) << '\n';
981 // local layout information
982 if (!local_layout.empty()) {
983 // remove '\n' from the end
984 string const tmplocal = rtrim(local_layout, "\n");
985 os << "\\begin_local_layout\n"
987 << "\n\\end_local_layout\n";
990 // then the text parameters
991 if (language != ignore_language)
992 os << "\\language " << language->lang() << '\n';
993 os << "\\language_package " << lang_package
994 << "\n\\inputencoding " << inputenc
995 << "\n\\fontencoding " << fontenc
996 << "\n\\font_roman " << fonts_roman
997 << "\n\\font_sans " << fonts_sans
998 << "\n\\font_typewriter " << fonts_typewriter
999 << "\n\\font_math " << fonts_math
1000 << "\n\\font_default_family " << fonts_default_family
1001 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1002 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1003 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1004 << "\n\\font_sf_scale " << fonts_sans_scale
1005 << "\n\\font_tt_scale " << fonts_typewriter_scale
1007 if (!fonts_cjk.empty()) {
1008 os << "\\font_cjk " << fonts_cjk << '\n';
1010 os << "\\graphics " << graphics_driver << '\n';
1011 os << "\\default_output_format " << default_output_format << '\n';
1012 os << "\\output_sync " << output_sync << '\n';
1013 if (!output_sync_macro.empty())
1014 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1015 os << "\\bibtex_command " << bibtex_command << '\n';
1016 os << "\\index_command " << index_command << '\n';
1018 if (!float_placement.empty()) {
1019 os << "\\float_placement " << float_placement << '\n';
1021 os << "\\paperfontsize " << fontsize << '\n';
1023 spacing().writeFile(os);
1024 pdfoptions().writeFile(os);
1026 os << "\\papersize " << string_papersize[papersize]
1027 << "\n\\use_geometry " << convert<string>(use_geometry);
1028 vector<string> const & packages = auto_packages();
1029 for (size_t i = 0; i < packages.size(); ++i)
1030 os << "\n\\use_package " << packages[i] << ' '
1031 << use_package(packages[i]);
1033 os << "\n\\cite_engine ";
1035 if (!cite_engine_.empty()) {
1036 LayoutModuleList::const_iterator be = cite_engine_.begin();
1037 LayoutModuleList::const_iterator en = cite_engine_.end();
1038 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1047 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1048 << "\n\\biblio_style " << biblio_style
1049 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1050 << "\n\\use_indices " << convert<string>(use_indices)
1051 << "\n\\paperorientation " << string_orientation[orientation]
1052 << "\n\\suppress_date " << convert<string>(suppress_date)
1053 << "\n\\justification " << convert<string>(justification)
1054 << "\n\\use_refstyle " << use_refstyle
1056 if (isbackgroundcolor == true)
1057 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1058 if (isfontcolor == true)
1059 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1060 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1061 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1062 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1063 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1065 BranchList::const_iterator it = branchlist().begin();
1066 BranchList::const_iterator end = branchlist().end();
1067 for (; it != end; ++it) {
1068 os << "\\branch " << to_utf8(it->branch())
1069 << "\n\\selected " << it->isSelected()
1070 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1071 << "\n\\color " << lyx::X11hexname(it->color())
1076 IndicesList::const_iterator iit = indiceslist().begin();
1077 IndicesList::const_iterator iend = indiceslist().end();
1078 for (; iit != iend; ++iit) {
1079 os << "\\index " << to_utf8(iit->index())
1080 << "\n\\shortcut " << to_utf8(iit->shortcut())
1081 << "\n\\color " << lyx::X11hexname(iit->color())
1086 if (!paperwidth.empty())
1087 os << "\\paperwidth "
1088 << VSpace(paperwidth).asLyXCommand() << '\n';
1089 if (!paperheight.empty())
1090 os << "\\paperheight "
1091 << VSpace(paperheight).asLyXCommand() << '\n';
1092 if (!leftmargin.empty())
1093 os << "\\leftmargin "
1094 << VSpace(leftmargin).asLyXCommand() << '\n';
1095 if (!topmargin.empty())
1096 os << "\\topmargin "
1097 << VSpace(topmargin).asLyXCommand() << '\n';
1098 if (!rightmargin.empty())
1099 os << "\\rightmargin "
1100 << VSpace(rightmargin).asLyXCommand() << '\n';
1101 if (!bottommargin.empty())
1102 os << "\\bottommargin "
1103 << VSpace(bottommargin).asLyXCommand() << '\n';
1104 if (!headheight.empty())
1105 os << "\\headheight "
1106 << VSpace(headheight).asLyXCommand() << '\n';
1107 if (!headsep.empty())
1109 << VSpace(headsep).asLyXCommand() << '\n';
1110 if (!footskip.empty())
1112 << VSpace(footskip).asLyXCommand() << '\n';
1113 if (!columnsep.empty())
1114 os << "\\columnsep "
1115 << VSpace(columnsep).asLyXCommand() << '\n';
1116 os << "\\secnumdepth " << secnumdepth
1117 << "\n\\tocdepth " << tocdepth
1118 << "\n\\paragraph_separation "
1119 << string_paragraph_separation[paragraph_separation];
1120 if (!paragraph_separation)
1121 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1123 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1124 os << "\n\\quotes_language "
1125 << string_quotes_language[quotes_language]
1126 << "\n\\papercolumns " << columns
1127 << "\n\\papersides " << sides
1128 << "\n\\paperpagestyle " << pagestyle << '\n';
1129 if (!listings_params.empty())
1130 os << "\\listings_params \"" <<
1131 InsetListingsParams(listings_params).encodedString() << "\"\n";
1132 for (int i = 0; i < 4; ++i) {
1133 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1134 if (user_defined_bullet(i).getFont() != -1) {
1135 os << "\\bullet " << i << " "
1136 << user_defined_bullet(i).getFont() << " "
1137 << user_defined_bullet(i).getCharacter() << " "
1138 << user_defined_bullet(i).getSize() << "\n";
1142 os << "\\bulletLaTeX " << i << " \""
1143 << lyx::to_ascii(user_defined_bullet(i).getText())
1149 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1150 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1151 << "\\html_math_output " << html_math_output << '\n'
1152 << "\\html_css_as_file " << html_css_as_file << '\n'
1153 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1155 if (html_math_img_scale != 1.0)
1156 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1157 if (!html_latex_start.empty())
1158 os << "\\html_latex_start " << html_latex_start << '\n';
1159 if (!html_latex_end.empty())
1160 os << "\\html_latex_end " << html_latex_end << '\n';
1162 os << pimpl_->authorlist;
1166 void BufferParams::validate(LaTeXFeatures & features) const
1168 features.require(documentClass().requires());
1170 if (columns > 1 && language->rightToLeft())
1171 features.require("rtloutputdblcol");
1173 if (outputChanges) {
1174 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1175 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1176 LaTeXFeatures::isAvailable("xcolor");
1178 switch (features.runparams().flavor) {
1179 case OutputParams::LATEX:
1180 case OutputParams::DVILUATEX:
1182 features.require("ct-dvipost");
1183 features.require("dvipost");
1184 } else if (xcolorulem) {
1185 features.require("ct-xcolor-ulem");
1186 features.require("ulem");
1187 features.require("xcolor");
1189 features.require("ct-none");
1192 case OutputParams::LUATEX:
1193 case OutputParams::PDFLATEX:
1194 case OutputParams::XETEX:
1196 features.require("ct-xcolor-ulem");
1197 features.require("ulem");
1198 features.require("xcolor");
1199 // improves color handling in PDF output
1200 features.require("pdfcolmk");
1202 features.require("ct-none");
1210 // Floats with 'Here definitely' as default setting.
1211 if (float_placement.find('H') != string::npos)
1212 features.require("float");
1214 for (PackageMap::const_iterator it = use_packages.begin();
1215 it != use_packages.end(); ++it) {
1216 if (it->first == "amsmath") {
1217 // AMS Style is at document level
1218 if (it->second == package_on ||
1219 features.isProvided("amsmath"))
1220 features.require(it->first);
1221 } else if (it->second == package_on)
1222 features.require(it->first);
1225 // Document-level line spacing
1226 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1227 features.require("setspace");
1229 // the bullet shapes are buffer level not paragraph level
1230 // so they are tested here
1231 for (int i = 0; i < 4; ++i) {
1232 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1234 int const font = user_defined_bullet(i).getFont();
1236 int const c = user_defined_bullet(i).getCharacter();
1242 features.require("latexsym");
1244 } else if (font == 1) {
1245 features.require("amssymb");
1246 } else if (font >= 2 && font <= 5) {
1247 features.require("pifont");
1251 if (pdfoptions().use_hyperref) {
1252 features.require("hyperref");
1253 // due to interferences with babel and hyperref, the color package has to
1254 // be loaded after hyperref when hyperref is used with the colorlinks
1255 // option, see http://www.lyx.org/trac/ticket/5291
1256 if (pdfoptions().colorlinks)
1257 features.require("color");
1260 // some languages are only available via polyglossia
1261 if (features.runparams().flavor == OutputParams::XETEX
1262 && (features.hasPolyglossiaExclusiveLanguages()
1264 features.require("polyglossia");
1266 if (useNonTeXFonts && fonts_math != "auto")
1267 features.require("unicode-math");
1269 if (!language->requires().empty())
1270 features.require(language->requires());
1274 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1275 FileName const & filepath) const
1277 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1278 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1279 // \RequirePackage to do so, rather than the normal \usepackage
1280 // Do not try to load any other package before the document class, unless you
1281 // have a thorough understanding of the LATEX internals and know exactly what you
1283 if (features.mustProvide("fix-cm"))
1284 os << "\\RequirePackage{fix-cm}\n";
1286 os << "\\documentclass";
1288 DocumentClass const & tclass = documentClass();
1290 ostringstream clsoptions; // the document class options.
1292 if (tokenPos(tclass.opt_fontsize(),
1293 '|', fontsize) >= 0) {
1294 // only write if existing in list (and not default)
1295 clsoptions << fontsize << "pt,";
1298 // all paper sizes except of A4, A5, B5 and the US sizes need the
1300 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1301 && papersize != PAPER_USLETTER
1302 && papersize != PAPER_USLEGAL
1303 && papersize != PAPER_USEXECUTIVE
1304 && papersize != PAPER_A4
1305 && papersize != PAPER_A5
1306 && papersize != PAPER_B5;
1308 if (!use_geometry) {
1309 switch (papersize) {
1311 clsoptions << "a4paper,";
1313 case PAPER_USLETTER:
1314 clsoptions << "letterpaper,";
1317 clsoptions << "a5paper,";
1320 clsoptions << "b5paper,";
1322 case PAPER_USEXECUTIVE:
1323 clsoptions << "executivepaper,";
1326 clsoptions << "legalpaper,";
1360 if (sides != tclass.sides()) {
1363 clsoptions << "oneside,";
1366 clsoptions << "twoside,";
1372 if (columns != tclass.columns()) {
1374 clsoptions << "twocolumn,";
1376 clsoptions << "onecolumn,";
1380 && orientation == ORIENTATION_LANDSCAPE)
1381 clsoptions << "landscape,";
1383 // language should be a parameter to \documentclass
1384 if (language->babel() == "hebrew"
1385 && default_language->babel() != "hebrew")
1386 // This seems necessary
1387 features.useLanguage(default_language);
1389 ostringstream language_options;
1390 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1391 bool const use_polyglossia = features.usePolyglossia();
1392 bool const global = lyxrc.language_global_options;
1393 if (use_babel || (use_polyglossia && global)) {
1394 language_options << features.getBabelLanguages();
1395 if (!language->babel().empty()) {
1396 if (!language_options.str().empty())
1397 language_options << ',';
1398 language_options << language->babel();
1400 if (global && !features.needBabelLangOptions()
1401 && !language_options.str().empty())
1402 clsoptions << language_options.str() << ',';
1405 // the predefined options from the layout
1406 if (use_default_options && !tclass.options().empty())
1407 clsoptions << tclass.options() << ',';
1409 // the user-defined options
1410 if (!options.empty()) {
1411 clsoptions << options << ',';
1414 string strOptions(clsoptions.str());
1415 if (!strOptions.empty()) {
1416 strOptions = rtrim(strOptions, ",");
1418 os << '[' << from_utf8(strOptions) << ']';
1421 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1422 // end of \documentclass defs
1424 // if we use fontspec, we have to load the AMS packages here
1425 string const ams = features.loadAMSPackages();
1426 if (useNonTeXFonts && !ams.empty())
1427 os << from_ascii(ams);
1429 if (useNonTeXFonts) {
1430 os << "\\usepackage{fontspec}\n";
1431 if (features.mustProvide("unicode-math")
1432 && features.isAvailable("unicode-math"))
1433 os << "\\usepackage{unicode-math}\n";
1436 // font selection must be done before loading fontenc.sty
1437 string const fonts = loadFonts(features);
1439 os << from_utf8(fonts);
1441 if (fonts_default_family != "default")
1442 os << "\\renewcommand{\\familydefault}{\\"
1443 << from_ascii(fonts_default_family) << "}\n";
1445 // set font encoding
1446 // for arabic_arabi and farsi we also need to load the LAE and
1448 // XeTeX and LuaTeX (with OS fonts) work without fontenc
1449 if (font_encoding() != "default" && language->lang() != "japanese"
1450 && !useNonTeXFonts && !features.isProvided("fontenc")) {
1451 docstring extra_encoding;
1452 if (features.mustProvide("textgreek"))
1453 extra_encoding += from_ascii("LGR");
1454 if (features.mustProvide("textcyr")) {
1455 if (!extra_encoding.empty())
1456 extra_encoding.push_back(',');
1457 extra_encoding += from_ascii("T2A");
1459 if (!extra_encoding.empty() && !font_encoding().empty())
1460 extra_encoding.push_back(',');
1461 size_t fars = language_options.str().find("farsi");
1462 size_t arab = language_options.str().find("arabic");
1463 if (language->lang() == "arabic_arabi"
1464 || language->lang() == "farsi" || fars != string::npos
1465 || arab != string::npos) {
1466 os << "\\usepackage[" << extra_encoding
1467 << from_ascii(font_encoding())
1468 << ",LFE,LAE]{fontenc}\n";
1470 os << "\\usepackage[" << extra_encoding
1471 << from_ascii(font_encoding())
1476 // handle inputenc etc.
1477 writeEncodingPreamble(os, features);
1480 if (!features.runparams().includeall && !included_children_.empty()) {
1481 os << "\\includeonly{";
1482 list<string>::const_iterator it = included_children_.begin();
1483 list<string>::const_iterator en = included_children_.end();
1485 for (; it != en; ++it) {
1486 string incfile = *it;
1487 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1488 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1490 if (!features.runparams().nice)
1492 // \includeonly doesn't want an extension
1493 incfile = changeExtension(incfile, string());
1494 incfile = support::latex_path(incfile);
1495 if (!incfile.empty()) {
1498 os << from_utf8(incfile);
1505 if (!listings_params.empty() || features.isRequired("listings"))
1506 os << "\\usepackage{listings}\n";
1508 if (!listings_params.empty()) {
1510 // do not test validity because listings_params is
1511 // supposed to be valid
1513 InsetListingsParams(listings_params).separatedParams(true);
1514 // we can't support all packages, but we should load the color package
1515 if (par.find("\\color", 0) != string::npos)
1516 features.require("color");
1517 os << from_utf8(par)
1520 if (!features.isProvided("geometry")
1521 && (use_geometry || nonstandard_papersize)) {
1522 odocstringstream ods;
1523 if (!getGraphicsDriver("geometry").empty())
1524 ods << getGraphicsDriver("geometry");
1525 if (orientation == ORIENTATION_LANDSCAPE)
1526 ods << ",landscape";
1527 switch (papersize) {
1529 if (!paperwidth.empty())
1530 ods << ",paperwidth="
1531 << from_ascii(paperwidth);
1532 if (!paperheight.empty())
1533 ods << ",paperheight="
1534 << from_ascii(paperheight);
1536 case PAPER_USLETTER:
1537 ods << ",letterpaper";
1540 ods << ",legalpaper";
1542 case PAPER_USEXECUTIVE:
1543 ods << ",executivepaper";
1632 docstring const g_options = trim(ods.str(), ",");
1633 os << "\\usepackage";
1634 if (!g_options.empty())
1635 os << '[' << g_options << ']';
1636 os << "{geometry}\n";
1637 // output this only if use_geometry is true
1639 os << "\\geometry{verbose";
1640 if (!topmargin.empty())
1641 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1642 if (!bottommargin.empty())
1643 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1644 if (!leftmargin.empty())
1645 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1646 if (!rightmargin.empty())
1647 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1648 if (!headheight.empty())
1649 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1650 if (!headsep.empty())
1651 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1652 if (!footskip.empty())
1653 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1654 if (!columnsep.empty())
1655 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1658 } else if (orientation == ORIENTATION_LANDSCAPE
1659 || papersize != PAPER_DEFAULT) {
1660 features.require("papersize");
1663 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1664 if (pagestyle == "fancy")
1665 os << "\\usepackage{fancyhdr}\n";
1666 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1669 // only output when the background color is not default
1670 if (isbackgroundcolor == true) {
1671 // only require color here, the background color will be defined
1672 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1674 features.require("color");
1675 features.require("pagecolor");
1678 // only output when the font color is not default
1679 if (isfontcolor == true) {
1680 // only require color here, the font color will be defined
1681 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1683 features.require("color");
1684 features.require("fontcolor");
1687 // Only if class has a ToC hierarchy
1688 if (tclass.hasTocLevels()) {
1689 if (secnumdepth != tclass.secnumdepth()) {
1690 os << "\\setcounter{secnumdepth}{"
1694 if (tocdepth != tclass.tocdepth()) {
1695 os << "\\setcounter{tocdepth}{"
1701 if (paragraph_separation) {
1702 // when skip separation
1703 switch (getDefSkip().kind()) {
1704 case VSpace::SMALLSKIP:
1705 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1707 case VSpace::MEDSKIP:
1708 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1710 case VSpace::BIGSKIP:
1711 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1713 case VSpace::LENGTH:
1714 os << "\\setlength{\\parskip}{"
1715 << from_utf8(getDefSkip().length().asLatexString())
1718 default: // should never happen // Then delete it.
1719 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1722 os << "\\setlength{\\parindent}{0pt}\n";
1724 // when separation by indentation
1725 // only output something when a width is given
1726 if (getIndentation().asLyXCommand() != "default") {
1727 os << "\\setlength{\\parindent}{"
1728 << from_utf8(getIndentation().asLatexCommand())
1733 // Now insert the LyX specific LaTeX commands...
1734 docstring lyxpreamble;
1735 features.resolveAlternatives();
1738 if (!output_sync_macro.empty())
1739 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1740 else if (features.runparams().flavor == OutputParams::LATEX)
1741 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1742 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1743 lyxpreamble += "\\synctex=-1\n";
1746 // due to interferences with babel and hyperref, the color package has to
1747 // be loaded (when it is not already loaded) before babel when hyperref
1748 // is used with the colorlinks option, see
1749 // http://www.lyx.org/trac/ticket/5291
1750 // we decided therefore to load color always before babel, see
1751 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1752 lyxpreamble += from_ascii(features.getColorOptions());
1754 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1756 && (features.isRequired("jurabib")
1757 || features.isRequired("hyperref")
1758 || features.isRequired("vietnamese")
1759 || features.isRequired("japanese"))) {
1761 lyxpreamble += from_utf8(features.getBabelPresettings());
1762 lyxpreamble += from_utf8(babelCall(language_options.str(),
1763 features.needBabelLangOptions())) + '\n';
1764 lyxpreamble += from_utf8(features.getBabelPostsettings());
1767 // The optional packages;
1768 lyxpreamble += from_ascii(features.getPackages());
1770 // Additional Indices
1771 if (features.isRequired("splitidx")) {
1772 IndicesList::const_iterator iit = indiceslist().begin();
1773 IndicesList::const_iterator iend = indiceslist().end();
1774 for (; iit != iend; ++iit) {
1775 pair<docstring, docstring> indexname_latex =
1776 features.runparams().encoding->latexString(iit->index(),
1777 features.runparams().dryrun);
1778 if (!indexname_latex.second.empty()) {
1779 // issue a warning about omitted characters
1780 // FIXME: should be passed to the error dialog
1781 frontend::Alert::warning(_("Uncodable characters"),
1782 bformat(_("The following characters that are used in an index name are not\n"
1783 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1784 indexname_latex.second));
1786 lyxpreamble += "\\newindex[";
1787 lyxpreamble += indexname_latex.first;
1788 lyxpreamble += "]{";
1789 lyxpreamble += escape(iit->shortcut());
1790 lyxpreamble += "}\n";
1795 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1798 // * Hyperref manual: "Make sure it comes last of your loaded
1799 // packages, to give it a fighting chance of not being over-written,
1800 // since its job is to redefine many LaTeX commands."
1801 // * Email from Heiko Oberdiek: "It is usually better to load babel
1802 // before hyperref. Then hyperref has a chance to detect babel.
1803 // * Has to be loaded before the "LyX specific LaTeX commands" to
1804 // avoid errors with algorithm floats.
1805 // use hyperref explicitly if it is required
1806 if (features.isRequired("hyperref")) {
1807 // pass what we have to stream here, since we need
1808 // to access the stream itself in PDFOptions.
1811 OutputParams tmp_params = features.runparams();
1812 pdfoptions().writeLaTeX(tmp_params, os,
1813 features.isProvided("hyperref"));
1814 // set back for the rest
1815 lyxpreamble.clear();
1816 // correctly break URLs with hyperref and dvi output
1817 if (features.runparams().flavor == OutputParams::LATEX
1818 && features.isAvailable("breakurl"))
1819 lyxpreamble += "\\usepackage{breakurl}\n";
1820 } else if (features.isRequired("nameref"))
1821 // hyperref loads this automatically
1822 lyxpreamble += "\\usepackage{nameref}\n";
1824 // bibtopic needs to be loaded after hyperref.
1825 // the dot provides the aux file naming which LyX can detect.
1826 if (features.mustProvide("bibtopic"))
1827 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1829 // Will be surrounded by \makeatletter and \makeatother when not empty
1830 docstring atlyxpreamble;
1832 // Some macros LyX will need
1833 docstring tmppreamble(features.getMacros());
1835 if (!tmppreamble.empty())
1836 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1837 "LyX specific LaTeX commands.\n"
1838 + tmppreamble + '\n';
1840 // the text class specific preamble
1841 tmppreamble = features.getTClassPreamble();
1842 if (!tmppreamble.empty())
1843 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1844 "Textclass specific LaTeX commands.\n"
1845 + tmppreamble + '\n';
1847 // suppress date if selected
1848 // use \@ifundefined because we cannot be sure that every document class
1849 // has a \date command
1851 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1853 /* the user-defined preamble */
1854 if (!containsOnly(preamble, " \n\t"))
1856 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1857 "User specified LaTeX commands.\n"
1858 + from_utf8(preamble) + '\n';
1860 // subfig loads internally the LaTeX package "caption". As
1861 // caption is a very popular package, users will load it in
1862 // the preamble. Therefore we must load subfig behind the
1863 // user-defined preamble and check if the caption package was
1864 // loaded or not. For the case that caption is loaded before
1865 // subfig, there is the subfig option "caption=false". This
1866 // option also works when a koma-script class is used and
1867 // koma's own caption commands are used instead of caption. We
1868 // use \PassOptionsToPackage here because the user could have
1869 // already loaded subfig in the preamble.
1870 if (features.isRequired("subfig")) {
1871 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1872 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1873 "\\usepackage{subfig}\n";
1876 // Itemize bullet settings need to be last in case the user
1877 // defines their own bullets that use a package included
1878 // in the user-defined preamble -- ARRae
1879 // Actually it has to be done much later than that
1880 // since some packages like frenchb make modifications
1881 // at \begin{document} time -- JMarc
1882 docstring bullets_def;
1883 for (int i = 0; i < 4; ++i) {
1884 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1885 if (bullets_def.empty())
1886 bullets_def += "\\AtBeginDocument{\n";
1887 bullets_def += " \\def\\labelitemi";
1889 // `i' is one less than the item to modify
1896 bullets_def += "ii";
1902 bullets_def += '{' +
1903 user_defined_bullet(i).getText()
1908 if (!bullets_def.empty())
1909 atlyxpreamble += bullets_def + "}\n\n";
1911 if (!atlyxpreamble.empty())
1912 lyxpreamble += "\n\\makeatletter\n"
1913 + atlyxpreamble + "\\makeatother\n\n";
1915 // We try to load babel late, in case it interferes with other packages.
1916 // Jurabib and Hyperref have to be called after babel, though.
1917 if (use_babel && !features.isRequired("jurabib")
1918 && !features.isRequired("hyperref")
1919 && !features.isRequired("vietnamese")
1920 && !features.isRequired("japanese")) {
1922 lyxpreamble += from_utf8(features.getBabelPresettings());
1923 lyxpreamble += from_utf8(babelCall(language_options.str(),
1924 features.needBabelLangOptions())) + '\n';
1925 lyxpreamble += from_utf8(features.getBabelPostsettings());
1928 // xunicode needs to be loaded at least after amsmath, amssymb,
1929 // esint and the other packages that provide special glyphs
1930 if (features.runparams().flavor == OutputParams::XETEX)
1931 lyxpreamble += "\\usepackage{xunicode}\n";
1933 // Polyglossia must be loaded last
1934 if (use_polyglossia) {
1936 lyxpreamble += "\\usepackage{polyglossia}\n";
1937 // set the main language
1938 lyxpreamble += "\\setdefaultlanguage";
1939 if (!language->polyglossiaOpts().empty())
1940 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
1941 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
1942 // now setup the other languages
1943 std::map<std::string, std::string> const polylangs =
1944 features.getPolyglossiaLanguages();
1945 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
1946 mit != polylangs.end() ; ++mit) {
1947 lyxpreamble += "\\setotherlanguage";
1948 if (!mit->second.empty())
1949 lyxpreamble += "[" + from_ascii(mit->second) + "]";
1950 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
1954 // Load custom language package here
1955 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
1956 if (lang_package == "default")
1957 lyxpreamble += from_utf8(lyxrc.language_custom_package);
1959 lyxpreamble += from_utf8(lang_package);
1960 lyxpreamble += '\n';
1963 docstring const i18npreamble =
1964 features.getTClassI18nPreamble(use_babel, use_polyglossia);
1965 if (!i18npreamble.empty())
1966 lyxpreamble += i18npreamble + '\n';
1974 void BufferParams::useClassDefaults()
1976 DocumentClass const & tclass = documentClass();
1978 sides = tclass.sides();
1979 columns = tclass.columns();
1980 pagestyle = tclass.pagestyle();
1981 use_default_options = true;
1982 // Only if class has a ToC hierarchy
1983 if (tclass.hasTocLevels()) {
1984 secnumdepth = tclass.secnumdepth();
1985 tocdepth = tclass.tocdepth();
1990 bool BufferParams::hasClassDefaults() const
1992 DocumentClass const & tclass = documentClass();
1994 return sides == tclass.sides()
1995 && columns == tclass.columns()
1996 && pagestyle == tclass.pagestyle()
1997 && use_default_options
1998 && secnumdepth == tclass.secnumdepth()
1999 && tocdepth == tclass.tocdepth();
2003 DocumentClass const & BufferParams::documentClass() const
2005 return *doc_class_.get();
2009 DocumentClassConstPtr BufferParams::documentClassPtr() const
2015 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2017 // evil, but this function is evil
2018 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2022 bool BufferParams::setBaseClass(string const & classname)
2024 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2025 LayoutFileList & bcl = LayoutFileList::get();
2026 if (!bcl.haveClass(classname)) {
2028 bformat(_("The layout file:\n"
2030 "could not be found. A default textclass with default\n"
2031 "layouts will be used. LyX will not be able to produce\n"
2033 from_utf8(classname));
2034 frontend::Alert::error(_("Document class not found"), s);
2035 bcl.addEmptyClass(classname);
2038 bool const success = bcl[classname].load();
2041 bformat(_("Due to some error in it, the layout file:\n"
2043 "could not be loaded. A default textclass with default\n"
2044 "layouts will be used. LyX will not be able to produce\n"
2046 from_utf8(classname));
2047 frontend::Alert::error(_("Could not load class"), s);
2048 bcl.addEmptyClass(classname);
2051 pimpl_->baseClass_ = classname;
2052 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2057 LayoutFile const * BufferParams::baseClass() const
2059 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2060 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2066 LayoutFileIndex const & BufferParams::baseClassID() const
2068 return pimpl_->baseClass_;
2072 void BufferParams::makeDocumentClass()
2077 LayoutModuleList mods;
2078 LayoutModuleList::iterator it = layout_modules_.begin();
2079 LayoutModuleList::iterator en = layout_modules_.end();
2080 for (; it != en; ++it)
2081 mods.push_back(*it);
2083 it = cite_engine_.begin();
2084 en = cite_engine_.end();
2085 for (; it != en; ++it)
2086 mods.push_back(*it);
2088 doc_class_ = getDocumentClass(*baseClass(), mods);
2090 if (!local_layout.empty()) {
2091 TextClass::ReturnValues success =
2092 doc_class_->read(local_layout, TextClass::MODULE);
2093 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2094 docstring const msg = _("Error reading internal layout information");
2095 frontend::Alert::warning(_("Read Error"), msg);
2101 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2103 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2107 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2109 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2113 bool BufferParams::addLayoutModule(string const & modName)
2115 LayoutModuleList::const_iterator it = layout_modules_.begin();
2116 LayoutModuleList::const_iterator end = layout_modules_.end();
2117 for (; it != end; ++it)
2120 layout_modules_.push_back(modName);
2125 string BufferParams::bufferFormat() const
2127 string format = documentClass().outputFormat();
2128 if (format == "latex") {
2131 if (encoding().package() == Encoding::japanese)
2138 bool BufferParams::isExportable(string const & format) const
2140 vector<string> backs = backends();
2141 for (vector<string>::const_iterator it = backs.begin();
2142 it != backs.end(); ++it)
2143 if (theConverters().isReachable(*it, format))
2151 bool formatSorter(Format const * lhs, Format const * rhs)
2153 return _(lhs->prettyname()) < _(rhs->prettyname());
2159 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2161 vector<string> const backs = backends();
2162 set<string> excludes;
2163 if (useNonTeXFonts) {
2164 excludes.insert("latex");
2165 excludes.insert("pdflatex");
2167 vector<Format const *> result =
2168 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2169 for (vector<string>::const_iterator it = backs.begin() + 1;
2170 it != backs.end(); ++it) {
2171 vector<Format const *> r =
2172 theConverters().getReachable(*it, only_viewable, false, excludes);
2173 result.insert(result.end(), r.begin(), r.end());
2175 sort(result.begin(), result.end(), formatSorter);
2180 bool BufferParams::isExportableFormat(string const & format) const
2182 typedef vector<Format const *> Formats;
2184 formats = exportableFormats(true);
2185 Formats::const_iterator fit = formats.begin();
2186 Formats::const_iterator end = formats.end();
2187 for (; fit != end ; ++fit) {
2188 if ((*fit)->name() == format)
2195 vector<string> BufferParams::backends() const
2198 string const buffmt = bufferFormat();
2200 // FIXME: Don't hardcode format names here, but use a flag
2201 if (buffmt == "latex") {
2202 if (!useNonTeXFonts) {
2203 v.push_back("pdflatex");
2204 v.push_back("latex");
2206 v.push_back("luatex");
2207 v.push_back("dviluatex");
2208 v.push_back("xetex");
2209 } else if (buffmt == "xetex") {
2210 v.push_back("xetex");
2211 v.push_back("luatex");
2212 v.push_back("dviluatex");
2214 v.push_back(buffmt);
2216 v.push_back("xhtml");
2217 v.push_back("text");
2223 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const format) const
2225 string const dformat = (format.empty() || format == "default") ?
2226 getDefaultOutputFormat() : format;
2227 DefaultFlavorCache::const_iterator it =
2228 default_flavors_.find(dformat);
2230 if (it != default_flavors_.end())
2233 OutputParams::FLAVOR result = OutputParams::LATEX;
2235 // FIXME It'd be better not to hardcode this, but to do
2236 // something with formats.
2237 if (dformat == "xhtml")
2238 result = OutputParams::HTML;
2239 else if (dformat == "text")
2240 result = OutputParams::TEXT;
2241 else if (dformat == "lyx")
2242 result = OutputParams::LYX;
2243 else if (dformat == "pdflatex")
2244 result = OutputParams::PDFLATEX;
2245 else if (dformat == "xetex")
2246 result = OutputParams::XETEX;
2247 else if (dformat == "luatex")
2248 result = OutputParams::LUATEX;
2249 else if (dformat == "dviluatex")
2250 result = OutputParams::DVILUATEX;
2252 // Try to determine flavor of default output format
2253 vector<string> backs = backends();
2254 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2255 // Get shortest path to format
2256 Graph::EdgePath path;
2257 for (vector<string>::const_iterator it = backs.begin();
2258 it != backs.end(); ++it) {
2259 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2260 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2265 result = theConverters().getFlavor(path);
2268 // cache this flavor
2269 default_flavors_[dformat] = result;
2274 string BufferParams::getDefaultOutputFormat() const
2276 if (!default_output_format.empty()
2277 && default_output_format != "default")
2278 return default_output_format;
2281 || encoding().package() == Encoding::japanese) {
2282 vector<Format const *> const formats = exportableFormats(true);
2283 if (formats.empty())
2285 // return the first we find
2286 return formats.front()->name();
2288 return lyxrc.default_view_format;
2291 Font const BufferParams::getFont() const
2293 FontInfo f = documentClass().defaultfont();
2294 if (fonts_default_family == "rmdefault")
2295 f.setFamily(ROMAN_FAMILY);
2296 else if (fonts_default_family == "sfdefault")
2297 f.setFamily(SANS_FAMILY);
2298 else if (fonts_default_family == "ttdefault")
2299 f.setFamily(TYPEWRITER_FAMILY);
2300 return Font(f, language);
2304 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const qs) const
2306 return quoteslangtranslator().find(qs);
2310 bool BufferParams::isLatex() const
2312 return documentClass().outputType() == LATEX;
2316 bool BufferParams::isLiterate() const
2318 return documentClass().outputType() == LITERATE;
2322 bool BufferParams::isDocBook() const
2324 return documentClass().outputType() == DOCBOOK;
2328 void BufferParams::readPreamble(Lexer & lex)
2330 if (lex.getString() != "\\begin_preamble")
2331 lyxerr << "Error (BufferParams::readPreamble):"
2332 "consistency check failed." << endl;
2334 preamble = lex.getLongString("\\end_preamble");
2338 void BufferParams::readLocalLayout(Lexer & lex)
2340 if (lex.getString() != "\\begin_local_layout")
2341 lyxerr << "Error (BufferParams::readLocalLayout):"
2342 "consistency check failed." << endl;
2344 local_layout = lex.getLongString("\\end_local_layout");
2348 bool BufferParams::setLanguage(string const & lang)
2350 Language const *new_language = languages.getLanguage(lang);
2351 if (!new_language) {
2352 // Language lang was not found
2355 language = new_language;
2360 void BufferParams::readLanguage(Lexer & lex)
2362 if (!lex.next()) return;
2364 string const tmptok = lex.getString();
2366 // check if tmptok is part of tex_babel in tex-defs.h
2367 if (!setLanguage(tmptok)) {
2368 // Language tmptok was not found
2369 language = default_language;
2370 lyxerr << "Warning: Setting language `"
2371 << tmptok << "' to `" << language->lang()
2377 void BufferParams::readGraphicsDriver(Lexer & lex)
2382 string const tmptok = lex.getString();
2383 // check if tmptok is part of tex_graphics in tex_defs.h
2386 string const test = tex_graphics[n++];
2388 if (test == tmptok) {
2389 graphics_driver = tmptok;
2394 "Warning: graphics driver `$$Token' not recognized!\n"
2395 " Setting graphics driver to `default'.\n");
2396 graphics_driver = "default";
2403 void BufferParams::readBullets(Lexer & lex)
2408 int const index = lex.getInteger();
2410 int temp_int = lex.getInteger();
2411 user_defined_bullet(index).setFont(temp_int);
2412 temp_bullet(index).setFont(temp_int);
2414 user_defined_bullet(index).setCharacter(temp_int);
2415 temp_bullet(index).setCharacter(temp_int);
2417 user_defined_bullet(index).setSize(temp_int);
2418 temp_bullet(index).setSize(temp_int);
2422 void BufferParams::readBulletsLaTeX(Lexer & lex)
2424 // The bullet class should be able to read this.
2427 int const index = lex.getInteger();
2429 docstring const temp_str = lex.getDocString();
2431 user_defined_bullet(index).setText(temp_str);
2432 temp_bullet(index).setText(temp_str);
2436 void BufferParams::readModules(Lexer & lex)
2438 if (!lex.eatLine()) {
2439 lyxerr << "Error (BufferParams::readModules):"
2440 "Unexpected end of input." << endl;
2444 string mod = lex.getString();
2445 if (mod == "\\end_modules")
2447 addLayoutModule(mod);
2453 void BufferParams::readRemovedModules(Lexer & lex)
2455 if (!lex.eatLine()) {
2456 lyxerr << "Error (BufferParams::readRemovedModules):"
2457 "Unexpected end of input." << endl;
2461 string mod = lex.getString();
2462 if (mod == "\\end_removed_modules")
2464 removed_modules_.push_back(mod);
2467 // now we want to remove any removed modules that were previously
2468 // added. normally, that will be because default modules were added in
2469 // setBaseClass(), which gets called when \textclass is read at the
2470 // start of the read.
2471 list<string>::const_iterator rit = removed_modules_.begin();
2472 list<string>::const_iterator const ren = removed_modules_.end();
2473 for (; rit != ren; ++rit) {
2474 LayoutModuleList::iterator const mit = layout_modules_.begin();
2475 LayoutModuleList::iterator const men = layout_modules_.end();
2476 LayoutModuleList::iterator found = find(mit, men, *rit);
2479 layout_modules_.erase(found);
2484 void BufferParams::readIncludeonly(Lexer & lex)
2486 if (!lex.eatLine()) {
2487 lyxerr << "Error (BufferParams::readIncludeonly):"
2488 "Unexpected end of input." << endl;
2492 string child = lex.getString();
2493 if (child == "\\end_includeonly")
2495 included_children_.push_back(child);
2501 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2503 switch (papersize) {
2505 // could be anything, so don't guess
2507 case PAPER_CUSTOM: {
2508 if (purpose == XDVI && !paperwidth.empty() &&
2509 !paperheight.empty()) {
2510 // heightxwidth<unit>
2511 string first = paperwidth;
2512 string second = paperheight;
2513 if (orientation == ORIENTATION_LANDSCAPE)
2516 return first.erase(first.length() - 2)
2522 // dvips and dvipdfm do not know this
2523 if (purpose == DVIPS || purpose == DVIPDFM)
2527 if (purpose == DVIPS || purpose == DVIPDFM)
2531 if (purpose == DVIPS || purpose == DVIPDFM)
2541 if (purpose == DVIPS || purpose == DVIPDFM)
2545 if (purpose == DVIPS || purpose == DVIPDFM)
2549 if (purpose == DVIPS || purpose == DVIPDFM)
2553 if (purpose == DVIPS || purpose == DVIPDFM)
2557 if (purpose == DVIPS || purpose == DVIPDFM)
2561 // dvipdfm does not know this
2562 if (purpose == DVIPDFM)
2566 if (purpose == DVIPDFM)
2570 if (purpose == DVIPS || purpose == DVIPDFM)
2574 if (purpose == DVIPS || purpose == DVIPDFM)
2578 if (purpose == DVIPS || purpose == DVIPDFM)
2582 if (purpose == DVIPS || purpose == DVIPDFM)
2586 if (purpose == DVIPS || purpose == DVIPDFM)
2590 if (purpose == DVIPS || purpose == DVIPDFM)
2594 if (purpose == DVIPS || purpose == DVIPDFM)
2598 if (purpose == DVIPS || purpose == DVIPDFM)
2602 if (purpose == DVIPS || purpose == DVIPDFM)
2606 if (purpose == DVIPS || purpose == DVIPDFM)
2610 if (purpose == DVIPS || purpose == DVIPDFM)
2614 if (purpose == DVIPS || purpose == DVIPDFM)
2618 if (purpose == DVIPS || purpose == DVIPDFM)
2622 if (purpose == DVIPS || purpose == DVIPDFM)
2626 if (purpose == DVIPS || purpose == DVIPDFM)
2629 case PAPER_USEXECUTIVE:
2630 // dvipdfm does not know this
2631 if (purpose == DVIPDFM)
2636 case PAPER_USLETTER:
2638 if (purpose == XDVI)
2645 string const BufferParams::dvips_options() const
2649 // If the class loads the geometry package, we do not know which
2650 // paper size is used, since we do not set it (bug 7013).
2651 // Therefore we must not specify any argument here.
2652 // dvips gets the correct paper size via DVI specials in this case
2653 // (if the class uses the geometry package correctly).
2654 if (documentClass().provides("geometry"))
2658 && papersize == PAPER_CUSTOM
2659 && !lyxrc.print_paper_dimension_flag.empty()
2660 && !paperwidth.empty()
2661 && !paperheight.empty()) {
2662 // using a custom papersize
2663 result = lyxrc.print_paper_dimension_flag;
2664 result += ' ' + paperwidth;
2665 result += ',' + paperheight;
2667 string const paper_option = paperSizeName(DVIPS);
2668 if (!paper_option.empty() && (paper_option != "letter" ||
2669 orientation != ORIENTATION_LANDSCAPE)) {
2670 // dvips won't accept -t letter -t landscape.
2671 // In all other cases, include the paper size
2673 result = lyxrc.print_paper_flag;
2674 result += ' ' + paper_option;
2677 if (orientation == ORIENTATION_LANDSCAPE &&
2678 papersize != PAPER_CUSTOM)
2679 result += ' ' + lyxrc.print_landscape_flag;
2684 string const BufferParams::font_encoding() const
2686 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2690 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2692 // suppress the babel call if there is no BabelName defined
2693 // for the document language in the lib/languages file and if no
2694 // other languages are used (lang_opts is then empty)
2695 if (lang_opts.empty())
2697 // either a specific language (AsBabelOptions setting in
2698 // lib/languages) or the prefs require the languages to
2699 // be submitted to babel itself (not the class).
2701 return "\\usepackage[" + lang_opts + "]{babel}";
2702 return "\\usepackage{babel}";
2706 docstring BufferParams::getGraphicsDriver(string const & package) const
2710 if (package == "geometry") {
2711 if (graphics_driver == "dvips"
2712 || graphics_driver == "dvipdfm"
2713 || graphics_driver == "pdftex"
2714 || graphics_driver == "vtex")
2715 result = from_ascii(graphics_driver);
2716 else if (graphics_driver == "dvipdfmx")
2717 result = from_ascii("dvipdfm");
2724 void BufferParams::writeEncodingPreamble(otexstream & os,
2725 LaTeXFeatures & features) const
2727 // XeTeX does not need this
2728 if (features.runparams().flavor == OutputParams::XETEX)
2730 // LuaTeX neither, but with tex fonts, we need to load
2731 // the luainputenc package.
2732 if (features.runparams().flavor == OutputParams::LUATEX
2733 || features.runparams().flavor == OutputParams::DVILUATEX) {
2734 if (!useNonTeXFonts && inputenc != "default"
2735 && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc)
2736 || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) {
2737 os << "\\usepackage[utf8]{luainputenc}\n";
2741 if (inputenc == "auto") {
2742 string const doc_encoding =
2743 language->encoding()->latexName();
2744 Encoding::Package const package =
2745 language->encoding()->package();
2747 // Create a list with all the input encodings used
2749 set<string> encodings =
2750 features.getEncodingSet(doc_encoding);
2752 // If the "japanese" package (i.e. pLaTeX) is used,
2753 // inputenc must be omitted.
2754 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2755 if ((!encodings.empty() || package == Encoding::inputenc)
2756 && !features.isRequired("japanese")) {
2757 os << "\\usepackage[";
2758 set<string>::const_iterator it = encodings.begin();
2759 set<string>::const_iterator const end = encodings.end();
2761 os << from_ascii(*it);
2764 for (; it != end; ++it)
2765 os << ',' << from_ascii(*it);
2766 if (package == Encoding::inputenc) {
2767 if (!encodings.empty())
2769 os << from_ascii(doc_encoding);
2771 os << "]{inputenc}\n";
2773 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2774 if (language->encoding()->name() == "utf8-cjk"
2775 && LaTeXFeatures::isAvailable("CJKutf8"))
2776 os << "\\usepackage{CJKutf8}\n";
2778 os << "\\usepackage{CJK}\n";
2780 } else if (inputenc != "default") {
2781 switch (encoding().package()) {
2782 case Encoding::none:
2783 case Encoding::japanese:
2785 case Encoding::inputenc:
2786 // do not load inputenc if japanese is used
2787 if (features.isRequired("japanese"))
2789 os << "\\usepackage[" << from_ascii(encoding().latexName())
2793 if (encoding().name() == "utf8-cjk"
2794 && LaTeXFeatures::isAvailable("CJKutf8"))
2795 os << "\\usepackage{CJKutf8}\n";
2797 os << "\\usepackage{CJK}\n";
2804 string const BufferParams::parseFontName(string const & name) const
2806 string mangled = name;
2807 size_t const idx = mangled.find('[');
2808 if (idx == string::npos || idx == 0)
2811 return mangled.substr(0, idx - 1);
2815 string const BufferParams::loadFonts(LaTeXFeatures & features) const
2817 if (fonts_roman == "default" && fonts_sans == "default"
2818 && fonts_typewriter == "default"
2819 && (fonts_math == "default" || fonts_math == "auto"))
2825 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
2826 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
2827 * Mapping=tex-text option assures TeX ligatures (such as "--")
2828 * are resolved. Note that tt does not use these ligatures.
2830 * -- add more GUI options?
2831 * -- add more fonts (fonts for other scripts)
2832 * -- if there's a way to find out if a font really supports
2833 * OldStyle, enable/disable the widget accordingly.
2835 if (useNonTeXFonts && features.isAvailable("fontspec")) {
2836 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
2837 // However, until v.2 (2010/07/11) fontspec only knew
2838 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
2839 // was introduced for both XeTeX and LuaTeX (LuaTeX
2840 // didn't understand "Mapping=tex-text", while XeTeX
2841 // understood both. With most recent versions, both
2842 // variants are understood by both engines. However,
2843 // we want to provide support for at least TeXLive 2009
2844 // (for XeTeX; LuaTeX is only supported as of v.2)
2845 string const texmapping =
2846 (features.runparams().flavor == OutputParams::XETEX) ?
2847 "Mapping=tex-text" : "Ligatures=TeX";
2848 if (fonts_roman != "default") {
2849 os << "\\setmainfont[" << texmapping;
2850 if (fonts_old_figures)
2851 os << ",Numbers=OldStyle";
2852 os << "]{" << parseFontName(fonts_roman) << "}\n";
2854 if (fonts_sans != "default") {
2855 string const sans = parseFontName(fonts_sans);
2856 if (fonts_sans_scale != 100)
2857 os << "\\setsansfont[Scale="
2858 << float(fonts_sans_scale) / 100
2859 << "," << texmapping << "]{"
2862 os << "\\setsansfont[" << texmapping << "]{"
2865 if (fonts_typewriter != "default") {
2866 string const mono = parseFontName(fonts_typewriter);
2867 if (fonts_typewriter_scale != 100)
2868 os << "\\setmonofont[Scale="
2869 << float(fonts_typewriter_scale) / 100
2873 os << "\\setmonofont{"
2880 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
2881 bool const dryrun = features.runparams().dryrun;
2882 bool const complete = (fonts_sans == "default" && fonts_typewriter == "default");
2883 bool const nomath = (fonts_math == "default");
2886 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_roman)).getLaTeXCode(
2887 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2891 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_sans)).getLaTeXCode(
2892 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2893 nomath, fonts_sans_scale);
2895 // MONOSPACED/TYPEWRITER
2896 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_typewriter)).getLaTeXCode(
2897 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2898 nomath, fonts_typewriter_scale);
2901 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getLaTeXCode(
2902 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2909 Encoding const & BufferParams::encoding() const
2911 // FIXME: actually, we should check for the flavor
2912 // or runparams.isFullyUnicode() here:
2913 // This check will not work with XeTeX/LuaTeX and tex fonts.
2914 // Thus we have to reset the encoding in Buffer::makeLaTeXFile.
2916 return *(encodings.fromLyXName("utf8-plain"));
2917 if (inputenc == "auto" || inputenc == "default")
2918 return *language->encoding();
2919 Encoding const * const enc = encodings.fromLyXName(inputenc);
2922 LYXERR0("Unknown inputenc value `" << inputenc
2923 << "'. Using `auto' instead.");
2924 return *language->encoding();
2928 bool BufferParams::addCiteEngine(string const & engine)
2930 LayoutModuleList::const_iterator it = cite_engine_.begin();
2931 LayoutModuleList::const_iterator en = cite_engine_.end();
2932 for (; it != en; ++it)
2935 cite_engine_.push_back(engine);
2940 bool BufferParams::addCiteEngine(vector<string> const & engine)
2942 vector<string>::const_iterator it = engine.begin();
2943 vector<string>::const_iterator en = engine.end();
2945 for (; it != en; ++it)
2946 if (!addCiteEngine(*it))
2952 string const & BufferParams::defaultBiblioStyle() const
2954 return documentClass().defaultBiblioStyle();
2958 bool const & BufferParams::fullAuthorList() const
2960 return documentClass().fullAuthorList();
2964 void BufferParams::setCiteEngine(string const & engine)
2967 addCiteEngine(engine);
2971 void BufferParams::setCiteEngine(vector<string> const & engine)
2974 addCiteEngine(engine);
2978 vector<string> BufferParams::citeCommands() const
2980 static CitationStyle const default_style;
2981 vector<string> commands =
2982 documentClass().citeCommands(citeEngineType());
2983 if (commands.empty())
2984 commands.push_back(default_style.cmd);
2989 vector<CitationStyle> BufferParams::citeStyles() const
2991 static CitationStyle const default_style;
2992 vector<CitationStyle> styles =
2993 documentClass().citeStyles(citeEngineType());
2995 styles.push_back(default_style);