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("cancel");
454 packages.push_back("esint");
455 packages.push_back("mathdots");
456 packages.push_back("mathtools");
457 packages.push_back("mhchem");
458 packages.push_back("stackrel");
459 packages.push_back("stmaryrd");
460 packages.push_back("undertilde");
466 AuthorList & BufferParams::authors()
468 return pimpl_->authorlist;
472 AuthorList const & BufferParams::authors() const
474 return pimpl_->authorlist;
478 BranchList & BufferParams::branchlist()
480 return pimpl_->branchlist;
484 BranchList const & BufferParams::branchlist() const
486 return pimpl_->branchlist;
490 IndicesList & BufferParams::indiceslist()
492 return pimpl_->indiceslist;
496 IndicesList const & BufferParams::indiceslist() const
498 return pimpl_->indiceslist;
502 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
504 LASSERT(index < 4, /**/);
505 return pimpl_->temp_bullets[index];
509 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
511 LASSERT(index < 4, /**/);
512 return pimpl_->temp_bullets[index];
516 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
518 LASSERT(index < 4, /**/);
519 return pimpl_->user_defined_bullets[index];
523 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
525 LASSERT(index < 4, /**/);
526 return pimpl_->user_defined_bullets[index];
530 Spacing & BufferParams::spacing()
532 return pimpl_->spacing;
536 Spacing const & BufferParams::spacing() const
538 return pimpl_->spacing;
542 PDFOptions & BufferParams::pdfoptions()
544 return pimpl_->pdfoptions;
548 PDFOptions const & BufferParams::pdfoptions() const
550 return pimpl_->pdfoptions;
554 HSpace const & BufferParams::getIndentation() const
556 return pimpl_->indentation;
560 void BufferParams::setIndentation(HSpace const & indent)
562 pimpl_->indentation = indent;
566 VSpace const & BufferParams::getDefSkip() const
568 return pimpl_->defskip;
572 void BufferParams::setDefSkip(VSpace const & vs)
574 // DEFSKIP will cause an infinite loop
575 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
576 pimpl_->defskip = vs;
580 string BufferParams::readToken(Lexer & lex, string const & token,
581 FileName const & filepath)
583 if (token == "\\textclass") {
585 string const classname = lex.getString();
586 // if there exists a local layout file, ignore the system one
587 // NOTE: in this case, the textclass (.cls file) is assumed to
590 LayoutFileList & bcl = LayoutFileList::get();
591 if (tcp.empty() && !filepath.empty())
592 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
596 setBaseClass(classname);
597 // We assume that a tex class exists for local or unknown
598 // layouts so this warning, will only be given for system layouts.
599 if (!baseClass()->isTeXClassAvailable()) {
600 docstring const desc =
601 translateIfPossible(from_utf8(baseClass()->description()));
602 docstring const prereqs =
603 from_utf8(baseClass()->prerequisites());
604 docstring const msg =
605 bformat(_("The selected document class\n"
607 "requires external files that are not available.\n"
608 "The document class can still be used, but the\n"
609 "document cannot be compiled until the following\n"
610 "prerequisites are installed:\n"
612 "See section 3.1.2.2 (Class Availability) of the\n"
613 "User's Guide for more information."), desc, prereqs);
614 frontend::Alert::warning(_("Document class not available"),
617 } else if (token == "\\begin_preamble") {
619 } else if (token == "\\begin_local_layout") {
620 readLocalLayout(lex);
621 } else if (token == "\\begin_modules") {
623 } else if (token == "\\begin_removed_modules") {
624 readRemovedModules(lex);
625 } else if (token == "\\begin_includeonly") {
626 readIncludeonly(lex);
627 } else if (token == "\\maintain_unincluded_children") {
628 lex >> maintain_unincluded_children;
629 } else if (token == "\\options") {
631 options = lex.getString();
632 } else if (token == "\\use_default_options") {
633 lex >> use_default_options;
634 } else if (token == "\\master") {
636 master = lex.getString();
637 } else if (token == "\\suppress_date") {
638 lex >> suppress_date;
639 } else if (token == "\\justification") {
640 lex >> justification;
641 } else if (token == "\\language") {
643 } else if (token == "\\language_package") {
645 lang_package = lex.getString();
646 } else if (token == "\\inputencoding") {
648 } else if (token == "\\graphics") {
649 readGraphicsDriver(lex);
650 } else if (token == "\\default_output_format") {
651 lex >> default_output_format;
652 } else if (token == "\\bibtex_command") {
654 bibtex_command = lex.getString();
655 } else if (token == "\\index_command") {
657 index_command = lex.getString();
658 } else if (token == "\\fontencoding") {
660 fontenc = lex.getString();
661 } else if (token == "\\font_roman") {
663 fonts_roman = lex.getString();
664 } else if (token == "\\font_sans") {
666 fonts_sans = lex.getString();
667 } else if (token == "\\font_typewriter") {
669 fonts_typewriter = lex.getString();
670 } else if (token == "\\font_math") {
672 fonts_math = lex.getString();
673 } else if (token == "\\font_default_family") {
674 lex >> fonts_default_family;
675 } else if (token == "\\use_non_tex_fonts") {
676 lex >> useNonTeXFonts;
677 } else if (token == "\\font_sc") {
678 lex >> fonts_expert_sc;
679 } else if (token == "\\font_osf") {
680 lex >> fonts_old_figures;
681 } else if (token == "\\font_sf_scale") {
682 lex >> fonts_sans_scale;
683 } else if (token == "\\font_tt_scale") {
684 lex >> fonts_typewriter_scale;
685 } else if (token == "\\font_cjk") {
687 } else if (token == "\\paragraph_separation") {
690 paragraph_separation = parseptranslator().find(parsep);
691 } else if (token == "\\paragraph_indentation") {
693 string indentation = lex.getString();
694 pimpl_->indentation = HSpace(indentation);
695 } else if (token == "\\defskip") {
697 string const defskip = lex.getString();
698 pimpl_->defskip = VSpace(defskip);
699 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
701 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
702 } else if (token == "\\quotes_language") {
705 quotes_language = quoteslangtranslator().find(quotes_lang);
706 } else if (token == "\\papersize") {
709 papersize = papersizetranslator().find(ppsize);
710 } else if (token == "\\use_geometry") {
712 } else if (token == "\\use_package") {
717 use_package(package, packagetranslator().find(use));
718 } else if (token == "\\cite_engine") {
720 vector<string> engine = getVectorFromString(lex.getString());
721 setCiteEngine(engine);
722 } else if (token == "\\cite_engine_type") {
725 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
726 } else if (token == "\\biblio_style") {
728 biblio_style = lex.getString();
729 } else if (token == "\\use_bibtopic") {
731 } else if (token == "\\use_indices") {
733 } else if (token == "\\tracking_changes") {
735 } else if (token == "\\output_changes") {
736 lex >> outputChanges;
737 } else if (token == "\\branch") {
739 docstring branch = lex.getDocString();
740 branchlist().add(branch);
743 string const tok = lex.getString();
744 if (tok == "\\end_branch")
746 Branch * branch_ptr = branchlist().find(branch);
747 if (tok == "\\selected") {
750 branch_ptr->setSelected(lex.getInteger());
752 if (tok == "\\filename_suffix") {
755 branch_ptr->setFileNameSuffix(lex.getInteger());
757 if (tok == "\\color") {
759 string color = lex.getString();
761 branch_ptr->setColor(color);
762 // Update also the Color table:
764 color = lcolor.getX11Name(Color_background);
766 lcolor.setColor(to_utf8(branch), color);
769 } else if (token == "\\index") {
771 docstring index = lex.getDocString();
773 indiceslist().add(index);
776 string const tok = lex.getString();
777 if (tok == "\\end_index")
779 Index * index_ptr = indiceslist().find(index);
780 if (tok == "\\shortcut") {
782 shortcut = lex.getDocString();
784 index_ptr->setShortcut(shortcut);
786 if (tok == "\\color") {
788 string color = lex.getString();
790 index_ptr->setColor(color);
791 // Update also the Color table:
793 color = lcolor.getX11Name(Color_background);
795 if (!shortcut.empty())
796 lcolor.setColor(to_utf8(shortcut), color);
799 } else if (token == "\\author") {
801 istringstream ss(lex.getString());
804 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
805 } else if (token == "\\paperorientation") {
808 orientation = paperorientationtranslator().find(orient);
809 } else if (token == "\\backgroundcolor") {
811 backgroundcolor = lyx::rgbFromHexName(lex.getString());
812 isbackgroundcolor = true;
813 } else if (token == "\\fontcolor") {
815 fontcolor = lyx::rgbFromHexName(lex.getString());
817 } else if (token == "\\notefontcolor") {
819 string color = lex.getString();
820 notefontcolor = lyx::rgbFromHexName(color);
821 lcolor.setColor("notefontcolor", color);
822 } else if (token == "\\boxbgcolor") {
824 string color = lex.getString();
825 boxbgcolor = lyx::rgbFromHexName(color);
826 lcolor.setColor("boxbgcolor", color);
827 } else if (token == "\\paperwidth") {
829 } else if (token == "\\paperheight") {
831 } else if (token == "\\leftmargin") {
833 } else if (token == "\\topmargin") {
835 } else if (token == "\\rightmargin") {
837 } else if (token == "\\bottommargin") {
839 } else if (token == "\\headheight") {
841 } else if (token == "\\headsep") {
843 } else if (token == "\\footskip") {
845 } else if (token == "\\columnsep") {
847 } else if (token == "\\paperfontsize") {
849 } else if (token == "\\papercolumns") {
851 } else if (token == "\\listings_params") {
854 listings_params = InsetListingsParams(par).params();
855 } else if (token == "\\papersides") {
858 sides = sidestranslator().find(psides);
859 } else if (token == "\\paperpagestyle") {
861 } else if (token == "\\bullet") {
863 } else if (token == "\\bulletLaTeX") {
864 readBulletsLaTeX(lex);
865 } else if (token == "\\secnumdepth") {
867 } else if (token == "\\tocdepth") {
869 } else if (token == "\\spacing") {
873 if (nspacing == "other") {
876 spacing().set(spacetranslator().find(nspacing), tmp_val);
877 } else if (token == "\\float_placement") {
878 lex >> float_placement;
880 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
881 string toktmp = pdfoptions().readToken(lex, token);
882 if (!toktmp.empty()) {
883 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
887 } else if (token == "\\html_math_output") {
890 html_math_output = static_cast<MathOutput>(temp);
891 } else if (token == "\\html_be_strict") {
892 lex >> html_be_strict;
893 } else if (token == "\\html_css_as_file") {
894 lex >> html_css_as_file;
895 } else if (token == "\\html_math_img_scale") {
896 lex >> html_math_img_scale;
897 } else if (token == "\\html_latex_start") {
899 html_latex_start = lex.getString();
900 } else if (token == "\\html_latex_end") {
902 html_latex_end = lex.getString();
903 } else if (token == "\\output_sync") {
905 } else if (token == "\\output_sync_macro") {
906 lex >> output_sync_macro;
907 } else if (token == "\\use_refstyle") {
910 lyxerr << "BufferParams::readToken(): Unknown token: " <<
919 void BufferParams::writeFile(ostream & os) const
921 // The top of the file is written by the buffer.
922 // Prints out the buffer info into the .lyx file given by file
925 os << "\\textclass " << baseClass()->name() << '\n';
928 if (!preamble.empty()) {
929 // remove '\n' from the end of preamble
930 string const tmppreamble = rtrim(preamble, "\n");
931 os << "\\begin_preamble\n"
933 << "\n\\end_preamble\n";
937 if (!options.empty()) {
938 os << "\\options " << options << '\n';
941 // use the class options defined in the layout?
942 os << "\\use_default_options "
943 << convert<string>(use_default_options) << "\n";
945 // the master document
946 if (!master.empty()) {
947 os << "\\master " << master << '\n';
951 if (!removed_modules_.empty()) {
952 os << "\\begin_removed_modules" << '\n';
953 list<string>::const_iterator it = removed_modules_.begin();
954 list<string>::const_iterator en = removed_modules_.end();
955 for (; it != en; ++it)
957 os << "\\end_removed_modules" << '\n';
961 if (!layout_modules_.empty()) {
962 os << "\\begin_modules" << '\n';
963 LayoutModuleList::const_iterator it = layout_modules_.begin();
964 LayoutModuleList::const_iterator en = layout_modules_.end();
965 for (; it != en; ++it)
967 os << "\\end_modules" << '\n';
971 if (!included_children_.empty()) {
972 os << "\\begin_includeonly" << '\n';
973 list<string>::const_iterator it = included_children_.begin();
974 list<string>::const_iterator en = included_children_.end();
975 for (; it != en; ++it)
977 os << "\\end_includeonly" << '\n';
979 os << "\\maintain_unincluded_children "
980 << convert<string>(maintain_unincluded_children) << '\n';
982 // local layout information
983 if (!local_layout.empty()) {
984 // remove '\n' from the end
985 string const tmplocal = rtrim(local_layout, "\n");
986 os << "\\begin_local_layout\n"
988 << "\n\\end_local_layout\n";
991 // then the text parameters
992 if (language != ignore_language)
993 os << "\\language " << language->lang() << '\n';
994 os << "\\language_package " << lang_package
995 << "\n\\inputencoding " << inputenc
996 << "\n\\fontencoding " << fontenc
997 << "\n\\font_roman " << fonts_roman
998 << "\n\\font_sans " << fonts_sans
999 << "\n\\font_typewriter " << fonts_typewriter
1000 << "\n\\font_math " << fonts_math
1001 << "\n\\font_default_family " << fonts_default_family
1002 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1003 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1004 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1005 << "\n\\font_sf_scale " << fonts_sans_scale
1006 << "\n\\font_tt_scale " << fonts_typewriter_scale
1008 if (!fonts_cjk.empty()) {
1009 os << "\\font_cjk " << fonts_cjk << '\n';
1011 os << "\\graphics " << graphics_driver << '\n';
1012 os << "\\default_output_format " << default_output_format << '\n';
1013 os << "\\output_sync " << output_sync << '\n';
1014 if (!output_sync_macro.empty())
1015 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1016 os << "\\bibtex_command " << bibtex_command << '\n';
1017 os << "\\index_command " << index_command << '\n';
1019 if (!float_placement.empty()) {
1020 os << "\\float_placement " << float_placement << '\n';
1022 os << "\\paperfontsize " << fontsize << '\n';
1024 spacing().writeFile(os);
1025 pdfoptions().writeFile(os);
1027 os << "\\papersize " << string_papersize[papersize]
1028 << "\n\\use_geometry " << convert<string>(use_geometry);
1029 vector<string> const & packages = auto_packages();
1030 for (size_t i = 0; i < packages.size(); ++i)
1031 os << "\n\\use_package " << packages[i] << ' '
1032 << use_package(packages[i]);
1034 os << "\n\\cite_engine ";
1036 if (!cite_engine_.empty()) {
1037 LayoutModuleList::const_iterator be = cite_engine_.begin();
1038 LayoutModuleList::const_iterator en = cite_engine_.end();
1039 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1048 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1049 << "\n\\biblio_style " << biblio_style
1050 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1051 << "\n\\use_indices " << convert<string>(use_indices)
1052 << "\n\\paperorientation " << string_orientation[orientation]
1053 << "\n\\suppress_date " << convert<string>(suppress_date)
1054 << "\n\\justification " << convert<string>(justification)
1055 << "\n\\use_refstyle " << use_refstyle
1057 if (isbackgroundcolor == true)
1058 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1059 if (isfontcolor == true)
1060 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1061 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1062 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1063 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1064 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1066 BranchList::const_iterator it = branchlist().begin();
1067 BranchList::const_iterator end = branchlist().end();
1068 for (; it != end; ++it) {
1069 os << "\\branch " << to_utf8(it->branch())
1070 << "\n\\selected " << it->isSelected()
1071 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1072 << "\n\\color " << lyx::X11hexname(it->color())
1077 IndicesList::const_iterator iit = indiceslist().begin();
1078 IndicesList::const_iterator iend = indiceslist().end();
1079 for (; iit != iend; ++iit) {
1080 os << "\\index " << to_utf8(iit->index())
1081 << "\n\\shortcut " << to_utf8(iit->shortcut())
1082 << "\n\\color " << lyx::X11hexname(iit->color())
1087 if (!paperwidth.empty())
1088 os << "\\paperwidth "
1089 << VSpace(paperwidth).asLyXCommand() << '\n';
1090 if (!paperheight.empty())
1091 os << "\\paperheight "
1092 << VSpace(paperheight).asLyXCommand() << '\n';
1093 if (!leftmargin.empty())
1094 os << "\\leftmargin "
1095 << VSpace(leftmargin).asLyXCommand() << '\n';
1096 if (!topmargin.empty())
1097 os << "\\topmargin "
1098 << VSpace(topmargin).asLyXCommand() << '\n';
1099 if (!rightmargin.empty())
1100 os << "\\rightmargin "
1101 << VSpace(rightmargin).asLyXCommand() << '\n';
1102 if (!bottommargin.empty())
1103 os << "\\bottommargin "
1104 << VSpace(bottommargin).asLyXCommand() << '\n';
1105 if (!headheight.empty())
1106 os << "\\headheight "
1107 << VSpace(headheight).asLyXCommand() << '\n';
1108 if (!headsep.empty())
1110 << VSpace(headsep).asLyXCommand() << '\n';
1111 if (!footskip.empty())
1113 << VSpace(footskip).asLyXCommand() << '\n';
1114 if (!columnsep.empty())
1115 os << "\\columnsep "
1116 << VSpace(columnsep).asLyXCommand() << '\n';
1117 os << "\\secnumdepth " << secnumdepth
1118 << "\n\\tocdepth " << tocdepth
1119 << "\n\\paragraph_separation "
1120 << string_paragraph_separation[paragraph_separation];
1121 if (!paragraph_separation)
1122 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1124 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1125 os << "\n\\quotes_language "
1126 << string_quotes_language[quotes_language]
1127 << "\n\\papercolumns " << columns
1128 << "\n\\papersides " << sides
1129 << "\n\\paperpagestyle " << pagestyle << '\n';
1130 if (!listings_params.empty())
1131 os << "\\listings_params \"" <<
1132 InsetListingsParams(listings_params).encodedString() << "\"\n";
1133 for (int i = 0; i < 4; ++i) {
1134 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1135 if (user_defined_bullet(i).getFont() != -1) {
1136 os << "\\bullet " << i << " "
1137 << user_defined_bullet(i).getFont() << " "
1138 << user_defined_bullet(i).getCharacter() << " "
1139 << user_defined_bullet(i).getSize() << "\n";
1143 os << "\\bulletLaTeX " << i << " \""
1144 << lyx::to_ascii(user_defined_bullet(i).getText())
1150 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1151 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1152 << "\\html_math_output " << html_math_output << '\n'
1153 << "\\html_css_as_file " << html_css_as_file << '\n'
1154 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1156 if (html_math_img_scale != 1.0)
1157 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1158 if (!html_latex_start.empty())
1159 os << "\\html_latex_start " << html_latex_start << '\n';
1160 if (!html_latex_end.empty())
1161 os << "\\html_latex_end " << html_latex_end << '\n';
1163 os << pimpl_->authorlist;
1167 void BufferParams::validate(LaTeXFeatures & features) const
1169 features.require(documentClass().requires());
1171 if (columns > 1 && language->rightToLeft())
1172 features.require("rtloutputdblcol");
1174 if (outputChanges) {
1175 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1176 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1177 LaTeXFeatures::isAvailable("xcolor");
1179 switch (features.runparams().flavor) {
1180 case OutputParams::LATEX:
1181 case OutputParams::DVILUATEX:
1183 features.require("ct-dvipost");
1184 features.require("dvipost");
1185 } else if (xcolorulem) {
1186 features.require("ct-xcolor-ulem");
1187 features.require("ulem");
1188 features.require("xcolor");
1190 features.require("ct-none");
1193 case OutputParams::LUATEX:
1194 case OutputParams::PDFLATEX:
1195 case OutputParams::XETEX:
1197 features.require("ct-xcolor-ulem");
1198 features.require("ulem");
1199 features.require("xcolor");
1200 // improves color handling in PDF output
1201 features.require("pdfcolmk");
1203 features.require("ct-none");
1211 // Floats with 'Here definitely' as default setting.
1212 if (float_placement.find('H') != string::npos)
1213 features.require("float");
1215 for (PackageMap::const_iterator it = use_packages.begin();
1216 it != use_packages.end(); ++it) {
1217 if (it->first == "amsmath") {
1218 // AMS Style is at document level
1219 if (it->second == package_on ||
1220 features.isProvided("amsmath"))
1221 features.require(it->first);
1222 } else if (it->second == package_on)
1223 features.require(it->first);
1226 // Document-level line spacing
1227 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1228 features.require("setspace");
1230 // the bullet shapes are buffer level not paragraph level
1231 // so they are tested here
1232 for (int i = 0; i < 4; ++i) {
1233 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1235 int const font = user_defined_bullet(i).getFont();
1237 int const c = user_defined_bullet(i).getCharacter();
1243 features.require("latexsym");
1245 } else if (font == 1) {
1246 features.require("amssymb");
1247 } else if (font >= 2 && font <= 5) {
1248 features.require("pifont");
1252 if (pdfoptions().use_hyperref) {
1253 features.require("hyperref");
1254 // due to interferences with babel and hyperref, the color package has to
1255 // be loaded after hyperref when hyperref is used with the colorlinks
1256 // option, see http://www.lyx.org/trac/ticket/5291
1257 if (pdfoptions().colorlinks)
1258 features.require("color");
1261 // some languages are only available via polyglossia
1262 if (features.runparams().flavor == OutputParams::XETEX
1263 && (features.hasPolyglossiaExclusiveLanguages()
1265 features.require("polyglossia");
1267 if (useNonTeXFonts && fonts_math != "auto")
1268 features.require("unicode-math");
1270 if (!language->requires().empty())
1271 features.require(language->requires());
1275 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1276 FileName const & filepath) const
1278 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1279 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1280 // \RequirePackage to do so, rather than the normal \usepackage
1281 // Do not try to load any other package before the document class, unless you
1282 // have a thorough understanding of the LATEX internals and know exactly what you
1284 if (features.mustProvide("fix-cm"))
1285 os << "\\RequirePackage{fix-cm}\n";
1287 os << "\\documentclass";
1289 DocumentClass const & tclass = documentClass();
1291 ostringstream clsoptions; // the document class options.
1293 if (tokenPos(tclass.opt_fontsize(),
1294 '|', fontsize) >= 0) {
1295 // only write if existing in list (and not default)
1296 clsoptions << fontsize << "pt,";
1299 // all paper sizes except of A4, A5, B5 and the US sizes need the
1301 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1302 && papersize != PAPER_USLETTER
1303 && papersize != PAPER_USLEGAL
1304 && papersize != PAPER_USEXECUTIVE
1305 && papersize != PAPER_A4
1306 && papersize != PAPER_A5
1307 && papersize != PAPER_B5;
1309 if (!use_geometry) {
1310 switch (papersize) {
1312 clsoptions << "a4paper,";
1314 case PAPER_USLETTER:
1315 clsoptions << "letterpaper,";
1318 clsoptions << "a5paper,";
1321 clsoptions << "b5paper,";
1323 case PAPER_USEXECUTIVE:
1324 clsoptions << "executivepaper,";
1327 clsoptions << "legalpaper,";
1361 if (sides != tclass.sides()) {
1364 clsoptions << "oneside,";
1367 clsoptions << "twoside,";
1373 if (columns != tclass.columns()) {
1375 clsoptions << "twocolumn,";
1377 clsoptions << "onecolumn,";
1381 && orientation == ORIENTATION_LANDSCAPE)
1382 clsoptions << "landscape,";
1384 // language should be a parameter to \documentclass
1385 if (language->babel() == "hebrew"
1386 && default_language->babel() != "hebrew")
1387 // This seems necessary
1388 features.useLanguage(default_language);
1390 ostringstream language_options;
1391 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1392 bool const use_polyglossia = features.usePolyglossia();
1393 bool const global = lyxrc.language_global_options;
1394 if (use_babel || (use_polyglossia && global)) {
1395 language_options << features.getBabelLanguages();
1396 if (!language->babel().empty()) {
1397 if (!language_options.str().empty())
1398 language_options << ',';
1399 language_options << language->babel();
1401 if (global && !features.needBabelLangOptions()
1402 && !language_options.str().empty())
1403 clsoptions << language_options.str() << ',';
1406 // the predefined options from the layout
1407 if (use_default_options && !tclass.options().empty())
1408 clsoptions << tclass.options() << ',';
1410 // the user-defined options
1411 if (!options.empty()) {
1412 clsoptions << options << ',';
1415 string strOptions(clsoptions.str());
1416 if (!strOptions.empty()) {
1417 strOptions = rtrim(strOptions, ",");
1419 os << '[' << from_utf8(strOptions) << ']';
1422 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1423 // end of \documentclass defs
1425 // if we use fontspec, we have to load the AMS packages here
1426 string const ams = features.loadAMSPackages();
1427 if (useNonTeXFonts && !ams.empty())
1428 os << from_ascii(ams);
1430 if (useNonTeXFonts) {
1431 os << "\\usepackage{fontspec}\n";
1432 if (features.mustProvide("unicode-math")
1433 && features.isAvailable("unicode-math"))
1434 os << "\\usepackage{unicode-math}\n";
1437 // font selection must be done before loading fontenc.sty
1438 string const fonts = loadFonts(features);
1440 os << from_utf8(fonts);
1442 if (fonts_default_family != "default")
1443 os << "\\renewcommand{\\familydefault}{\\"
1444 << from_ascii(fonts_default_family) << "}\n";
1446 // set font encoding
1447 // for arabic_arabi and farsi we also need to load the LAE and
1449 // XeTeX and LuaTeX (with OS fonts) work without fontenc
1450 if (font_encoding() != "default" && language->lang() != "japanese"
1451 && !useNonTeXFonts && !features.isProvided("fontenc")) {
1452 docstring extra_encoding;
1453 if (features.mustProvide("textgreek"))
1454 extra_encoding += from_ascii("LGR");
1455 if (features.mustProvide("textcyr")) {
1456 if (!extra_encoding.empty())
1457 extra_encoding.push_back(',');
1458 extra_encoding += from_ascii("T2A");
1460 if (!extra_encoding.empty() && !font_encoding().empty())
1461 extra_encoding.push_back(',');
1462 size_t fars = language_options.str().find("farsi");
1463 size_t arab = language_options.str().find("arabic");
1464 if (language->lang() == "arabic_arabi"
1465 || language->lang() == "farsi" || fars != string::npos
1466 || arab != string::npos) {
1467 os << "\\usepackage[" << extra_encoding
1468 << from_ascii(font_encoding())
1469 << ",LFE,LAE]{fontenc}\n";
1471 os << "\\usepackage[" << extra_encoding
1472 << from_ascii(font_encoding())
1477 // handle inputenc etc.
1478 writeEncodingPreamble(os, features);
1481 if (!features.runparams().includeall && !included_children_.empty()) {
1482 os << "\\includeonly{";
1483 list<string>::const_iterator it = included_children_.begin();
1484 list<string>::const_iterator en = included_children_.end();
1486 for (; it != en; ++it) {
1487 string incfile = *it;
1488 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1489 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1491 if (!features.runparams().nice)
1493 // \includeonly doesn't want an extension
1494 incfile = changeExtension(incfile, string());
1495 incfile = support::latex_path(incfile);
1496 if (!incfile.empty()) {
1499 os << from_utf8(incfile);
1506 if (!listings_params.empty() || features.isRequired("listings"))
1507 os << "\\usepackage{listings}\n";
1509 if (!listings_params.empty()) {
1511 // do not test validity because listings_params is
1512 // supposed to be valid
1514 InsetListingsParams(listings_params).separatedParams(true);
1515 // we can't support all packages, but we should load the color package
1516 if (par.find("\\color", 0) != string::npos)
1517 features.require("color");
1518 os << from_utf8(par)
1521 if (!features.isProvided("geometry")
1522 && (use_geometry || nonstandard_papersize)) {
1523 odocstringstream ods;
1524 if (!getGraphicsDriver("geometry").empty())
1525 ods << getGraphicsDriver("geometry");
1526 if (orientation == ORIENTATION_LANDSCAPE)
1527 ods << ",landscape";
1528 switch (papersize) {
1530 if (!paperwidth.empty())
1531 ods << ",paperwidth="
1532 << from_ascii(paperwidth);
1533 if (!paperheight.empty())
1534 ods << ",paperheight="
1535 << from_ascii(paperheight);
1537 case PAPER_USLETTER:
1538 ods << ",letterpaper";
1541 ods << ",legalpaper";
1543 case PAPER_USEXECUTIVE:
1544 ods << ",executivepaper";
1633 docstring const g_options = trim(ods.str(), ",");
1634 os << "\\usepackage";
1635 if (!g_options.empty())
1636 os << '[' << g_options << ']';
1637 os << "{geometry}\n";
1638 // output this only if use_geometry is true
1640 os << "\\geometry{verbose";
1641 if (!topmargin.empty())
1642 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1643 if (!bottommargin.empty())
1644 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1645 if (!leftmargin.empty())
1646 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1647 if (!rightmargin.empty())
1648 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1649 if (!headheight.empty())
1650 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1651 if (!headsep.empty())
1652 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1653 if (!footskip.empty())
1654 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1655 if (!columnsep.empty())
1656 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1659 } else if (orientation == ORIENTATION_LANDSCAPE
1660 || papersize != PAPER_DEFAULT) {
1661 features.require("papersize");
1664 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1665 if (pagestyle == "fancy")
1666 os << "\\usepackage{fancyhdr}\n";
1667 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1670 // only output when the background color is not default
1671 if (isbackgroundcolor == true) {
1672 // only require color here, the background color will be defined
1673 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1675 features.require("color");
1676 features.require("pagecolor");
1679 // only output when the font color is not default
1680 if (isfontcolor == true) {
1681 // only require color here, the font color will be defined
1682 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1684 features.require("color");
1685 features.require("fontcolor");
1688 // Only if class has a ToC hierarchy
1689 if (tclass.hasTocLevels()) {
1690 if (secnumdepth != tclass.secnumdepth()) {
1691 os << "\\setcounter{secnumdepth}{"
1695 if (tocdepth != tclass.tocdepth()) {
1696 os << "\\setcounter{tocdepth}{"
1702 if (paragraph_separation) {
1703 // when skip separation
1704 switch (getDefSkip().kind()) {
1705 case VSpace::SMALLSKIP:
1706 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1708 case VSpace::MEDSKIP:
1709 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1711 case VSpace::BIGSKIP:
1712 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1714 case VSpace::LENGTH:
1715 os << "\\setlength{\\parskip}{"
1716 << from_utf8(getDefSkip().length().asLatexString())
1719 default: // should never happen // Then delete it.
1720 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1723 os << "\\setlength{\\parindent}{0pt}\n";
1725 // when separation by indentation
1726 // only output something when a width is given
1727 if (getIndentation().asLyXCommand() != "default") {
1728 os << "\\setlength{\\parindent}{"
1729 << from_utf8(getIndentation().asLatexCommand())
1734 // Now insert the LyX specific LaTeX commands...
1735 docstring lyxpreamble;
1736 features.resolveAlternatives();
1739 if (!output_sync_macro.empty())
1740 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1741 else if (features.runparams().flavor == OutputParams::LATEX)
1742 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1743 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1744 lyxpreamble += "\\synctex=-1\n";
1747 // due to interferences with babel and hyperref, the color package has to
1748 // be loaded (when it is not already loaded) before babel when hyperref
1749 // is used with the colorlinks option, see
1750 // http://www.lyx.org/trac/ticket/5291
1751 // we decided therefore to load color always before babel, see
1752 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1753 lyxpreamble += from_ascii(features.getColorOptions());
1755 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1757 && (features.isRequired("jurabib")
1758 || features.isRequired("hyperref")
1759 || features.isRequired("vietnamese")
1760 || features.isRequired("japanese"))) {
1762 lyxpreamble += from_utf8(features.getBabelPresettings());
1763 lyxpreamble += from_utf8(babelCall(language_options.str(),
1764 features.needBabelLangOptions())) + '\n';
1765 lyxpreamble += from_utf8(features.getBabelPostsettings());
1768 // The optional packages;
1769 lyxpreamble += from_ascii(features.getPackages());
1771 // Additional Indices
1772 if (features.isRequired("splitidx")) {
1773 IndicesList::const_iterator iit = indiceslist().begin();
1774 IndicesList::const_iterator iend = indiceslist().end();
1775 for (; iit != iend; ++iit) {
1776 pair<docstring, docstring> indexname_latex =
1777 features.runparams().encoding->latexString(iit->index(),
1778 features.runparams().dryrun);
1779 if (!indexname_latex.second.empty()) {
1780 // issue a warning about omitted characters
1781 // FIXME: should be passed to the error dialog
1782 frontend::Alert::warning(_("Uncodable characters"),
1783 bformat(_("The following characters that are used in an index name are not\n"
1784 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1785 indexname_latex.second));
1787 lyxpreamble += "\\newindex[";
1788 lyxpreamble += indexname_latex.first;
1789 lyxpreamble += "]{";
1790 lyxpreamble += escape(iit->shortcut());
1791 lyxpreamble += "}\n";
1796 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1799 // * Hyperref manual: "Make sure it comes last of your loaded
1800 // packages, to give it a fighting chance of not being over-written,
1801 // since its job is to redefine many LaTeX commands."
1802 // * Email from Heiko Oberdiek: "It is usually better to load babel
1803 // before hyperref. Then hyperref has a chance to detect babel.
1804 // * Has to be loaded before the "LyX specific LaTeX commands" to
1805 // avoid errors with algorithm floats.
1806 // use hyperref explicitly if it is required
1807 if (features.isRequired("hyperref")) {
1808 // pass what we have to stream here, since we need
1809 // to access the stream itself in PDFOptions.
1812 OutputParams tmp_params = features.runparams();
1813 pdfoptions().writeLaTeX(tmp_params, os,
1814 features.isProvided("hyperref"));
1815 // set back for the rest
1816 lyxpreamble.clear();
1817 // correctly break URLs with hyperref and dvi output
1818 if (features.runparams().flavor == OutputParams::LATEX
1819 && features.isAvailable("breakurl"))
1820 lyxpreamble += "\\usepackage{breakurl}\n";
1821 } else if (features.isRequired("nameref"))
1822 // hyperref loads this automatically
1823 lyxpreamble += "\\usepackage{nameref}\n";
1825 // bibtopic needs to be loaded after hyperref.
1826 // the dot provides the aux file naming which LyX can detect.
1827 if (features.mustProvide("bibtopic"))
1828 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1830 // Will be surrounded by \makeatletter and \makeatother when not empty
1831 docstring atlyxpreamble;
1833 // Some macros LyX will need
1834 docstring tmppreamble(features.getMacros());
1836 if (!tmppreamble.empty())
1837 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1838 "LyX specific LaTeX commands.\n"
1839 + tmppreamble + '\n';
1841 // the text class specific preamble
1842 tmppreamble = features.getTClassPreamble();
1843 if (!tmppreamble.empty())
1844 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1845 "Textclass specific LaTeX commands.\n"
1846 + tmppreamble + '\n';
1848 // suppress date if selected
1849 // use \@ifundefined because we cannot be sure that every document class
1850 // has a \date command
1852 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1854 /* the user-defined preamble */
1855 if (!containsOnly(preamble, " \n\t"))
1857 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1858 "User specified LaTeX commands.\n"
1859 + from_utf8(preamble) + '\n';
1861 // subfig loads internally the LaTeX package "caption". As
1862 // caption is a very popular package, users will load it in
1863 // the preamble. Therefore we must load subfig behind the
1864 // user-defined preamble and check if the caption package was
1865 // loaded or not. For the case that caption is loaded before
1866 // subfig, there is the subfig option "caption=false". This
1867 // option also works when a koma-script class is used and
1868 // koma's own caption commands are used instead of caption. We
1869 // use \PassOptionsToPackage here because the user could have
1870 // already loaded subfig in the preamble.
1871 if (features.isRequired("subfig")) {
1872 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1873 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1874 "\\usepackage{subfig}\n";
1877 // Itemize bullet settings need to be last in case the user
1878 // defines their own bullets that use a package included
1879 // in the user-defined preamble -- ARRae
1880 // Actually it has to be done much later than that
1881 // since some packages like frenchb make modifications
1882 // at \begin{document} time -- JMarc
1883 docstring bullets_def;
1884 for (int i = 0; i < 4; ++i) {
1885 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1886 if (bullets_def.empty())
1887 bullets_def += "\\AtBeginDocument{\n";
1888 bullets_def += " \\def\\labelitemi";
1890 // `i' is one less than the item to modify
1897 bullets_def += "ii";
1903 bullets_def += '{' +
1904 user_defined_bullet(i).getText()
1909 if (!bullets_def.empty())
1910 atlyxpreamble += bullets_def + "}\n\n";
1912 if (!atlyxpreamble.empty())
1913 lyxpreamble += "\n\\makeatletter\n"
1914 + atlyxpreamble + "\\makeatother\n\n";
1916 // We try to load babel late, in case it interferes with other packages.
1917 // Jurabib and Hyperref have to be called after babel, though.
1918 if (use_babel && !features.isRequired("jurabib")
1919 && !features.isRequired("hyperref")
1920 && !features.isRequired("vietnamese")
1921 && !features.isRequired("japanese")) {
1923 lyxpreamble += from_utf8(features.getBabelPresettings());
1924 lyxpreamble += from_utf8(babelCall(language_options.str(),
1925 features.needBabelLangOptions())) + '\n';
1926 lyxpreamble += from_utf8(features.getBabelPostsettings());
1929 // xunicode needs to be loaded at least after amsmath, amssymb,
1930 // esint and the other packages that provide special glyphs
1931 if (features.runparams().flavor == OutputParams::XETEX)
1932 lyxpreamble += "\\usepackage{xunicode}\n";
1934 // Polyglossia must be loaded last
1935 if (use_polyglossia) {
1937 lyxpreamble += "\\usepackage{polyglossia}\n";
1938 // set the main language
1939 lyxpreamble += "\\setdefaultlanguage";
1940 if (!language->polyglossiaOpts().empty())
1941 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
1942 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
1943 // now setup the other languages
1944 std::map<std::string, std::string> const polylangs =
1945 features.getPolyglossiaLanguages();
1946 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
1947 mit != polylangs.end() ; ++mit) {
1948 lyxpreamble += "\\setotherlanguage";
1949 if (!mit->second.empty())
1950 lyxpreamble += "[" + from_ascii(mit->second) + "]";
1951 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
1955 // Load custom language package here
1956 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
1957 if (lang_package == "default")
1958 lyxpreamble += from_utf8(lyxrc.language_custom_package);
1960 lyxpreamble += from_utf8(lang_package);
1961 lyxpreamble += '\n';
1964 docstring const i18npreamble =
1965 features.getTClassI18nPreamble(use_babel, use_polyglossia);
1966 if (!i18npreamble.empty())
1967 lyxpreamble += i18npreamble + '\n';
1975 void BufferParams::useClassDefaults()
1977 DocumentClass const & tclass = documentClass();
1979 sides = tclass.sides();
1980 columns = tclass.columns();
1981 pagestyle = tclass.pagestyle();
1982 use_default_options = true;
1983 // Only if class has a ToC hierarchy
1984 if (tclass.hasTocLevels()) {
1985 secnumdepth = tclass.secnumdepth();
1986 tocdepth = tclass.tocdepth();
1991 bool BufferParams::hasClassDefaults() const
1993 DocumentClass const & tclass = documentClass();
1995 return sides == tclass.sides()
1996 && columns == tclass.columns()
1997 && pagestyle == tclass.pagestyle()
1998 && use_default_options
1999 && secnumdepth == tclass.secnumdepth()
2000 && tocdepth == tclass.tocdepth();
2004 DocumentClass const & BufferParams::documentClass() const
2006 return *doc_class_.get();
2010 DocumentClassConstPtr BufferParams::documentClassPtr() const
2016 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2018 // evil, but this function is evil
2019 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2023 bool BufferParams::setBaseClass(string const & classname)
2025 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2026 LayoutFileList & bcl = LayoutFileList::get();
2027 if (!bcl.haveClass(classname)) {
2029 bformat(_("The layout file:\n"
2031 "could not be found. A default textclass with default\n"
2032 "layouts will be used. LyX will not be able to produce\n"
2034 from_utf8(classname));
2035 frontend::Alert::error(_("Document class not found"), s);
2036 bcl.addEmptyClass(classname);
2039 bool const success = bcl[classname].load();
2042 bformat(_("Due to some error in it, the layout file:\n"
2044 "could not be loaded. A default textclass with default\n"
2045 "layouts will be used. LyX will not be able to produce\n"
2047 from_utf8(classname));
2048 frontend::Alert::error(_("Could not load class"), s);
2049 bcl.addEmptyClass(classname);
2052 pimpl_->baseClass_ = classname;
2053 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2058 LayoutFile const * BufferParams::baseClass() const
2060 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2061 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2067 LayoutFileIndex const & BufferParams::baseClassID() const
2069 return pimpl_->baseClass_;
2073 void BufferParams::makeDocumentClass()
2078 LayoutModuleList mods;
2079 LayoutModuleList::iterator it = layout_modules_.begin();
2080 LayoutModuleList::iterator en = layout_modules_.end();
2081 for (; it != en; ++it)
2082 mods.push_back(*it);
2084 it = cite_engine_.begin();
2085 en = cite_engine_.end();
2086 for (; it != en; ++it)
2087 mods.push_back(*it);
2089 doc_class_ = getDocumentClass(*baseClass(), mods);
2091 if (!local_layout.empty()) {
2092 TextClass::ReturnValues success =
2093 doc_class_->read(local_layout, TextClass::MODULE);
2094 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2095 docstring const msg = _("Error reading internal layout information");
2096 frontend::Alert::warning(_("Read Error"), msg);
2102 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2104 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2108 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2110 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2114 bool BufferParams::addLayoutModule(string const & modName)
2116 LayoutModuleList::const_iterator it = layout_modules_.begin();
2117 LayoutModuleList::const_iterator end = layout_modules_.end();
2118 for (; it != end; ++it)
2121 layout_modules_.push_back(modName);
2126 string BufferParams::bufferFormat() const
2128 string format = documentClass().outputFormat();
2129 if (format == "latex") {
2132 if (encoding().package() == Encoding::japanese)
2139 bool BufferParams::isExportable(string const & format) const
2141 vector<string> backs = backends();
2142 for (vector<string>::const_iterator it = backs.begin();
2143 it != backs.end(); ++it)
2144 if (theConverters().isReachable(*it, format))
2152 bool formatSorter(Format const * lhs, Format const * rhs)
2154 return _(lhs->prettyname()) < _(rhs->prettyname());
2160 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2162 vector<string> const backs = backends();
2163 set<string> excludes;
2164 if (useNonTeXFonts) {
2165 excludes.insert("latex");
2166 excludes.insert("pdflatex");
2168 vector<Format const *> result =
2169 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2170 for (vector<string>::const_iterator it = backs.begin() + 1;
2171 it != backs.end(); ++it) {
2172 vector<Format const *> r =
2173 theConverters().getReachable(*it, only_viewable, false, excludes);
2174 result.insert(result.end(), r.begin(), r.end());
2176 sort(result.begin(), result.end(), formatSorter);
2181 bool BufferParams::isExportableFormat(string const & format) const
2183 typedef vector<Format const *> Formats;
2185 formats = exportableFormats(true);
2186 Formats::const_iterator fit = formats.begin();
2187 Formats::const_iterator end = formats.end();
2188 for (; fit != end ; ++fit) {
2189 if ((*fit)->name() == format)
2196 vector<string> BufferParams::backends() const
2199 string const buffmt = bufferFormat();
2201 // FIXME: Don't hardcode format names here, but use a flag
2202 if (buffmt == "latex") {
2203 if (!useNonTeXFonts) {
2204 v.push_back("pdflatex");
2205 v.push_back("latex");
2207 v.push_back("luatex");
2208 v.push_back("dviluatex");
2209 v.push_back("xetex");
2210 } else if (buffmt == "xetex") {
2211 v.push_back("xetex");
2212 v.push_back("luatex");
2213 v.push_back("dviluatex");
2215 v.push_back(buffmt);
2217 v.push_back("xhtml");
2218 v.push_back("text");
2224 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const format) const
2226 string const dformat = (format.empty() || format == "default") ?
2227 getDefaultOutputFormat() : format;
2228 DefaultFlavorCache::const_iterator it =
2229 default_flavors_.find(dformat);
2231 if (it != default_flavors_.end())
2234 OutputParams::FLAVOR result = OutputParams::LATEX;
2236 // FIXME It'd be better not to hardcode this, but to do
2237 // something with formats.
2238 if (dformat == "xhtml")
2239 result = OutputParams::HTML;
2240 else if (dformat == "text")
2241 result = OutputParams::TEXT;
2242 else if (dformat == "lyx")
2243 result = OutputParams::LYX;
2244 else if (dformat == "pdflatex")
2245 result = OutputParams::PDFLATEX;
2246 else if (dformat == "xetex")
2247 result = OutputParams::XETEX;
2248 else if (dformat == "luatex")
2249 result = OutputParams::LUATEX;
2250 else if (dformat == "dviluatex")
2251 result = OutputParams::DVILUATEX;
2253 // Try to determine flavor of default output format
2254 vector<string> backs = backends();
2255 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2256 // Get shortest path to format
2257 Graph::EdgePath path;
2258 for (vector<string>::const_iterator it = backs.begin();
2259 it != backs.end(); ++it) {
2260 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2261 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2266 result = theConverters().getFlavor(path);
2269 // cache this flavor
2270 default_flavors_[dformat] = result;
2275 string BufferParams::getDefaultOutputFormat() const
2277 if (!default_output_format.empty()
2278 && default_output_format != "default")
2279 return default_output_format;
2282 || encoding().package() == Encoding::japanese) {
2283 vector<Format const *> const formats = exportableFormats(true);
2284 if (formats.empty())
2286 // return the first we find
2287 return formats.front()->name();
2289 return lyxrc.default_view_format;
2292 Font const BufferParams::getFont() const
2294 FontInfo f = documentClass().defaultfont();
2295 if (fonts_default_family == "rmdefault")
2296 f.setFamily(ROMAN_FAMILY);
2297 else if (fonts_default_family == "sfdefault")
2298 f.setFamily(SANS_FAMILY);
2299 else if (fonts_default_family == "ttdefault")
2300 f.setFamily(TYPEWRITER_FAMILY);
2301 return Font(f, language);
2305 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const qs) const
2307 return quoteslangtranslator().find(qs);
2311 bool BufferParams::isLatex() const
2313 return documentClass().outputType() == LATEX;
2317 bool BufferParams::isLiterate() const
2319 return documentClass().outputType() == LITERATE;
2323 bool BufferParams::isDocBook() const
2325 return documentClass().outputType() == DOCBOOK;
2329 void BufferParams::readPreamble(Lexer & lex)
2331 if (lex.getString() != "\\begin_preamble")
2332 lyxerr << "Error (BufferParams::readPreamble):"
2333 "consistency check failed." << endl;
2335 preamble = lex.getLongString("\\end_preamble");
2339 void BufferParams::readLocalLayout(Lexer & lex)
2341 if (lex.getString() != "\\begin_local_layout")
2342 lyxerr << "Error (BufferParams::readLocalLayout):"
2343 "consistency check failed." << endl;
2345 local_layout = lex.getLongString("\\end_local_layout");
2349 bool BufferParams::setLanguage(string const & lang)
2351 Language const *new_language = languages.getLanguage(lang);
2352 if (!new_language) {
2353 // Language lang was not found
2356 language = new_language;
2361 void BufferParams::readLanguage(Lexer & lex)
2363 if (!lex.next()) return;
2365 string const tmptok = lex.getString();
2367 // check if tmptok is part of tex_babel in tex-defs.h
2368 if (!setLanguage(tmptok)) {
2369 // Language tmptok was not found
2370 language = default_language;
2371 lyxerr << "Warning: Setting language `"
2372 << tmptok << "' to `" << language->lang()
2378 void BufferParams::readGraphicsDriver(Lexer & lex)
2383 string const tmptok = lex.getString();
2384 // check if tmptok is part of tex_graphics in tex_defs.h
2387 string const test = tex_graphics[n++];
2389 if (test == tmptok) {
2390 graphics_driver = tmptok;
2395 "Warning: graphics driver `$$Token' not recognized!\n"
2396 " Setting graphics driver to `default'.\n");
2397 graphics_driver = "default";
2404 void BufferParams::readBullets(Lexer & lex)
2409 int const index = lex.getInteger();
2411 int temp_int = lex.getInteger();
2412 user_defined_bullet(index).setFont(temp_int);
2413 temp_bullet(index).setFont(temp_int);
2415 user_defined_bullet(index).setCharacter(temp_int);
2416 temp_bullet(index).setCharacter(temp_int);
2418 user_defined_bullet(index).setSize(temp_int);
2419 temp_bullet(index).setSize(temp_int);
2423 void BufferParams::readBulletsLaTeX(Lexer & lex)
2425 // The bullet class should be able to read this.
2428 int const index = lex.getInteger();
2430 docstring const temp_str = lex.getDocString();
2432 user_defined_bullet(index).setText(temp_str);
2433 temp_bullet(index).setText(temp_str);
2437 void BufferParams::readModules(Lexer & lex)
2439 if (!lex.eatLine()) {
2440 lyxerr << "Error (BufferParams::readModules):"
2441 "Unexpected end of input." << endl;
2445 string mod = lex.getString();
2446 if (mod == "\\end_modules")
2448 addLayoutModule(mod);
2454 void BufferParams::readRemovedModules(Lexer & lex)
2456 if (!lex.eatLine()) {
2457 lyxerr << "Error (BufferParams::readRemovedModules):"
2458 "Unexpected end of input." << endl;
2462 string mod = lex.getString();
2463 if (mod == "\\end_removed_modules")
2465 removed_modules_.push_back(mod);
2468 // now we want to remove any removed modules that were previously
2469 // added. normally, that will be because default modules were added in
2470 // setBaseClass(), which gets called when \textclass is read at the
2471 // start of the read.
2472 list<string>::const_iterator rit = removed_modules_.begin();
2473 list<string>::const_iterator const ren = removed_modules_.end();
2474 for (; rit != ren; ++rit) {
2475 LayoutModuleList::iterator const mit = layout_modules_.begin();
2476 LayoutModuleList::iterator const men = layout_modules_.end();
2477 LayoutModuleList::iterator found = find(mit, men, *rit);
2480 layout_modules_.erase(found);
2485 void BufferParams::readIncludeonly(Lexer & lex)
2487 if (!lex.eatLine()) {
2488 lyxerr << "Error (BufferParams::readIncludeonly):"
2489 "Unexpected end of input." << endl;
2493 string child = lex.getString();
2494 if (child == "\\end_includeonly")
2496 included_children_.push_back(child);
2502 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2504 switch (papersize) {
2506 // could be anything, so don't guess
2508 case PAPER_CUSTOM: {
2509 if (purpose == XDVI && !paperwidth.empty() &&
2510 !paperheight.empty()) {
2511 // heightxwidth<unit>
2512 string first = paperwidth;
2513 string second = paperheight;
2514 if (orientation == ORIENTATION_LANDSCAPE)
2517 return first.erase(first.length() - 2)
2523 // dvips and dvipdfm do not know this
2524 if (purpose == DVIPS || purpose == DVIPDFM)
2528 if (purpose == DVIPS || purpose == DVIPDFM)
2532 if (purpose == DVIPS || purpose == DVIPDFM)
2542 if (purpose == DVIPS || purpose == DVIPDFM)
2546 if (purpose == DVIPS || purpose == DVIPDFM)
2550 if (purpose == DVIPS || purpose == DVIPDFM)
2554 if (purpose == DVIPS || purpose == DVIPDFM)
2558 if (purpose == DVIPS || purpose == DVIPDFM)
2562 // dvipdfm does not know this
2563 if (purpose == DVIPDFM)
2567 if (purpose == DVIPDFM)
2571 if (purpose == DVIPS || purpose == DVIPDFM)
2575 if (purpose == DVIPS || purpose == DVIPDFM)
2579 if (purpose == DVIPS || purpose == DVIPDFM)
2583 if (purpose == DVIPS || purpose == DVIPDFM)
2587 if (purpose == DVIPS || purpose == DVIPDFM)
2591 if (purpose == DVIPS || purpose == DVIPDFM)
2595 if (purpose == DVIPS || purpose == DVIPDFM)
2599 if (purpose == DVIPS || purpose == DVIPDFM)
2603 if (purpose == DVIPS || purpose == DVIPDFM)
2607 if (purpose == DVIPS || purpose == DVIPDFM)
2611 if (purpose == DVIPS || purpose == DVIPDFM)
2615 if (purpose == DVIPS || purpose == DVIPDFM)
2619 if (purpose == DVIPS || purpose == DVIPDFM)
2623 if (purpose == DVIPS || purpose == DVIPDFM)
2627 if (purpose == DVIPS || purpose == DVIPDFM)
2630 case PAPER_USEXECUTIVE:
2631 // dvipdfm does not know this
2632 if (purpose == DVIPDFM)
2637 case PAPER_USLETTER:
2639 if (purpose == XDVI)
2646 string const BufferParams::dvips_options() const
2650 // If the class loads the geometry package, we do not know which
2651 // paper size is used, since we do not set it (bug 7013).
2652 // Therefore we must not specify any argument here.
2653 // dvips gets the correct paper size via DVI specials in this case
2654 // (if the class uses the geometry package correctly).
2655 if (documentClass().provides("geometry"))
2659 && papersize == PAPER_CUSTOM
2660 && !lyxrc.print_paper_dimension_flag.empty()
2661 && !paperwidth.empty()
2662 && !paperheight.empty()) {
2663 // using a custom papersize
2664 result = lyxrc.print_paper_dimension_flag;
2665 result += ' ' + paperwidth;
2666 result += ',' + paperheight;
2668 string const paper_option = paperSizeName(DVIPS);
2669 if (!paper_option.empty() && (paper_option != "letter" ||
2670 orientation != ORIENTATION_LANDSCAPE)) {
2671 // dvips won't accept -t letter -t landscape.
2672 // In all other cases, include the paper size
2674 result = lyxrc.print_paper_flag;
2675 result += ' ' + paper_option;
2678 if (orientation == ORIENTATION_LANDSCAPE &&
2679 papersize != PAPER_CUSTOM)
2680 result += ' ' + lyxrc.print_landscape_flag;
2685 string const BufferParams::font_encoding() const
2687 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2691 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2693 // suppress the babel call if there is no BabelName defined
2694 // for the document language in the lib/languages file and if no
2695 // other languages are used (lang_opts is then empty)
2696 if (lang_opts.empty())
2698 // either a specific language (AsBabelOptions setting in
2699 // lib/languages) or the prefs require the languages to
2700 // be submitted to babel itself (not the class).
2702 return "\\usepackage[" + lang_opts + "]{babel}";
2703 return "\\usepackage{babel}";
2707 docstring BufferParams::getGraphicsDriver(string const & package) const
2711 if (package == "geometry") {
2712 if (graphics_driver == "dvips"
2713 || graphics_driver == "dvipdfm"
2714 || graphics_driver == "pdftex"
2715 || graphics_driver == "vtex")
2716 result = from_ascii(graphics_driver);
2717 else if (graphics_driver == "dvipdfmx")
2718 result = from_ascii("dvipdfm");
2725 void BufferParams::writeEncodingPreamble(otexstream & os,
2726 LaTeXFeatures & features) const
2728 // XeTeX does not need this
2729 if (features.runparams().flavor == OutputParams::XETEX)
2731 // LuaTeX neither, but with tex fonts, we need to load
2732 // the luainputenc package.
2733 if (features.runparams().flavor == OutputParams::LUATEX
2734 || features.runparams().flavor == OutputParams::DVILUATEX) {
2735 if (!useNonTeXFonts && inputenc != "default"
2736 && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc)
2737 || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) {
2738 os << "\\usepackage[utf8]{luainputenc}\n";
2742 if (inputenc == "auto") {
2743 string const doc_encoding =
2744 language->encoding()->latexName();
2745 Encoding::Package const package =
2746 language->encoding()->package();
2748 // Create a list with all the input encodings used
2750 set<string> encodings =
2751 features.getEncodingSet(doc_encoding);
2753 // If the "japanese" package (i.e. pLaTeX) is used,
2754 // inputenc must be omitted.
2755 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2756 if ((!encodings.empty() || package == Encoding::inputenc)
2757 && !features.isRequired("japanese")) {
2758 os << "\\usepackage[";
2759 set<string>::const_iterator it = encodings.begin();
2760 set<string>::const_iterator const end = encodings.end();
2762 os << from_ascii(*it);
2765 for (; it != end; ++it)
2766 os << ',' << from_ascii(*it);
2767 if (package == Encoding::inputenc) {
2768 if (!encodings.empty())
2770 os << from_ascii(doc_encoding);
2772 os << "]{inputenc}\n";
2774 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2775 if (language->encoding()->name() == "utf8-cjk"
2776 && LaTeXFeatures::isAvailable("CJKutf8"))
2777 os << "\\usepackage{CJKutf8}\n";
2779 os << "\\usepackage{CJK}\n";
2781 } else if (inputenc != "default") {
2782 switch (encoding().package()) {
2783 case Encoding::none:
2784 case Encoding::japanese:
2786 case Encoding::inputenc:
2787 // do not load inputenc if japanese is used
2788 if (features.isRequired("japanese"))
2790 os << "\\usepackage[" << from_ascii(encoding().latexName())
2794 if (encoding().name() == "utf8-cjk"
2795 && LaTeXFeatures::isAvailable("CJKutf8"))
2796 os << "\\usepackage{CJKutf8}\n";
2798 os << "\\usepackage{CJK}\n";
2805 string const BufferParams::parseFontName(string const & name) const
2807 string mangled = name;
2808 size_t const idx = mangled.find('[');
2809 if (idx == string::npos || idx == 0)
2812 return mangled.substr(0, idx - 1);
2816 string const BufferParams::loadFonts(LaTeXFeatures & features) const
2818 if (fonts_roman == "default" && fonts_sans == "default"
2819 && fonts_typewriter == "default"
2820 && (fonts_math == "default" || fonts_math == "auto"))
2826 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
2827 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
2828 * Mapping=tex-text option assures TeX ligatures (such as "--")
2829 * are resolved. Note that tt does not use these ligatures.
2831 * -- add more GUI options?
2832 * -- add more fonts (fonts for other scripts)
2833 * -- if there's a way to find out if a font really supports
2834 * OldStyle, enable/disable the widget accordingly.
2836 if (useNonTeXFonts && features.isAvailable("fontspec")) {
2837 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
2838 // However, until v.2 (2010/07/11) fontspec only knew
2839 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
2840 // was introduced for both XeTeX and LuaTeX (LuaTeX
2841 // didn't understand "Mapping=tex-text", while XeTeX
2842 // understood both. With most recent versions, both
2843 // variants are understood by both engines. However,
2844 // we want to provide support for at least TeXLive 2009
2845 // (for XeTeX; LuaTeX is only supported as of v.2)
2846 string const texmapping =
2847 (features.runparams().flavor == OutputParams::XETEX) ?
2848 "Mapping=tex-text" : "Ligatures=TeX";
2849 if (fonts_roman != "default") {
2850 os << "\\setmainfont[" << texmapping;
2851 if (fonts_old_figures)
2852 os << ",Numbers=OldStyle";
2853 os << "]{" << parseFontName(fonts_roman) << "}\n";
2855 if (fonts_sans != "default") {
2856 string const sans = parseFontName(fonts_sans);
2857 if (fonts_sans_scale != 100)
2858 os << "\\setsansfont[Scale="
2859 << float(fonts_sans_scale) / 100
2860 << "," << texmapping << "]{"
2863 os << "\\setsansfont[" << texmapping << "]{"
2866 if (fonts_typewriter != "default") {
2867 string const mono = parseFontName(fonts_typewriter);
2868 if (fonts_typewriter_scale != 100)
2869 os << "\\setmonofont[Scale="
2870 << float(fonts_typewriter_scale) / 100
2874 os << "\\setmonofont{"
2881 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
2882 bool const dryrun = features.runparams().dryrun;
2883 bool const complete = (fonts_sans == "default" && fonts_typewriter == "default");
2884 bool const nomath = (fonts_math == "default");
2887 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_roman)).getLaTeXCode(
2888 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2892 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_sans)).getLaTeXCode(
2893 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2894 nomath, fonts_sans_scale);
2896 // MONOSPACED/TYPEWRITER
2897 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_typewriter)).getLaTeXCode(
2898 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2899 nomath, fonts_typewriter_scale);
2902 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getLaTeXCode(
2903 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2910 Encoding const & BufferParams::encoding() const
2912 // FIXME: actually, we should check for the flavor
2913 // or runparams.isFullyUnicode() here:
2914 // This check will not work with XeTeX/LuaTeX and tex fonts.
2915 // Thus we have to reset the encoding in Buffer::makeLaTeXFile.
2917 return *(encodings.fromLyXName("utf8-plain"));
2918 if (inputenc == "auto" || inputenc == "default")
2919 return *language->encoding();
2920 Encoding const * const enc = encodings.fromLyXName(inputenc);
2923 LYXERR0("Unknown inputenc value `" << inputenc
2924 << "'. Using `auto' instead.");
2925 return *language->encoding();
2929 bool BufferParams::addCiteEngine(string const & engine)
2931 LayoutModuleList::const_iterator it = cite_engine_.begin();
2932 LayoutModuleList::const_iterator en = cite_engine_.end();
2933 for (; it != en; ++it)
2936 cite_engine_.push_back(engine);
2941 bool BufferParams::addCiteEngine(vector<string> const & engine)
2943 vector<string>::const_iterator it = engine.begin();
2944 vector<string>::const_iterator en = engine.end();
2946 for (; it != en; ++it)
2947 if (!addCiteEngine(*it))
2953 string const & BufferParams::defaultBiblioStyle() const
2955 return documentClass().defaultBiblioStyle();
2959 bool const & BufferParams::fullAuthorList() const
2961 return documentClass().fullAuthorList();
2965 void BufferParams::setCiteEngine(string const & engine)
2968 addCiteEngine(engine);
2972 void BufferParams::setCiteEngine(vector<string> const & engine)
2975 addCiteEngine(engine);
2979 vector<string> BufferParams::citeCommands() const
2981 static CitationStyle const default_style;
2982 vector<string> commands =
2983 documentClass().citeCommands(citeEngineType());
2984 if (commands.empty())
2985 commands.push_back(default_style.cmd);
2990 vector<CitationStyle> BufferParams::citeStyles() const
2992 static CitationStyle const default_style;
2993 vector<CitationStyle> styles =
2994 documentClass().citeStyles(citeEngineType());
2996 styles.push_back(default_style);