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 biblio_style = "plain";
371 use_bibtopic = false;
373 trackChanges = false;
374 outputChanges = false;
375 use_default_options = true;
376 maintain_unincluded_children = false;
379 language = default_language;
381 fonts_roman = "default";
382 fonts_sans = "default";
383 fonts_typewriter = "default";
384 fonts_default_family = "default";
385 useNonTeXFonts = false;
386 fonts_expert_sc = false;
387 fonts_old_figures = false;
388 fonts_sans_scale = 100;
389 fonts_typewriter_scale = 100;
391 lang_package = "default";
392 graphics_driver = "default";
393 default_output_format = "default";
394 bibtex_command = "default";
395 index_command = "default";
398 listings_params = string();
399 pagestyle = "default";
400 suppress_date = false;
401 justification = true;
402 // no color is the default (white)
403 backgroundcolor = lyx::rgbFromHexName("#ffffff");
404 isbackgroundcolor = false;
405 // no color is the default (black)
406 fontcolor = lyx::rgbFromHexName("#000000");
408 // light gray is the default font color for greyed-out notes
409 notefontcolor = lyx::rgbFromHexName("#cccccc");
410 boxbgcolor = lyx::rgbFromHexName("#ff0000");
411 compressed = lyxrc.save_compressed;
412 for (int iter = 0; iter < 4; ++iter) {
413 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
414 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
417 indiceslist().addDefault(B_("Index"));
418 html_be_strict = false;
419 html_math_output = MathML;
420 html_math_img_scale = 1.0;
421 html_css_as_file = false;
428 docstring BufferParams::B_(string const & l10n) const
430 LASSERT(language, /**/);
431 return getMessages(language->code()).get(l10n);
435 AuthorList & BufferParams::authors()
437 return pimpl_->authorlist;
441 AuthorList const & BufferParams::authors() const
443 return pimpl_->authorlist;
447 BranchList & BufferParams::branchlist()
449 return pimpl_->branchlist;
453 BranchList const & BufferParams::branchlist() const
455 return pimpl_->branchlist;
459 IndicesList & BufferParams::indiceslist()
461 return pimpl_->indiceslist;
465 IndicesList const & BufferParams::indiceslist() const
467 return pimpl_->indiceslist;
471 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
473 LASSERT(index < 4, /**/);
474 return pimpl_->temp_bullets[index];
478 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
480 LASSERT(index < 4, /**/);
481 return pimpl_->temp_bullets[index];
485 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
487 LASSERT(index < 4, /**/);
488 return pimpl_->user_defined_bullets[index];
492 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
494 LASSERT(index < 4, /**/);
495 return pimpl_->user_defined_bullets[index];
499 Spacing & BufferParams::spacing()
501 return pimpl_->spacing;
505 Spacing const & BufferParams::spacing() const
507 return pimpl_->spacing;
511 PDFOptions & BufferParams::pdfoptions()
513 return pimpl_->pdfoptions;
517 PDFOptions const & BufferParams::pdfoptions() const
519 return pimpl_->pdfoptions;
523 HSpace const & BufferParams::getIndentation() const
525 return pimpl_->indentation;
529 void BufferParams::setIndentation(HSpace const & indent)
531 pimpl_->indentation = indent;
535 VSpace const & BufferParams::getDefSkip() const
537 return pimpl_->defskip;
541 void BufferParams::setDefSkip(VSpace const & vs)
543 // DEFSKIP will cause an infinite loop
544 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
545 pimpl_->defskip = vs;
549 string BufferParams::readToken(Lexer & lex, string const & token,
550 FileName const & filepath)
552 if (token == "\\textclass") {
554 string const classname = lex.getString();
555 // if there exists a local layout file, ignore the system one
556 // NOTE: in this case, the textclass (.cls file) is assumed to
559 LayoutFileList & bcl = LayoutFileList::get();
560 if (tcp.empty() && !filepath.empty())
561 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
565 setBaseClass(classname);
566 // We assume that a tex class exists for local or unknown
567 // layouts so this warning, will only be given for system layouts.
568 if (!baseClass()->isTeXClassAvailable()) {
569 docstring const desc =
570 translateIfPossible(from_utf8(baseClass()->description()));
571 docstring const prereqs =
572 from_utf8(baseClass()->prerequisites());
573 docstring const msg =
574 bformat(_("The selected document class\n"
576 "requires external files that are not available.\n"
577 "The document class can still be used, but the\n"
578 "document cannot be compiled until the following\n"
579 "prerequisites are installed:\n"
581 "See section 3.1.2.2 (Class Availability) of the\n"
582 "User's Guide for more information."), desc, prereqs);
583 frontend::Alert::warning(_("Document class not available"),
586 } else if (token == "\\begin_preamble") {
588 } else if (token == "\\begin_local_layout") {
589 readLocalLayout(lex);
590 } else if (token == "\\begin_modules") {
592 } else if (token == "\\begin_removed_modules") {
593 readRemovedModules(lex);
594 } else if (token == "\\begin_includeonly") {
595 readIncludeonly(lex);
596 } else if (token == "\\maintain_unincluded_children") {
597 lex >> maintain_unincluded_children;
598 } else if (token == "\\options") {
600 options = lex.getString();
601 } else if (token == "\\use_default_options") {
602 lex >> use_default_options;
603 } else if (token == "\\master") {
605 master = lex.getString();
606 } else if (token == "\\suppress_date") {
607 lex >> suppress_date;
608 } else if (token == "\\justification") {
609 lex >> justification;
610 } else if (token == "\\language") {
612 } else if (token == "\\language_package") {
614 lang_package = lex.getString();
615 } else if (token == "\\inputencoding") {
617 } else if (token == "\\graphics") {
618 readGraphicsDriver(lex);
619 } else if (token == "\\default_output_format") {
620 lex >> default_output_format;
621 } else if (token == "\\bibtex_command") {
623 bibtex_command = lex.getString();
624 } else if (token == "\\index_command") {
626 index_command = lex.getString();
627 } else if (token == "\\fontencoding") {
629 fontenc = lex.getString();
630 } else if (token == "\\font_roman") {
632 fonts_roman = lex.getString();
633 } else if (token == "\\font_sans") {
635 fonts_sans = lex.getString();
636 } else if (token == "\\font_typewriter") {
638 fonts_typewriter = lex.getString();
639 } else if (token == "\\font_default_family") {
640 lex >> fonts_default_family;
641 } else if (token == "\\use_non_tex_fonts") {
642 lex >> useNonTeXFonts;
643 } else if (token == "\\font_sc") {
644 lex >> fonts_expert_sc;
645 } else if (token == "\\font_osf") {
646 lex >> fonts_old_figures;
647 } else if (token == "\\font_sf_scale") {
648 lex >> fonts_sans_scale;
649 } else if (token == "\\font_tt_scale") {
650 lex >> fonts_typewriter_scale;
651 } else if (token == "\\font_cjk") {
653 } else if (token == "\\paragraph_separation") {
656 paragraph_separation = parseptranslator().find(parsep);
657 } else if (token == "\\paragraph_indentation") {
659 string indentation = lex.getString();
660 pimpl_->indentation = HSpace(indentation);
661 } else if (token == "\\defskip") {
663 string const defskip = lex.getString();
664 pimpl_->defskip = VSpace(defskip);
665 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
667 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
668 } else if (token == "\\quotes_language") {
671 quotes_language = quoteslangtranslator().find(quotes_lang);
672 } else if (token == "\\papersize") {
675 papersize = papersizetranslator().find(ppsize);
676 } else if (token == "\\use_geometry") {
678 } else if (token == "\\use_amsmath") {
681 use_amsmath = packagetranslator().find(use_ams);
682 } else if (token == "\\use_esint") {
685 use_esint = packagetranslator().find(useesint);
686 } else if (token == "\\use_mhchem") {
689 use_mhchem = packagetranslator().find(usemhchem);
690 } else if (token == "\\use_mathdots") {
693 use_mathdots = packagetranslator().find(usemathdots);
694 } else if (token == "\\use_undertilde") {
696 lex >> useundertilde;
697 use_undertilde = packagetranslator().find(useundertilde);
698 } else if (token == "\\cite_engine") {
701 cite_engine_ = citeenginetranslator().find(engine);
702 } else if (token == "\\biblio_style") {
704 biblio_style = lex.getString();
705 } else if (token == "\\use_bibtopic") {
707 } else if (token == "\\use_indices") {
709 } else if (token == "\\tracking_changes") {
711 } else if (token == "\\output_changes") {
712 lex >> outputChanges;
713 } else if (token == "\\branch") {
715 docstring branch = lex.getDocString();
716 branchlist().add(branch);
719 string const tok = lex.getString();
720 if (tok == "\\end_branch")
722 Branch * branch_ptr = branchlist().find(branch);
723 if (tok == "\\selected") {
726 branch_ptr->setSelected(lex.getInteger());
728 if (tok == "\\filename_suffix") {
731 branch_ptr->setFileNameSuffix(lex.getInteger());
733 if (tok == "\\color") {
735 string color = lex.getString();
737 branch_ptr->setColor(color);
738 // Update also the Color table:
740 color = lcolor.getX11Name(Color_background);
742 lcolor.setColor(to_utf8(branch), color);
745 } else if (token == "\\index") {
747 docstring index = lex.getDocString();
749 indiceslist().add(index);
752 string const tok = lex.getString();
753 if (tok == "\\end_index")
755 Index * index_ptr = indiceslist().find(index);
756 if (tok == "\\shortcut") {
758 shortcut = lex.getDocString();
760 index_ptr->setShortcut(shortcut);
762 if (tok == "\\color") {
764 string color = lex.getString();
766 index_ptr->setColor(color);
767 // Update also the Color table:
769 color = lcolor.getX11Name(Color_background);
771 if (!shortcut.empty())
772 lcolor.setColor(to_utf8(shortcut), color);
775 } else if (token == "\\author") {
777 istringstream ss(lex.getString());
780 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
781 } else if (token == "\\paperorientation") {
784 orientation = paperorientationtranslator().find(orient);
785 } else if (token == "\\backgroundcolor") {
787 backgroundcolor = lyx::rgbFromHexName(lex.getString());
788 isbackgroundcolor = true;
789 } else if (token == "\\fontcolor") {
791 fontcolor = lyx::rgbFromHexName(lex.getString());
793 } else if (token == "\\notefontcolor") {
795 string color = lex.getString();
796 notefontcolor = lyx::rgbFromHexName(color);
797 } else if (token == "\\boxbgcolor") {
799 string color = lex.getString();
800 boxbgcolor = lyx::rgbFromHexName(color);
801 } else if (token == "\\paperwidth") {
803 } else if (token == "\\paperheight") {
805 } else if (token == "\\leftmargin") {
807 } else if (token == "\\topmargin") {
809 } else if (token == "\\rightmargin") {
811 } else if (token == "\\bottommargin") {
813 } else if (token == "\\headheight") {
815 } else if (token == "\\headsep") {
817 } else if (token == "\\footskip") {
819 } else if (token == "\\columnsep") {
821 } else if (token == "\\paperfontsize") {
823 } else if (token == "\\papercolumns") {
825 } else if (token == "\\listings_params") {
828 listings_params = InsetListingsParams(par).params();
829 } else if (token == "\\papersides") {
832 sides = sidestranslator().find(psides);
833 } else if (token == "\\paperpagestyle") {
835 } else if (token == "\\bullet") {
837 } else if (token == "\\bulletLaTeX") {
838 readBulletsLaTeX(lex);
839 } else if (token == "\\secnumdepth") {
841 } else if (token == "\\tocdepth") {
843 } else if (token == "\\spacing") {
847 if (nspacing == "other") {
850 spacing().set(spacetranslator().find(nspacing), tmp_val);
851 } else if (token == "\\float_placement") {
852 lex >> float_placement;
854 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
855 string toktmp = pdfoptions().readToken(lex, token);
856 if (!toktmp.empty()) {
857 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
861 } else if (token == "\\html_math_output") {
864 html_math_output = static_cast<MathOutput>(temp);
865 } else if (token == "\\html_be_strict") {
866 lex >> html_be_strict;
867 } else if (token == "\\html_css_as_file") {
868 lex >> html_css_as_file;
869 } else if (token == "\\html_math_img_scale") {
870 lex >> html_math_img_scale;
871 } else if (token == "\\html_latex_start") {
873 html_latex_start = lex.getString();
874 } else if (token == "\\html_latex_end") {
876 html_latex_end = lex.getString();
877 } else if (token == "\\output_sync") {
879 } else if (token == "\\output_sync_macro") {
880 lex >> output_sync_macro;
881 } else if (token == "\\use_refstyle") {
884 lyxerr << "BufferParams::readToken(): Unknown token: " <<
893 void BufferParams::writeFile(ostream & os) const
895 // The top of the file is written by the buffer.
896 // Prints out the buffer info into the .lyx file given by file
899 os << "\\textclass " << baseClass()->name() << '\n';
902 if (!preamble.empty()) {
903 // remove '\n' from the end of preamble
904 string const tmppreamble = rtrim(preamble, "\n");
905 os << "\\begin_preamble\n"
907 << "\n\\end_preamble\n";
911 if (!options.empty()) {
912 os << "\\options " << options << '\n';
915 // use the class options defined in the layout?
916 os << "\\use_default_options "
917 << convert<string>(use_default_options) << "\n";
919 // the master document
920 if (!master.empty()) {
921 os << "\\master " << master << '\n';
925 if (!removed_modules_.empty()) {
926 os << "\\begin_removed_modules" << '\n';
927 list<string>::const_iterator it = removed_modules_.begin();
928 list<string>::const_iterator en = removed_modules_.end();
929 for (; it != en; it++)
931 os << "\\end_removed_modules" << '\n';
935 if (!layout_modules_.empty()) {
936 os << "\\begin_modules" << '\n';
937 LayoutModuleList::const_iterator it = layout_modules_.begin();
938 LayoutModuleList::const_iterator en = layout_modules_.end();
939 for (; it != en; it++)
941 os << "\\end_modules" << '\n';
945 if (!included_children_.empty()) {
946 os << "\\begin_includeonly" << '\n';
947 list<string>::const_iterator it = included_children_.begin();
948 list<string>::const_iterator en = included_children_.end();
949 for (; it != en; it++)
951 os << "\\end_includeonly" << '\n';
953 os << "\\maintain_unincluded_children "
954 << convert<string>(maintain_unincluded_children) << '\n';
956 // local layout information
957 if (!local_layout.empty()) {
958 // remove '\n' from the end
959 string const tmplocal = rtrim(local_layout, "\n");
960 os << "\\begin_local_layout\n"
962 << "\n\\end_local_layout\n";
965 // then the text parameters
966 if (language != ignore_language)
967 os << "\\language " << language->lang() << '\n';
968 os << "\\language_package " << lang_package
969 << "\n\\inputencoding " << inputenc
970 << "\n\\fontencoding " << fontenc
971 << "\n\\font_roman " << fonts_roman
972 << "\n\\font_sans " << fonts_sans
973 << "\n\\font_typewriter " << fonts_typewriter
974 << "\n\\font_default_family " << fonts_default_family
975 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
976 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
977 << "\n\\font_osf " << convert<string>(fonts_old_figures)
978 << "\n\\font_sf_scale " << fonts_sans_scale
979 << "\n\\font_tt_scale " << fonts_typewriter_scale
981 if (!fonts_cjk.empty()) {
982 os << "\\font_cjk " << fonts_cjk << '\n';
984 os << "\n\\graphics " << graphics_driver << '\n';
985 os << "\\default_output_format " << default_output_format << '\n';
986 os << "\\output_sync " << output_sync << '\n';
987 if (!output_sync_macro.empty())
988 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
989 os << "\\bibtex_command " << bibtex_command << '\n';
990 os << "\\index_command " << index_command << '\n';
992 if (!float_placement.empty()) {
993 os << "\\float_placement " << float_placement << '\n';
995 os << "\\paperfontsize " << fontsize << '\n';
997 spacing().writeFile(os);
998 pdfoptions().writeFile(os);
1000 os << "\\papersize " << string_papersize[papersize]
1001 << "\n\\use_geometry " << convert<string>(use_geometry)
1002 << "\n\\use_amsmath " << use_amsmath
1003 << "\n\\use_esint " << use_esint
1004 << "\n\\use_mhchem " << use_mhchem
1005 << "\n\\use_mathdots " << use_mathdots
1006 << "\n\\use_undertilde " << use_undertilde
1007 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
1008 << "\n\\biblio_style " << biblio_style
1009 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1010 << "\n\\use_indices " << convert<string>(use_indices)
1011 << "\n\\paperorientation " << string_orientation[orientation]
1012 << "\n\\suppress_date " << convert<string>(suppress_date)
1013 << "\n\\justification " << convert<string>(justification)
1014 << "\n\\use_refstyle " << use_refstyle
1016 if (isbackgroundcolor == true)
1017 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1018 if (isfontcolor == true)
1019 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1020 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1021 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1022 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1023 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1025 BranchList::const_iterator it = branchlist().begin();
1026 BranchList::const_iterator end = branchlist().end();
1027 for (; it != end; ++it) {
1028 os << "\\branch " << to_utf8(it->branch())
1029 << "\n\\selected " << it->isSelected()
1030 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1031 << "\n\\color " << lyx::X11hexname(it->color())
1036 IndicesList::const_iterator iit = indiceslist().begin();
1037 IndicesList::const_iterator iend = indiceslist().end();
1038 for (; iit != iend; ++iit) {
1039 os << "\\index " << to_utf8(iit->index())
1040 << "\n\\shortcut " << to_utf8(iit->shortcut())
1041 << "\n\\color " << lyx::X11hexname(iit->color())
1046 if (!paperwidth.empty())
1047 os << "\\paperwidth "
1048 << VSpace(paperwidth).asLyXCommand() << '\n';
1049 if (!paperheight.empty())
1050 os << "\\paperheight "
1051 << VSpace(paperheight).asLyXCommand() << '\n';
1052 if (!leftmargin.empty())
1053 os << "\\leftmargin "
1054 << VSpace(leftmargin).asLyXCommand() << '\n';
1055 if (!topmargin.empty())
1056 os << "\\topmargin "
1057 << VSpace(topmargin).asLyXCommand() << '\n';
1058 if (!rightmargin.empty())
1059 os << "\\rightmargin "
1060 << VSpace(rightmargin).asLyXCommand() << '\n';
1061 if (!bottommargin.empty())
1062 os << "\\bottommargin "
1063 << VSpace(bottommargin).asLyXCommand() << '\n';
1064 if (!headheight.empty())
1065 os << "\\headheight "
1066 << VSpace(headheight).asLyXCommand() << '\n';
1067 if (!headsep.empty())
1069 << VSpace(headsep).asLyXCommand() << '\n';
1070 if (!footskip.empty())
1072 << VSpace(footskip).asLyXCommand() << '\n';
1073 if (!columnsep.empty())
1074 os << "\\columnsep "
1075 << VSpace(columnsep).asLyXCommand() << '\n';
1076 os << "\\secnumdepth " << secnumdepth
1077 << "\n\\tocdepth " << tocdepth
1078 << "\n\\paragraph_separation "
1079 << string_paragraph_separation[paragraph_separation];
1080 if (!paragraph_separation)
1081 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1083 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1084 os << "\n\\quotes_language "
1085 << string_quotes_language[quotes_language]
1086 << "\n\\papercolumns " << columns
1087 << "\n\\papersides " << sides
1088 << "\n\\paperpagestyle " << pagestyle << '\n';
1089 if (!listings_params.empty())
1090 os << "\\listings_params \"" <<
1091 InsetListingsParams(listings_params).encodedString() << "\"\n";
1092 for (int i = 0; i < 4; ++i) {
1093 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1094 if (user_defined_bullet(i).getFont() != -1) {
1095 os << "\\bullet " << i << " "
1096 << user_defined_bullet(i).getFont() << " "
1097 << user_defined_bullet(i).getCharacter() << " "
1098 << user_defined_bullet(i).getSize() << "\n";
1102 os << "\\bulletLaTeX " << i << " \""
1103 << lyx::to_ascii(user_defined_bullet(i).getText())
1109 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1110 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1111 << "\\html_math_output " << html_math_output << '\n'
1112 << "\\html_css_as_file " << html_css_as_file << '\n'
1113 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1115 if (html_math_img_scale != 1.0)
1116 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1117 if (!html_latex_start.empty())
1118 os << "\\html_latex_start " << html_latex_start << '\n';
1119 if (!html_latex_end.empty())
1120 os << "\\html_latex_end " << html_latex_end << '\n';
1122 os << pimpl_->authorlist;
1126 void BufferParams::validate(LaTeXFeatures & features) const
1128 features.require(documentClass().requires());
1130 if (outputChanges) {
1131 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1132 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1133 LaTeXFeatures::isAvailable("xcolor");
1135 switch (features.runparams().flavor) {
1136 case OutputParams::LATEX:
1137 case OutputParams::DVILUATEX:
1139 features.require("ct-dvipost");
1140 features.require("dvipost");
1141 } else if (xcolorulem) {
1142 features.require("ct-xcolor-ulem");
1143 features.require("ulem");
1144 features.require("xcolor");
1146 features.require("ct-none");
1149 case OutputParams::LUATEX:
1150 case OutputParams::PDFLATEX:
1151 case OutputParams::XETEX:
1153 features.require("ct-xcolor-ulem");
1154 features.require("ulem");
1155 features.require("xcolor");
1156 // improves color handling in PDF output
1157 features.require("pdfcolmk");
1159 features.require("ct-none");
1167 // Floats with 'Here definitely' as default setting.
1168 if (float_placement.find('H') != string::npos)
1169 features.require("float");
1171 // AMS Style is at document level
1172 if (use_amsmath == package_on
1173 || documentClass().provides("amsmath"))
1174 features.require("amsmath");
1175 if (use_esint == package_on)
1176 features.require("esint");
1177 if (use_mhchem == package_on)
1178 features.require("mhchem");
1179 if (use_mathdots == package_on)
1180 features.require("mathdots");
1181 if (use_undertilde == package_on)
1182 features.require("undertilde");
1184 // Document-level line spacing
1185 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1186 features.require("setspace");
1188 // the bullet shapes are buffer level not paragraph level
1189 // so they are tested here
1190 for (int i = 0; i < 4; ++i) {
1191 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1193 int const font = user_defined_bullet(i).getFont();
1195 int const c = user_defined_bullet(i).getCharacter();
1201 features.require("latexsym");
1203 } else if (font == 1) {
1204 features.require("amssymb");
1205 } else if (font >= 2 && font <= 5) {
1206 features.require("pifont");
1210 if (pdfoptions().use_hyperref) {
1211 features.require("hyperref");
1212 // due to interferences with babel and hyperref, the color package has to
1213 // be loaded after hyperref when hyperref is used with the colorlinks
1214 // option, see http://www.lyx.org/trac/ticket/5291
1215 if (pdfoptions().colorlinks)
1216 features.require("color");
1219 if (features.runparams().flavor == OutputParams::XETEX
1221 features.require("polyglossia");
1223 if (language->lang() == "vietnamese")
1224 features.require("vietnamese");
1225 else if (language->lang() == "japanese")
1226 features.require("japanese");
1230 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1231 FileName const & filepath) const
1233 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1234 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1235 // \RequirePackage to do so, rather than the normal \usepackage
1236 // Do not try to load any other package before the document class, unless you
1237 // have a thorough understanding of the LATEX internals and know exactly what you
1239 if (features.mustProvide("fix-cm"))
1240 os << "\\RequirePackage{fix-cm}\n";
1242 os << "\\documentclass";
1244 DocumentClass const & tclass = documentClass();
1246 ostringstream clsoptions; // the document class options.
1248 if (tokenPos(tclass.opt_fontsize(),
1249 '|', fontsize) >= 0) {
1250 // only write if existing in list (and not default)
1251 clsoptions << fontsize << "pt,";
1254 // all paper sizes except of A4, A5, B5 and the US sizes need the
1256 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1257 && papersize != PAPER_USLETTER
1258 && papersize != PAPER_USLEGAL
1259 && papersize != PAPER_USEXECUTIVE
1260 && papersize != PAPER_A4
1261 && papersize != PAPER_A5
1262 && papersize != PAPER_B5;
1264 if (!use_geometry) {
1265 switch (papersize) {
1267 clsoptions << "a4paper,";
1269 case PAPER_USLETTER:
1270 clsoptions << "letterpaper,";
1273 clsoptions << "a5paper,";
1276 clsoptions << "b5paper,";
1278 case PAPER_USEXECUTIVE:
1279 clsoptions << "executivepaper,";
1282 clsoptions << "legalpaper,";
1316 if (sides != tclass.sides()) {
1319 clsoptions << "oneside,";
1322 clsoptions << "twoside,";
1328 if (columns != tclass.columns()) {
1330 clsoptions << "twocolumn,";
1332 clsoptions << "onecolumn,";
1336 && orientation == ORIENTATION_LANDSCAPE)
1337 clsoptions << "landscape,";
1339 // language should be a parameter to \documentclass
1340 if (language->babel() == "hebrew"
1341 && default_language->babel() != "hebrew")
1342 // This seems necessary
1343 features.useLanguage(default_language);
1345 ostringstream language_options;
1346 bool const use_babel = features.useBabel() && !tclass.provides("babel");
1347 bool const use_polyglossia = features.usePolyglossia();
1348 bool const global = lyxrc.language_global_options;
1349 if (use_babel || (use_polyglossia && global)) {
1350 language_options << features.getLanguages();
1351 if (!language->babel().empty()) {
1352 if (!language_options.str().empty())
1353 language_options << ',';
1354 language_options << language->babel();
1356 if (global && !features.needBabelLangOptions())
1357 clsoptions << language_options.str() << ',';
1360 // the predefined options from the layout
1361 if (use_default_options && !tclass.options().empty())
1362 clsoptions << tclass.options() << ',';
1364 // the user-defined options
1365 if (!options.empty()) {
1366 clsoptions << options << ',';
1369 string strOptions(clsoptions.str());
1370 if (!strOptions.empty()) {
1371 strOptions = rtrim(strOptions, ",");
1373 os << '[' << from_utf8(strOptions) << ']';
1376 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1377 // end of \documentclass defs
1379 // if we use fontspec, we have to load the AMS packages here
1380 string const ams = features.loadAMSPackages();
1381 if (useNonTeXFonts && !ams.empty())
1382 os << from_ascii(ams);
1385 os << "\\usepackage{fontspec}\n";
1387 // font selection must be done before loading fontenc.sty
1388 string const fonts =
1389 loadFonts(fonts_roman, fonts_sans, fonts_typewriter,
1390 fonts_expert_sc, fonts_old_figures,
1391 fonts_sans_scale, fonts_typewriter_scale,
1392 useNonTeXFonts, features);
1394 os << from_utf8(fonts);
1396 if (fonts_default_family != "default")
1397 os << "\\renewcommand{\\familydefault}{\\"
1398 << from_ascii(fonts_default_family) << "}\n";
1400 // set font encoding
1401 // for arabic_arabi and farsi we also need to load the LAE and
1403 // XeTeX and LuaTeX (with OS fonts) work without fontenc
1404 if (font_encoding() != "default" && language->lang() != "japanese"
1405 && !useNonTeXFonts && !tclass.provides("fontenc")) {
1406 size_t fars = language_options.str().find("farsi");
1407 size_t arab = language_options.str().find("arabic");
1408 if (language->lang() == "arabic_arabi"
1409 || language->lang() == "farsi" || fars != string::npos
1410 || arab != string::npos) {
1411 os << "\\usepackage[" << from_ascii(font_encoding())
1412 << ",LFE,LAE]{fontenc}\n";
1414 os << "\\usepackage[" << from_ascii(font_encoding())
1419 // handle inputenc etc.
1420 writeEncodingPreamble(os, features);
1423 if (!features.runparams().includeall && !included_children_.empty()) {
1424 os << "\\includeonly{";
1425 list<string>::const_iterator it = included_children_.begin();
1426 list<string>::const_iterator en = included_children_.end();
1428 for (; it != en; ++it) {
1429 string incfile = *it;
1430 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1431 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1433 if (!features.runparams().nice)
1435 // \includeonly doesn't want an extension
1436 incfile = changeExtension(incfile, string());
1437 incfile = support::latex_path(incfile);
1438 if (!incfile.empty()) {
1441 os << from_utf8(incfile);
1448 if (!listings_params.empty() || features.isRequired("listings"))
1449 os << "\\usepackage{listings}\n";
1451 if (!listings_params.empty()) {
1453 // do not test validity because listings_params is
1454 // supposed to be valid
1456 InsetListingsParams(listings_params).separatedParams(true);
1457 // we can't support all packages, but we should load the color package
1458 if (par.find("\\color", 0) != string::npos)
1459 features.require("color");
1460 os << from_utf8(par)
1463 if (!tclass.provides("geometry")
1464 && (use_geometry || nonstandard_papersize)) {
1465 odocstringstream ods;
1466 if (!getGraphicsDriver("geometry").empty())
1467 ods << getGraphicsDriver("geometry");
1468 if (orientation == ORIENTATION_LANDSCAPE)
1469 ods << ",landscape";
1470 switch (papersize) {
1472 if (!paperwidth.empty())
1473 ods << ",paperwidth="
1474 << from_ascii(paperwidth);
1475 if (!paperheight.empty())
1476 ods << ",paperheight="
1477 << from_ascii(paperheight);
1479 case PAPER_USLETTER:
1480 ods << ",letterpaper";
1483 ods << ",legalpaper";
1485 case PAPER_USEXECUTIVE:
1486 ods << ",executivepaper";
1575 docstring const g_options = trim(ods.str(), ",");
1576 os << "\\usepackage";
1577 if (!g_options.empty())
1578 os << '[' << g_options << ']';
1579 os << "{geometry}\n";
1580 // output this only if use_geometry is true
1582 os << "\\geometry{verbose";
1583 if (!topmargin.empty())
1584 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1585 if (!bottommargin.empty())
1586 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1587 if (!leftmargin.empty())
1588 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1589 if (!rightmargin.empty())
1590 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1591 if (!headheight.empty())
1592 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1593 if (!headsep.empty())
1594 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1595 if (!footskip.empty())
1596 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1597 if (!columnsep.empty())
1598 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1601 } else if (orientation == ORIENTATION_LANDSCAPE
1602 || papersize != PAPER_DEFAULT) {
1603 features.require("papersize");
1606 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1607 if (pagestyle == "fancy")
1608 os << "\\usepackage{fancyhdr}\n";
1609 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1612 // only output when the background color is not default
1613 if (isbackgroundcolor == true) {
1614 // only require color here, the background color will be defined
1615 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1617 features.require("color");
1618 features.require("pagecolor");
1621 // only output when the font color is not default
1622 if (isfontcolor == true) {
1623 // only require color here, the font color will be defined
1624 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1626 features.require("color");
1627 features.require("fontcolor");
1630 // Only if class has a ToC hierarchy
1631 if (tclass.hasTocLevels()) {
1632 if (secnumdepth != tclass.secnumdepth()) {
1633 os << "\\setcounter{secnumdepth}{"
1637 if (tocdepth != tclass.tocdepth()) {
1638 os << "\\setcounter{tocdepth}{"
1644 if (paragraph_separation) {
1645 // when skip separation
1646 switch (getDefSkip().kind()) {
1647 case VSpace::SMALLSKIP:
1648 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1650 case VSpace::MEDSKIP:
1651 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1653 case VSpace::BIGSKIP:
1654 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1656 case VSpace::LENGTH:
1657 os << "\\setlength{\\parskip}{"
1658 << from_utf8(getDefSkip().length().asLatexString())
1661 default: // should never happen // Then delete it.
1662 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1665 os << "\\setlength{\\parindent}{0pt}\n";
1667 // when separation by indentation
1668 // only output something when a width is given
1669 if (getIndentation().asLyXCommand() != "default") {
1670 os << "\\setlength{\\parindent}{"
1671 << from_utf8(getIndentation().asLatexCommand())
1676 // Now insert the LyX specific LaTeX commands...
1677 docstring lyxpreamble;
1678 features.resolveAlternatives();
1681 if (!output_sync_macro.empty())
1682 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1683 else if (features.runparams().flavor == OutputParams::LATEX)
1684 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1685 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1686 lyxpreamble += "\\synctex=-1\n";
1689 // due to interferences with babel and hyperref, the color package has to
1690 // be loaded (when it is not already loaded) before babel when hyperref
1691 // is used with the colorlinks option, see
1692 // http://www.lyx.org/trac/ticket/5291
1693 // we decided therefore to load color always before babel, see
1694 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1695 lyxpreamble += from_ascii(features.getColorOptions());
1697 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1699 && (features.isRequired("jurabib")
1700 || features.isRequired("hyperref")
1701 || features.isRequired("vietnamese")
1702 || features.isRequired("japanese"))) {
1704 lyxpreamble += from_utf8(features.getBabelPresettings());
1705 lyxpreamble += from_utf8(babelCall(language_options.str(),
1706 features.needBabelLangOptions())) + '\n';
1707 lyxpreamble += from_utf8(features.getBabelPostsettings());
1710 // The optional packages;
1711 lyxpreamble += from_ascii(features.getPackages());
1713 // Additional Indices
1714 if (features.isRequired("splitidx")) {
1715 IndicesList::const_iterator iit = indiceslist().begin();
1716 IndicesList::const_iterator iend = indiceslist().end();
1717 for (; iit != iend; ++iit) {
1718 lyxpreamble += "\\newindex[";
1719 lyxpreamble += iit->index();
1720 lyxpreamble += "]{";
1721 lyxpreamble += iit->shortcut();
1722 lyxpreamble += "}\n";
1727 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1730 // * Hyperref manual: "Make sure it comes last of your loaded
1731 // packages, to give it a fighting chance of not being over-written,
1732 // since its job is to redefine many LaTeX commands."
1733 // * Email from Heiko Oberdiek: "It is usually better to load babel
1734 // before hyperref. Then hyperref has a chance to detect babel.
1735 // * Has to be loaded before the "LyX specific LaTeX commands" to
1736 // avoid errors with algorithm floats.
1737 // use hyperref explicitly if it is required
1738 if (features.isRequired("hyperref")) {
1739 // pass what we have to stream here, since we need
1740 // to access the stream itself in PDFOptions.
1743 OutputParams tmp_params = features.runparams();
1744 pdfoptions().writeLaTeX(tmp_params, os,
1745 documentClass().provides("hyperref"));
1746 // set back for the rest
1747 lyxpreamble.clear();
1748 // correctly break URLs with hyperref and dvi output
1749 if (features.runparams().flavor == OutputParams::LATEX
1750 && features.isAvailable("breakurl"))
1751 lyxpreamble += "\\usepackage{breakurl}\n";
1752 } else if (features.isRequired("nameref"))
1753 // hyperref loads this automatically
1754 lyxpreamble += "\\usepackage{nameref}\n";
1756 // Will be surrounded by \makeatletter and \makeatother when not empty
1757 docstring atlyxpreamble;
1759 // Some macros LyX will need
1760 docstring tmppreamble(features.getMacros());
1762 if (!tmppreamble.empty())
1763 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1764 "LyX specific LaTeX commands.\n"
1765 + tmppreamble + '\n';
1767 // the text class specific preamble
1768 tmppreamble = features.getTClassPreamble();
1769 if (!tmppreamble.empty())
1770 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1771 "Textclass specific LaTeX commands.\n"
1772 + tmppreamble + '\n';
1774 // suppress date if selected
1775 // use \@ifundefined because we cannot be sure that every document class
1776 // has a \date command
1778 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1780 /* the user-defined preamble */
1781 if (!containsOnly(preamble, " \n\t"))
1783 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1784 "User specified LaTeX commands.\n"
1785 + from_utf8(preamble) + '\n';
1787 // subfig loads internally the LaTeX package "caption". As
1788 // caption is a very popular package, users will load it in
1789 // the preamble. Therefore we must load subfig behind the
1790 // user-defined preamble and check if the caption package was
1791 // loaded or not. For the case that caption is loaded before
1792 // subfig, there is the subfig option "caption=false". This
1793 // option also works when a koma-script class is used and
1794 // koma's own caption commands are used instead of caption. We
1795 // use \PassOptionsToPackage here because the user could have
1796 // already loaded subfig in the preamble.
1797 if (features.isRequired("subfig")) {
1798 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1799 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1800 "\\usepackage{subfig}\n";
1803 // Itemize bullet settings need to be last in case the user
1804 // defines their own bullets that use a package included
1805 // in the user-defined preamble -- ARRae
1806 // Actually it has to be done much later than that
1807 // since some packages like frenchb make modifications
1808 // at \begin{document} time -- JMarc
1809 docstring bullets_def;
1810 for (int i = 0; i < 4; ++i) {
1811 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1812 if (bullets_def.empty())
1813 bullets_def += "\\AtBeginDocument{\n";
1814 bullets_def += " \\def\\labelitemi";
1816 // `i' is one less than the item to modify
1823 bullets_def += "ii";
1829 bullets_def += '{' +
1830 user_defined_bullet(i).getText()
1835 if (!bullets_def.empty())
1836 atlyxpreamble += bullets_def + "}\n\n";
1838 if (!atlyxpreamble.empty())
1839 lyxpreamble += "\n\\makeatletter\n"
1840 + atlyxpreamble + "\\makeatother\n\n";
1842 // We try to load babel late, in case it interferes with other packages.
1843 // Jurabib and Hyperref have to be called after babel, though.
1844 if (use_babel && !features.isRequired("jurabib")
1845 && !features.isRequired("hyperref")
1846 && !features.isRequired("vietnamese")
1847 && !features.isRequired("japanese")) {
1849 lyxpreamble += from_utf8(features.getBabelPresettings());
1850 lyxpreamble += from_utf8(babelCall(language_options.str(),
1851 features.needBabelLangOptions())) + '\n';
1852 lyxpreamble += from_utf8(features.getBabelPostsettings());
1855 // xunicode needs to be loaded at least after amsmath, amssymb,
1856 // esint and the other packages that provide special glyphs
1857 if (features.runparams().flavor == OutputParams::XETEX)
1858 lyxpreamble += "\\usepackage{xunicode}\n";
1860 // Polyglossia must be loaded last
1861 if (use_polyglossia) {
1863 lyxpreamble += "\\usepackage{polyglossia}\n";
1864 // set the main language
1865 lyxpreamble += "\\setdefaultlanguage";
1866 if (!language->polyglossiaOpts().empty())
1867 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
1868 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
1869 // now setup the other languages
1870 std::map<std::string, std::string> const polylangs =
1871 features.getPolyglossiaLanguages();
1872 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
1873 mit != polylangs.end() ; ++mit) {
1874 lyxpreamble += "\\setotherlanguage";
1875 if (!mit->second.empty())
1876 lyxpreamble += "[" + from_ascii(mit->second) + "]";
1877 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
1881 docstring const i18npreamble =
1882 features.getTClassI18nPreamble(use_babel, use_polyglossia);
1883 if (!i18npreamble.empty())
1884 lyxpreamble += i18npreamble + '\n';
1892 void BufferParams::useClassDefaults()
1894 DocumentClass const & tclass = documentClass();
1896 sides = tclass.sides();
1897 columns = tclass.columns();
1898 pagestyle = tclass.pagestyle();
1899 use_default_options = true;
1900 // Only if class has a ToC hierarchy
1901 if (tclass.hasTocLevels()) {
1902 secnumdepth = tclass.secnumdepth();
1903 tocdepth = tclass.tocdepth();
1908 bool BufferParams::hasClassDefaults() const
1910 DocumentClass const & tclass = documentClass();
1912 return sides == tclass.sides()
1913 && columns == tclass.columns()
1914 && pagestyle == tclass.pagestyle()
1915 && use_default_options
1916 && secnumdepth == tclass.secnumdepth()
1917 && tocdepth == tclass.tocdepth();
1921 DocumentClass const & BufferParams::documentClass() const
1927 DocumentClass const * BufferParams::documentClassPtr() const
1933 void BufferParams::setDocumentClass(DocumentClass const * const tc)
1935 // evil, but this function is evil
1936 doc_class_ = const_cast<DocumentClass *>(tc);
1940 bool BufferParams::setBaseClass(string const & classname)
1942 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1943 LayoutFileList & bcl = LayoutFileList::get();
1944 if (!bcl.haveClass(classname)) {
1946 bformat(_("The layout file:\n"
1948 "could not be found. A default textclass with default\n"
1949 "layouts will be used. LyX will not be able to produce\n"
1951 from_utf8(classname));
1952 frontend::Alert::error(_("Document class not found"), s);
1953 bcl.addEmptyClass(classname);
1956 bool const success = bcl[classname].load();
1959 bformat(_("Due to some error in it, the layout file:\n"
1961 "could not be loaded. A default textclass with default\n"
1962 "layouts will be used. LyX will not be able to produce\n"
1964 from_utf8(classname));
1965 frontend::Alert::error(_("Could not load class"), s);
1966 bcl.addEmptyClass(classname);
1969 pimpl_->baseClass_ = classname;
1970 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
1975 LayoutFile const * BufferParams::baseClass() const
1977 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1978 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1984 LayoutFileIndex const & BufferParams::baseClassID() const
1986 return pimpl_->baseClass_;
1990 void BufferParams::makeDocumentClass()
1995 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layout_modules_));
1997 if (!local_layout.empty()) {
1998 TextClass::ReturnValues success =
1999 doc_class_->read(local_layout, TextClass::MODULE);
2000 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2001 docstring const msg = _("Error reading internal layout information");
2002 frontend::Alert::warning(_("Read Error"), msg);
2008 bool BufferParams::moduleCanBeAdded(string const & modName) const
2010 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2014 bool BufferParams::addLayoutModule(string const & modName)
2016 LayoutModuleList::const_iterator it = layout_modules_.begin();
2017 LayoutModuleList::const_iterator end = layout_modules_.end();
2018 for (; it != end; it++)
2021 layout_modules_.push_back(modName);
2026 string BufferParams::bufferFormat() const
2028 string format = documentClass().outputFormat();
2029 if (format == "latex") {
2032 if (encoding().package() == Encoding::japanese)
2039 bool BufferParams::isExportable(string const & format) const
2041 vector<string> backs = backends();
2042 for (vector<string>::const_iterator it = backs.begin();
2043 it != backs.end(); ++it)
2044 if (theConverters().isReachable(*it, format))
2051 bool formatSorter(Format const * lhs, Format const * rhs) {
2052 return _(lhs->prettyname()) < _(rhs->prettyname());
2057 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2059 vector<string> const backs = backends();
2060 set<string> excludes;
2061 if (useNonTeXFonts) {
2062 excludes.insert("latex");
2063 excludes.insert("pdflatex");
2065 vector<Format const *> result =
2066 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2067 for (vector<string>::const_iterator it = backs.begin() + 1;
2068 it != backs.end(); ++it) {
2069 vector<Format const *> r =
2070 theConverters().getReachable(*it, only_viewable, false, excludes);
2071 result.insert(result.end(), r.begin(), r.end());
2073 sort(result.begin(), result.end(), formatSorter);
2078 bool BufferParams::isExportableFormat(string const & format) const
2080 typedef vector<Format const *> Formats;
2082 formats = exportableFormats(true);
2083 Formats::const_iterator fit = formats.begin();
2084 Formats::const_iterator end = formats.end();
2085 for (; fit != end ; ++fit) {
2086 if ((*fit)->name() == format)
2093 vector<string> BufferParams::backends() const
2096 v.push_back(bufferFormat());
2097 // FIXME: Don't hardcode format names here, but use a flag
2098 if (v.back() == "latex") {
2099 v.push_back("pdflatex");
2100 v.push_back("luatex");
2101 v.push_back("dviluatex");
2102 v.push_back("xetex");
2103 } else if (v.back() == "xetex") {
2104 v.push_back("luatex");
2105 v.push_back("dviluatex");
2107 v.push_back("xhtml");
2108 v.push_back("text");
2114 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const format) const
2116 string const dformat = (format.empty() || format == "default") ?
2117 getDefaultOutputFormat() : format;
2118 DefaultFlavorCache::const_iterator it =
2119 default_flavors_.find(dformat);
2121 if (it != default_flavors_.end())
2124 OutputParams::FLAVOR result = OutputParams::LATEX;
2126 if (dformat == "xhtml")
2127 result = OutputParams::HTML;
2129 // Try to determine flavor of default output format
2130 vector<string> backs = backends();
2131 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2132 // Get shortest path to format
2133 Graph::EdgePath path;
2134 for (vector<string>::const_iterator it = backs.begin();
2135 it != backs.end(); ++it) {
2136 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2137 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2142 result = theConverters().getFlavor(path);
2145 // cache this flavor
2146 default_flavors_[dformat] = result;
2151 string BufferParams::getDefaultOutputFormat() const
2153 if (!default_output_format.empty()
2154 && default_output_format != "default")
2155 return default_output_format;
2158 || encoding().package() == Encoding::japanese) {
2159 vector<Format const *> const formats = exportableFormats(true);
2160 if (formats.empty())
2162 // return the first we find
2163 return formats.front()->name();
2165 return lyxrc.default_view_format;
2168 Font const BufferParams::getFont() const
2170 FontInfo f = documentClass().defaultfont();
2171 if (fonts_default_family == "rmdefault")
2172 f.setFamily(ROMAN_FAMILY);
2173 else if (fonts_default_family == "sfdefault")
2174 f.setFamily(SANS_FAMILY);
2175 else if (fonts_default_family == "ttdefault")
2176 f.setFamily(TYPEWRITER_FAMILY);
2177 return Font(f, language);
2181 bool BufferParams::isLatex() const
2183 return documentClass().outputType() == LATEX;
2187 bool BufferParams::isLiterate() const
2189 return documentClass().outputType() == LITERATE;
2193 bool BufferParams::isDocBook() const
2195 return documentClass().outputType() == DOCBOOK;
2199 void BufferParams::readPreamble(Lexer & lex)
2201 if (lex.getString() != "\\begin_preamble")
2202 lyxerr << "Error (BufferParams::readPreamble):"
2203 "consistency check failed." << endl;
2205 preamble = lex.getLongString("\\end_preamble");
2209 void BufferParams::readLocalLayout(Lexer & lex)
2211 if (lex.getString() != "\\begin_local_layout")
2212 lyxerr << "Error (BufferParams::readLocalLayout):"
2213 "consistency check failed." << endl;
2215 local_layout = lex.getLongString("\\end_local_layout");
2219 bool BufferParams::setLanguage(string const & lang)
2221 Language const *new_language = languages.getLanguage(lang);
2222 if (!new_language) {
2223 // Language lang was not found
2226 language = new_language;
2231 void BufferParams::readLanguage(Lexer & lex)
2233 if (!lex.next()) return;
2235 string const tmptok = lex.getString();
2237 // check if tmptok is part of tex_babel in tex-defs.h
2238 if (!setLanguage(tmptok)) {
2239 // Language tmptok was not found
2240 language = default_language;
2241 lyxerr << "Warning: Setting language `"
2242 << tmptok << "' to `" << language->lang()
2248 void BufferParams::readGraphicsDriver(Lexer & lex)
2253 string const tmptok = lex.getString();
2254 // check if tmptok is part of tex_graphics in tex_defs.h
2257 string const test = tex_graphics[n++];
2259 if (test == tmptok) {
2260 graphics_driver = tmptok;
2265 "Warning: graphics driver `$$Token' not recognized!\n"
2266 " Setting graphics driver to `default'.\n");
2267 graphics_driver = "default";
2274 void BufferParams::readBullets(Lexer & lex)
2279 int const index = lex.getInteger();
2281 int temp_int = lex.getInteger();
2282 user_defined_bullet(index).setFont(temp_int);
2283 temp_bullet(index).setFont(temp_int);
2285 user_defined_bullet(index).setCharacter(temp_int);
2286 temp_bullet(index).setCharacter(temp_int);
2288 user_defined_bullet(index).setSize(temp_int);
2289 temp_bullet(index).setSize(temp_int);
2293 void BufferParams::readBulletsLaTeX(Lexer & lex)
2295 // The bullet class should be able to read this.
2298 int const index = lex.getInteger();
2300 docstring const temp_str = lex.getDocString();
2302 user_defined_bullet(index).setText(temp_str);
2303 temp_bullet(index).setText(temp_str);
2307 void BufferParams::readModules(Lexer & lex)
2309 if (!lex.eatLine()) {
2310 lyxerr << "Error (BufferParams::readModules):"
2311 "Unexpected end of input." << endl;
2315 string mod = lex.getString();
2316 if (mod == "\\end_modules")
2318 addLayoutModule(mod);
2324 void BufferParams::readRemovedModules(Lexer & lex)
2326 if (!lex.eatLine()) {
2327 lyxerr << "Error (BufferParams::readRemovedModules):"
2328 "Unexpected end of input." << endl;
2332 string mod = lex.getString();
2333 if (mod == "\\end_removed_modules")
2335 removed_modules_.push_back(mod);
2338 // now we want to remove any removed modules that were previously
2339 // added. normally, that will be because default modules were added in
2340 // setBaseClass(), which gets called when \textclass is read at the
2341 // start of the read.
2342 list<string>::const_iterator rit = removed_modules_.begin();
2343 list<string>::const_iterator const ren = removed_modules_.end();
2344 for (; rit != ren; rit++) {
2345 LayoutModuleList::iterator const mit = layout_modules_.begin();
2346 LayoutModuleList::iterator const men = layout_modules_.end();
2347 LayoutModuleList::iterator found = find(mit, men, *rit);
2350 layout_modules_.erase(found);
2355 void BufferParams::readIncludeonly(Lexer & lex)
2357 if (!lex.eatLine()) {
2358 lyxerr << "Error (BufferParams::readIncludeonly):"
2359 "Unexpected end of input." << endl;
2363 string child = lex.getString();
2364 if (child == "\\end_includeonly")
2366 included_children_.push_back(child);
2372 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2374 switch (papersize) {
2376 // could be anything, so don't guess
2378 case PAPER_CUSTOM: {
2379 if (purpose == XDVI && !paperwidth.empty() &&
2380 !paperheight.empty()) {
2381 // heightxwidth<unit>
2382 string first = paperwidth;
2383 string second = paperheight;
2384 if (orientation == ORIENTATION_LANDSCAPE)
2387 return first.erase(first.length() - 2)
2393 // dvips and dvipdfm do not know this
2394 if (purpose == DVIPS || purpose == DVIPDFM)
2398 if (purpose == DVIPS || purpose == DVIPDFM)
2402 if (purpose == DVIPS || purpose == DVIPDFM)
2412 if (purpose == DVIPS || purpose == DVIPDFM)
2416 if (purpose == DVIPS || purpose == DVIPDFM)
2420 if (purpose == DVIPS || purpose == DVIPDFM)
2424 if (purpose == DVIPS || purpose == DVIPDFM)
2428 if (purpose == DVIPS || purpose == DVIPDFM)
2432 // dvipdfm does not know this
2433 if (purpose == DVIPDFM)
2437 if (purpose == DVIPDFM)
2441 if (purpose == DVIPS || purpose == DVIPDFM)
2445 if (purpose == DVIPS || purpose == DVIPDFM)
2449 if (purpose == DVIPS || purpose == DVIPDFM)
2453 if (purpose == DVIPS || purpose == DVIPDFM)
2457 if (purpose == DVIPS || purpose == DVIPDFM)
2461 if (purpose == DVIPS || purpose == DVIPDFM)
2465 if (purpose == DVIPS || purpose == DVIPDFM)
2469 if (purpose == DVIPS || purpose == DVIPDFM)
2473 if (purpose == DVIPS || purpose == DVIPDFM)
2477 if (purpose == DVIPS || purpose == DVIPDFM)
2481 if (purpose == DVIPS || purpose == DVIPDFM)
2485 if (purpose == DVIPS || purpose == DVIPDFM)
2489 if (purpose == DVIPS || purpose == DVIPDFM)
2493 if (purpose == DVIPS || purpose == DVIPDFM)
2497 if (purpose == DVIPS || purpose == DVIPDFM)
2500 case PAPER_USEXECUTIVE:
2501 // dvipdfm does not know this
2502 if (purpose == DVIPDFM)
2507 case PAPER_USLETTER:
2509 if (purpose == XDVI)
2516 string const BufferParams::dvips_options() const
2521 && papersize == PAPER_CUSTOM
2522 && !lyxrc.print_paper_dimension_flag.empty()
2523 && !paperwidth.empty()
2524 && !paperheight.empty()) {
2525 // using a custom papersize
2526 result = lyxrc.print_paper_dimension_flag;
2527 result += ' ' + paperwidth;
2528 result += ',' + paperheight;
2530 string const paper_option = paperSizeName(DVIPS);
2531 if (!paper_option.empty() && (paper_option != "letter" ||
2532 orientation != ORIENTATION_LANDSCAPE)) {
2533 // dvips won't accept -t letter -t landscape.
2534 // In all other cases, include the paper size
2536 result = lyxrc.print_paper_flag;
2537 result += ' ' + paper_option;
2540 if (orientation == ORIENTATION_LANDSCAPE &&
2541 papersize != PAPER_CUSTOM)
2542 result += ' ' + lyxrc.print_landscape_flag;
2547 string const BufferParams::font_encoding() const
2549 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2553 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2555 if (lang_package != "auto" && lang_package != "babel"
2556 && lang_package != "default" && lang_package != "none")
2557 return lang_package;
2558 if (lyxrc.language_package_selection == LyXRC::LP_CUSTOM)
2559 return lyxrc.language_custom_package;
2560 // suppress the babel call if there is no BabelName defined
2561 // for the document language in the lib/languages file and if no
2562 // other languages are used (lang_opts is then empty)
2563 if (lang_opts.empty())
2565 // either a specific language (AsBabelOptions setting in
2566 // lib/languages) or the prefs require the languages to
2567 // be submitted to babel itself (not the class).
2569 return "\\usepackage[" + lang_opts + "]{babel}";
2570 return "\\usepackage{babel}";
2574 docstring BufferParams::getGraphicsDriver(string const & package) const
2578 if (package == "geometry") {
2579 if (graphics_driver == "dvips"
2580 || graphics_driver == "dvipdfm"
2581 || graphics_driver == "pdftex"
2582 || graphics_driver == "vtex")
2583 result = from_ascii(graphics_driver);
2584 else if (graphics_driver == "dvipdfmx")
2585 result = from_ascii("dvipdfm");
2592 void BufferParams::writeEncodingPreamble(otexstream & os,
2593 LaTeXFeatures & features) const
2595 // XeTeX does not need this
2596 if (features.runparams().flavor == OutputParams::XETEX)
2598 // LuaTeX neither, but with tex fonts, we need to load
2599 // the luainputenc package.
2600 if (features.runparams().flavor == OutputParams::LUATEX
2601 || features.runparams().flavor == OutputParams::DVILUATEX) {
2602 if (!useNonTeXFonts && inputenc != "default"
2603 && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc)
2604 || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) {
2605 os << "\\usepackage[utf8]{luainputenc}\n";
2609 if (inputenc == "auto") {
2610 string const doc_encoding =
2611 language->encoding()->latexName();
2612 Encoding::Package const package =
2613 language->encoding()->package();
2615 // Create a list with all the input encodings used
2617 set<string> encodings =
2618 features.getEncodingSet(doc_encoding);
2620 // If the "japanese" package (i.e. pLaTeX) is used,
2621 // inputenc must be omitted.
2622 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2623 if (package == Encoding::japanese)
2624 features.require("japanese");
2626 if ((!encodings.empty() || package == Encoding::inputenc)
2627 && !features.isRequired("japanese")) {
2628 os << "\\usepackage[";
2629 set<string>::const_iterator it = encodings.begin();
2630 set<string>::const_iterator const end = encodings.end();
2632 os << from_ascii(*it);
2635 for (; it != end; ++it)
2636 os << ',' << from_ascii(*it);
2637 if (package == Encoding::inputenc) {
2638 if (!encodings.empty())
2640 os << from_ascii(doc_encoding);
2642 os << "]{inputenc}\n";
2644 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2645 if (language->encoding()->name() == "utf8-cjk"
2646 && LaTeXFeatures::isAvailable("CJKutf8"))
2647 os << "\\usepackage{CJKutf8}\n";
2649 os << "\\usepackage{CJK}\n";
2651 } else if (inputenc != "default") {
2652 switch (encoding().package()) {
2653 case Encoding::none:
2654 case Encoding::japanese:
2656 case Encoding::inputenc:
2657 // do not load inputenc if japanese is used
2658 if (features.isRequired("japanese"))
2660 os << "\\usepackage[" << from_ascii(inputenc)
2664 if (encoding().name() == "utf8-cjk"
2665 && LaTeXFeatures::isAvailable("CJKutf8"))
2666 os << "\\usepackage{CJKutf8}\n";
2668 os << "\\usepackage{CJK}\n";
2673 // The encoding "armscii8" (for Armenian) is only available when
2674 // the package "armtex" is loaded.
2675 if (language->encoding()->latexName() == "armscii8"
2676 || inputenc == "armscii8")
2677 os << "\\usepackage{armtex}\n";
2681 string const BufferParams::parseFontName(string const & name) const
2683 string mangled = name;
2684 size_t const idx = mangled.find('[');
2685 if (idx == string::npos || idx == 0)
2688 return mangled.substr(0, idx - 1);
2692 string const BufferParams::loadFonts(string const & rm,
2693 string const & sf, string const & tt,
2694 bool const & sc, bool const & osf,
2695 int const & sfscale, int const & ttscale,
2696 bool const & use_systemfonts,
2697 LaTeXFeatures & features) const
2699 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2700 several packages have been replaced by others, that might not
2701 be installed on every system. We have to take care for that
2702 (see psnfss.pdf). We try to support all psnfss fonts as well
2703 as the fonts that have become de facto standard in the LaTeX
2704 world (e.g. Latin Modern). We do not support obsolete fonts
2705 (like PSLatex). In general, it should be possible to mix any
2706 rm font with any sf or tt font, respectively. (JSpitzm)
2708 -- separate math fonts.
2711 if (rm == "default" && sf == "default" && tt == "default")
2717 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
2718 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
2719 * Mapping=tex-text option assures TeX ligatures (such as "--")
2720 * are resolved. Note that tt does not use these ligatures.
2722 * -- add more GUI options?
2723 * -- add more fonts (fonts for other scripts)
2724 * -- if there's a way to find out if a font really supports
2725 * OldStyle, enable/disable the widget accordingly.
2727 if (use_systemfonts && features.isAvailable("fontspec")) {
2728 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
2729 // However, until v.2 (2010/07/11) fontspec only knew
2730 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
2731 // was introduced for both XeTeX and LuaTeX (LuaTeX
2732 // didn't understand "Mapping=tex-text", while XeTeX
2733 // understood both. With most recent versions, both
2734 // variants are understood by both engines. However,
2735 // we want to provide support for at least TeXLive 2009
2736 // (for XeTeX; LuaTeX is only supported as of v.2)
2737 string const texmapping =
2738 (features.runparams().flavor == OutputParams::XETEX) ?
2739 "Mapping=tex-text" : "Ligatures=TeX";
2740 if (rm != "default") {
2741 os << "\\setmainfont[" << texmapping;
2743 os << ",Numbers=OldStyle";
2744 os << "]{" << parseFontName(rm) << "}\n";
2746 if (sf != "default") {
2747 string const sans = parseFontName(sf);
2749 os << "\\setsansfont[Scale="
2750 << float(sfscale) / 100
2751 << "," << texmapping << "]{"
2754 os << "\\setsansfont[" << texmapping << "]{"
2757 if (tt != "default") {
2758 string const mono = parseFontName(tt);
2760 os << "\\setmonofont[Scale="
2761 << float(ttscale) / 100
2765 os << "\\setmonofont{"
2772 // Computer Modern (must be explicitly selectable -- there might be classes
2773 // that define a different default font!
2775 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2776 // osf for Computer Modern needs eco.sty
2778 os << "\\usepackage{eco}\n";
2780 // Latin Modern Roman
2781 else if (rm == "lmodern")
2782 os << "\\usepackage{lmodern}\n";
2784 else if (rm == "ae") {
2785 // not needed when using OT1 font encoding.
2786 if (font_encoding() != "default")
2787 os << "\\usepackage{ae,aecompl}\n";
2790 else if (rm == "times") {
2791 // try to load the best available package
2792 if (LaTeXFeatures::isAvailable("mathptmx"))
2793 os << "\\usepackage{mathptmx}\n";
2794 else if (LaTeXFeatures::isAvailable("mathptm"))
2795 os << "\\usepackage{mathptm}\n";
2797 os << "\\usepackage{times}\n";
2800 else if (rm == "palatino") {
2801 // try to load the best available package
2802 if (LaTeXFeatures::isAvailable("mathpazo")) {
2803 os << "\\usepackage";
2809 // "osf" includes "sc"!
2813 os << "{mathpazo}\n";
2815 else if (LaTeXFeatures::isAvailable("mathpple"))
2816 os << "\\usepackage{mathpple}\n";
2818 os << "\\usepackage{palatino}\n";
2821 else if (rm == "utopia") {
2822 // fourier supersedes utopia.sty, but does
2823 // not work with OT1 encoding.
2824 if (LaTeXFeatures::isAvailable("fourier")
2825 && font_encoding() != "default") {
2826 os << "\\usepackage";
2837 os << "{fourier}\n";
2840 os << "\\usepackage{utopia}\n";
2842 // Bera (complete fontset)
2843 else if (rm == "bera" && sf == "default" && tt == "default")
2844 os << "\\usepackage{bera}\n";
2846 else if (rm != "default")
2847 os << "\\usepackage" << "{" << rm << "}\n";
2850 // Helvetica, Bera Sans
2851 if (sf == "helvet" || sf == "berasans") {
2853 os << "\\usepackage[scaled=" << float(sfscale) / 100
2854 << "]{" << sf << "}\n";
2856 os << "\\usepackage{" << sf << "}\n";
2859 else if (sf == "avant")
2860 os << "\\usepackage{" << sf << "}\n";
2861 // Computer Modern, Latin Modern, CM Bright
2862 else if (sf != "default")
2863 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2865 // monospaced/typewriter
2866 // Courier, LuxiMono
2867 if (tt == "luximono" || tt == "beramono") {
2869 os << "\\usepackage[scaled=" << float(ttscale) / 100
2870 << "]{" << tt << "}\n";
2872 os << "\\usepackage{" << tt << "}\n";
2875 else if (tt == "courier" )
2876 os << "\\usepackage{" << tt << "}\n";
2877 // Computer Modern, Latin Modern, CM Bright
2878 else if (tt != "default")
2879 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2885 Encoding const & BufferParams::encoding() const
2887 // FIXME: actually, we should check for the flavor
2888 // or runparams.isFullyUnicode() here:
2889 // This check will not work with XeTeX/LuaTeX and tex fonts.
2890 // Thus we have to reset the encoding in Buffer::makeLaTeXFile.
2892 return *(encodings.fromLaTeXName("utf8-plain"));
2893 if (inputenc == "auto" || inputenc == "default")
2894 return *language->encoding();
2895 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2898 LYXERR0("Unknown inputenc value `" << inputenc
2899 << "'. Using `auto' instead.");
2900 return *language->encoding();
2904 CiteEngine BufferParams::citeEngine() const
2906 // FIXME the class should provide the numerical/
2907 // authoryear choice
2908 if (documentClass().provides("natbib")
2909 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2910 return ENGINE_NATBIB_AUTHORYEAR;
2911 return cite_engine_;
2915 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2917 cite_engine_ = cite_engine;