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 use_amsmath = package_auto;
365 use_esint = package_auto;
366 use_mhchem = package_auto;
367 use_mathdots = package_auto;
368 use_undertilde = package_auto;
369 cite_engine_ = ENGINE_BASIC;
370 use_bibtopic = false;
372 trackChanges = false;
373 outputChanges = false;
374 use_default_options = true;
375 maintain_unincluded_children = false;
378 language = default_language;
380 fonts_roman = "default";
381 fonts_sans = "default";
382 fonts_typewriter = "default";
383 fonts_default_family = "default";
384 useNonTeXFonts = false;
385 fonts_expert_sc = false;
386 fonts_old_figures = false;
387 fonts_sans_scale = 100;
388 fonts_typewriter_scale = 100;
390 lang_package = "default";
391 graphics_driver = "default";
392 default_output_format = "default";
393 bibtex_command = "default";
394 index_command = "default";
397 listings_params = string();
398 pagestyle = "default";
399 suppress_date = false;
400 justification = true;
401 // no color is the default (white)
402 backgroundcolor = lyx::rgbFromHexName("#ffffff");
403 isbackgroundcolor = false;
404 // no color is the default (black)
405 fontcolor = lyx::rgbFromHexName("#000000");
407 // light gray is the default font color for greyed-out notes
408 notefontcolor = lyx::rgbFromHexName("#cccccc");
409 boxbgcolor = lyx::rgbFromHexName("#ff0000");
410 compressed = lyxrc.save_compressed;
411 for (int iter = 0; iter < 4; ++iter) {
412 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
413 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
416 indiceslist().addDefault(B_("Index"));
417 html_be_strict = false;
418 html_math_output = MathML;
419 html_math_img_scale = 1.0;
420 html_css_as_file = false;
427 docstring BufferParams::B_(string const & l10n) const
429 LASSERT(language, /**/);
430 return getMessages(language->code()).get(l10n);
434 AuthorList & BufferParams::authors()
436 return pimpl_->authorlist;
440 AuthorList const & BufferParams::authors() const
442 return pimpl_->authorlist;
446 BranchList & BufferParams::branchlist()
448 return pimpl_->branchlist;
452 BranchList const & BufferParams::branchlist() const
454 return pimpl_->branchlist;
458 IndicesList & BufferParams::indiceslist()
460 return pimpl_->indiceslist;
464 IndicesList const & BufferParams::indiceslist() const
466 return pimpl_->indiceslist;
470 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
472 LASSERT(index < 4, /**/);
473 return pimpl_->temp_bullets[index];
477 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
479 LASSERT(index < 4, /**/);
480 return pimpl_->temp_bullets[index];
484 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
486 LASSERT(index < 4, /**/);
487 return pimpl_->user_defined_bullets[index];
491 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
493 LASSERT(index < 4, /**/);
494 return pimpl_->user_defined_bullets[index];
498 Spacing & BufferParams::spacing()
500 return pimpl_->spacing;
504 Spacing const & BufferParams::spacing() const
506 return pimpl_->spacing;
510 PDFOptions & BufferParams::pdfoptions()
512 return pimpl_->pdfoptions;
516 PDFOptions const & BufferParams::pdfoptions() const
518 return pimpl_->pdfoptions;
522 HSpace const & BufferParams::getIndentation() const
524 return pimpl_->indentation;
528 void BufferParams::setIndentation(HSpace const & indent)
530 pimpl_->indentation = indent;
534 VSpace const & BufferParams::getDefSkip() const
536 return pimpl_->defskip;
540 void BufferParams::setDefSkip(VSpace const & vs)
542 // DEFSKIP will cause an infinite loop
543 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
544 pimpl_->defskip = vs;
548 string BufferParams::readToken(Lexer & lex, string const & token,
549 FileName const & filepath)
551 if (token == "\\textclass") {
553 string const classname = lex.getString();
554 // if there exists a local layout file, ignore the system one
555 // NOTE: in this case, the textclass (.cls file) is assumed to
558 LayoutFileList & bcl = LayoutFileList::get();
559 if (tcp.empty() && !filepath.empty())
560 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
564 setBaseClass(classname);
565 // We assume that a tex class exists for local or unknown
566 // layouts so this warning, will only be given for system layouts.
567 if (!baseClass()->isTeXClassAvailable()) {
568 docstring const desc =
569 translateIfPossible(from_utf8(baseClass()->description()));
570 docstring const prereqs =
571 from_utf8(baseClass()->prerequisites());
572 docstring const msg =
573 bformat(_("The selected document class\n"
575 "requires external files that are not available.\n"
576 "The document class can still be used, but the\n"
577 "document cannot be compiled until the following\n"
578 "prerequisites are installed:\n"
580 "See section 3.1.2.2 (Class Availability) of the\n"
581 "User's Guide for more information."), desc, prereqs);
582 frontend::Alert::warning(_("Document class not available"),
585 } else if (token == "\\begin_preamble") {
587 } else if (token == "\\begin_local_layout") {
588 readLocalLayout(lex);
589 } else if (token == "\\begin_modules") {
591 } else if (token == "\\begin_removed_modules") {
592 readRemovedModules(lex);
593 } else if (token == "\\begin_includeonly") {
594 readIncludeonly(lex);
595 } else if (token == "\\maintain_unincluded_children") {
596 lex >> maintain_unincluded_children;
597 } else if (token == "\\options") {
599 options = lex.getString();
600 } else if (token == "\\use_default_options") {
601 lex >> use_default_options;
602 } else if (token == "\\master") {
604 master = lex.getString();
605 } else if (token == "\\suppress_date") {
606 lex >> suppress_date;
607 } else if (token == "\\justification") {
608 lex >> justification;
609 } else if (token == "\\language") {
611 } else if (token == "\\language_package") {
613 lang_package = lex.getString();
614 } else if (token == "\\inputencoding") {
616 } else if (token == "\\graphics") {
617 readGraphicsDriver(lex);
618 } else if (token == "\\default_output_format") {
619 lex >> default_output_format;
620 } else if (token == "\\bibtex_command") {
622 bibtex_command = lex.getString();
623 } else if (token == "\\index_command") {
625 index_command = lex.getString();
626 } else if (token == "\\fontencoding") {
628 fontenc = lex.getString();
629 } else if (token == "\\font_roman") {
631 fonts_roman = lex.getString();
632 } else if (token == "\\font_sans") {
634 fonts_sans = lex.getString();
635 } else if (token == "\\font_typewriter") {
637 fonts_typewriter = lex.getString();
638 } else if (token == "\\font_default_family") {
639 lex >> fonts_default_family;
640 } else if (token == "\\use_non_tex_fonts") {
641 lex >> useNonTeXFonts;
642 } else if (token == "\\font_sc") {
643 lex >> fonts_expert_sc;
644 } else if (token == "\\font_osf") {
645 lex >> fonts_old_figures;
646 } else if (token == "\\font_sf_scale") {
647 lex >> fonts_sans_scale;
648 } else if (token == "\\font_tt_scale") {
649 lex >> fonts_typewriter_scale;
650 } else if (token == "\\font_cjk") {
652 } else if (token == "\\paragraph_separation") {
655 paragraph_separation = parseptranslator().find(parsep);
656 } else if (token == "\\paragraph_indentation") {
658 string indentation = lex.getString();
659 pimpl_->indentation = HSpace(indentation);
660 } else if (token == "\\defskip") {
662 string const defskip = lex.getString();
663 pimpl_->defskip = VSpace(defskip);
664 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
666 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
667 } else if (token == "\\quotes_language") {
670 quotes_language = quoteslangtranslator().find(quotes_lang);
671 } else if (token == "\\papersize") {
674 papersize = papersizetranslator().find(ppsize);
675 } else if (token == "\\use_geometry") {
677 } else if (token == "\\use_amsmath") {
680 use_amsmath = packagetranslator().find(use_ams);
681 } else if (token == "\\use_esint") {
684 use_esint = packagetranslator().find(useesint);
685 } else if (token == "\\use_mhchem") {
688 use_mhchem = packagetranslator().find(usemhchem);
689 } else if (token == "\\use_mathdots") {
692 use_mathdots = packagetranslator().find(usemathdots);
693 } else if (token == "\\use_undertilde") {
695 lex >> useundertilde;
696 use_undertilde = packagetranslator().find(useundertilde);
697 } else if (token == "\\cite_engine") {
700 cite_engine_ = citeenginetranslator().find(engine);
701 } else if (token == "\\use_bibtopic") {
703 } else if (token == "\\use_indices") {
705 } else if (token == "\\tracking_changes") {
707 } else if (token == "\\output_changes") {
708 lex >> outputChanges;
709 } else if (token == "\\branch") {
711 docstring branch = lex.getDocString();
712 branchlist().add(branch);
715 string const tok = lex.getString();
716 if (tok == "\\end_branch")
718 Branch * branch_ptr = branchlist().find(branch);
719 if (tok == "\\selected") {
722 branch_ptr->setSelected(lex.getInteger());
724 if (tok == "\\filename_suffix") {
727 branch_ptr->setFileNameSuffix(lex.getInteger());
729 if (tok == "\\color") {
731 string color = lex.getString();
733 branch_ptr->setColor(color);
734 // Update also the Color table:
736 color = lcolor.getX11Name(Color_background);
738 lcolor.setColor(to_utf8(branch), color);
741 } else if (token == "\\index") {
743 docstring index = lex.getDocString();
745 indiceslist().add(index);
748 string const tok = lex.getString();
749 if (tok == "\\end_index")
751 Index * index_ptr = indiceslist().find(index);
752 if (tok == "\\shortcut") {
754 shortcut = lex.getDocString();
756 index_ptr->setShortcut(shortcut);
758 if (tok == "\\color") {
760 string color = lex.getString();
762 index_ptr->setColor(color);
763 // Update also the Color table:
765 color = lcolor.getX11Name(Color_background);
767 if (!shortcut.empty())
768 lcolor.setColor(to_utf8(shortcut), color);
771 } else if (token == "\\author") {
773 istringstream ss(lex.getString());
776 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
777 } else if (token == "\\paperorientation") {
780 orientation = paperorientationtranslator().find(orient);
781 } else if (token == "\\backgroundcolor") {
783 backgroundcolor = lyx::rgbFromHexName(lex.getString());
784 isbackgroundcolor = true;
785 } else if (token == "\\fontcolor") {
787 fontcolor = lyx::rgbFromHexName(lex.getString());
789 } else if (token == "\\notefontcolor") {
791 string color = lex.getString();
792 notefontcolor = lyx::rgbFromHexName(color);
793 } else if (token == "\\boxbgcolor") {
795 string color = lex.getString();
796 boxbgcolor = lyx::rgbFromHexName(color);
797 } else if (token == "\\paperwidth") {
799 } else if (token == "\\paperheight") {
801 } else if (token == "\\leftmargin") {
803 } else if (token == "\\topmargin") {
805 } else if (token == "\\rightmargin") {
807 } else if (token == "\\bottommargin") {
809 } else if (token == "\\headheight") {
811 } else if (token == "\\headsep") {
813 } else if (token == "\\footskip") {
815 } else if (token == "\\columnsep") {
817 } else if (token == "\\paperfontsize") {
819 } else if (token == "\\papercolumns") {
821 } else if (token == "\\listings_params") {
824 listings_params = InsetListingsParams(par).params();
825 } else if (token == "\\papersides") {
828 sides = sidestranslator().find(psides);
829 } else if (token == "\\paperpagestyle") {
831 } else if (token == "\\bullet") {
833 } else if (token == "\\bulletLaTeX") {
834 readBulletsLaTeX(lex);
835 } else if (token == "\\secnumdepth") {
837 } else if (token == "\\tocdepth") {
839 } else if (token == "\\spacing") {
843 if (nspacing == "other") {
846 spacing().set(spacetranslator().find(nspacing), tmp_val);
847 } else if (token == "\\float_placement") {
848 lex >> float_placement;
850 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
851 string toktmp = pdfoptions().readToken(lex, token);
852 if (!toktmp.empty()) {
853 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
857 } else if (token == "\\html_math_output") {
860 html_math_output = static_cast<MathOutput>(temp);
861 } else if (token == "\\html_be_strict") {
862 lex >> html_be_strict;
863 } else if (token == "\\html_css_as_file") {
864 lex >> html_css_as_file;
865 } else if (token == "\\html_math_img_scale") {
866 lex >> html_math_img_scale;
867 } else if (token == "\\html_latex_start") {
869 html_latex_start = lex.getString();
870 } else if (token == "\\html_latex_end") {
872 html_latex_end = lex.getString();
873 } else if (token == "\\output_sync") {
875 } else if (token == "\\output_sync_macro") {
876 lex >> output_sync_macro;
877 } else if (token == "\\use_refstyle") {
880 lyxerr << "BufferParams::readToken(): Unknown token: " <<
889 void BufferParams::writeFile(ostream & os) const
891 // The top of the file is written by the buffer.
892 // Prints out the buffer info into the .lyx file given by file
895 os << "\\textclass " << baseClass()->name() << '\n';
898 if (!preamble.empty()) {
899 // remove '\n' from the end of preamble
900 string const tmppreamble = rtrim(preamble, "\n");
901 os << "\\begin_preamble\n"
903 << "\n\\end_preamble\n";
907 if (!options.empty()) {
908 os << "\\options " << options << '\n';
911 // use the class options defined in the layout?
912 os << "\\use_default_options "
913 << convert<string>(use_default_options) << "\n";
915 // the master document
916 if (!master.empty()) {
917 os << "\\master " << master << '\n';
921 if (!removed_modules_.empty()) {
922 os << "\\begin_removed_modules" << '\n';
923 list<string>::const_iterator it = removed_modules_.begin();
924 list<string>::const_iterator en = removed_modules_.end();
925 for (; it != en; it++)
927 os << "\\end_removed_modules" << '\n';
931 if (!layout_modules_.empty()) {
932 os << "\\begin_modules" << '\n';
933 LayoutModuleList::const_iterator it = layout_modules_.begin();
934 LayoutModuleList::const_iterator en = layout_modules_.end();
935 for (; it != en; it++)
937 os << "\\end_modules" << '\n';
941 if (!included_children_.empty()) {
942 os << "\\begin_includeonly" << '\n';
943 list<string>::const_iterator it = included_children_.begin();
944 list<string>::const_iterator en = included_children_.end();
945 for (; it != en; it++)
947 os << "\\end_includeonly" << '\n';
949 os << "\\maintain_unincluded_children "
950 << convert<string>(maintain_unincluded_children) << '\n';
952 // local layout information
953 if (!local_layout.empty()) {
954 // remove '\n' from the end
955 string const tmplocal = rtrim(local_layout, "\n");
956 os << "\\begin_local_layout\n"
958 << "\n\\end_local_layout\n";
961 // then the text parameters
962 if (language != ignore_language)
963 os << "\\language " << language->lang() << '\n';
964 os << "\\language_package " << lang_package
965 << "\n\\inputencoding " << inputenc
966 << "\n\\fontencoding " << fontenc
967 << "\n\\font_roman " << fonts_roman
968 << "\n\\font_sans " << fonts_sans
969 << "\n\\font_typewriter " << fonts_typewriter
970 << "\n\\font_default_family " << fonts_default_family
971 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
972 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
973 << "\n\\font_osf " << convert<string>(fonts_old_figures)
974 << "\n\\font_sf_scale " << fonts_sans_scale
975 << "\n\\font_tt_scale " << fonts_typewriter_scale
977 if (!fonts_cjk.empty()) {
978 os << "\\font_cjk " << fonts_cjk << '\n';
980 os << "\n\\graphics " << graphics_driver << '\n';
981 os << "\\default_output_format " << default_output_format << '\n';
982 os << "\\output_sync " << output_sync << '\n';
983 if (!output_sync_macro.empty())
984 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
985 os << "\\bibtex_command " << bibtex_command << '\n';
986 os << "\\index_command " << index_command << '\n';
988 if (!float_placement.empty()) {
989 os << "\\float_placement " << float_placement << '\n';
991 os << "\\paperfontsize " << fontsize << '\n';
993 spacing().writeFile(os);
994 pdfoptions().writeFile(os);
996 os << "\\papersize " << string_papersize[papersize]
997 << "\n\\use_geometry " << convert<string>(use_geometry)
998 << "\n\\use_amsmath " << use_amsmath
999 << "\n\\use_esint " << use_esint
1000 << "\n\\use_mhchem " << use_mhchem
1001 << "\n\\use_mathdots " << use_mathdots
1002 << "\n\\use_undertilde " << use_undertilde
1003 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
1004 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1005 << "\n\\use_indices " << convert<string>(use_indices)
1006 << "\n\\paperorientation " << string_orientation[orientation]
1007 << "\n\\suppress_date " << convert<string>(suppress_date)
1008 << "\n\\justification " << convert<string>(justification)
1009 << "\n\\use_refstyle " << use_refstyle
1011 if (isbackgroundcolor == true)
1012 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1013 if (isfontcolor == true)
1014 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1015 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1016 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1017 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1018 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1020 BranchList::const_iterator it = branchlist().begin();
1021 BranchList::const_iterator end = branchlist().end();
1022 for (; it != end; ++it) {
1023 os << "\\branch " << to_utf8(it->branch())
1024 << "\n\\selected " << it->isSelected()
1025 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1026 << "\n\\color " << lyx::X11hexname(it->color())
1031 IndicesList::const_iterator iit = indiceslist().begin();
1032 IndicesList::const_iterator iend = indiceslist().end();
1033 for (; iit != iend; ++iit) {
1034 os << "\\index " << to_utf8(iit->index())
1035 << "\n\\shortcut " << to_utf8(iit->shortcut())
1036 << "\n\\color " << lyx::X11hexname(iit->color())
1041 if (!paperwidth.empty())
1042 os << "\\paperwidth "
1043 << VSpace(paperwidth).asLyXCommand() << '\n';
1044 if (!paperheight.empty())
1045 os << "\\paperheight "
1046 << VSpace(paperheight).asLyXCommand() << '\n';
1047 if (!leftmargin.empty())
1048 os << "\\leftmargin "
1049 << VSpace(leftmargin).asLyXCommand() << '\n';
1050 if (!topmargin.empty())
1051 os << "\\topmargin "
1052 << VSpace(topmargin).asLyXCommand() << '\n';
1053 if (!rightmargin.empty())
1054 os << "\\rightmargin "
1055 << VSpace(rightmargin).asLyXCommand() << '\n';
1056 if (!bottommargin.empty())
1057 os << "\\bottommargin "
1058 << VSpace(bottommargin).asLyXCommand() << '\n';
1059 if (!headheight.empty())
1060 os << "\\headheight "
1061 << VSpace(headheight).asLyXCommand() << '\n';
1062 if (!headsep.empty())
1064 << VSpace(headsep).asLyXCommand() << '\n';
1065 if (!footskip.empty())
1067 << VSpace(footskip).asLyXCommand() << '\n';
1068 if (!columnsep.empty())
1069 os << "\\columnsep "
1070 << VSpace(columnsep).asLyXCommand() << '\n';
1071 os << "\\secnumdepth " << secnumdepth
1072 << "\n\\tocdepth " << tocdepth
1073 << "\n\\paragraph_separation "
1074 << string_paragraph_separation[paragraph_separation];
1075 if (!paragraph_separation)
1076 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1078 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1079 os << "\n\\quotes_language "
1080 << string_quotes_language[quotes_language]
1081 << "\n\\papercolumns " << columns
1082 << "\n\\papersides " << sides
1083 << "\n\\paperpagestyle " << pagestyle << '\n';
1084 if (!listings_params.empty())
1085 os << "\\listings_params \"" <<
1086 InsetListingsParams(listings_params).encodedString() << "\"\n";
1087 for (int i = 0; i < 4; ++i) {
1088 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1089 if (user_defined_bullet(i).getFont() != -1) {
1090 os << "\\bullet " << i << " "
1091 << user_defined_bullet(i).getFont() << " "
1092 << user_defined_bullet(i).getCharacter() << " "
1093 << user_defined_bullet(i).getSize() << "\n";
1097 os << "\\bulletLaTeX " << i << " \""
1098 << lyx::to_ascii(user_defined_bullet(i).getText())
1104 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1105 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1106 << "\\html_math_output " << html_math_output << '\n'
1107 << "\\html_css_as_file " << html_css_as_file << '\n'
1108 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1110 if (html_math_img_scale != 1.0)
1111 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1112 if (!html_latex_start.empty())
1113 os << "\\html_latex_start " << html_latex_start << '\n';
1114 if (!html_latex_end.empty())
1115 os << "\\html_latex_end " << html_latex_end << '\n';
1117 os << pimpl_->authorlist;
1121 void BufferParams::validate(LaTeXFeatures & features) const
1123 features.require(documentClass().requires());
1125 if (outputChanges) {
1126 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1127 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1128 LaTeXFeatures::isAvailable("xcolor");
1130 switch (features.runparams().flavor) {
1131 case OutputParams::LATEX:
1132 case OutputParams::DVILUATEX:
1134 features.require("ct-dvipost");
1135 features.require("dvipost");
1136 } else if (xcolorulem) {
1137 features.require("ct-xcolor-ulem");
1138 features.require("ulem");
1139 features.require("xcolor");
1141 features.require("ct-none");
1144 case OutputParams::LUATEX:
1145 case OutputParams::PDFLATEX:
1146 case OutputParams::XETEX:
1148 features.require("ct-xcolor-ulem");
1149 features.require("ulem");
1150 features.require("xcolor");
1151 // improves color handling in PDF output
1152 features.require("pdfcolmk");
1154 features.require("ct-none");
1162 // Floats with 'Here definitely' as default setting.
1163 if (float_placement.find('H') != string::npos)
1164 features.require("float");
1166 // AMS Style is at document level
1167 if (use_amsmath == package_on
1168 || documentClass().provides("amsmath"))
1169 features.require("amsmath");
1170 if (use_esint == package_on)
1171 features.require("esint");
1172 if (use_mhchem == package_on)
1173 features.require("mhchem");
1174 if (use_mathdots == package_on)
1175 features.require("mathdots");
1176 if (use_undertilde == package_on)
1177 features.require("undertilde");
1179 // Document-level line spacing
1180 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1181 features.require("setspace");
1183 // the bullet shapes are buffer level not paragraph level
1184 // so they are tested here
1185 for (int i = 0; i < 4; ++i) {
1186 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1188 int const font = user_defined_bullet(i).getFont();
1190 int const c = user_defined_bullet(i).getCharacter();
1196 features.require("latexsym");
1198 } else if (font == 1) {
1199 features.require("amssymb");
1200 } else if (font >= 2 && font <= 5) {
1201 features.require("pifont");
1205 if (pdfoptions().use_hyperref) {
1206 features.require("hyperref");
1207 // due to interferences with babel and hyperref, the color package has to
1208 // be loaded after hyperref when hyperref is used with the colorlinks
1209 // option, see http://www.lyx.org/trac/ticket/5291
1210 if (pdfoptions().colorlinks)
1211 features.require("color");
1214 if (features.runparams().flavor == OutputParams::XETEX
1216 features.require("polyglossia");
1218 if (language->lang() == "vietnamese")
1219 features.require("vietnamese");
1220 else if (language->lang() == "japanese")
1221 features.require("japanese");
1225 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1226 FileName const & filepath) const
1228 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1229 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1230 // \RequirePackage to do so, rather than the normal \usepackage
1231 // Do not try to load any other package before the document class, unless you
1232 // have a thorough understanding of the LATEX internals and know exactly what you
1234 if (features.mustProvide("fix-cm"))
1235 os << "\\RequirePackage{fix-cm}\n";
1237 os << "\\documentclass";
1239 DocumentClass const & tclass = documentClass();
1241 ostringstream clsoptions; // the document class options.
1243 if (tokenPos(tclass.opt_fontsize(),
1244 '|', fontsize) >= 0) {
1245 // only write if existing in list (and not default)
1246 clsoptions << fontsize << "pt,";
1249 // all paper sizes except of A4, A5, B5 and the US sizes need the
1251 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1252 && papersize != PAPER_USLETTER
1253 && papersize != PAPER_USLEGAL
1254 && papersize != PAPER_USEXECUTIVE
1255 && papersize != PAPER_A4
1256 && papersize != PAPER_A5
1257 && papersize != PAPER_B5;
1259 if (!use_geometry) {
1260 switch (papersize) {
1262 clsoptions << "a4paper,";
1264 case PAPER_USLETTER:
1265 clsoptions << "letterpaper,";
1268 clsoptions << "a5paper,";
1271 clsoptions << "b5paper,";
1273 case PAPER_USEXECUTIVE:
1274 clsoptions << "executivepaper,";
1277 clsoptions << "legalpaper,";
1311 if (sides != tclass.sides()) {
1314 clsoptions << "oneside,";
1317 clsoptions << "twoside,";
1323 if (columns != tclass.columns()) {
1325 clsoptions << "twocolumn,";
1327 clsoptions << "onecolumn,";
1331 && orientation == ORIENTATION_LANDSCAPE)
1332 clsoptions << "landscape,";
1334 // language should be a parameter to \documentclass
1335 if (language->babel() == "hebrew"
1336 && default_language->babel() != "hebrew")
1337 // This seems necessary
1338 features.useLanguage(default_language);
1340 ostringstream language_options;
1341 bool const use_babel = features.useBabel() && !tclass.provides("babel");
1342 bool const use_polyglossia = features.usePolyglossia();
1343 bool const global = lyxrc.language_global_options;
1344 if (use_babel || (use_polyglossia && global)) {
1345 language_options << features.getLanguages();
1346 if (!language->babel().empty()) {
1347 if (!language_options.str().empty())
1348 language_options << ',';
1349 language_options << language->babel();
1351 if (global && !features.needBabelLangOptions())
1352 clsoptions << language_options.str() << ',';
1355 // the predefined options from the layout
1356 if (use_default_options && !tclass.options().empty())
1357 clsoptions << tclass.options() << ',';
1359 // the user-defined options
1360 if (!options.empty()) {
1361 clsoptions << options << ',';
1364 string strOptions(clsoptions.str());
1365 if (!strOptions.empty()) {
1366 strOptions = rtrim(strOptions, ",");
1368 os << '[' << from_utf8(strOptions) << ']';
1371 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1372 // end of \documentclass defs
1374 // if we use fontspec, we have to load the AMS packages here
1375 string const ams = features.loadAMSPackages();
1376 if (useNonTeXFonts && !ams.empty())
1377 os << from_ascii(ams);
1380 os << "\\usepackage{fontspec}\n";
1382 // font selection must be done before loading fontenc.sty
1383 string const fonts =
1384 loadFonts(fonts_roman, fonts_sans, fonts_typewriter,
1385 fonts_expert_sc, fonts_old_figures,
1386 fonts_sans_scale, fonts_typewriter_scale,
1387 useNonTeXFonts, features);
1389 os << from_utf8(fonts);
1391 if (fonts_default_family != "default")
1392 os << "\\renewcommand{\\familydefault}{\\"
1393 << from_ascii(fonts_default_family) << "}\n";
1395 // set font encoding
1396 // for arabic_arabi and farsi we also need to load the LAE and
1398 // XeTeX and LuaTeX (with OS fonts) work without fontenc
1399 if (font_encoding() != "default" && language->lang() != "japanese"
1400 && !useNonTeXFonts && !tclass.provides("fontenc")) {
1401 size_t fars = language_options.str().find("farsi");
1402 size_t arab = language_options.str().find("arabic");
1403 if (language->lang() == "arabic_arabi"
1404 || language->lang() == "farsi" || fars != string::npos
1405 || arab != string::npos) {
1406 os << "\\usepackage[" << from_ascii(font_encoding())
1407 << ",LFE,LAE]{fontenc}\n";
1409 os << "\\usepackage[" << from_ascii(font_encoding())
1414 // handle inputenc etc.
1415 writeEncodingPreamble(os, features);
1418 if (!features.runparams().includeall && !included_children_.empty()) {
1419 os << "\\includeonly{";
1420 list<string>::const_iterator it = included_children_.begin();
1421 list<string>::const_iterator en = included_children_.end();
1423 for (; it != en; ++it) {
1424 string incfile = *it;
1425 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1426 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1428 if (!features.runparams().nice)
1430 // \includeonly doesn't want an extension
1431 incfile = changeExtension(incfile, string());
1432 incfile = support::latex_path(incfile);
1433 if (!incfile.empty()) {
1436 os << from_utf8(incfile);
1443 if (!listings_params.empty() || features.isRequired("listings"))
1444 os << "\\usepackage{listings}\n";
1446 if (!listings_params.empty()) {
1448 // do not test validity because listings_params is
1449 // supposed to be valid
1451 InsetListingsParams(listings_params).separatedParams(true);
1452 // we can't support all packages, but we should load the color package
1453 if (par.find("\\color", 0) != string::npos)
1454 features.require("color");
1455 os << from_utf8(par)
1458 if (!tclass.provides("geometry")
1459 && (use_geometry || nonstandard_papersize)) {
1460 odocstringstream ods;
1461 if (!getGraphicsDriver("geometry").empty())
1462 ods << getGraphicsDriver("geometry");
1463 if (orientation == ORIENTATION_LANDSCAPE)
1464 ods << ",landscape";
1465 switch (papersize) {
1467 if (!paperwidth.empty())
1468 ods << ",paperwidth="
1469 << from_ascii(paperwidth);
1470 if (!paperheight.empty())
1471 ods << ",paperheight="
1472 << from_ascii(paperheight);
1474 case PAPER_USLETTER:
1475 ods << ",letterpaper";
1478 ods << ",legalpaper";
1480 case PAPER_USEXECUTIVE:
1481 ods << ",executivepaper";
1570 docstring const g_options = trim(ods.str(), ",");
1571 os << "\\usepackage";
1572 if (!g_options.empty())
1573 os << '[' << g_options << ']';
1574 os << "{geometry}\n";
1575 // output this only if use_geometry is true
1577 os << "\\geometry{verbose";
1578 if (!topmargin.empty())
1579 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1580 if (!bottommargin.empty())
1581 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1582 if (!leftmargin.empty())
1583 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1584 if (!rightmargin.empty())
1585 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1586 if (!headheight.empty())
1587 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1588 if (!headsep.empty())
1589 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1590 if (!footskip.empty())
1591 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1592 if (!columnsep.empty())
1593 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1596 } else if (orientation == ORIENTATION_LANDSCAPE
1597 || papersize != PAPER_DEFAULT) {
1598 features.require("papersize");
1601 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1602 if (pagestyle == "fancy")
1603 os << "\\usepackage{fancyhdr}\n";
1604 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1607 // only output when the background color is not default
1608 if (isbackgroundcolor == true) {
1609 // only require color here, the background color will be defined
1610 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1612 features.require("color");
1613 features.require("pagecolor");
1616 // only output when the font color is not default
1617 if (isfontcolor == true) {
1618 // only require color here, the font color will be defined
1619 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1621 features.require("color");
1622 features.require("fontcolor");
1625 // Only if class has a ToC hierarchy
1626 if (tclass.hasTocLevels()) {
1627 if (secnumdepth != tclass.secnumdepth()) {
1628 os << "\\setcounter{secnumdepth}{"
1632 if (tocdepth != tclass.tocdepth()) {
1633 os << "\\setcounter{tocdepth}{"
1639 if (paragraph_separation) {
1640 // when skip separation
1641 switch (getDefSkip().kind()) {
1642 case VSpace::SMALLSKIP:
1643 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1645 case VSpace::MEDSKIP:
1646 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1648 case VSpace::BIGSKIP:
1649 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1651 case VSpace::LENGTH:
1652 os << "\\setlength{\\parskip}{"
1653 << from_utf8(getDefSkip().length().asLatexString())
1656 default: // should never happen // Then delete it.
1657 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1660 os << "\\setlength{\\parindent}{0pt}\n";
1662 // when separation by indentation
1663 // only output something when a width is given
1664 if (getIndentation().asLyXCommand() != "default") {
1665 os << "\\setlength{\\parindent}{"
1666 << from_utf8(getIndentation().asLatexCommand())
1671 // Now insert the LyX specific LaTeX commands...
1672 docstring lyxpreamble;
1673 features.resolveAlternatives();
1676 if (!output_sync_macro.empty())
1677 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1678 else if (features.runparams().flavor == OutputParams::LATEX)
1679 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1680 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1681 lyxpreamble += "\\synctex=-1\n";
1684 // due to interferences with babel and hyperref, the color package has to
1685 // be loaded (when it is not already loaded) before babel when hyperref
1686 // is used with the colorlinks option, see
1687 // http://www.lyx.org/trac/ticket/5291
1688 // we decided therefore to load color always before babel, see
1689 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1690 lyxpreamble += from_ascii(features.getColorOptions());
1692 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1694 && (features.isRequired("jurabib")
1695 || features.isRequired("hyperref")
1696 || features.isRequired("vietnamese")
1697 || features.isRequired("japanese"))) {
1699 lyxpreamble += from_utf8(features.getBabelPresettings());
1700 lyxpreamble += from_utf8(babelCall(language_options.str(),
1701 features.needBabelLangOptions())) + '\n';
1702 lyxpreamble += from_utf8(features.getBabelPostsettings());
1705 // The optional packages;
1706 lyxpreamble += from_ascii(features.getPackages());
1708 // Additional Indices
1709 if (features.isRequired("splitidx")) {
1710 IndicesList::const_iterator iit = indiceslist().begin();
1711 IndicesList::const_iterator iend = indiceslist().end();
1712 for (; iit != iend; ++iit) {
1713 lyxpreamble += "\\newindex[";
1714 lyxpreamble += iit->index();
1715 lyxpreamble += "]{";
1716 lyxpreamble += iit->shortcut();
1717 lyxpreamble += "}\n";
1722 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1725 // * Hyperref manual: "Make sure it comes last of your loaded
1726 // packages, to give it a fighting chance of not being over-written,
1727 // since its job is to redefine many LaTeX commands."
1728 // * Email from Heiko Oberdiek: "It is usually better to load babel
1729 // before hyperref. Then hyperref has a chance to detect babel.
1730 // * Has to be loaded before the "LyX specific LaTeX commands" to
1731 // avoid errors with algorithm floats.
1732 // use hyperref explicitly if it is required
1733 if (features.isRequired("hyperref")) {
1734 // pass what we have to stream here, since we need
1735 // to access the stream itself in PDFOptions.
1738 OutputParams tmp_params = features.runparams();
1739 pdfoptions().writeLaTeX(tmp_params, os,
1740 documentClass().provides("hyperref"));
1741 // set back for the rest
1742 lyxpreamble.clear();
1743 // correctly break URLs with hyperref and dvi output
1744 if (features.runparams().flavor == OutputParams::LATEX
1745 && features.isAvailable("breakurl"))
1746 lyxpreamble += "\\usepackage{breakurl}\n";
1747 } else if (features.isRequired("nameref"))
1748 // hyperref loads this automatically
1749 lyxpreamble += "\\usepackage{nameref}\n";
1751 // Will be surrounded by \makeatletter and \makeatother when not empty
1752 docstring atlyxpreamble;
1754 // Some macros LyX will need
1755 docstring tmppreamble(features.getMacros());
1757 if (!tmppreamble.empty())
1758 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1759 "LyX specific LaTeX commands.\n"
1760 + tmppreamble + '\n';
1762 // the text class specific preamble
1763 tmppreamble = features.getTClassPreamble();
1764 if (!tmppreamble.empty())
1765 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1766 "Textclass specific LaTeX commands.\n"
1767 + tmppreamble + '\n';
1769 // suppress date if selected
1770 // use \@ifundefined because we cannot be sure that every document class
1771 // has a \date command
1773 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1775 /* the user-defined preamble */
1776 if (!containsOnly(preamble, " \n\t"))
1778 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1779 "User specified LaTeX commands.\n"
1780 + from_utf8(preamble) + '\n';
1782 // subfig loads internally the LaTeX package "caption". As
1783 // caption is a very popular package, users will load it in
1784 // the preamble. Therefore we must load subfig behind the
1785 // user-defined preamble and check if the caption package was
1786 // loaded or not. For the case that caption is loaded before
1787 // subfig, there is the subfig option "caption=false". This
1788 // option also works when a koma-script class is used and
1789 // koma's own caption commands are used instead of caption. We
1790 // use \PassOptionsToPackage here because the user could have
1791 // already loaded subfig in the preamble.
1792 if (features.isRequired("subfig")) {
1793 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1794 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1795 "\\usepackage{subfig}\n";
1798 // Itemize bullet settings need to be last in case the user
1799 // defines their own bullets that use a package included
1800 // in the user-defined preamble -- ARRae
1801 // Actually it has to be done much later than that
1802 // since some packages like frenchb make modifications
1803 // at \begin{document} time -- JMarc
1804 docstring bullets_def;
1805 for (int i = 0; i < 4; ++i) {
1806 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1807 if (bullets_def.empty())
1808 bullets_def += "\\AtBeginDocument{\n";
1809 bullets_def += " \\def\\labelitemi";
1811 // `i' is one less than the item to modify
1818 bullets_def += "ii";
1824 bullets_def += '{' +
1825 user_defined_bullet(i).getText()
1830 if (!bullets_def.empty())
1831 atlyxpreamble += bullets_def + "}\n\n";
1833 if (!atlyxpreamble.empty())
1834 lyxpreamble += "\n\\makeatletter\n"
1835 + atlyxpreamble + "\\makeatother\n\n";
1837 // We try to load babel late, in case it interferes with other packages.
1838 // Jurabib and Hyperref have to be called after babel, though.
1839 if (use_babel && !features.isRequired("jurabib")
1840 && !features.isRequired("hyperref")
1841 && !features.isRequired("vietnamese")
1842 && !features.isRequired("japanese")) {
1844 lyxpreamble += from_utf8(features.getBabelPresettings());
1845 lyxpreamble += from_utf8(babelCall(language_options.str(),
1846 features.needBabelLangOptions())) + '\n';
1847 lyxpreamble += from_utf8(features.getBabelPostsettings());
1850 // xunicode needs to be loaded at least after amsmath, amssymb,
1851 // esint and the other packages that provide special glyphs
1852 if (features.runparams().flavor == OutputParams::XETEX)
1853 lyxpreamble += "\\usepackage{xunicode}\n";
1855 // Polyglossia must be loaded last
1856 if (use_polyglossia) {
1858 lyxpreamble += "\\usepackage{polyglossia}\n";
1859 // set the main language
1860 lyxpreamble += "\\setdefaultlanguage";
1861 if (!language->polyglossiaOpts().empty())
1862 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
1863 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
1864 // now setup the other languages
1865 std::map<std::string, std::string> const polylangs =
1866 features.getPolyglossiaLanguages();
1867 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
1868 mit != polylangs.end() ; ++mit) {
1869 lyxpreamble += "\\setotherlanguage";
1870 if (!mit->second.empty())
1871 lyxpreamble += "[" + from_ascii(mit->second) + "]";
1872 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
1876 docstring const i18npreamble =
1877 features.getTClassI18nPreamble(use_babel, use_polyglossia);
1878 if (!i18npreamble.empty())
1879 lyxpreamble += i18npreamble + '\n';
1887 void BufferParams::useClassDefaults()
1889 DocumentClass const & tclass = documentClass();
1891 sides = tclass.sides();
1892 columns = tclass.columns();
1893 pagestyle = tclass.pagestyle();
1894 use_default_options = true;
1895 // Only if class has a ToC hierarchy
1896 if (tclass.hasTocLevels()) {
1897 secnumdepth = tclass.secnumdepth();
1898 tocdepth = tclass.tocdepth();
1903 bool BufferParams::hasClassDefaults() const
1905 DocumentClass const & tclass = documentClass();
1907 return sides == tclass.sides()
1908 && columns == tclass.columns()
1909 && pagestyle == tclass.pagestyle()
1910 && use_default_options
1911 && secnumdepth == tclass.secnumdepth()
1912 && tocdepth == tclass.tocdepth();
1916 DocumentClass const & BufferParams::documentClass() const
1922 DocumentClass const * BufferParams::documentClassPtr() const
1928 void BufferParams::setDocumentClass(DocumentClass const * const tc)
1930 // evil, but this function is evil
1931 doc_class_ = const_cast<DocumentClass *>(tc);
1935 bool BufferParams::setBaseClass(string const & classname)
1937 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1938 LayoutFileList & bcl = LayoutFileList::get();
1939 if (!bcl.haveClass(classname)) {
1941 bformat(_("The layout file:\n"
1943 "could not be found. A default textclass with default\n"
1944 "layouts will be used. LyX will not be able to produce\n"
1946 from_utf8(classname));
1947 frontend::Alert::error(_("Document class not found"), s);
1948 bcl.addEmptyClass(classname);
1951 bool const success = bcl[classname].load();
1954 bformat(_("Due to some error in it, the layout file:\n"
1956 "could not be loaded. A default textclass with default\n"
1957 "layouts will be used. LyX will not be able to produce\n"
1959 from_utf8(classname));
1960 frontend::Alert::error(_("Could not load class"), s);
1961 bcl.addEmptyClass(classname);
1964 pimpl_->baseClass_ = classname;
1965 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
1970 LayoutFile const * BufferParams::baseClass() const
1972 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1973 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1979 LayoutFileIndex const & BufferParams::baseClassID() const
1981 return pimpl_->baseClass_;
1985 void BufferParams::makeDocumentClass()
1990 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layout_modules_));
1992 if (!local_layout.empty()) {
1993 TextClass::ReturnValues success =
1994 doc_class_->read(local_layout, TextClass::MODULE);
1995 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
1996 docstring const msg = _("Error reading internal layout information");
1997 frontend::Alert::warning(_("Read Error"), msg);
2003 bool BufferParams::moduleCanBeAdded(string const & modName) const
2005 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2009 bool BufferParams::addLayoutModule(string const & modName)
2011 LayoutModuleList::const_iterator it = layout_modules_.begin();
2012 LayoutModuleList::const_iterator end = layout_modules_.end();
2013 for (; it != end; it++)
2016 layout_modules_.push_back(modName);
2021 string BufferParams::bufferFormat() const
2023 string format = documentClass().outputFormat();
2024 if (format == "latex") {
2027 if (encoding().package() == Encoding::japanese)
2034 bool BufferParams::isExportable(string const & format) const
2036 vector<string> backs = backends();
2037 for (vector<string>::const_iterator it = backs.begin();
2038 it != backs.end(); ++it)
2039 if (theConverters().isReachable(*it, format))
2046 bool formatSorter(Format const * lhs, Format const * rhs) {
2047 return _(lhs->prettyname()) < _(rhs->prettyname());
2052 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2054 vector<string> const backs = backends();
2055 set<string> excludes;
2056 if (useNonTeXFonts) {
2057 excludes.insert("latex");
2058 excludes.insert("pdflatex");
2060 vector<Format const *> result =
2061 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2062 for (vector<string>::const_iterator it = backs.begin() + 1;
2063 it != backs.end(); ++it) {
2064 vector<Format const *> r =
2065 theConverters().getReachable(*it, only_viewable, false, excludes);
2066 result.insert(result.end(), r.begin(), r.end());
2068 sort(result.begin(), result.end(), formatSorter);
2073 bool BufferParams::isExportableFormat(string const & format) const
2075 typedef vector<Format const *> Formats;
2077 formats = exportableFormats(true);
2078 Formats::const_iterator fit = formats.begin();
2079 Formats::const_iterator end = formats.end();
2080 for (; fit != end ; ++fit) {
2081 if ((*fit)->name() == format)
2088 vector<string> BufferParams::backends() const
2091 v.push_back(bufferFormat());
2092 // FIXME: Don't hardcode format names here, but use a flag
2093 if (v.back() == "latex") {
2094 v.push_back("pdflatex");
2095 v.push_back("luatex");
2096 v.push_back("dviluatex");
2097 v.push_back("xetex");
2098 } else if (v.back() == "xetex") {
2099 v.push_back("luatex");
2100 v.push_back("dviluatex");
2102 v.push_back("xhtml");
2103 v.push_back("text");
2109 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const format) const
2111 string const dformat = (format.empty() || format == "default") ?
2112 getDefaultOutputFormat() : format;
2113 DefaultFlavorCache::const_iterator it =
2114 default_flavors_.find(dformat);
2116 if (it != default_flavors_.end())
2119 OutputParams::FLAVOR result = OutputParams::LATEX;
2121 if (dformat == "xhtml")
2122 result = OutputParams::HTML;
2124 // Try to determine flavor of default output format
2125 vector<string> backs = backends();
2126 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2127 // Get shortest path to format
2128 Graph::EdgePath path;
2129 for (vector<string>::const_iterator it = backs.begin();
2130 it != backs.end(); ++it) {
2131 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2132 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2137 result = theConverters().getFlavor(path);
2140 // cache this flavor
2141 default_flavors_[dformat] = result;
2146 string BufferParams::getDefaultOutputFormat() const
2148 if (!default_output_format.empty()
2149 && default_output_format != "default")
2150 return default_output_format;
2153 || encoding().package() == Encoding::japanese) {
2154 vector<Format const *> const formats = exportableFormats(true);
2155 if (formats.empty())
2157 // return the first we find
2158 return formats.front()->name();
2160 return lyxrc.default_view_format;
2163 Font const BufferParams::getFont() const
2165 FontInfo f = documentClass().defaultfont();
2166 if (fonts_default_family == "rmdefault")
2167 f.setFamily(ROMAN_FAMILY);
2168 else if (fonts_default_family == "sfdefault")
2169 f.setFamily(SANS_FAMILY);
2170 else if (fonts_default_family == "ttdefault")
2171 f.setFamily(TYPEWRITER_FAMILY);
2172 return Font(f, language);
2176 bool BufferParams::isLatex() const
2178 return documentClass().outputType() == LATEX;
2182 bool BufferParams::isLiterate() const
2184 return documentClass().outputType() == LITERATE;
2188 bool BufferParams::isDocBook() const
2190 return documentClass().outputType() == DOCBOOK;
2194 void BufferParams::readPreamble(Lexer & lex)
2196 if (lex.getString() != "\\begin_preamble")
2197 lyxerr << "Error (BufferParams::readPreamble):"
2198 "consistency check failed." << endl;
2200 preamble = lex.getLongString("\\end_preamble");
2204 void BufferParams::readLocalLayout(Lexer & lex)
2206 if (lex.getString() != "\\begin_local_layout")
2207 lyxerr << "Error (BufferParams::readLocalLayout):"
2208 "consistency check failed." << endl;
2210 local_layout = lex.getLongString("\\end_local_layout");
2214 bool BufferParams::setLanguage(string const & lang)
2216 Language const *new_language = languages.getLanguage(lang);
2217 if (!new_language) {
2218 // Language lang was not found
2221 language = new_language;
2226 void BufferParams::readLanguage(Lexer & lex)
2228 if (!lex.next()) return;
2230 string const tmptok = lex.getString();
2232 // check if tmptok is part of tex_babel in tex-defs.h
2233 if (!setLanguage(tmptok)) {
2234 // Language tmptok was not found
2235 language = default_language;
2236 lyxerr << "Warning: Setting language `"
2237 << tmptok << "' to `" << language->lang()
2243 void BufferParams::readGraphicsDriver(Lexer & lex)
2248 string const tmptok = lex.getString();
2249 // check if tmptok is part of tex_graphics in tex_defs.h
2252 string const test = tex_graphics[n++];
2254 if (test == tmptok) {
2255 graphics_driver = tmptok;
2260 "Warning: graphics driver `$$Token' not recognized!\n"
2261 " Setting graphics driver to `default'.\n");
2262 graphics_driver = "default";
2269 void BufferParams::readBullets(Lexer & lex)
2274 int const index = lex.getInteger();
2276 int temp_int = lex.getInteger();
2277 user_defined_bullet(index).setFont(temp_int);
2278 temp_bullet(index).setFont(temp_int);
2280 user_defined_bullet(index).setCharacter(temp_int);
2281 temp_bullet(index).setCharacter(temp_int);
2283 user_defined_bullet(index).setSize(temp_int);
2284 temp_bullet(index).setSize(temp_int);
2288 void BufferParams::readBulletsLaTeX(Lexer & lex)
2290 // The bullet class should be able to read this.
2293 int const index = lex.getInteger();
2295 docstring const temp_str = lex.getDocString();
2297 user_defined_bullet(index).setText(temp_str);
2298 temp_bullet(index).setText(temp_str);
2302 void BufferParams::readModules(Lexer & lex)
2304 if (!lex.eatLine()) {
2305 lyxerr << "Error (BufferParams::readModules):"
2306 "Unexpected end of input." << endl;
2310 string mod = lex.getString();
2311 if (mod == "\\end_modules")
2313 addLayoutModule(mod);
2319 void BufferParams::readRemovedModules(Lexer & lex)
2321 if (!lex.eatLine()) {
2322 lyxerr << "Error (BufferParams::readRemovedModules):"
2323 "Unexpected end of input." << endl;
2327 string mod = lex.getString();
2328 if (mod == "\\end_removed_modules")
2330 removed_modules_.push_back(mod);
2333 // now we want to remove any removed modules that were previously
2334 // added. normally, that will be because default modules were added in
2335 // setBaseClass(), which gets called when \textclass is read at the
2336 // start of the read.
2337 list<string>::const_iterator rit = removed_modules_.begin();
2338 list<string>::const_iterator const ren = removed_modules_.end();
2339 for (; rit != ren; rit++) {
2340 LayoutModuleList::iterator const mit = layout_modules_.begin();
2341 LayoutModuleList::iterator const men = layout_modules_.end();
2342 LayoutModuleList::iterator found = find(mit, men, *rit);
2345 layout_modules_.erase(found);
2350 void BufferParams::readIncludeonly(Lexer & lex)
2352 if (!lex.eatLine()) {
2353 lyxerr << "Error (BufferParams::readIncludeonly):"
2354 "Unexpected end of input." << endl;
2358 string child = lex.getString();
2359 if (child == "\\end_includeonly")
2361 included_children_.push_back(child);
2367 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2369 switch (papersize) {
2371 // could be anything, so don't guess
2373 case PAPER_CUSTOM: {
2374 if (purpose == XDVI && !paperwidth.empty() &&
2375 !paperheight.empty()) {
2376 // heightxwidth<unit>
2377 string first = paperwidth;
2378 string second = paperheight;
2379 if (orientation == ORIENTATION_LANDSCAPE)
2382 return first.erase(first.length() - 2)
2388 // dvips and dvipdfm do not know this
2389 if (purpose == DVIPS || purpose == DVIPDFM)
2393 if (purpose == DVIPS || purpose == DVIPDFM)
2397 if (purpose == DVIPS || purpose == DVIPDFM)
2407 if (purpose == DVIPS || purpose == DVIPDFM)
2411 if (purpose == DVIPS || purpose == DVIPDFM)
2415 if (purpose == DVIPS || purpose == DVIPDFM)
2419 if (purpose == DVIPS || purpose == DVIPDFM)
2423 if (purpose == DVIPS || purpose == DVIPDFM)
2427 // dvipdfm does not know this
2428 if (purpose == DVIPDFM)
2432 if (purpose == DVIPDFM)
2436 if (purpose == DVIPS || purpose == DVIPDFM)
2440 if (purpose == DVIPS || purpose == DVIPDFM)
2444 if (purpose == DVIPS || purpose == DVIPDFM)
2448 if (purpose == DVIPS || purpose == DVIPDFM)
2452 if (purpose == DVIPS || purpose == DVIPDFM)
2456 if (purpose == DVIPS || purpose == DVIPDFM)
2460 if (purpose == DVIPS || 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)
2495 case PAPER_USEXECUTIVE:
2496 // dvipdfm does not know this
2497 if (purpose == DVIPDFM)
2502 case PAPER_USLETTER:
2504 if (purpose == XDVI)
2511 string const BufferParams::dvips_options() const
2516 && papersize == PAPER_CUSTOM
2517 && !lyxrc.print_paper_dimension_flag.empty()
2518 && !paperwidth.empty()
2519 && !paperheight.empty()) {
2520 // using a custom papersize
2521 result = lyxrc.print_paper_dimension_flag;
2522 result += ' ' + paperwidth;
2523 result += ',' + paperheight;
2525 string const paper_option = paperSizeName(DVIPS);
2526 if (!paper_option.empty() && (paper_option != "letter" ||
2527 orientation != ORIENTATION_LANDSCAPE)) {
2528 // dvips won't accept -t letter -t landscape.
2529 // In all other cases, include the paper size
2531 result = lyxrc.print_paper_flag;
2532 result += ' ' + paper_option;
2535 if (orientation == ORIENTATION_LANDSCAPE &&
2536 papersize != PAPER_CUSTOM)
2537 result += ' ' + lyxrc.print_landscape_flag;
2542 string const BufferParams::font_encoding() const
2544 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2548 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2550 if (lang_package != "auto" && lang_package != "babel"
2551 && lang_package != "default" && lang_package != "none")
2552 return lang_package;
2553 if (lyxrc.language_package_selection == LyXRC::LP_CUSTOM)
2554 return lyxrc.language_custom_package;
2555 // suppress the babel call if there is no BabelName defined
2556 // for the document language in the lib/languages file and if no
2557 // other languages are used (lang_opts is then empty)
2558 if (lang_opts.empty())
2560 // either a specific language (AsBabelOptions setting in
2561 // lib/languages) or the prefs require the languages to
2562 // be submitted to babel itself (not the class).
2564 return "\\usepackage[" + lang_opts + "]{babel}";
2565 return "\\usepackage{babel}";
2569 docstring BufferParams::getGraphicsDriver(string const & package) const
2573 if (package == "geometry") {
2574 if (graphics_driver == "dvips"
2575 || graphics_driver == "dvipdfm"
2576 || graphics_driver == "pdftex"
2577 || graphics_driver == "vtex")
2578 result = from_ascii(graphics_driver);
2579 else if (graphics_driver == "dvipdfmx")
2580 result = from_ascii("dvipdfm");
2587 void BufferParams::writeEncodingPreamble(otexstream & os,
2588 LaTeXFeatures & features) const
2590 // XeTeX does not need this
2591 if (features.runparams().flavor == OutputParams::XETEX)
2593 // LuaTeX neither, but with tex fonts, we need to load
2594 // the luainputenc package.
2595 if (features.runparams().flavor == OutputParams::LUATEX
2596 || features.runparams().flavor == OutputParams::DVILUATEX) {
2597 if (!useNonTeXFonts && inputenc != "default"
2598 && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc)
2599 || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) {
2600 os << "\\usepackage[utf8]{luainputenc}\n";
2604 if (inputenc == "auto") {
2605 string const doc_encoding =
2606 language->encoding()->latexName();
2607 Encoding::Package const package =
2608 language->encoding()->package();
2610 // Create a list with all the input encodings used
2612 set<string> encodings =
2613 features.getEncodingSet(doc_encoding);
2615 // If the "japanese" package (i.e. pLaTeX) is used,
2616 // inputenc must be omitted.
2617 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2618 if (package == Encoding::japanese)
2619 features.require("japanese");
2621 if ((!encodings.empty() || package == Encoding::inputenc)
2622 && !features.isRequired("japanese")) {
2623 os << "\\usepackage[";
2624 set<string>::const_iterator it = encodings.begin();
2625 set<string>::const_iterator const end = encodings.end();
2627 os << from_ascii(*it);
2630 for (; it != end; ++it)
2631 os << ',' << from_ascii(*it);
2632 if (package == Encoding::inputenc) {
2633 if (!encodings.empty())
2635 os << from_ascii(doc_encoding);
2637 os << "]{inputenc}\n";
2639 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2640 if (language->encoding()->name() == "utf8-cjk"
2641 && LaTeXFeatures::isAvailable("CJKutf8"))
2642 os << "\\usepackage{CJKutf8}\n";
2644 os << "\\usepackage{CJK}\n";
2646 } else if (inputenc != "default") {
2647 switch (encoding().package()) {
2648 case Encoding::none:
2649 case Encoding::japanese:
2651 case Encoding::inputenc:
2652 // do not load inputenc if japanese is used
2653 if (features.isRequired("japanese"))
2655 os << "\\usepackage[" << from_ascii(inputenc)
2659 if (encoding().name() == "utf8-cjk"
2660 && LaTeXFeatures::isAvailable("CJKutf8"))
2661 os << "\\usepackage{CJKutf8}\n";
2663 os << "\\usepackage{CJK}\n";
2668 // The encoding "armscii8" (for Armenian) is only available when
2669 // the package "armtex" is loaded.
2670 if (language->encoding()->latexName() == "armscii8"
2671 || inputenc == "armscii8")
2672 os << "\\usepackage{armtex}\n";
2676 string const BufferParams::parseFontName(string const & name) const
2678 string mangled = name;
2679 size_t const idx = mangled.find('[');
2680 if (idx == string::npos || idx == 0)
2683 return mangled.substr(0, idx - 1);
2687 string const BufferParams::loadFonts(string const & rm,
2688 string const & sf, string const & tt,
2689 bool const & sc, bool const & osf,
2690 int const & sfscale, int const & ttscale,
2691 bool const & use_systemfonts,
2692 LaTeXFeatures & features) const
2694 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2695 several packages have been replaced by others, that might not
2696 be installed on every system. We have to take care for that
2697 (see psnfss.pdf). We try to support all psnfss fonts as well
2698 as the fonts that have become de facto standard in the LaTeX
2699 world (e.g. Latin Modern). We do not support obsolete fonts
2700 (like PSLatex). In general, it should be possible to mix any
2701 rm font with any sf or tt font, respectively. (JSpitzm)
2703 -- separate math fonts.
2706 if (rm == "default" && sf == "default" && tt == "default")
2712 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
2713 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
2714 * Mapping=tex-text option assures TeX ligatures (such as "--")
2715 * are resolved. Note that tt does not use these ligatures.
2717 * -- add more GUI options?
2718 * -- add more fonts (fonts for other scripts)
2719 * -- if there's a way to find out if a font really supports
2720 * OldStyle, enable/disable the widget accordingly.
2722 if (use_systemfonts && features.isAvailable("fontspec")) {
2723 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
2724 // However, until v.2 (2010/07/11) fontspec only knew
2725 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
2726 // was introduced for both XeTeX and LuaTeX (LuaTeX
2727 // didn't understand "Mapping=tex-text", while XeTeX
2728 // understood both. With most recent versions, both
2729 // variants are understood by both engines. However,
2730 // we want to provide support for at least TeXLive 2009
2731 // (for XeTeX; LuaTeX is only supported as of v.2)
2732 string const texmapping =
2733 (features.runparams().flavor == OutputParams::XETEX) ?
2734 "Mapping=tex-text" : "Ligatures=TeX";
2735 if (rm != "default") {
2736 os << "\\setmainfont[" << texmapping;
2738 os << ",Numbers=OldStyle";
2739 os << "]{" << parseFontName(rm) << "}\n";
2741 if (sf != "default") {
2742 string const sans = parseFontName(sf);
2744 os << "\\setsansfont[Scale="
2745 << float(sfscale) / 100
2746 << "," << texmapping << "]{"
2749 os << "\\setsansfont[" << texmapping << "]{"
2752 if (tt != "default") {
2753 string const mono = parseFontName(tt);
2755 os << "\\setmonofont[Scale="
2756 << float(ttscale) / 100
2760 os << "\\setmonofont{"
2767 // Computer Modern (must be explicitly selectable -- there might be classes
2768 // that define a different default font!
2770 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2771 // osf for Computer Modern needs eco.sty
2773 os << "\\usepackage{eco}\n";
2775 // Latin Modern Roman
2776 else if (rm == "lmodern")
2777 os << "\\usepackage{lmodern}\n";
2779 else if (rm == "ae") {
2780 // not needed when using OT1 font encoding.
2781 if (font_encoding() != "default")
2782 os << "\\usepackage{ae,aecompl}\n";
2785 else if (rm == "times") {
2786 // try to load the best available package
2787 if (LaTeXFeatures::isAvailable("mathptmx"))
2788 os << "\\usepackage{mathptmx}\n";
2789 else if (LaTeXFeatures::isAvailable("mathptm"))
2790 os << "\\usepackage{mathptm}\n";
2792 os << "\\usepackage{times}\n";
2795 else if (rm == "palatino") {
2796 // try to load the best available package
2797 if (LaTeXFeatures::isAvailable("mathpazo")) {
2798 os << "\\usepackage";
2804 // "osf" includes "sc"!
2808 os << "{mathpazo}\n";
2810 else if (LaTeXFeatures::isAvailable("mathpple"))
2811 os << "\\usepackage{mathpple}\n";
2813 os << "\\usepackage{palatino}\n";
2816 else if (rm == "utopia") {
2817 // fourier supersedes utopia.sty, but does
2818 // not work with OT1 encoding.
2819 if (LaTeXFeatures::isAvailable("fourier")
2820 && font_encoding() != "default") {
2821 os << "\\usepackage";
2832 os << "{fourier}\n";
2835 os << "\\usepackage{utopia}\n";
2837 // Bera (complete fontset)
2838 else if (rm == "bera" && sf == "default" && tt == "default")
2839 os << "\\usepackage{bera}\n";
2841 else if (rm != "default")
2842 os << "\\usepackage" << "{" << rm << "}\n";
2845 // Helvetica, Bera Sans
2846 if (sf == "helvet" || sf == "berasans") {
2848 os << "\\usepackage[scaled=" << float(sfscale) / 100
2849 << "]{" << sf << "}\n";
2851 os << "\\usepackage{" << sf << "}\n";
2854 else if (sf == "avant")
2855 os << "\\usepackage{" << sf << "}\n";
2856 // Computer Modern, Latin Modern, CM Bright
2857 else if (sf != "default")
2858 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2860 // monospaced/typewriter
2861 // Courier, LuxiMono
2862 if (tt == "luximono" || tt == "beramono") {
2864 os << "\\usepackage[scaled=" << float(ttscale) / 100
2865 << "]{" << tt << "}\n";
2867 os << "\\usepackage{" << tt << "}\n";
2870 else if (tt == "courier" )
2871 os << "\\usepackage{" << tt << "}\n";
2872 // Computer Modern, Latin Modern, CM Bright
2873 else if (tt != "default")
2874 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2880 Encoding const & BufferParams::encoding() const
2882 // FIXME: actually, we should check for the flavor
2883 // or runparams.isFullyUnicode() here:
2884 // This check will not work with XeTeX/LuaTeX and tex fonts.
2885 // Thus we have to reset the encoding in Buffer::makeLaTeXFile.
2887 return *(encodings.fromLaTeXName("utf8-plain"));
2888 if (inputenc == "auto" || inputenc == "default")
2889 return *language->encoding();
2890 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2893 LYXERR0("Unknown inputenc value `" << inputenc
2894 << "'. Using `auto' instead.");
2895 return *language->encoding();
2899 CiteEngine BufferParams::citeEngine() const
2901 // FIXME the class should provide the numerical/
2902 // authoryear choice
2903 if (documentClass().provides("natbib")
2904 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2905 return ENGINE_NATBIB_AUTHORYEAR;
2906 return cite_engine_;
2910 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2912 cite_engine_ = cite_engine;