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 "ModuleList.h"
37 #include "OutputParams.h"
41 #include "PDFOptions.h"
43 #include "frontends/alert.h"
45 #include "insets/InsetListingsParams.h"
47 #include "support/convert.h"
48 #include "support/debug.h"
49 #include "support/docstream.h"
50 #include "support/FileName.h"
51 #include "support/filetools.h"
52 #include "support/gettext.h"
53 #include "support/Messages.h"
54 #include "support/Translator.h"
55 #include "support/lstrings.h"
61 using namespace lyx::support;
64 static char const * const string_paragraph_separation[] = {
69 static char const * const string_quotes_language[] = {
70 "english", "swedish", "german", "polish", "french", "danish", ""
74 static char const * const string_papersize[] = {
75 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
76 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
77 "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
78 "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
79 "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
84 static char const * const string_orientation[] = {
85 "portrait", "landscape", ""
89 static char const * const string_footnotekinds[] = {
90 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
94 static char const * const tex_graphics[] = {
95 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
96 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
97 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
98 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
109 // Paragraph separation
110 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
113 ParSepTranslator const init_parseptranslator()
115 ParSepTranslator translator
116 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
117 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
122 ParSepTranslator const & parseptranslator()
124 static ParSepTranslator translator = init_parseptranslator();
130 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
133 QuotesLangTranslator const init_quoteslangtranslator()
135 QuotesLangTranslator translator
136 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
137 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
138 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
139 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
140 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
141 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
146 QuotesLangTranslator const & quoteslangtranslator()
148 static QuotesLangTranslator translator = init_quoteslangtranslator();
154 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
157 static PaperSizeTranslator initPaperSizeTranslator()
159 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
160 translator.addPair(string_papersize[1], PAPER_CUSTOM);
161 translator.addPair(string_papersize[2], PAPER_USLETTER);
162 translator.addPair(string_papersize[3], PAPER_USLEGAL);
163 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
164 translator.addPair(string_papersize[5], PAPER_A0);
165 translator.addPair(string_papersize[6], PAPER_A1);
166 translator.addPair(string_papersize[7], PAPER_A2);
167 translator.addPair(string_papersize[8], PAPER_A3);
168 translator.addPair(string_papersize[9], PAPER_A4);
169 translator.addPair(string_papersize[10], PAPER_A5);
170 translator.addPair(string_papersize[11], PAPER_A6);
171 translator.addPair(string_papersize[12], PAPER_B0);
172 translator.addPair(string_papersize[13], PAPER_B1);
173 translator.addPair(string_papersize[14], PAPER_B2);
174 translator.addPair(string_papersize[15], PAPER_B3);
175 translator.addPair(string_papersize[16], PAPER_B4);
176 translator.addPair(string_papersize[17], PAPER_B5);
177 translator.addPair(string_papersize[18], PAPER_B6);
178 translator.addPair(string_papersize[19], PAPER_C0);
179 translator.addPair(string_papersize[20], PAPER_C1);
180 translator.addPair(string_papersize[21], PAPER_C2);
181 translator.addPair(string_papersize[22], PAPER_C3);
182 translator.addPair(string_papersize[23], PAPER_C4);
183 translator.addPair(string_papersize[24], PAPER_C5);
184 translator.addPair(string_papersize[25], PAPER_C6);
185 translator.addPair(string_papersize[26], PAPER_JISB0);
186 translator.addPair(string_papersize[27], PAPER_JISB1);
187 translator.addPair(string_papersize[28], PAPER_JISB2);
188 translator.addPair(string_papersize[29], PAPER_JISB3);
189 translator.addPair(string_papersize[30], PAPER_JISB4);
190 translator.addPair(string_papersize[31], PAPER_JISB5);
191 translator.addPair(string_papersize[32], PAPER_JISB6);
196 PaperSizeTranslator const & papersizetranslator()
198 static PaperSizeTranslator translator = initPaperSizeTranslator();
204 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
207 PaperOrientationTranslator const init_paperorientationtranslator()
209 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
210 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
215 PaperOrientationTranslator const & paperorientationtranslator()
217 static PaperOrientationTranslator translator = init_paperorientationtranslator();
223 typedef Translator<int, PageSides> SidesTranslator;
226 SidesTranslator const init_sidestranslator()
228 SidesTranslator translator(1, OneSide);
229 translator.addPair(2, TwoSides);
234 SidesTranslator const & sidestranslator()
236 static SidesTranslator translator = init_sidestranslator();
242 typedef Translator<int, BufferParams::Package> PackageTranslator;
245 PackageTranslator const init_packagetranslator()
247 PackageTranslator translator(0, BufferParams::package_off);
248 translator.addPair(1, BufferParams::package_auto);
249 translator.addPair(2, BufferParams::package_on);
254 PackageTranslator const & packagetranslator()
256 static PackageTranslator translator = init_packagetranslator();
262 typedef Translator<string, CiteEngine> CiteEngineTranslator;
265 CiteEngineTranslator const init_citeenginetranslator()
267 CiteEngineTranslator translator("basic", ENGINE_BASIC);
268 translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
269 translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
270 translator.addPair("jurabib", ENGINE_JURABIB);
275 CiteEngineTranslator const & citeenginetranslator()
277 static CiteEngineTranslator translator = init_citeenginetranslator();
283 typedef Translator<string, Spacing::Space> SpaceTranslator;
286 SpaceTranslator const init_spacetranslator()
288 SpaceTranslator translator("default", Spacing::Default);
289 translator.addPair("single", Spacing::Single);
290 translator.addPair("onehalf", Spacing::Onehalf);
291 translator.addPair("double", Spacing::Double);
292 translator.addPair("other", Spacing::Other);
297 SpaceTranslator const & spacetranslator()
299 static SpaceTranslator translator = init_spacetranslator();
306 class BufferParams::Impl
311 AuthorList authorlist;
312 BranchList branchlist;
313 Bullet temp_bullets[4];
314 Bullet user_defined_bullets[4];
315 IndicesList indiceslist;
317 /** This is the amount of space used for paragraph_separation "skip",
318 * and for detached paragraphs in "indented" documents.
322 PDFOptions pdfoptions;
323 LayoutFileIndex baseClass_;
327 BufferParams::Impl::Impl()
328 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
330 // set initial author
332 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
337 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
341 return new BufferParams::Impl(*ptr);
345 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
351 BufferParams::BufferParams()
354 setBaseClass(defaultBaseclass());
356 paragraph_separation = ParagraphIndentSeparation;
357 quotes_language = InsetQuotes::EnglishQuotes;
358 fontsize = "default";
361 papersize = PAPER_DEFAULT;
362 orientation = ORIENTATION_PORTRAIT;
363 use_geometry = false;
364 cite_engine_ = ENGINE_BASIC;
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";
379 fonts_default_family = "default";
380 useNonTeXFonts = false;
381 fonts_expert_sc = false;
382 fonts_old_figures = false;
383 fonts_sans_scale = 100;
384 fonts_typewriter_scale = 100;
386 lang_package = "default";
387 graphics_driver = "default";
388 default_output_format = "default";
389 bibtex_command = "default";
390 index_command = "default";
393 listings_params = string();
394 pagestyle = "default";
395 suppress_date = false;
396 justification = true;
397 // no color is the default (white)
398 backgroundcolor = lyx::rgbFromHexName("#ffffff");
399 isbackgroundcolor = false;
400 // no color is the default (black)
401 fontcolor = lyx::rgbFromHexName("#000000");
403 // light gray is the default font color for greyed-out notes
404 notefontcolor = lyx::rgbFromHexName("#cccccc");
405 boxbgcolor = lyx::rgbFromHexName("#ff0000");
406 compressed = lyxrc.save_compressed;
407 for (int iter = 0; iter < 4; ++iter) {
408 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
409 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
412 indiceslist().addDefault(B_("Index"));
413 html_be_strict = false;
414 html_math_output = MathML;
415 html_math_img_scale = 1.0;
416 html_css_as_file = false;
423 docstring BufferParams::B_(string const & l10n) const
425 LASSERT(language, /**/);
426 return getMessages(language->code()).get(l10n);
430 BufferParams::Package BufferParams::use_package(std::string const & p) const
432 PackageMap::const_iterator it = use_packages.find(p);
433 if (it == use_packages.end())
439 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
445 vector<string> const & BufferParams::auto_packages()
447 static vector<string> packages;
448 if (packages.empty()) {
449 // adding a package here implies a file format change!
450 packages.push_back("amsmath");
451 packages.push_back("esint");
452 packages.push_back("mathdots");
453 packages.push_back("mhchem");
454 packages.push_back("undertilde");
460 AuthorList & BufferParams::authors()
462 return pimpl_->authorlist;
466 AuthorList const & BufferParams::authors() const
468 return pimpl_->authorlist;
472 BranchList & BufferParams::branchlist()
474 return pimpl_->branchlist;
478 BranchList const & BufferParams::branchlist() const
480 return pimpl_->branchlist;
484 IndicesList & BufferParams::indiceslist()
486 return pimpl_->indiceslist;
490 IndicesList const & BufferParams::indiceslist() const
492 return pimpl_->indiceslist;
496 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
498 LASSERT(index < 4, /**/);
499 return pimpl_->temp_bullets[index];
503 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
505 LASSERT(index < 4, /**/);
506 return pimpl_->temp_bullets[index];
510 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
512 LASSERT(index < 4, /**/);
513 return pimpl_->user_defined_bullets[index];
517 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
519 LASSERT(index < 4, /**/);
520 return pimpl_->user_defined_bullets[index];
524 Spacing & BufferParams::spacing()
526 return pimpl_->spacing;
530 Spacing const & BufferParams::spacing() const
532 return pimpl_->spacing;
536 PDFOptions & BufferParams::pdfoptions()
538 return pimpl_->pdfoptions;
542 PDFOptions const & BufferParams::pdfoptions() const
544 return pimpl_->pdfoptions;
548 HSpace const & BufferParams::getIndentation() const
550 return pimpl_->indentation;
554 void BufferParams::setIndentation(HSpace const & indent)
556 pimpl_->indentation = indent;
560 VSpace const & BufferParams::getDefSkip() const
562 return pimpl_->defskip;
566 void BufferParams::setDefSkip(VSpace const & vs)
568 // DEFSKIP will cause an infinite loop
569 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
570 pimpl_->defskip = vs;
574 string BufferParams::readToken(Lexer & lex, string const & token,
575 FileName const & filepath)
577 if (token == "\\textclass") {
579 string const classname = lex.getString();
580 // if there exists a local layout file, ignore the system one
581 // NOTE: in this case, the textclass (.cls file) is assumed to
584 LayoutFileList & bcl = LayoutFileList::get();
585 if (tcp.empty() && !filepath.empty())
586 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
590 setBaseClass(classname);
591 // We assume that a tex class exists for local or unknown
592 // layouts so this warning, will only be given for system layouts.
593 if (!baseClass()->isTeXClassAvailable()) {
594 docstring const desc =
595 translateIfPossible(from_utf8(baseClass()->description()));
596 docstring const prereqs =
597 from_utf8(baseClass()->prerequisites());
598 docstring const msg =
599 bformat(_("The selected document class\n"
601 "requires external files that are not available.\n"
602 "The document class can still be used, but the\n"
603 "document cannot be compiled until the following\n"
604 "prerequisites are installed:\n"
606 "See section 3.1.2.2 (Class Availability) of the\n"
607 "User's Guide for more information."), desc, prereqs);
608 frontend::Alert::warning(_("Document class not available"),
611 } else if (token == "\\begin_preamble") {
613 } else if (token == "\\begin_local_layout") {
614 readLocalLayout(lex);
615 } else if (token == "\\begin_modules") {
617 } else if (token == "\\begin_removed_modules") {
618 readRemovedModules(lex);
619 } else if (token == "\\begin_includeonly") {
620 readIncludeonly(lex);
621 } else if (token == "\\maintain_unincluded_children") {
622 lex >> maintain_unincluded_children;
623 } else if (token == "\\options") {
625 options = lex.getString();
626 } else if (token == "\\use_default_options") {
627 lex >> use_default_options;
628 } else if (token == "\\master") {
630 master = lex.getString();
631 } else if (token == "\\suppress_date") {
632 lex >> suppress_date;
633 } else if (token == "\\justification") {
634 lex >> justification;
635 } else if (token == "\\language") {
637 } else if (token == "\\language_package") {
639 lang_package = lex.getString();
640 } else if (token == "\\inputencoding") {
642 } else if (token == "\\graphics") {
643 readGraphicsDriver(lex);
644 } else if (token == "\\default_output_format") {
645 lex >> default_output_format;
646 } else if (token == "\\bibtex_command") {
648 bibtex_command = lex.getString();
649 } else if (token == "\\index_command") {
651 index_command = lex.getString();
652 } else if (token == "\\fontencoding") {
654 fontenc = lex.getString();
655 } else if (token == "\\font_roman") {
657 fonts_roman = lex.getString();
658 } else if (token == "\\font_sans") {
660 fonts_sans = lex.getString();
661 } else if (token == "\\font_typewriter") {
663 fonts_typewriter = lex.getString();
664 } else if (token == "\\font_default_family") {
665 lex >> fonts_default_family;
666 } else if (token == "\\use_non_tex_fonts") {
667 lex >> useNonTeXFonts;
668 } else if (token == "\\font_sc") {
669 lex >> fonts_expert_sc;
670 } else if (token == "\\font_osf") {
671 lex >> fonts_old_figures;
672 } else if (token == "\\font_sf_scale") {
673 lex >> fonts_sans_scale;
674 } else if (token == "\\font_tt_scale") {
675 lex >> fonts_typewriter_scale;
676 } else if (token == "\\font_cjk") {
678 } else if (token == "\\paragraph_separation") {
681 paragraph_separation = parseptranslator().find(parsep);
682 } else if (token == "\\paragraph_indentation") {
684 string indentation = lex.getString();
685 pimpl_->indentation = HSpace(indentation);
686 } else if (token == "\\defskip") {
688 string const defskip = lex.getString();
689 pimpl_->defskip = VSpace(defskip);
690 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
692 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
693 } else if (token == "\\quotes_language") {
696 quotes_language = quoteslangtranslator().find(quotes_lang);
697 } else if (token == "\\papersize") {
700 papersize = papersizetranslator().find(ppsize);
701 } else if (token == "\\use_geometry") {
703 } else if (token == "\\use_amsmath") {
706 use_package("amsmath", packagetranslator().find(use_ams));
707 } else if (token == "\\use_esint") {
710 use_package("esint", packagetranslator().find(useesint));
711 } else if (token == "\\use_mhchem") {
714 use_package("mhchem", packagetranslator().find(usemhchem));
715 } else if (token == "\\use_mathdots") {
718 use_package("mathdots", packagetranslator().find(usemathdots));
719 } else if (token == "\\use_undertilde") {
721 lex >> useundertilde;
722 use_package("undertilde", packagetranslator().find(useundertilde));
723 } else if (token == "\\cite_engine") {
726 cite_engine_ = citeenginetranslator().find(engine);
727 } else if (token == "\\biblio_style") {
729 biblio_style = lex.getString();
730 } else if (token == "\\use_bibtopic") {
732 } else if (token == "\\use_indices") {
734 } else if (token == "\\tracking_changes") {
736 } else if (token == "\\output_changes") {
737 lex >> outputChanges;
738 } else if (token == "\\branch") {
740 docstring branch = lex.getDocString();
741 branchlist().add(branch);
744 string const tok = lex.getString();
745 if (tok == "\\end_branch")
747 Branch * branch_ptr = branchlist().find(branch);
748 if (tok == "\\selected") {
751 branch_ptr->setSelected(lex.getInteger());
753 if (tok == "\\filename_suffix") {
756 branch_ptr->setFileNameSuffix(lex.getInteger());
758 if (tok == "\\color") {
760 string color = lex.getString();
762 branch_ptr->setColor(color);
763 // Update also the Color table:
765 color = lcolor.getX11Name(Color_background);
767 lcolor.setColor(to_utf8(branch), color);
770 } else if (token == "\\index") {
772 docstring index = lex.getDocString();
774 indiceslist().add(index);
777 string const tok = lex.getString();
778 if (tok == "\\end_index")
780 Index * index_ptr = indiceslist().find(index);
781 if (tok == "\\shortcut") {
783 shortcut = lex.getDocString();
785 index_ptr->setShortcut(shortcut);
787 if (tok == "\\color") {
789 string color = lex.getString();
791 index_ptr->setColor(color);
792 // Update also the Color table:
794 color = lcolor.getX11Name(Color_background);
796 if (!shortcut.empty())
797 lcolor.setColor(to_utf8(shortcut), color);
800 } else if (token == "\\author") {
802 istringstream ss(lex.getString());
805 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
806 } else if (token == "\\paperorientation") {
809 orientation = paperorientationtranslator().find(orient);
810 } else if (token == "\\backgroundcolor") {
812 backgroundcolor = lyx::rgbFromHexName(lex.getString());
813 isbackgroundcolor = true;
814 } else if (token == "\\fontcolor") {
816 fontcolor = lyx::rgbFromHexName(lex.getString());
818 } else if (token == "\\notefontcolor") {
820 string color = lex.getString();
821 notefontcolor = lyx::rgbFromHexName(color);
822 } else if (token == "\\boxbgcolor") {
824 string color = lex.getString();
825 boxbgcolor = lyx::rgbFromHexName(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_default_family " << fonts_default_family
1000 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1001 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1002 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1003 << "\n\\font_sf_scale " << fonts_sans_scale
1004 << "\n\\font_tt_scale " << fonts_typewriter_scale
1006 if (!fonts_cjk.empty()) {
1007 os << "\\font_cjk " << fonts_cjk << '\n';
1009 os << "\n\\graphics " << graphics_driver << '\n';
1010 os << "\\default_output_format " << default_output_format << '\n';
1011 os << "\\output_sync " << output_sync << '\n';
1012 if (!output_sync_macro.empty())
1013 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1014 os << "\\bibtex_command " << bibtex_command << '\n';
1015 os << "\\index_command " << index_command << '\n';
1017 if (!float_placement.empty()) {
1018 os << "\\float_placement " << float_placement << '\n';
1020 os << "\\paperfontsize " << fontsize << '\n';
1022 spacing().writeFile(os);
1023 pdfoptions().writeFile(os);
1025 os << "\\papersize " << string_papersize[papersize]
1026 << "\n\\use_geometry " << convert<string>(use_geometry)
1027 << "\n\\use_amsmath " << use_package("amsmath")
1028 << "\n\\use_esint " << use_package("esint")
1029 << "\n\\use_mhchem " << use_package("mhchem")
1030 << "\n\\use_mathdots " << use_package("mathdots")
1031 << "\n\\use_undertilde " << use_package("undertilde")
1032 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
1033 << "\n\\biblio_style " << biblio_style
1034 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1035 << "\n\\use_indices " << convert<string>(use_indices)
1036 << "\n\\paperorientation " << string_orientation[orientation]
1037 << "\n\\suppress_date " << convert<string>(suppress_date)
1038 << "\n\\justification " << convert<string>(justification)
1039 << "\n\\use_refstyle " << use_refstyle
1041 if (isbackgroundcolor == true)
1042 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1043 if (isfontcolor == true)
1044 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1045 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1046 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1047 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1048 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1050 BranchList::const_iterator it = branchlist().begin();
1051 BranchList::const_iterator end = branchlist().end();
1052 for (; it != end; ++it) {
1053 os << "\\branch " << to_utf8(it->branch())
1054 << "\n\\selected " << it->isSelected()
1055 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1056 << "\n\\color " << lyx::X11hexname(it->color())
1061 IndicesList::const_iterator iit = indiceslist().begin();
1062 IndicesList::const_iterator iend = indiceslist().end();
1063 for (; iit != iend; ++iit) {
1064 os << "\\index " << to_utf8(iit->index())
1065 << "\n\\shortcut " << to_utf8(iit->shortcut())
1066 << "\n\\color " << lyx::X11hexname(iit->color())
1071 if (!paperwidth.empty())
1072 os << "\\paperwidth "
1073 << VSpace(paperwidth).asLyXCommand() << '\n';
1074 if (!paperheight.empty())
1075 os << "\\paperheight "
1076 << VSpace(paperheight).asLyXCommand() << '\n';
1077 if (!leftmargin.empty())
1078 os << "\\leftmargin "
1079 << VSpace(leftmargin).asLyXCommand() << '\n';
1080 if (!topmargin.empty())
1081 os << "\\topmargin "
1082 << VSpace(topmargin).asLyXCommand() << '\n';
1083 if (!rightmargin.empty())
1084 os << "\\rightmargin "
1085 << VSpace(rightmargin).asLyXCommand() << '\n';
1086 if (!bottommargin.empty())
1087 os << "\\bottommargin "
1088 << VSpace(bottommargin).asLyXCommand() << '\n';
1089 if (!headheight.empty())
1090 os << "\\headheight "
1091 << VSpace(headheight).asLyXCommand() << '\n';
1092 if (!headsep.empty())
1094 << VSpace(headsep).asLyXCommand() << '\n';
1095 if (!footskip.empty())
1097 << VSpace(footskip).asLyXCommand() << '\n';
1098 if (!columnsep.empty())
1099 os << "\\columnsep "
1100 << VSpace(columnsep).asLyXCommand() << '\n';
1101 os << "\\secnumdepth " << secnumdepth
1102 << "\n\\tocdepth " << tocdepth
1103 << "\n\\paragraph_separation "
1104 << string_paragraph_separation[paragraph_separation];
1105 if (!paragraph_separation)
1106 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1108 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1109 os << "\n\\quotes_language "
1110 << string_quotes_language[quotes_language]
1111 << "\n\\papercolumns " << columns
1112 << "\n\\papersides " << sides
1113 << "\n\\paperpagestyle " << pagestyle << '\n';
1114 if (!listings_params.empty())
1115 os << "\\listings_params \"" <<
1116 InsetListingsParams(listings_params).encodedString() << "\"\n";
1117 for (int i = 0; i < 4; ++i) {
1118 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1119 if (user_defined_bullet(i).getFont() != -1) {
1120 os << "\\bullet " << i << " "
1121 << user_defined_bullet(i).getFont() << " "
1122 << user_defined_bullet(i).getCharacter() << " "
1123 << user_defined_bullet(i).getSize() << "\n";
1127 os << "\\bulletLaTeX " << i << " \""
1128 << lyx::to_ascii(user_defined_bullet(i).getText())
1134 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1135 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1136 << "\\html_math_output " << html_math_output << '\n'
1137 << "\\html_css_as_file " << html_css_as_file << '\n'
1138 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1140 if (html_math_img_scale != 1.0)
1141 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1142 if (!html_latex_start.empty())
1143 os << "\\html_latex_start " << html_latex_start << '\n';
1144 if (!html_latex_end.empty())
1145 os << "\\html_latex_end " << html_latex_end << '\n';
1147 os << pimpl_->authorlist;
1151 void BufferParams::validate(LaTeXFeatures & features) const
1153 features.require(documentClass().requires());
1155 if (outputChanges) {
1156 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1157 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1158 LaTeXFeatures::isAvailable("xcolor");
1160 switch (features.runparams().flavor) {
1161 case OutputParams::LATEX:
1162 case OutputParams::DVILUATEX:
1164 features.require("ct-dvipost");
1165 features.require("dvipost");
1166 } else if (xcolorulem) {
1167 features.require("ct-xcolor-ulem");
1168 features.require("ulem");
1169 features.require("xcolor");
1171 features.require("ct-none");
1174 case OutputParams::LUATEX:
1175 case OutputParams::PDFLATEX:
1176 case OutputParams::XETEX:
1178 features.require("ct-xcolor-ulem");
1179 features.require("ulem");
1180 features.require("xcolor");
1181 // improves color handling in PDF output
1182 features.require("pdfcolmk");
1184 features.require("ct-none");
1192 // Floats with 'Here definitely' as default setting.
1193 if (float_placement.find('H') != string::npos)
1194 features.require("float");
1196 for (PackageMap::const_iterator it = use_packages.begin();
1197 it != use_packages.end(); ++it) {
1198 if (it->first == "amsmath") {
1199 // AMS Style is at document level
1200 if (it->second == package_on ||
1201 documentClass().provides("amsmath"))
1202 features.require(it->first);
1203 } else if (it->second == package_on)
1204 features.require(it->first);
1207 // Document-level line spacing
1208 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1209 features.require("setspace");
1211 // the bullet shapes are buffer level not paragraph level
1212 // so they are tested here
1213 for (int i = 0; i < 4; ++i) {
1214 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1216 int const font = user_defined_bullet(i).getFont();
1218 int const c = user_defined_bullet(i).getCharacter();
1224 features.require("latexsym");
1226 } else if (font == 1) {
1227 features.require("amssymb");
1228 } else if (font >= 2 && font <= 5) {
1229 features.require("pifont");
1233 if (pdfoptions().use_hyperref) {
1234 features.require("hyperref");
1235 // due to interferences with babel and hyperref, the color package has to
1236 // be loaded after hyperref when hyperref is used with the colorlinks
1237 // option, see http://www.lyx.org/trac/ticket/5291
1238 if (pdfoptions().colorlinks)
1239 features.require("color");
1242 if (features.runparams().flavor == OutputParams::XETEX
1244 features.require("polyglossia");
1246 if (language->lang() == "vietnamese")
1247 features.require("vietnamese");
1248 else if (language->lang() == "japanese")
1249 features.require("japanese");
1253 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1254 FileName const & filepath) const
1256 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1257 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1258 // \RequirePackage to do so, rather than the normal \usepackage
1259 // Do not try to load any other package before the document class, unless you
1260 // have a thorough understanding of the LATEX internals and know exactly what you
1262 if (features.mustProvide("fix-cm"))
1263 os << "\\RequirePackage{fix-cm}\n";
1265 os << "\\documentclass";
1267 DocumentClass const & tclass = documentClass();
1269 ostringstream clsoptions; // the document class options.
1271 if (tokenPos(tclass.opt_fontsize(),
1272 '|', fontsize) >= 0) {
1273 // only write if existing in list (and not default)
1274 clsoptions << fontsize << "pt,";
1277 // all paper sizes except of A4, A5, B5 and the US sizes need the
1279 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1280 && papersize != PAPER_USLETTER
1281 && papersize != PAPER_USLEGAL
1282 && papersize != PAPER_USEXECUTIVE
1283 && papersize != PAPER_A4
1284 && papersize != PAPER_A5
1285 && papersize != PAPER_B5;
1287 if (!use_geometry) {
1288 switch (papersize) {
1290 clsoptions << "a4paper,";
1292 case PAPER_USLETTER:
1293 clsoptions << "letterpaper,";
1296 clsoptions << "a5paper,";
1299 clsoptions << "b5paper,";
1301 case PAPER_USEXECUTIVE:
1302 clsoptions << "executivepaper,";
1305 clsoptions << "legalpaper,";
1339 if (sides != tclass.sides()) {
1342 clsoptions << "oneside,";
1345 clsoptions << "twoside,";
1351 if (columns != tclass.columns()) {
1353 clsoptions << "twocolumn,";
1355 clsoptions << "onecolumn,";
1359 && orientation == ORIENTATION_LANDSCAPE)
1360 clsoptions << "landscape,";
1362 // language should be a parameter to \documentclass
1363 if (language->babel() == "hebrew"
1364 && default_language->babel() != "hebrew")
1365 // This seems necessary
1366 features.useLanguage(default_language);
1368 ostringstream language_options;
1369 bool const use_babel = features.useBabel() && !tclass.provides("babel");
1370 bool const use_polyglossia = features.usePolyglossia();
1371 bool const global = lyxrc.language_global_options;
1372 if (use_babel || (use_polyglossia && global)) {
1373 language_options << features.getLanguages();
1374 if (!language->babel().empty()) {
1375 if (!language_options.str().empty())
1376 language_options << ',';
1377 language_options << language->babel();
1379 if (global && !features.needBabelLangOptions())
1380 clsoptions << language_options.str() << ',';
1383 // the predefined options from the layout
1384 if (use_default_options && !tclass.options().empty())
1385 clsoptions << tclass.options() << ',';
1387 // the user-defined options
1388 if (!options.empty()) {
1389 clsoptions << options << ',';
1392 string strOptions(clsoptions.str());
1393 if (!strOptions.empty()) {
1394 strOptions = rtrim(strOptions, ",");
1396 os << '[' << from_utf8(strOptions) << ']';
1399 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1400 // end of \documentclass defs
1402 // if we use fontspec, we have to load the AMS packages here
1403 string const ams = features.loadAMSPackages();
1404 if (useNonTeXFonts && !ams.empty())
1405 os << from_ascii(ams);
1408 os << "\\usepackage{fontspec}\n";
1410 // font selection must be done before loading fontenc.sty
1411 string const fonts =
1412 loadFonts(fonts_roman, fonts_sans, fonts_typewriter,
1413 fonts_expert_sc, fonts_old_figures,
1414 fonts_sans_scale, fonts_typewriter_scale,
1415 useNonTeXFonts, features);
1417 os << from_utf8(fonts);
1419 if (fonts_default_family != "default")
1420 os << "\\renewcommand{\\familydefault}{\\"
1421 << from_ascii(fonts_default_family) << "}\n";
1423 // set font encoding
1424 // for arabic_arabi and farsi we also need to load the LAE and
1426 // XeTeX and LuaTeX (with OS fonts) work without fontenc
1427 if (font_encoding() != "default" && language->lang() != "japanese"
1428 && !useNonTeXFonts && !tclass.provides("fontenc")) {
1429 size_t fars = language_options.str().find("farsi");
1430 size_t arab = language_options.str().find("arabic");
1431 if (language->lang() == "arabic_arabi"
1432 || language->lang() == "farsi" || fars != string::npos
1433 || arab != string::npos) {
1434 os << "\\usepackage[" << from_ascii(font_encoding())
1435 << ",LFE,LAE]{fontenc}\n";
1437 os << "\\usepackage[" << from_ascii(font_encoding())
1442 // handle inputenc etc.
1443 writeEncodingPreamble(os, features);
1446 if (!features.runparams().includeall && !included_children_.empty()) {
1447 os << "\\includeonly{";
1448 list<string>::const_iterator it = included_children_.begin();
1449 list<string>::const_iterator en = included_children_.end();
1451 for (; it != en; ++it) {
1452 string incfile = *it;
1453 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1454 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1456 if (!features.runparams().nice)
1458 // \includeonly doesn't want an extension
1459 incfile = changeExtension(incfile, string());
1460 incfile = support::latex_path(incfile);
1461 if (!incfile.empty()) {
1464 os << from_utf8(incfile);
1471 if (!listings_params.empty() || features.isRequired("listings"))
1472 os << "\\usepackage{listings}\n";
1474 if (!listings_params.empty()) {
1476 // do not test validity because listings_params is
1477 // supposed to be valid
1479 InsetListingsParams(listings_params).separatedParams(true);
1480 // we can't support all packages, but we should load the color package
1481 if (par.find("\\color", 0) != string::npos)
1482 features.require("color");
1483 os << from_utf8(par)
1486 if (!tclass.provides("geometry")
1487 && (use_geometry || nonstandard_papersize)) {
1488 odocstringstream ods;
1489 if (!getGraphicsDriver("geometry").empty())
1490 ods << getGraphicsDriver("geometry");
1491 if (orientation == ORIENTATION_LANDSCAPE)
1492 ods << ",landscape";
1493 switch (papersize) {
1495 if (!paperwidth.empty())
1496 ods << ",paperwidth="
1497 << from_ascii(paperwidth);
1498 if (!paperheight.empty())
1499 ods << ",paperheight="
1500 << from_ascii(paperheight);
1502 case PAPER_USLETTER:
1503 ods << ",letterpaper";
1506 ods << ",legalpaper";
1508 case PAPER_USEXECUTIVE:
1509 ods << ",executivepaper";
1598 docstring const g_options = trim(ods.str(), ",");
1599 os << "\\usepackage";
1600 if (!g_options.empty())
1601 os << '[' << g_options << ']';
1602 os << "{geometry}\n";
1603 // output this only if use_geometry is true
1605 os << "\\geometry{verbose";
1606 if (!topmargin.empty())
1607 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1608 if (!bottommargin.empty())
1609 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1610 if (!leftmargin.empty())
1611 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1612 if (!rightmargin.empty())
1613 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1614 if (!headheight.empty())
1615 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1616 if (!headsep.empty())
1617 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1618 if (!footskip.empty())
1619 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1620 if (!columnsep.empty())
1621 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1624 } else if (orientation == ORIENTATION_LANDSCAPE
1625 || papersize != PAPER_DEFAULT) {
1626 features.require("papersize");
1629 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1630 if (pagestyle == "fancy")
1631 os << "\\usepackage{fancyhdr}\n";
1632 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1635 // only output when the background color is not default
1636 if (isbackgroundcolor == true) {
1637 // only require color here, the background color will be defined
1638 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1640 features.require("color");
1641 features.require("pagecolor");
1644 // only output when the font color is not default
1645 if (isfontcolor == true) {
1646 // only require color here, the font color will be defined
1647 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1649 features.require("color");
1650 features.require("fontcolor");
1653 // Only if class has a ToC hierarchy
1654 if (tclass.hasTocLevels()) {
1655 if (secnumdepth != tclass.secnumdepth()) {
1656 os << "\\setcounter{secnumdepth}{"
1660 if (tocdepth != tclass.tocdepth()) {
1661 os << "\\setcounter{tocdepth}{"
1667 if (paragraph_separation) {
1668 // when skip separation
1669 switch (getDefSkip().kind()) {
1670 case VSpace::SMALLSKIP:
1671 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1673 case VSpace::MEDSKIP:
1674 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1676 case VSpace::BIGSKIP:
1677 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1679 case VSpace::LENGTH:
1680 os << "\\setlength{\\parskip}{"
1681 << from_utf8(getDefSkip().length().asLatexString())
1684 default: // should never happen // Then delete it.
1685 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1688 os << "\\setlength{\\parindent}{0pt}\n";
1690 // when separation by indentation
1691 // only output something when a width is given
1692 if (getIndentation().asLyXCommand() != "default") {
1693 os << "\\setlength{\\parindent}{"
1694 << from_utf8(getIndentation().asLatexCommand())
1699 // Now insert the LyX specific LaTeX commands...
1700 docstring lyxpreamble;
1701 features.resolveAlternatives();
1704 if (!output_sync_macro.empty())
1705 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1706 else if (features.runparams().flavor == OutputParams::LATEX)
1707 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1708 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1709 lyxpreamble += "\\synctex=-1\n";
1712 // due to interferences with babel and hyperref, the color package has to
1713 // be loaded (when it is not already loaded) before babel when hyperref
1714 // is used with the colorlinks option, see
1715 // http://www.lyx.org/trac/ticket/5291
1716 // we decided therefore to load color always before babel, see
1717 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1718 lyxpreamble += from_ascii(features.getColorOptions());
1720 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1722 && (features.isRequired("jurabib")
1723 || features.isRequired("hyperref")
1724 || features.isRequired("vietnamese")
1725 || features.isRequired("japanese"))) {
1727 lyxpreamble += from_utf8(features.getBabelPresettings());
1728 lyxpreamble += from_utf8(babelCall(language_options.str(),
1729 features.needBabelLangOptions())) + '\n';
1730 lyxpreamble += from_utf8(features.getBabelPostsettings());
1733 // The optional packages;
1734 lyxpreamble += from_ascii(features.getPackages());
1736 // Additional Indices
1737 if (features.isRequired("splitidx")) {
1738 IndicesList::const_iterator iit = indiceslist().begin();
1739 IndicesList::const_iterator iend = indiceslist().end();
1740 for (; iit != iend; ++iit) {
1741 lyxpreamble += "\\newindex[";
1742 lyxpreamble += iit->index();
1743 lyxpreamble += "]{";
1744 lyxpreamble += iit->shortcut();
1745 lyxpreamble += "}\n";
1750 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1753 // * Hyperref manual: "Make sure it comes last of your loaded
1754 // packages, to give it a fighting chance of not being over-written,
1755 // since its job is to redefine many LaTeX commands."
1756 // * Email from Heiko Oberdiek: "It is usually better to load babel
1757 // before hyperref. Then hyperref has a chance to detect babel.
1758 // * Has to be loaded before the "LyX specific LaTeX commands" to
1759 // avoid errors with algorithm floats.
1760 // use hyperref explicitly if it is required
1761 if (features.isRequired("hyperref")) {
1762 // pass what we have to stream here, since we need
1763 // to access the stream itself in PDFOptions.
1766 OutputParams tmp_params = features.runparams();
1767 pdfoptions().writeLaTeX(tmp_params, os,
1768 documentClass().provides("hyperref"));
1769 // set back for the rest
1770 lyxpreamble.clear();
1771 // correctly break URLs with hyperref and dvi output
1772 if (features.runparams().flavor == OutputParams::LATEX
1773 && features.isAvailable("breakurl"))
1774 lyxpreamble += "\\usepackage{breakurl}\n";
1775 } else if (features.isRequired("nameref"))
1776 // hyperref loads this automatically
1777 lyxpreamble += "\\usepackage{nameref}\n";
1779 // Will be surrounded by \makeatletter and \makeatother when not empty
1780 docstring atlyxpreamble;
1782 // Some macros LyX will need
1783 docstring tmppreamble(features.getMacros());
1785 if (!tmppreamble.empty())
1786 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1787 "LyX specific LaTeX commands.\n"
1788 + tmppreamble + '\n';
1790 // the text class specific preamble
1791 tmppreamble = features.getTClassPreamble();
1792 if (!tmppreamble.empty())
1793 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1794 "Textclass specific LaTeX commands.\n"
1795 + tmppreamble + '\n';
1797 // suppress date if selected
1798 // use \@ifundefined because we cannot be sure that every document class
1799 // has a \date command
1801 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1803 /* the user-defined preamble */
1804 if (!containsOnly(preamble, " \n\t"))
1806 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1807 "User specified LaTeX commands.\n"
1808 + from_utf8(preamble) + '\n';
1810 // subfig loads internally the LaTeX package "caption". As
1811 // caption is a very popular package, users will load it in
1812 // the preamble. Therefore we must load subfig behind the
1813 // user-defined preamble and check if the caption package was
1814 // loaded or not. For the case that caption is loaded before
1815 // subfig, there is the subfig option "caption=false". This
1816 // option also works when a koma-script class is used and
1817 // koma's own caption commands are used instead of caption. We
1818 // use \PassOptionsToPackage here because the user could have
1819 // already loaded subfig in the preamble.
1820 if (features.isRequired("subfig")) {
1821 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1822 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1823 "\\usepackage{subfig}\n";
1826 // Itemize bullet settings need to be last in case the user
1827 // defines their own bullets that use a package included
1828 // in the user-defined preamble -- ARRae
1829 // Actually it has to be done much later than that
1830 // since some packages like frenchb make modifications
1831 // at \begin{document} time -- JMarc
1832 docstring bullets_def;
1833 for (int i = 0; i < 4; ++i) {
1834 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1835 if (bullets_def.empty())
1836 bullets_def += "\\AtBeginDocument{\n";
1837 bullets_def += " \\def\\labelitemi";
1839 // `i' is one less than the item to modify
1846 bullets_def += "ii";
1852 bullets_def += '{' +
1853 user_defined_bullet(i).getText()
1858 if (!bullets_def.empty())
1859 atlyxpreamble += bullets_def + "}\n\n";
1861 if (!atlyxpreamble.empty())
1862 lyxpreamble += "\n\\makeatletter\n"
1863 + atlyxpreamble + "\\makeatother\n\n";
1865 // We try to load babel late, in case it interferes with other packages.
1866 // Jurabib and Hyperref have to be called after babel, though.
1867 if (use_babel && !features.isRequired("jurabib")
1868 && !features.isRequired("hyperref")
1869 && !features.isRequired("vietnamese")
1870 && !features.isRequired("japanese")) {
1872 lyxpreamble += from_utf8(features.getBabelPresettings());
1873 lyxpreamble += from_utf8(babelCall(language_options.str(),
1874 features.needBabelLangOptions())) + '\n';
1875 lyxpreamble += from_utf8(features.getBabelPostsettings());
1878 // xunicode needs to be loaded at least after amsmath, amssymb,
1879 // esint and the other packages that provide special glyphs
1880 if (features.runparams().flavor == OutputParams::XETEX)
1881 lyxpreamble += "\\usepackage{xunicode}\n";
1883 // Polyglossia must be loaded last
1884 if (use_polyglossia) {
1886 lyxpreamble += "\\usepackage{polyglossia}\n";
1887 // set the main language
1888 lyxpreamble += "\\setdefaultlanguage";
1889 if (!language->polyglossiaOpts().empty())
1890 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
1891 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
1892 // now setup the other languages
1893 std::map<std::string, std::string> const polylangs =
1894 features.getPolyglossiaLanguages();
1895 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
1896 mit != polylangs.end() ; ++mit) {
1897 lyxpreamble += "\\setotherlanguage";
1898 if (!mit->second.empty())
1899 lyxpreamble += "[" + from_ascii(mit->second) + "]";
1900 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
1904 docstring const i18npreamble =
1905 features.getTClassI18nPreamble(use_babel, use_polyglossia);
1906 if (!i18npreamble.empty())
1907 lyxpreamble += i18npreamble + '\n';
1915 void BufferParams::useClassDefaults()
1917 DocumentClass const & tclass = documentClass();
1919 sides = tclass.sides();
1920 columns = tclass.columns();
1921 pagestyle = tclass.pagestyle();
1922 use_default_options = true;
1923 // Only if class has a ToC hierarchy
1924 if (tclass.hasTocLevels()) {
1925 secnumdepth = tclass.secnumdepth();
1926 tocdepth = tclass.tocdepth();
1931 bool BufferParams::hasClassDefaults() const
1933 DocumentClass const & tclass = documentClass();
1935 return sides == tclass.sides()
1936 && columns == tclass.columns()
1937 && pagestyle == tclass.pagestyle()
1938 && use_default_options
1939 && secnumdepth == tclass.secnumdepth()
1940 && tocdepth == tclass.tocdepth();
1944 DocumentClass const & BufferParams::documentClass() const
1950 DocumentClass const * BufferParams::documentClassPtr() const
1956 void BufferParams::setDocumentClass(DocumentClass const * const tc)
1958 // evil, but this function is evil
1959 doc_class_ = const_cast<DocumentClass *>(tc);
1963 bool BufferParams::setBaseClass(string const & classname)
1965 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1966 LayoutFileList & bcl = LayoutFileList::get();
1967 if (!bcl.haveClass(classname)) {
1969 bformat(_("The layout file:\n"
1971 "could not be found. A default textclass with default\n"
1972 "layouts will be used. LyX will not be able to produce\n"
1974 from_utf8(classname));
1975 frontend::Alert::error(_("Document class not found"), s);
1976 bcl.addEmptyClass(classname);
1979 bool const success = bcl[classname].load();
1982 bformat(_("Due to some error in it, the layout file:\n"
1984 "could not be loaded. A default textclass with default\n"
1985 "layouts will be used. LyX will not be able to produce\n"
1987 from_utf8(classname));
1988 frontend::Alert::error(_("Could not load class"), s);
1989 bcl.addEmptyClass(classname);
1992 pimpl_->baseClass_ = classname;
1993 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
1998 LayoutFile const * BufferParams::baseClass() const
2000 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2001 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2007 LayoutFileIndex const & BufferParams::baseClassID() const
2009 return pimpl_->baseClass_;
2013 void BufferParams::makeDocumentClass()
2018 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layout_modules_));
2020 if (!local_layout.empty()) {
2021 TextClass::ReturnValues success =
2022 doc_class_->read(local_layout, TextClass::MODULE);
2023 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2024 docstring const msg = _("Error reading internal layout information");
2025 frontend::Alert::warning(_("Read Error"), msg);
2031 bool BufferParams::moduleCanBeAdded(string const & modName) const
2033 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2037 bool BufferParams::addLayoutModule(string const & modName)
2039 LayoutModuleList::const_iterator it = layout_modules_.begin();
2040 LayoutModuleList::const_iterator end = layout_modules_.end();
2041 for (; it != end; it++)
2044 layout_modules_.push_back(modName);
2049 string BufferParams::bufferFormat() const
2051 string format = documentClass().outputFormat();
2052 if (format == "latex") {
2055 if (encoding().package() == Encoding::japanese)
2062 bool BufferParams::isExportable(string const & format) const
2064 vector<string> backs = backends();
2065 for (vector<string>::const_iterator it = backs.begin();
2066 it != backs.end(); ++it)
2067 if (theConverters().isReachable(*it, format))
2074 bool formatSorter(Format const * lhs, Format const * rhs) {
2075 return _(lhs->prettyname()) < _(rhs->prettyname());
2080 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2082 vector<string> const backs = backends();
2083 set<string> excludes;
2084 if (useNonTeXFonts) {
2085 excludes.insert("latex");
2086 excludes.insert("pdflatex");
2088 vector<Format const *> result =
2089 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2090 for (vector<string>::const_iterator it = backs.begin() + 1;
2091 it != backs.end(); ++it) {
2092 vector<Format const *> r =
2093 theConverters().getReachable(*it, only_viewable, false, excludes);
2094 result.insert(result.end(), r.begin(), r.end());
2096 sort(result.begin(), result.end(), formatSorter);
2101 bool BufferParams::isExportableFormat(string const & format) const
2103 typedef vector<Format const *> Formats;
2105 formats = exportableFormats(true);
2106 Formats::const_iterator fit = formats.begin();
2107 Formats::const_iterator end = formats.end();
2108 for (; fit != end ; ++fit) {
2109 if ((*fit)->name() == format)
2116 vector<string> BufferParams::backends() const
2119 v.push_back(bufferFormat());
2120 // FIXME: Don't hardcode format names here, but use a flag
2121 if (v.back() == "latex") {
2122 v.push_back("pdflatex");
2123 v.push_back("luatex");
2124 v.push_back("dviluatex");
2125 v.push_back("xetex");
2126 } else if (v.back() == "xetex") {
2127 v.push_back("luatex");
2128 v.push_back("dviluatex");
2130 v.push_back("xhtml");
2131 v.push_back("text");
2137 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const format) const
2139 string const dformat = (format.empty() || format == "default") ?
2140 getDefaultOutputFormat() : format;
2141 DefaultFlavorCache::const_iterator it =
2142 default_flavors_.find(dformat);
2144 if (it != default_flavors_.end())
2147 OutputParams::FLAVOR result = OutputParams::LATEX;
2149 if (dformat == "xhtml")
2150 result = OutputParams::HTML;
2152 // Try to determine flavor of default output format
2153 vector<string> backs = backends();
2154 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2155 // Get shortest path to format
2156 Graph::EdgePath path;
2157 for (vector<string>::const_iterator it = backs.begin();
2158 it != backs.end(); ++it) {
2159 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2160 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2165 result = theConverters().getFlavor(path);
2168 // cache this flavor
2169 default_flavors_[dformat] = result;
2174 string BufferParams::getDefaultOutputFormat() const
2176 if (!default_output_format.empty()
2177 && default_output_format != "default")
2178 return default_output_format;
2181 || encoding().package() == Encoding::japanese) {
2182 vector<Format const *> const formats = exportableFormats(true);
2183 if (formats.empty())
2185 // return the first we find
2186 return formats.front()->name();
2188 return lyxrc.default_view_format;
2191 Font const BufferParams::getFont() const
2193 FontInfo f = documentClass().defaultfont();
2194 if (fonts_default_family == "rmdefault")
2195 f.setFamily(ROMAN_FAMILY);
2196 else if (fonts_default_family == "sfdefault")
2197 f.setFamily(SANS_FAMILY);
2198 else if (fonts_default_family == "ttdefault")
2199 f.setFamily(TYPEWRITER_FAMILY);
2200 return Font(f, language);
2204 bool BufferParams::isLatex() const
2206 return documentClass().outputType() == LATEX;
2210 bool BufferParams::isLiterate() const
2212 return documentClass().outputType() == LITERATE;
2216 bool BufferParams::isDocBook() const
2218 return documentClass().outputType() == DOCBOOK;
2222 void BufferParams::readPreamble(Lexer & lex)
2224 if (lex.getString() != "\\begin_preamble")
2225 lyxerr << "Error (BufferParams::readPreamble):"
2226 "consistency check failed." << endl;
2228 preamble = lex.getLongString("\\end_preamble");
2232 void BufferParams::readLocalLayout(Lexer & lex)
2234 if (lex.getString() != "\\begin_local_layout")
2235 lyxerr << "Error (BufferParams::readLocalLayout):"
2236 "consistency check failed." << endl;
2238 local_layout = lex.getLongString("\\end_local_layout");
2242 bool BufferParams::setLanguage(string const & lang)
2244 Language const *new_language = languages.getLanguage(lang);
2245 if (!new_language) {
2246 // Language lang was not found
2249 language = new_language;
2254 void BufferParams::readLanguage(Lexer & lex)
2256 if (!lex.next()) return;
2258 string const tmptok = lex.getString();
2260 // check if tmptok is part of tex_babel in tex-defs.h
2261 if (!setLanguage(tmptok)) {
2262 // Language tmptok was not found
2263 language = default_language;
2264 lyxerr << "Warning: Setting language `"
2265 << tmptok << "' to `" << language->lang()
2271 void BufferParams::readGraphicsDriver(Lexer & lex)
2276 string const tmptok = lex.getString();
2277 // check if tmptok is part of tex_graphics in tex_defs.h
2280 string const test = tex_graphics[n++];
2282 if (test == tmptok) {
2283 graphics_driver = tmptok;
2288 "Warning: graphics driver `$$Token' not recognized!\n"
2289 " Setting graphics driver to `default'.\n");
2290 graphics_driver = "default";
2297 void BufferParams::readBullets(Lexer & lex)
2302 int const index = lex.getInteger();
2304 int temp_int = lex.getInteger();
2305 user_defined_bullet(index).setFont(temp_int);
2306 temp_bullet(index).setFont(temp_int);
2308 user_defined_bullet(index).setCharacter(temp_int);
2309 temp_bullet(index).setCharacter(temp_int);
2311 user_defined_bullet(index).setSize(temp_int);
2312 temp_bullet(index).setSize(temp_int);
2316 void BufferParams::readBulletsLaTeX(Lexer & lex)
2318 // The bullet class should be able to read this.
2321 int const index = lex.getInteger();
2323 docstring const temp_str = lex.getDocString();
2325 user_defined_bullet(index).setText(temp_str);
2326 temp_bullet(index).setText(temp_str);
2330 void BufferParams::readModules(Lexer & lex)
2332 if (!lex.eatLine()) {
2333 lyxerr << "Error (BufferParams::readModules):"
2334 "Unexpected end of input." << endl;
2338 string mod = lex.getString();
2339 if (mod == "\\end_modules")
2341 addLayoutModule(mod);
2347 void BufferParams::readRemovedModules(Lexer & lex)
2349 if (!lex.eatLine()) {
2350 lyxerr << "Error (BufferParams::readRemovedModules):"
2351 "Unexpected end of input." << endl;
2355 string mod = lex.getString();
2356 if (mod == "\\end_removed_modules")
2358 removed_modules_.push_back(mod);
2361 // now we want to remove any removed modules that were previously
2362 // added. normally, that will be because default modules were added in
2363 // setBaseClass(), which gets called when \textclass is read at the
2364 // start of the read.
2365 list<string>::const_iterator rit = removed_modules_.begin();
2366 list<string>::const_iterator const ren = removed_modules_.end();
2367 for (; rit != ren; rit++) {
2368 LayoutModuleList::iterator const mit = layout_modules_.begin();
2369 LayoutModuleList::iterator const men = layout_modules_.end();
2370 LayoutModuleList::iterator found = find(mit, men, *rit);
2373 layout_modules_.erase(found);
2378 void BufferParams::readIncludeonly(Lexer & lex)
2380 if (!lex.eatLine()) {
2381 lyxerr << "Error (BufferParams::readIncludeonly):"
2382 "Unexpected end of input." << endl;
2386 string child = lex.getString();
2387 if (child == "\\end_includeonly")
2389 included_children_.push_back(child);
2395 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2397 switch (papersize) {
2399 // could be anything, so don't guess
2401 case PAPER_CUSTOM: {
2402 if (purpose == XDVI && !paperwidth.empty() &&
2403 !paperheight.empty()) {
2404 // heightxwidth<unit>
2405 string first = paperwidth;
2406 string second = paperheight;
2407 if (orientation == ORIENTATION_LANDSCAPE)
2410 return first.erase(first.length() - 2)
2416 // dvips and dvipdfm do not know this
2417 if (purpose == DVIPS || purpose == DVIPDFM)
2421 if (purpose == DVIPS || purpose == DVIPDFM)
2425 if (purpose == DVIPS || purpose == DVIPDFM)
2435 if (purpose == DVIPS || purpose == DVIPDFM)
2439 if (purpose == DVIPS || purpose == DVIPDFM)
2443 if (purpose == DVIPS || purpose == DVIPDFM)
2447 if (purpose == DVIPS || purpose == DVIPDFM)
2451 if (purpose == DVIPS || purpose == DVIPDFM)
2455 // dvipdfm does not know this
2456 if (purpose == DVIPDFM)
2460 if (purpose == DVIPDFM)
2464 if (purpose == DVIPS || purpose == DVIPDFM)
2468 if (purpose == DVIPS || purpose == DVIPDFM)
2472 if (purpose == DVIPS || purpose == DVIPDFM)
2476 if (purpose == DVIPS || purpose == DVIPDFM)
2480 if (purpose == DVIPS || purpose == DVIPDFM)
2484 if (purpose == DVIPS || purpose == DVIPDFM)
2488 if (purpose == DVIPS || purpose == DVIPDFM)
2492 if (purpose == DVIPS || purpose == DVIPDFM)
2496 if (purpose == DVIPS || purpose == DVIPDFM)
2500 if (purpose == DVIPS || purpose == DVIPDFM)
2504 if (purpose == DVIPS || purpose == DVIPDFM)
2508 if (purpose == DVIPS || purpose == DVIPDFM)
2512 if (purpose == DVIPS || purpose == DVIPDFM)
2516 if (purpose == DVIPS || purpose == DVIPDFM)
2520 if (purpose == DVIPS || purpose == DVIPDFM)
2523 case PAPER_USEXECUTIVE:
2524 // dvipdfm does not know this
2525 if (purpose == DVIPDFM)
2530 case PAPER_USLETTER:
2532 if (purpose == XDVI)
2539 string const BufferParams::dvips_options() const
2544 && papersize == PAPER_CUSTOM
2545 && !lyxrc.print_paper_dimension_flag.empty()
2546 && !paperwidth.empty()
2547 && !paperheight.empty()) {
2548 // using a custom papersize
2549 result = lyxrc.print_paper_dimension_flag;
2550 result += ' ' + paperwidth;
2551 result += ',' + paperheight;
2553 string const paper_option = paperSizeName(DVIPS);
2554 if (!paper_option.empty() && (paper_option != "letter" ||
2555 orientation != ORIENTATION_LANDSCAPE)) {
2556 // dvips won't accept -t letter -t landscape.
2557 // In all other cases, include the paper size
2559 result = lyxrc.print_paper_flag;
2560 result += ' ' + paper_option;
2563 if (orientation == ORIENTATION_LANDSCAPE &&
2564 papersize != PAPER_CUSTOM)
2565 result += ' ' + lyxrc.print_landscape_flag;
2570 string const BufferParams::font_encoding() const
2572 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2576 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2578 if (lang_package != "auto" && lang_package != "babel"
2579 && lang_package != "default" && lang_package != "none")
2580 return lang_package;
2581 if (lyxrc.language_package_selection == LyXRC::LP_CUSTOM)
2582 return lyxrc.language_custom_package;
2583 // suppress the babel call if there is no BabelName defined
2584 // for the document language in the lib/languages file and if no
2585 // other languages are used (lang_opts is then empty)
2586 if (lang_opts.empty())
2588 // either a specific language (AsBabelOptions setting in
2589 // lib/languages) or the prefs require the languages to
2590 // be submitted to babel itself (not the class).
2592 return "\\usepackage[" + lang_opts + "]{babel}";
2593 return "\\usepackage{babel}";
2597 docstring BufferParams::getGraphicsDriver(string const & package) const
2601 if (package == "geometry") {
2602 if (graphics_driver == "dvips"
2603 || graphics_driver == "dvipdfm"
2604 || graphics_driver == "pdftex"
2605 || graphics_driver == "vtex")
2606 result = from_ascii(graphics_driver);
2607 else if (graphics_driver == "dvipdfmx")
2608 result = from_ascii("dvipdfm");
2615 void BufferParams::writeEncodingPreamble(otexstream & os,
2616 LaTeXFeatures & features) const
2618 // XeTeX does not need this
2619 if (features.runparams().flavor == OutputParams::XETEX)
2621 // LuaTeX neither, but with tex fonts, we need to load
2622 // the luainputenc package.
2623 if (features.runparams().flavor == OutputParams::LUATEX
2624 || features.runparams().flavor == OutputParams::DVILUATEX) {
2625 if (!useNonTeXFonts && inputenc != "default"
2626 && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc)
2627 || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) {
2628 os << "\\usepackage[utf8]{luainputenc}\n";
2632 if (inputenc == "auto") {
2633 string const doc_encoding =
2634 language->encoding()->latexName();
2635 Encoding::Package const package =
2636 language->encoding()->package();
2638 // Create a list with all the input encodings used
2640 set<string> encodings =
2641 features.getEncodingSet(doc_encoding);
2643 // If the "japanese" package (i.e. pLaTeX) is used,
2644 // inputenc must be omitted.
2645 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2646 if (package == Encoding::japanese)
2647 features.require("japanese");
2649 if ((!encodings.empty() || package == Encoding::inputenc)
2650 && !features.isRequired("japanese")) {
2651 os << "\\usepackage[";
2652 set<string>::const_iterator it = encodings.begin();
2653 set<string>::const_iterator const end = encodings.end();
2655 os << from_ascii(*it);
2658 for (; it != end; ++it)
2659 os << ',' << from_ascii(*it);
2660 if (package == Encoding::inputenc) {
2661 if (!encodings.empty())
2663 os << from_ascii(doc_encoding);
2665 os << "]{inputenc}\n";
2667 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2668 if (language->encoding()->name() == "utf8-cjk"
2669 && LaTeXFeatures::isAvailable("CJKutf8"))
2670 os << "\\usepackage{CJKutf8}\n";
2672 os << "\\usepackage{CJK}\n";
2674 } else if (inputenc != "default") {
2675 switch (encoding().package()) {
2676 case Encoding::none:
2677 case Encoding::japanese:
2679 case Encoding::inputenc:
2680 // do not load inputenc if japanese is used
2681 if (features.isRequired("japanese"))
2683 os << "\\usepackage[" << from_ascii(inputenc)
2687 if (encoding().name() == "utf8-cjk"
2688 && LaTeXFeatures::isAvailable("CJKutf8"))
2689 os << "\\usepackage{CJKutf8}\n";
2691 os << "\\usepackage{CJK}\n";
2696 // The encoding "armscii8" (for Armenian) is only available when
2697 // the package "armtex" is loaded.
2698 if (language->encoding()->latexName() == "armscii8"
2699 || inputenc == "armscii8")
2700 os << "\\usepackage{armtex}\n";
2704 string const BufferParams::parseFontName(string const & name) const
2706 string mangled = name;
2707 size_t const idx = mangled.find('[');
2708 if (idx == string::npos || idx == 0)
2711 return mangled.substr(0, idx - 1);
2715 string const BufferParams::loadFonts(string const & rm,
2716 string const & sf, string const & tt,
2717 bool const & sc, bool const & osf,
2718 int const & sfscale, int const & ttscale,
2719 bool const & use_systemfonts,
2720 LaTeXFeatures & features) const
2722 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2723 several packages have been replaced by others, that might not
2724 be installed on every system. We have to take care for that
2725 (see psnfss.pdf). We try to support all psnfss fonts as well
2726 as the fonts that have become de facto standard in the LaTeX
2727 world (e.g. Latin Modern). We do not support obsolete fonts
2728 (like PSLatex). In general, it should be possible to mix any
2729 rm font with any sf or tt font, respectively. (JSpitzm)
2731 -- separate math fonts.
2734 if (rm == "default" && sf == "default" && tt == "default")
2740 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
2741 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
2742 * Mapping=tex-text option assures TeX ligatures (such as "--")
2743 * are resolved. Note that tt does not use these ligatures.
2745 * -- add more GUI options?
2746 * -- add more fonts (fonts for other scripts)
2747 * -- if there's a way to find out if a font really supports
2748 * OldStyle, enable/disable the widget accordingly.
2750 if (use_systemfonts && features.isAvailable("fontspec")) {
2751 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
2752 // However, until v.2 (2010/07/11) fontspec only knew
2753 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
2754 // was introduced for both XeTeX and LuaTeX (LuaTeX
2755 // didn't understand "Mapping=tex-text", while XeTeX
2756 // understood both. With most recent versions, both
2757 // variants are understood by both engines. However,
2758 // we want to provide support for at least TeXLive 2009
2759 // (for XeTeX; LuaTeX is only supported as of v.2)
2760 string const texmapping =
2761 (features.runparams().flavor == OutputParams::XETEX) ?
2762 "Mapping=tex-text" : "Ligatures=TeX";
2763 if (rm != "default") {
2764 os << "\\setmainfont[" << texmapping;
2766 os << ",Numbers=OldStyle";
2767 os << "]{" << parseFontName(rm) << "}\n";
2769 if (sf != "default") {
2770 string const sans = parseFontName(sf);
2772 os << "\\setsansfont[Scale="
2773 << float(sfscale) / 100
2774 << "," << texmapping << "]{"
2777 os << "\\setsansfont[" << texmapping << "]{"
2780 if (tt != "default") {
2781 string const mono = parseFontName(tt);
2783 os << "\\setmonofont[Scale="
2784 << float(ttscale) / 100
2788 os << "\\setmonofont{"
2795 // Computer Modern (must be explicitly selectable -- there might be classes
2796 // that define a different default font!
2798 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2799 // osf for Computer Modern needs eco.sty
2801 os << "\\usepackage{eco}\n";
2803 // Latin Modern Roman
2804 else if (rm == "lmodern")
2805 os << "\\usepackage{lmodern}\n";
2807 else if (rm == "ae") {
2808 // not needed when using OT1 font encoding.
2809 if (font_encoding() != "default")
2810 os << "\\usepackage{ae,aecompl}\n";
2813 else if (rm == "times") {
2814 // try to load the best available package
2815 if (LaTeXFeatures::isAvailable("mathptmx"))
2816 os << "\\usepackage{mathptmx}\n";
2817 else if (LaTeXFeatures::isAvailable("mathptm"))
2818 os << "\\usepackage{mathptm}\n";
2820 os << "\\usepackage{times}\n";
2823 else if (rm == "palatino") {
2824 // try to load the best available package
2825 if (LaTeXFeatures::isAvailable("mathpazo")) {
2826 os << "\\usepackage";
2832 // "osf" includes "sc"!
2836 os << "{mathpazo}\n";
2838 else if (LaTeXFeatures::isAvailable("mathpple"))
2839 os << "\\usepackage{mathpple}\n";
2841 os << "\\usepackage{palatino}\n";
2844 else if (rm == "utopia") {
2845 // fourier supersedes utopia.sty, but does
2846 // not work with OT1 encoding.
2847 if (LaTeXFeatures::isAvailable("fourier")
2848 && font_encoding() != "default") {
2849 os << "\\usepackage";
2860 os << "{fourier}\n";
2863 os << "\\usepackage{utopia}\n";
2865 // Bera (complete fontset)
2866 else if (rm == "bera" && sf == "default" && tt == "default")
2867 os << "\\usepackage{bera}\n";
2869 else if (rm != "default")
2870 os << "\\usepackage" << "{" << rm << "}\n";
2873 // Helvetica, Bera Sans
2874 if (sf == "helvet" || sf == "berasans") {
2876 os << "\\usepackage[scaled=" << float(sfscale) / 100
2877 << "]{" << sf << "}\n";
2879 os << "\\usepackage{" << sf << "}\n";
2882 else if (sf == "avant")
2883 os << "\\usepackage{" << sf << "}\n";
2884 // Computer Modern, Latin Modern, CM Bright
2885 else if (sf != "default")
2886 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2888 // monospaced/typewriter
2889 // Courier, LuxiMono
2890 if (tt == "luximono" || tt == "beramono") {
2892 os << "\\usepackage[scaled=" << float(ttscale) / 100
2893 << "]{" << tt << "}\n";
2895 os << "\\usepackage{" << tt << "}\n";
2898 else if (tt == "courier" )
2899 os << "\\usepackage{" << tt << "}\n";
2900 // Computer Modern, Latin Modern, CM Bright
2901 else if (tt != "default")
2902 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2908 Encoding const & BufferParams::encoding() const
2910 // FIXME: actually, we should check for the flavor
2911 // or runparams.isFullyUnicode() here:
2912 // This check will not work with XeTeX/LuaTeX and tex fonts.
2913 // Thus we have to reset the encoding in Buffer::makeLaTeXFile.
2915 return *(encodings.fromLaTeXName("utf8-plain"));
2916 if (inputenc == "auto" || inputenc == "default")
2917 return *language->encoding();
2918 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2921 LYXERR0("Unknown inputenc value `" << inputenc
2922 << "'. Using `auto' instead.");
2923 return *language->encoding();
2927 CiteEngine BufferParams::citeEngine() const
2929 // FIXME the class should provide the numerical/
2930 // authoryear choice
2931 if (documentClass().provides("natbib")
2932 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2933 return ENGINE_NATBIB_AUTHORYEAR;
2934 return cite_engine_;
2938 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2940 cite_engine_ = cite_engine;