2 * \file BufferParams.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Alfredo Braunstein
7 * \author Lars Gullik Bjønnes
8 * \author Jean-Marc Lasgouttes
10 * \author André Pönitz
11 * \author Martin Vermeer
13 * Full author contact details are available in file CREDITS.
18 #include "BufferParams.h"
21 #include "LayoutFile.h"
22 #include "BranchList.h"
23 #include "buffer_funcs.h"
27 #include "Converter.h"
30 #include "IndicesList.h"
32 #include "LaTeXFeatures.h"
33 #include "LaTeXFonts.h"
34 #include "ModuleList.h"
38 #include "OutputParams.h"
42 #include "PDFOptions.h"
44 #include "frontends/alert.h"
46 #include "insets/InsetListingsParams.h"
48 #include "support/convert.h"
49 #include "support/debug.h"
50 #include "support/docstream.h"
51 #include "support/FileName.h"
52 #include "support/filetools.h"
53 #include "support/gettext.h"
54 #include "support/Messages.h"
55 #include "support/Translator.h"
56 #include "support/lstrings.h"
62 using namespace lyx::support;
65 static char const * const string_paragraph_separation[] = {
70 static char const * const string_quotes_language[] = {
71 "english", "swedish", "german", "polish", "french", "danish", ""
75 static char const * const string_papersize[] = {
76 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
77 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
78 "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
79 "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
80 "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
85 static char const * const string_orientation[] = {
86 "portrait", "landscape", ""
90 static char const * const string_footnotekinds[] = {
91 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
95 static char const * const tex_graphics[] = {
96 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
97 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
98 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
99 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
110 // Paragraph separation
111 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
114 ParSepTranslator const init_parseptranslator()
116 ParSepTranslator translator
117 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
118 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
123 ParSepTranslator const & parseptranslator()
125 static ParSepTranslator translator = init_parseptranslator();
131 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
134 QuotesLangTranslator const init_quoteslangtranslator()
136 QuotesLangTranslator translator
137 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
138 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
139 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
140 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
141 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
142 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
147 QuotesLangTranslator const & quoteslangtranslator()
149 static QuotesLangTranslator translator = init_quoteslangtranslator();
155 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
158 static PaperSizeTranslator initPaperSizeTranslator()
160 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
161 translator.addPair(string_papersize[1], PAPER_CUSTOM);
162 translator.addPair(string_papersize[2], PAPER_USLETTER);
163 translator.addPair(string_papersize[3], PAPER_USLEGAL);
164 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
165 translator.addPair(string_papersize[5], PAPER_A0);
166 translator.addPair(string_papersize[6], PAPER_A1);
167 translator.addPair(string_papersize[7], PAPER_A2);
168 translator.addPair(string_papersize[8], PAPER_A3);
169 translator.addPair(string_papersize[9], PAPER_A4);
170 translator.addPair(string_papersize[10], PAPER_A5);
171 translator.addPair(string_papersize[11], PAPER_A6);
172 translator.addPair(string_papersize[12], PAPER_B0);
173 translator.addPair(string_papersize[13], PAPER_B1);
174 translator.addPair(string_papersize[14], PAPER_B2);
175 translator.addPair(string_papersize[15], PAPER_B3);
176 translator.addPair(string_papersize[16], PAPER_B4);
177 translator.addPair(string_papersize[17], PAPER_B5);
178 translator.addPair(string_papersize[18], PAPER_B6);
179 translator.addPair(string_papersize[19], PAPER_C0);
180 translator.addPair(string_papersize[20], PAPER_C1);
181 translator.addPair(string_papersize[21], PAPER_C2);
182 translator.addPair(string_papersize[22], PAPER_C3);
183 translator.addPair(string_papersize[23], PAPER_C4);
184 translator.addPair(string_papersize[24], PAPER_C5);
185 translator.addPair(string_papersize[25], PAPER_C6);
186 translator.addPair(string_papersize[26], PAPER_JISB0);
187 translator.addPair(string_papersize[27], PAPER_JISB1);
188 translator.addPair(string_papersize[28], PAPER_JISB2);
189 translator.addPair(string_papersize[29], PAPER_JISB3);
190 translator.addPair(string_papersize[30], PAPER_JISB4);
191 translator.addPair(string_papersize[31], PAPER_JISB5);
192 translator.addPair(string_papersize[32], PAPER_JISB6);
197 PaperSizeTranslator const & papersizetranslator()
199 static PaperSizeTranslator translator = initPaperSizeTranslator();
205 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
208 PaperOrientationTranslator const init_paperorientationtranslator()
210 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
211 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
216 PaperOrientationTranslator const & paperorientationtranslator()
218 static PaperOrientationTranslator translator = init_paperorientationtranslator();
224 typedef Translator<int, PageSides> SidesTranslator;
227 SidesTranslator const init_sidestranslator()
229 SidesTranslator translator(1, OneSide);
230 translator.addPair(2, TwoSides);
235 SidesTranslator const & sidestranslator()
237 static SidesTranslator translator = init_sidestranslator();
243 typedef Translator<int, BufferParams::Package> PackageTranslator;
246 PackageTranslator const init_packagetranslator()
248 PackageTranslator translator(0, BufferParams::package_off);
249 translator.addPair(1, BufferParams::package_auto);
250 translator.addPair(2, BufferParams::package_on);
255 PackageTranslator const & packagetranslator()
257 static PackageTranslator translator = init_packagetranslator();
263 typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator;
266 CiteEngineTypeTranslator const init_citeenginetypetranslator()
268 CiteEngineTypeTranslator translator("authoryear", ENGINE_TYPE_AUTHORYEAR);
269 translator.addPair("numerical", ENGINE_TYPE_NUMERICAL);
270 translator.addPair("default", ENGINE_TYPE_DEFAULT);
275 CiteEngineTypeTranslator const & citeenginetypetranslator()
277 static CiteEngineTypeTranslator translator = init_citeenginetypetranslator();
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)
340 return new BufferParams::Impl(*ptr);
344 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
350 BufferParams::BufferParams()
353 setBaseClass(defaultBaseclass());
355 paragraph_separation = ParagraphIndentSeparation;
356 quotes_language = InsetQuotes::EnglishQuotes;
357 fontsize = "default";
360 papersize = PAPER_DEFAULT;
361 orientation = ORIENTATION_PORTRAIT;
362 use_geometry = false;
363 cite_engine_.push_back("basic");
364 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
365 biblio_style = "plain";
366 use_bibtopic = false;
368 trackChanges = false;
369 outputChanges = false;
370 use_default_options = true;
371 maintain_unincluded_children = false;
374 language = default_language;
376 fonts_roman = "default";
377 fonts_sans = "default";
378 fonts_typewriter = "default";
380 fonts_default_family = "default";
381 useNonTeXFonts = false;
382 fonts_expert_sc = false;
383 fonts_old_figures = false;
384 fonts_sans_scale = 100;
385 fonts_typewriter_scale = 100;
387 lang_package = "default";
388 graphics_driver = "default";
389 default_output_format = "default";
390 bibtex_command = "default";
391 index_command = "default";
394 listings_params = string();
395 pagestyle = "default";
396 suppress_date = false;
397 justification = true;
398 // no color is the default (white)
399 backgroundcolor = lyx::rgbFromHexName("#ffffff");
400 isbackgroundcolor = false;
401 // no color is the default (black)
402 fontcolor = lyx::rgbFromHexName("#000000");
404 // light gray is the default font color for greyed-out notes
405 notefontcolor = lyx::rgbFromHexName("#cccccc");
406 boxbgcolor = lyx::rgbFromHexName("#ff0000");
407 compressed = lyxrc.save_compressed;
408 for (int iter = 0; iter < 4; ++iter) {
409 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
410 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
413 indiceslist().addDefault(B_("Index"));
414 html_be_strict = false;
415 html_math_output = MathML;
416 html_math_img_scale = 1.0;
417 html_css_as_file = false;
424 docstring BufferParams::B_(string const & l10n) const
426 LASSERT(language, return from_utf8(l10n));
427 return getMessages(language->code()).get(l10n);
431 BufferParams::Package BufferParams::use_package(std::string const & p) const
433 PackageMap::const_iterator it = use_packages.find(p);
434 if (it == use_packages.end())
440 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
446 map<string, string> const & BufferParams::auto_packages()
448 static map<string, string> packages;
449 if (packages.empty()) {
450 // adding a package here implies a file format change!
451 packages["amsmath"] =
452 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
453 packages["amssymb"] =
454 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
456 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
458 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
459 packages["mathdots"] =
460 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
461 packages["mathtools"] =
462 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
464 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
465 packages["stackrel"] =
466 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
467 packages["stmaryrd"] =
468 N_("The LaTeX package stmaryrd is only used if symbols from the St Mary's Road symbol font for theoretical computer science are inserted into formulas");
469 packages["undertilde"] =
470 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
476 AuthorList & BufferParams::authors()
478 return pimpl_->authorlist;
482 AuthorList const & BufferParams::authors() const
484 return pimpl_->authorlist;
488 BranchList & BufferParams::branchlist()
490 return pimpl_->branchlist;
494 BranchList const & BufferParams::branchlist() const
496 return pimpl_->branchlist;
500 IndicesList & BufferParams::indiceslist()
502 return pimpl_->indiceslist;
506 IndicesList const & BufferParams::indiceslist() const
508 return pimpl_->indiceslist;
512 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
514 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
515 return pimpl_->temp_bullets[index];
519 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
521 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
522 return pimpl_->temp_bullets[index];
526 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
528 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
529 return pimpl_->user_defined_bullets[index];
533 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
535 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
536 return pimpl_->user_defined_bullets[index];
540 Spacing & BufferParams::spacing()
542 return pimpl_->spacing;
546 Spacing const & BufferParams::spacing() const
548 return pimpl_->spacing;
552 PDFOptions & BufferParams::pdfoptions()
554 return pimpl_->pdfoptions;
558 PDFOptions const & BufferParams::pdfoptions() const
560 return pimpl_->pdfoptions;
564 HSpace const & BufferParams::getIndentation() const
566 return pimpl_->indentation;
570 void BufferParams::setIndentation(HSpace const & indent)
572 pimpl_->indentation = indent;
576 VSpace const & BufferParams::getDefSkip() const
578 return pimpl_->defskip;
582 void BufferParams::setDefSkip(VSpace const & vs)
584 // DEFSKIP will cause an infinite loop
585 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
586 pimpl_->defskip = vs;
590 string BufferParams::readToken(Lexer & lex, string const & token,
591 FileName const & filepath)
593 if (token == "\\textclass") {
595 string const classname = lex.getString();
596 // if there exists a local layout file, ignore the system one
597 // NOTE: in this case, the textclass (.cls file) is assumed to
600 LayoutFileList & bcl = LayoutFileList::get();
601 if (!filepath.empty())
602 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
603 // that returns non-empty if a "local" layout file is found.
607 setBaseClass(classname);
608 // We assume that a tex class exists for local or unknown
609 // layouts so this warning, will only be given for system layouts.
610 if (!baseClass()->isTeXClassAvailable()) {
611 docstring const desc =
612 translateIfPossible(from_utf8(baseClass()->description()));
613 docstring const prereqs =
614 from_utf8(baseClass()->prerequisites());
615 docstring const msg =
616 bformat(_("The selected document class\n"
618 "requires external files that are not available.\n"
619 "The document class can still be used, but the\n"
620 "document cannot be compiled until the following\n"
621 "prerequisites are installed:\n"
623 "See section 3.1.2.2 (Class Availability) of the\n"
624 "User's Guide for more information."), desc, prereqs);
625 frontend::Alert::warning(_("Document class not available"),
628 } else if (token == "\\begin_preamble") {
630 } else if (token == "\\begin_local_layout") {
631 readLocalLayout(lex, false);
632 } else if (token == "\\begin_forced_local_layout") {
633 readLocalLayout(lex, true);
634 } else if (token == "\\begin_modules") {
636 } else if (token == "\\begin_removed_modules") {
637 readRemovedModules(lex);
638 } else if (token == "\\begin_includeonly") {
639 readIncludeonly(lex);
640 } else if (token == "\\maintain_unincluded_children") {
641 lex >> maintain_unincluded_children;
642 } else if (token == "\\options") {
644 options = lex.getString();
645 } else if (token == "\\use_default_options") {
646 lex >> use_default_options;
647 } else if (token == "\\master") {
649 master = lex.getString();
650 } else if (token == "\\suppress_date") {
651 lex >> suppress_date;
652 } else if (token == "\\justification") {
653 lex >> justification;
654 } else if (token == "\\language") {
656 } else if (token == "\\language_package") {
658 lang_package = lex.getString();
659 } else if (token == "\\inputencoding") {
661 } else if (token == "\\graphics") {
662 readGraphicsDriver(lex);
663 } else if (token == "\\default_output_format") {
664 lex >> default_output_format;
665 } else if (token == "\\bibtex_command") {
667 bibtex_command = lex.getString();
668 } else if (token == "\\index_command") {
670 index_command = lex.getString();
671 } else if (token == "\\fontencoding") {
673 fontenc = lex.getString();
674 } else if (token == "\\font_roman") {
676 fonts_roman = lex.getString();
677 } else if (token == "\\font_sans") {
679 fonts_sans = lex.getString();
680 } else if (token == "\\font_typewriter") {
682 fonts_typewriter = lex.getString();
683 } else if (token == "\\font_math") {
685 fonts_math = lex.getString();
686 } else if (token == "\\font_default_family") {
687 lex >> fonts_default_family;
688 } else if (token == "\\use_non_tex_fonts") {
689 lex >> useNonTeXFonts;
690 } else if (token == "\\font_sc") {
691 lex >> fonts_expert_sc;
692 } else if (token == "\\font_osf") {
693 lex >> fonts_old_figures;
694 } else if (token == "\\font_sf_scale") {
695 lex >> fonts_sans_scale;
696 } else if (token == "\\font_tt_scale") {
697 lex >> fonts_typewriter_scale;
698 } else if (token == "\\font_cjk") {
700 } else if (token == "\\paragraph_separation") {
703 paragraph_separation = parseptranslator().find(parsep);
704 } else if (token == "\\paragraph_indentation") {
706 string indentation = lex.getString();
707 pimpl_->indentation = HSpace(indentation);
708 } else if (token == "\\defskip") {
710 string const defskip = lex.getString();
711 pimpl_->defskip = VSpace(defskip);
712 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
714 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
715 } else if (token == "\\quotes_language") {
718 quotes_language = quoteslangtranslator().find(quotes_lang);
719 } else if (token == "\\papersize") {
722 papersize = papersizetranslator().find(ppsize);
723 } else if (token == "\\use_geometry") {
725 } else if (token == "\\use_package") {
730 use_package(package, packagetranslator().find(use));
731 } else if (token == "\\cite_engine") {
733 vector<string> engine = getVectorFromString(lex.getString());
734 setCiteEngine(engine);
735 } else if (token == "\\cite_engine_type") {
738 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
739 } else if (token == "\\biblio_style") {
741 biblio_style = lex.getString();
742 } else if (token == "\\use_bibtopic") {
744 } else if (token == "\\use_indices") {
746 } else if (token == "\\tracking_changes") {
748 } else if (token == "\\output_changes") {
749 lex >> outputChanges;
750 } else if (token == "\\branch") {
752 docstring branch = lex.getDocString();
753 branchlist().add(branch);
756 string const tok = lex.getString();
757 if (tok == "\\end_branch")
759 Branch * branch_ptr = branchlist().find(branch);
760 if (tok == "\\selected") {
763 branch_ptr->setSelected(lex.getInteger());
765 if (tok == "\\filename_suffix") {
768 branch_ptr->setFileNameSuffix(lex.getInteger());
770 if (tok == "\\color") {
772 string color = lex.getString();
774 branch_ptr->setColor(color);
775 // Update also the Color table:
777 color = lcolor.getX11Name(Color_background);
779 lcolor.setColor(to_utf8(branch), color);
782 } else if (token == "\\index") {
784 docstring index = lex.getDocString();
786 indiceslist().add(index);
789 string const tok = lex.getString();
790 if (tok == "\\end_index")
792 Index * index_ptr = indiceslist().find(index);
793 if (tok == "\\shortcut") {
795 shortcut = lex.getDocString();
797 index_ptr->setShortcut(shortcut);
799 if (tok == "\\color") {
801 string color = lex.getString();
803 index_ptr->setColor(color);
804 // Update also the Color table:
806 color = lcolor.getX11Name(Color_background);
808 if (!shortcut.empty())
809 lcolor.setColor(to_utf8(shortcut), color);
812 } else if (token == "\\author") {
814 istringstream ss(lex.getString());
817 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
818 } else if (token == "\\paperorientation") {
821 orientation = paperorientationtranslator().find(orient);
822 } else if (token == "\\backgroundcolor") {
824 backgroundcolor = lyx::rgbFromHexName(lex.getString());
825 isbackgroundcolor = true;
826 } else if (token == "\\fontcolor") {
828 fontcolor = lyx::rgbFromHexName(lex.getString());
830 } else if (token == "\\notefontcolor") {
832 string color = lex.getString();
833 notefontcolor = lyx::rgbFromHexName(color);
834 lcolor.setColor("notefontcolor", color);
835 } else if (token == "\\boxbgcolor") {
837 string color = lex.getString();
838 boxbgcolor = lyx::rgbFromHexName(color);
839 lcolor.setColor("boxbgcolor", color);
840 } else if (token == "\\paperwidth") {
842 } else if (token == "\\paperheight") {
844 } else if (token == "\\leftmargin") {
846 } else if (token == "\\topmargin") {
848 } else if (token == "\\rightmargin") {
850 } else if (token == "\\bottommargin") {
852 } else if (token == "\\headheight") {
854 } else if (token == "\\headsep") {
856 } else if (token == "\\footskip") {
858 } else if (token == "\\columnsep") {
860 } else if (token == "\\paperfontsize") {
862 } else if (token == "\\papercolumns") {
864 } else if (token == "\\listings_params") {
867 listings_params = InsetListingsParams(par).params();
868 } else if (token == "\\papersides") {
871 sides = sidestranslator().find(psides);
872 } else if (token == "\\paperpagestyle") {
874 } else if (token == "\\bullet") {
876 } else if (token == "\\bulletLaTeX") {
877 readBulletsLaTeX(lex);
878 } else if (token == "\\secnumdepth") {
880 } else if (token == "\\tocdepth") {
882 } else if (token == "\\spacing") {
886 if (nspacing == "other") {
889 spacing().set(spacetranslator().find(nspacing), tmp_val);
890 } else if (token == "\\float_placement") {
891 lex >> float_placement;
893 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
894 string toktmp = pdfoptions().readToken(lex, token);
895 if (!toktmp.empty()) {
896 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
900 } else if (token == "\\html_math_output") {
903 html_math_output = static_cast<MathOutput>(temp);
904 } else if (token == "\\html_be_strict") {
905 lex >> html_be_strict;
906 } else if (token == "\\html_css_as_file") {
907 lex >> html_css_as_file;
908 } else if (token == "\\html_math_img_scale") {
909 lex >> html_math_img_scale;
910 } else if (token == "\\html_latex_start") {
912 html_latex_start = lex.getString();
913 } else if (token == "\\html_latex_end") {
915 html_latex_end = lex.getString();
916 } else if (token == "\\output_sync") {
918 } else if (token == "\\output_sync_macro") {
919 lex >> output_sync_macro;
920 } else if (token == "\\use_refstyle") {
923 lyxerr << "BufferParams::readToken(): Unknown token: " <<
932 void BufferParams::writeFile(ostream & os) const
934 // The top of the file is written by the buffer.
935 // Prints out the buffer info into the .lyx file given by file
938 os << "\\textclass " << baseClass()->name() << '\n';
941 if (!preamble.empty()) {
942 // remove '\n' from the end of preamble
943 string const tmppreamble = rtrim(preamble, "\n");
944 os << "\\begin_preamble\n"
946 << "\n\\end_preamble\n";
950 if (!options.empty()) {
951 os << "\\options " << options << '\n';
954 // use the class options defined in the layout?
955 os << "\\use_default_options "
956 << convert<string>(use_default_options) << "\n";
958 // the master document
959 if (!master.empty()) {
960 os << "\\master " << master << '\n';
964 if (!removed_modules_.empty()) {
965 os << "\\begin_removed_modules" << '\n';
966 list<string>::const_iterator it = removed_modules_.begin();
967 list<string>::const_iterator en = removed_modules_.end();
968 for (; it != en; ++it)
970 os << "\\end_removed_modules" << '\n';
974 if (!layout_modules_.empty()) {
975 os << "\\begin_modules" << '\n';
976 LayoutModuleList::const_iterator it = layout_modules_.begin();
977 LayoutModuleList::const_iterator en = layout_modules_.end();
978 for (; it != en; ++it)
980 os << "\\end_modules" << '\n';
984 if (!included_children_.empty()) {
985 os << "\\begin_includeonly" << '\n';
986 list<string>::const_iterator it = included_children_.begin();
987 list<string>::const_iterator en = included_children_.end();
988 for (; it != en; ++it)
990 os << "\\end_includeonly" << '\n';
992 os << "\\maintain_unincluded_children "
993 << convert<string>(maintain_unincluded_children) << '\n';
995 // local layout information
996 string const local_layout = getLocalLayout(false);
997 if (!local_layout.empty()) {
998 // remove '\n' from the end
999 string const tmplocal = rtrim(local_layout, "\n");
1000 os << "\\begin_local_layout\n"
1002 << "\n\\end_local_layout\n";
1004 string const forced_local_layout = getLocalLayout(true);
1005 if (!forced_local_layout.empty()) {
1006 // remove '\n' from the end
1007 string const tmplocal = rtrim(forced_local_layout, "\n");
1008 os << "\\begin_forced_local_layout\n"
1010 << "\n\\end_forced_local_layout\n";
1013 // then the text parameters
1014 if (language != ignore_language)
1015 os << "\\language " << language->lang() << '\n';
1016 os << "\\language_package " << lang_package
1017 << "\n\\inputencoding " << inputenc
1018 << "\n\\fontencoding " << fontenc
1019 << "\n\\font_roman " << fonts_roman
1020 << "\n\\font_sans " << fonts_sans
1021 << "\n\\font_typewriter " << fonts_typewriter
1022 << "\n\\font_math " << fonts_math
1023 << "\n\\font_default_family " << fonts_default_family
1024 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1025 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1026 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1027 << "\n\\font_sf_scale " << fonts_sans_scale
1028 << "\n\\font_tt_scale " << fonts_typewriter_scale
1030 if (!fonts_cjk.empty()) {
1031 os << "\\font_cjk " << fonts_cjk << '\n';
1033 os << "\\graphics " << graphics_driver << '\n';
1034 os << "\\default_output_format " << default_output_format << '\n';
1035 os << "\\output_sync " << output_sync << '\n';
1036 if (!output_sync_macro.empty())
1037 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1038 os << "\\bibtex_command " << bibtex_command << '\n';
1039 os << "\\index_command " << index_command << '\n';
1041 if (!float_placement.empty()) {
1042 os << "\\float_placement " << float_placement << '\n';
1044 os << "\\paperfontsize " << fontsize << '\n';
1046 spacing().writeFile(os);
1047 pdfoptions().writeFile(os);
1049 os << "\\papersize " << string_papersize[papersize]
1050 << "\n\\use_geometry " << convert<string>(use_geometry);
1051 map<string, string> const & packages = auto_packages();
1052 for (map<string, string>::const_iterator it = packages.begin();
1053 it != packages.end(); ++it)
1054 os << "\n\\use_package " << it->first << ' '
1055 << use_package(it->first);
1057 os << "\n\\cite_engine ";
1059 if (!cite_engine_.empty()) {
1060 LayoutModuleList::const_iterator be = cite_engine_.begin();
1061 LayoutModuleList::const_iterator en = cite_engine_.end();
1062 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1071 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1072 << "\n\\biblio_style " << biblio_style
1073 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1074 << "\n\\use_indices " << convert<string>(use_indices)
1075 << "\n\\paperorientation " << string_orientation[orientation]
1076 << "\n\\suppress_date " << convert<string>(suppress_date)
1077 << "\n\\justification " << convert<string>(justification)
1078 << "\n\\use_refstyle " << use_refstyle
1080 if (isbackgroundcolor == true)
1081 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1082 if (isfontcolor == true)
1083 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1084 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1085 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1086 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1087 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1089 BranchList::const_iterator it = branchlist().begin();
1090 BranchList::const_iterator end = branchlist().end();
1091 for (; it != end; ++it) {
1092 os << "\\branch " << to_utf8(it->branch())
1093 << "\n\\selected " << it->isSelected()
1094 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1095 << "\n\\color " << lyx::X11hexname(it->color())
1100 IndicesList::const_iterator iit = indiceslist().begin();
1101 IndicesList::const_iterator iend = indiceslist().end();
1102 for (; iit != iend; ++iit) {
1103 os << "\\index " << to_utf8(iit->index())
1104 << "\n\\shortcut " << to_utf8(iit->shortcut())
1105 << "\n\\color " << lyx::X11hexname(iit->color())
1110 if (!paperwidth.empty())
1111 os << "\\paperwidth "
1112 << VSpace(paperwidth).asLyXCommand() << '\n';
1113 if (!paperheight.empty())
1114 os << "\\paperheight "
1115 << VSpace(paperheight).asLyXCommand() << '\n';
1116 if (!leftmargin.empty())
1117 os << "\\leftmargin "
1118 << VSpace(leftmargin).asLyXCommand() << '\n';
1119 if (!topmargin.empty())
1120 os << "\\topmargin "
1121 << VSpace(topmargin).asLyXCommand() << '\n';
1122 if (!rightmargin.empty())
1123 os << "\\rightmargin "
1124 << VSpace(rightmargin).asLyXCommand() << '\n';
1125 if (!bottommargin.empty())
1126 os << "\\bottommargin "
1127 << VSpace(bottommargin).asLyXCommand() << '\n';
1128 if (!headheight.empty())
1129 os << "\\headheight "
1130 << VSpace(headheight).asLyXCommand() << '\n';
1131 if (!headsep.empty())
1133 << VSpace(headsep).asLyXCommand() << '\n';
1134 if (!footskip.empty())
1136 << VSpace(footskip).asLyXCommand() << '\n';
1137 if (!columnsep.empty())
1138 os << "\\columnsep "
1139 << VSpace(columnsep).asLyXCommand() << '\n';
1140 os << "\\secnumdepth " << secnumdepth
1141 << "\n\\tocdepth " << tocdepth
1142 << "\n\\paragraph_separation "
1143 << string_paragraph_separation[paragraph_separation];
1144 if (!paragraph_separation)
1145 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1147 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1148 os << "\n\\quotes_language "
1149 << string_quotes_language[quotes_language]
1150 << "\n\\papercolumns " << columns
1151 << "\n\\papersides " << sides
1152 << "\n\\paperpagestyle " << pagestyle << '\n';
1153 if (!listings_params.empty())
1154 os << "\\listings_params \"" <<
1155 InsetListingsParams(listings_params).encodedString() << "\"\n";
1156 for (int i = 0; i < 4; ++i) {
1157 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1158 if (user_defined_bullet(i).getFont() != -1) {
1159 os << "\\bullet " << i << " "
1160 << user_defined_bullet(i).getFont() << " "
1161 << user_defined_bullet(i).getCharacter() << " "
1162 << user_defined_bullet(i).getSize() << "\n";
1166 os << "\\bulletLaTeX " << i << " \""
1167 << lyx::to_ascii(user_defined_bullet(i).getText())
1173 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1174 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1175 << "\\html_math_output " << html_math_output << '\n'
1176 << "\\html_css_as_file " << html_css_as_file << '\n'
1177 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1179 if (html_math_img_scale != 1.0)
1180 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1181 if (!html_latex_start.empty())
1182 os << "\\html_latex_start " << html_latex_start << '\n';
1183 if (!html_latex_end.empty())
1184 os << "\\html_latex_end " << html_latex_end << '\n';
1186 os << pimpl_->authorlist;
1190 void BufferParams::validate(LaTeXFeatures & features) const
1192 features.require(documentClass().requires());
1194 if (columns > 1 && language->rightToLeft())
1195 features.require("rtloutputdblcol");
1197 if (outputChanges) {
1198 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1199 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1200 LaTeXFeatures::isAvailable("xcolor");
1202 switch (features.runparams().flavor) {
1203 case OutputParams::LATEX:
1204 case OutputParams::DVILUATEX:
1206 features.require("ct-dvipost");
1207 features.require("dvipost");
1208 } else if (xcolorulem) {
1209 features.require("ct-xcolor-ulem");
1210 features.require("ulem");
1211 features.require("xcolor");
1213 features.require("ct-none");
1216 case OutputParams::LUATEX:
1217 case OutputParams::PDFLATEX:
1218 case OutputParams::XETEX:
1220 features.require("ct-xcolor-ulem");
1221 features.require("ulem");
1222 features.require("xcolor");
1223 // improves color handling in PDF output
1224 features.require("pdfcolmk");
1226 features.require("ct-none");
1234 // Floats with 'Here definitely' as default setting.
1235 if (float_placement.find('H') != string::npos)
1236 features.require("float");
1238 for (PackageMap::const_iterator it = use_packages.begin();
1239 it != use_packages.end(); ++it) {
1240 if (it->first == "amsmath") {
1241 // AMS Style is at document level
1242 if (it->second == package_on ||
1243 features.isProvided("amsmath"))
1244 features.require(it->first);
1245 } else if (it->second == package_on)
1246 features.require(it->first);
1249 // Document-level line spacing
1250 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1251 features.require("setspace");
1253 // the bullet shapes are buffer level not paragraph level
1254 // so they are tested here
1255 for (int i = 0; i < 4; ++i) {
1256 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1258 int const font = user_defined_bullet(i).getFont();
1260 int const c = user_defined_bullet(i).getCharacter();
1266 features.require("latexsym");
1268 } else if (font == 1) {
1269 features.require("amssymb");
1270 } else if (font >= 2 && font <= 5) {
1271 features.require("pifont");
1275 if (pdfoptions().use_hyperref) {
1276 features.require("hyperref");
1277 // due to interferences with babel and hyperref, the color package has to
1278 // be loaded after hyperref when hyperref is used with the colorlinks
1279 // option, see http://www.lyx.org/trac/ticket/5291
1280 if (pdfoptions().colorlinks)
1281 features.require("color");
1283 if (!listings_params.empty()) {
1284 // do not test validity because listings_params is
1285 // supposed to be valid
1287 InsetListingsParams(listings_params).separatedParams(true);
1288 // we can't support all packages, but we should load the color package
1289 if (par.find("\\color", 0) != string::npos)
1290 features.require("color");
1293 // some languages are only available via polyglossia
1294 if (features.runparams().flavor == OutputParams::XETEX
1295 && (features.hasPolyglossiaExclusiveLanguages()
1297 features.require("polyglossia");
1299 if (useNonTeXFonts && fonts_math != "auto")
1300 features.require("unicode-math");
1302 if (!language->requires().empty())
1303 features.require(language->requires());
1307 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1308 FileName const & filepath) const
1310 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1311 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1312 // \RequirePackage to do so, rather than the normal \usepackage
1313 // Do not try to load any other package before the document class, unless you
1314 // have a thorough understanding of the LATEX internals and know exactly what you
1316 if (features.mustProvide("fix-cm"))
1317 os << "\\RequirePackage{fix-cm}\n";
1319 os << "\\documentclass";
1321 DocumentClass const & tclass = documentClass();
1323 ostringstream clsoptions; // the document class options.
1325 if (tokenPos(tclass.opt_fontsize(),
1326 '|', fontsize) >= 0) {
1327 // only write if existing in list (and not default)
1328 clsoptions << fontsize << "pt,";
1331 // all paper sizes except of A4, A5, B5 and the US sizes need the
1333 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1334 && papersize != PAPER_USLETTER
1335 && papersize != PAPER_USLEGAL
1336 && papersize != PAPER_USEXECUTIVE
1337 && papersize != PAPER_A4
1338 && papersize != PAPER_A5
1339 && papersize != PAPER_B5;
1341 if (!use_geometry) {
1342 switch (papersize) {
1344 clsoptions << "a4paper,";
1346 case PAPER_USLETTER:
1347 clsoptions << "letterpaper,";
1350 clsoptions << "a5paper,";
1353 clsoptions << "b5paper,";
1355 case PAPER_USEXECUTIVE:
1356 clsoptions << "executivepaper,";
1359 clsoptions << "legalpaper,";
1393 if (sides != tclass.sides()) {
1396 clsoptions << "oneside,";
1399 clsoptions << "twoside,";
1405 if (columns != tclass.columns()) {
1407 clsoptions << "twocolumn,";
1409 clsoptions << "onecolumn,";
1413 && orientation == ORIENTATION_LANDSCAPE)
1414 clsoptions << "landscape,";
1416 // language should be a parameter to \documentclass
1417 if (language->babel() == "hebrew"
1418 && default_language->babel() != "hebrew")
1419 // This seems necessary
1420 features.useLanguage(default_language);
1422 ostringstream language_options;
1423 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1424 bool const use_polyglossia = features.usePolyglossia();
1425 bool const global = lyxrc.language_global_options;
1426 if (use_babel || (use_polyglossia && global)) {
1427 language_options << features.getBabelLanguages();
1428 if (!language->babel().empty()) {
1429 if (!language_options.str().empty())
1430 language_options << ',';
1431 language_options << language->babel();
1433 if (global && !features.needBabelLangOptions()
1434 && !language_options.str().empty())
1435 clsoptions << language_options.str() << ',';
1438 // the predefined options from the layout
1439 if (use_default_options && !tclass.options().empty())
1440 clsoptions << tclass.options() << ',';
1442 // the user-defined options
1443 if (!options.empty()) {
1444 clsoptions << options << ',';
1447 string strOptions(clsoptions.str());
1448 if (!strOptions.empty()) {
1449 strOptions = rtrim(strOptions, ",");
1451 os << '[' << from_utf8(strOptions) << ']';
1454 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1455 // end of \documentclass defs
1457 // if we use fontspec or newtxmath, we have to load the AMS packages here
1458 string const ams = features.loadAMSPackages();
1459 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1460 bool const use_newtxmath =
1461 theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getUsedPackage(
1462 ot1, false, false) == "newtxmath";
1463 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1464 os << from_ascii(ams);
1466 if (useNonTeXFonts) {
1467 os << "\\usepackage{fontspec}\n";
1468 if (features.mustProvide("unicode-math")
1469 && features.isAvailable("unicode-math"))
1470 os << "\\usepackage{unicode-math}\n";
1473 // font selection must be done before loading fontenc.sty
1474 string const fonts = loadFonts(features);
1476 os << from_utf8(fonts);
1478 if (fonts_default_family != "default")
1479 os << "\\renewcommand{\\familydefault}{\\"
1480 << from_ascii(fonts_default_family) << "}\n";
1482 // set font encoding
1483 // for arabic_arabi and farsi we also need to load the LAE and
1485 // XeTeX and LuaTeX (with OS fonts) work without fontenc
1486 if (font_encoding() != "default" && language->lang() != "japanese"
1487 && !useNonTeXFonts && !features.isProvided("fontenc")) {
1488 docstring extra_encoding;
1489 if (features.mustProvide("textgreek"))
1490 extra_encoding += from_ascii("LGR");
1491 if (features.mustProvide("textcyr")) {
1492 if (!extra_encoding.empty())
1493 extra_encoding.push_back(',');
1494 extra_encoding += from_ascii("T2A");
1496 if (!extra_encoding.empty() && !font_encoding().empty())
1497 extra_encoding.push_back(',');
1498 size_t fars = language_options.str().find("farsi");
1499 size_t arab = language_options.str().find("arabic");
1500 if (language->lang() == "arabic_arabi"
1501 || language->lang() == "farsi" || fars != string::npos
1502 || arab != string::npos) {
1503 os << "\\usepackage[" << extra_encoding
1504 << from_ascii(font_encoding())
1505 << ",LFE,LAE]{fontenc}\n";
1507 os << "\\usepackage[" << extra_encoding
1508 << from_ascii(font_encoding())
1513 // handle inputenc etc.
1514 writeEncodingPreamble(os, features);
1517 if (!features.runparams().includeall && !included_children_.empty()) {
1518 os << "\\includeonly{";
1519 list<string>::const_iterator it = included_children_.begin();
1520 list<string>::const_iterator en = included_children_.end();
1522 for (; it != en; ++it) {
1523 string incfile = *it;
1524 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1525 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1527 if (!features.runparams().nice)
1529 // \includeonly doesn't want an extension
1530 incfile = changeExtension(incfile, string());
1531 incfile = support::latex_path(incfile);
1532 if (!incfile.empty()) {
1535 os << from_utf8(incfile);
1542 if (!features.isProvided("geometry")
1543 && (use_geometry || nonstandard_papersize)) {
1544 odocstringstream ods;
1545 if (!getGraphicsDriver("geometry").empty())
1546 ods << getGraphicsDriver("geometry");
1547 if (orientation == ORIENTATION_LANDSCAPE)
1548 ods << ",landscape";
1549 switch (papersize) {
1551 if (!paperwidth.empty())
1552 ods << ",paperwidth="
1553 << from_ascii(paperwidth);
1554 if (!paperheight.empty())
1555 ods << ",paperheight="
1556 << from_ascii(paperheight);
1558 case PAPER_USLETTER:
1559 ods << ",letterpaper";
1562 ods << ",legalpaper";
1564 case PAPER_USEXECUTIVE:
1565 ods << ",executivepaper";
1654 docstring const g_options = trim(ods.str(), ",");
1655 os << "\\usepackage";
1656 if (!g_options.empty())
1657 os << '[' << g_options << ']';
1658 os << "{geometry}\n";
1659 // output this only if use_geometry is true
1661 os << "\\geometry{verbose";
1662 if (!topmargin.empty())
1663 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1664 if (!bottommargin.empty())
1665 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1666 if (!leftmargin.empty())
1667 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1668 if (!rightmargin.empty())
1669 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1670 if (!headheight.empty())
1671 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1672 if (!headsep.empty())
1673 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1674 if (!footskip.empty())
1675 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1676 if (!columnsep.empty())
1677 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1680 } else if (orientation == ORIENTATION_LANDSCAPE
1681 || papersize != PAPER_DEFAULT) {
1682 features.require("papersize");
1685 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1686 if (pagestyle == "fancy")
1687 os << "\\usepackage{fancyhdr}\n";
1688 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1691 // only output when the background color is not default
1692 if (isbackgroundcolor == true) {
1693 // only require color here, the background color will be defined
1694 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1696 features.require("color");
1697 features.require("pagecolor");
1700 // only output when the font color is not default
1701 if (isfontcolor == true) {
1702 // only require color here, the font color will be defined
1703 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1705 features.require("color");
1706 features.require("fontcolor");
1709 // Only if class has a ToC hierarchy
1710 if (tclass.hasTocLevels()) {
1711 if (secnumdepth != tclass.secnumdepth()) {
1712 os << "\\setcounter{secnumdepth}{"
1716 if (tocdepth != tclass.tocdepth()) {
1717 os << "\\setcounter{tocdepth}{"
1723 if (paragraph_separation) {
1724 // when skip separation
1725 switch (getDefSkip().kind()) {
1726 case VSpace::SMALLSKIP:
1727 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1729 case VSpace::MEDSKIP:
1730 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1732 case VSpace::BIGSKIP:
1733 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1735 case VSpace::LENGTH:
1736 os << "\\setlength{\\parskip}{"
1737 << from_utf8(getDefSkip().length().asLatexString())
1740 default: // should never happen // Then delete it.
1741 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1744 os << "\\setlength{\\parindent}{0pt}\n";
1746 // when separation by indentation
1747 // only output something when a width is given
1748 if (getIndentation().asLyXCommand() != "default") {
1749 os << "\\setlength{\\parindent}{"
1750 << from_utf8(getIndentation().asLatexCommand())
1755 // Now insert the LyX specific LaTeX commands...
1756 docstring lyxpreamble;
1757 features.resolveAlternatives();
1760 if (!output_sync_macro.empty())
1761 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1762 else if (features.runparams().flavor == OutputParams::LATEX)
1763 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1764 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1765 lyxpreamble += "\\synctex=-1\n";
1768 // due to interferences with babel and hyperref, the color package has to
1769 // be loaded (when it is not already loaded) before babel when hyperref
1770 // is used with the colorlinks option, see
1771 // http://www.lyx.org/trac/ticket/5291
1772 // we decided therefore to load color always before babel, see
1773 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1774 lyxpreamble += from_ascii(features.getColorOptions());
1776 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1777 // we have to call babel before
1779 && (features.isRequired("jurabib")
1780 || features.isRequired("hyperref")
1781 || features.isRequired("varioref")
1782 || features.isRequired("vietnamese")
1783 || features.isRequired("japanese"))) {
1785 lyxpreamble += from_utf8(features.getBabelPresettings());
1786 lyxpreamble += from_utf8(babelCall(language_options.str(),
1787 features.needBabelLangOptions())) + '\n';
1788 lyxpreamble += from_utf8(features.getBabelPostsettings());
1791 // The optional packages;
1792 lyxpreamble += from_ascii(features.getPackages());
1794 // Additional Indices
1795 if (features.isRequired("splitidx")) {
1796 IndicesList::const_iterator iit = indiceslist().begin();
1797 IndicesList::const_iterator iend = indiceslist().end();
1798 for (; iit != iend; ++iit) {
1799 pair<docstring, docstring> indexname_latex =
1800 features.runparams().encoding->latexString(iit->index(),
1801 features.runparams().dryrun);
1802 if (!indexname_latex.second.empty()) {
1803 // issue a warning about omitted characters
1804 // FIXME: should be passed to the error dialog
1805 frontend::Alert::warning(_("Uncodable characters"),
1806 bformat(_("The following characters that are used in an index name are not\n"
1807 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1808 indexname_latex.second));
1810 lyxpreamble += "\\newindex[";
1811 lyxpreamble += indexname_latex.first;
1812 lyxpreamble += "]{";
1813 lyxpreamble += escape(iit->shortcut());
1814 lyxpreamble += "}\n";
1819 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1822 // * Hyperref manual: "Make sure it comes last of your loaded
1823 // packages, to give it a fighting chance of not being over-written,
1824 // since its job is to redefine many LaTeX commands."
1825 // * Email from Heiko Oberdiek: "It is usually better to load babel
1826 // before hyperref. Then hyperref has a chance to detect babel.
1827 // * Has to be loaded before the "LyX specific LaTeX commands" to
1828 // avoid errors with algorithm floats.
1829 // use hyperref explicitly if it is required
1830 if (features.isRequired("hyperref")) {
1831 // pass what we have to stream here, since we need
1832 // to access the stream itself in PDFOptions.
1835 OutputParams tmp_params = features.runparams();
1836 pdfoptions().writeLaTeX(tmp_params, os,
1837 features.isProvided("hyperref"));
1838 // set back for the rest
1839 lyxpreamble.clear();
1840 // correctly break URLs with hyperref and dvi output
1841 if (features.runparams().flavor == OutputParams::LATEX
1842 && features.isAvailable("breakurl"))
1843 lyxpreamble += "\\usepackage{breakurl}\n";
1844 } else if (features.isRequired("nameref"))
1845 // hyperref loads this automatically
1846 lyxpreamble += "\\usepackage{nameref}\n";
1848 // bibtopic needs to be loaded after hyperref.
1849 // the dot provides the aux file naming which LyX can detect.
1850 if (features.mustProvide("bibtopic"))
1851 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1853 // Will be surrounded by \makeatletter and \makeatother when not empty
1854 docstring atlyxpreamble;
1856 // Some macros LyX will need
1857 docstring tmppreamble(features.getMacros());
1859 if (!tmppreamble.empty())
1860 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1861 "LyX specific LaTeX commands.\n"
1862 + tmppreamble + '\n';
1864 // the text class specific preamble
1865 tmppreamble = features.getTClassPreamble();
1866 if (!tmppreamble.empty())
1867 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1868 "Textclass specific LaTeX commands.\n"
1869 + tmppreamble + '\n';
1871 // suppress date if selected
1872 // use \@ifundefined because we cannot be sure that every document class
1873 // has a \date command
1875 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1877 /* the user-defined preamble */
1878 if (!containsOnly(preamble, " \n\t"))
1880 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1881 "User specified LaTeX commands.\n"
1882 + from_utf8(preamble) + '\n';
1884 // subfig loads internally the LaTeX package "caption". As
1885 // caption is a very popular package, users will load it in
1886 // the preamble. Therefore we must load subfig behind the
1887 // user-defined preamble and check if the caption package was
1888 // loaded or not. For the case that caption is loaded before
1889 // subfig, there is the subfig option "caption=false". This
1890 // option also works when a koma-script class is used and
1891 // koma's own caption commands are used instead of caption. We
1892 // use \PassOptionsToPackage here because the user could have
1893 // already loaded subfig in the preamble.
1894 if (features.isRequired("subfig")) {
1895 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1896 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1897 "\\usepackage{subfig}\n";
1900 // Itemize bullet settings need to be last in case the user
1901 // defines their own bullets that use a package included
1902 // in the user-defined preamble -- ARRae
1903 // Actually it has to be done much later than that
1904 // since some packages like frenchb make modifications
1905 // at \begin{document} time -- JMarc
1906 docstring bullets_def;
1907 for (int i = 0; i < 4; ++i) {
1908 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1909 if (bullets_def.empty())
1910 bullets_def += "\\AtBeginDocument{\n";
1911 bullets_def += " \\def\\labelitemi";
1913 // `i' is one less than the item to modify
1920 bullets_def += "ii";
1926 bullets_def += '{' +
1927 user_defined_bullet(i).getText()
1932 if (!bullets_def.empty())
1933 atlyxpreamble += bullets_def + "}\n\n";
1935 if (!atlyxpreamble.empty())
1936 lyxpreamble += "\n\\makeatletter\n"
1937 + atlyxpreamble + "\\makeatother\n\n";
1939 // We try to load babel late, in case it interferes with other packages.
1940 // Jurabib, hyperref, varioref and listings (bug 8995) have to be
1941 // called after babel, though.
1942 if (use_babel && !features.isRequired("jurabib")
1943 && !features.isRequired("hyperref")
1944 && !features.isRequired("varioref")
1945 && !features.isRequired("vietnamese")
1946 && !features.isRequired("japanese")) {
1948 lyxpreamble += from_utf8(features.getBabelPresettings());
1949 lyxpreamble += from_utf8(babelCall(language_options.str(),
1950 features.needBabelLangOptions())) + '\n';
1951 lyxpreamble += from_utf8(features.getBabelPostsettings());
1953 if (!listings_params.empty() || features.isRequired("listings"))
1954 lyxpreamble += "\\usepackage{listings}\n";
1955 if (!listings_params.empty()) {
1956 lyxpreamble += "\\lstset{";
1957 // do not test validity because listings_params is
1958 // supposed to be valid
1960 InsetListingsParams(listings_params).separatedParams(true);
1961 lyxpreamble += from_utf8(par);
1962 lyxpreamble += "}\n";
1965 // xunicode needs to be loaded at least after amsmath, amssymb,
1966 // esint and the other packages that provide special glyphs
1967 if (features.runparams().flavor == OutputParams::XETEX
1969 lyxpreamble += "\\usepackage{xunicode}\n";
1971 // Polyglossia must be loaded last
1972 if (use_polyglossia) {
1974 lyxpreamble += "\\usepackage{polyglossia}\n";
1975 // set the main language
1976 lyxpreamble += "\\setdefaultlanguage";
1977 if (!language->polyglossiaOpts().empty())
1978 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
1979 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
1980 // now setup the other languages
1981 std::map<std::string, std::string> const polylangs =
1982 features.getPolyglossiaLanguages();
1983 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
1984 mit != polylangs.end() ; ++mit) {
1985 lyxpreamble += "\\setotherlanguage";
1986 if (!mit->second.empty())
1987 lyxpreamble += "[" + from_ascii(mit->second) + "]";
1988 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
1992 // Load custom language package here
1993 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
1994 if (lang_package == "default")
1995 lyxpreamble += from_utf8(lyxrc.language_custom_package);
1997 lyxpreamble += from_utf8(lang_package);
1998 lyxpreamble += '\n';
2001 docstring const i18npreamble =
2002 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2003 if (!i18npreamble.empty())
2004 lyxpreamble += i18npreamble + '\n';
2012 void BufferParams::useClassDefaults()
2014 DocumentClass const & tclass = documentClass();
2016 sides = tclass.sides();
2017 columns = tclass.columns();
2018 pagestyle = tclass.pagestyle();
2019 use_default_options = true;
2020 // Only if class has a ToC hierarchy
2021 if (tclass.hasTocLevels()) {
2022 secnumdepth = tclass.secnumdepth();
2023 tocdepth = tclass.tocdepth();
2028 bool BufferParams::hasClassDefaults() const
2030 DocumentClass const & tclass = documentClass();
2032 return sides == tclass.sides()
2033 && columns == tclass.columns()
2034 && pagestyle == tclass.pagestyle()
2035 && use_default_options
2036 && secnumdepth == tclass.secnumdepth()
2037 && tocdepth == tclass.tocdepth();
2041 DocumentClass const & BufferParams::documentClass() const
2043 return *doc_class_.get();
2047 DocumentClassConstPtr BufferParams::documentClassPtr() const
2053 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2055 // evil, but this function is evil
2056 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2060 bool BufferParams::setBaseClass(string const & classname)
2062 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2063 LayoutFileList & bcl = LayoutFileList::get();
2064 if (!bcl.haveClass(classname)) {
2066 bformat(_("The layout file:\n"
2068 "could not be found. A default textclass with default\n"
2069 "layouts will be used. LyX will not be able to produce\n"
2071 from_utf8(classname));
2072 frontend::Alert::error(_("Document class not found"), s);
2073 bcl.addEmptyClass(classname);
2076 bool const success = bcl[classname].load();
2079 bformat(_("Due to some error in it, the layout file:\n"
2081 "could not be loaded. A default textclass with default\n"
2082 "layouts will be used. LyX will not be able to produce\n"
2084 from_utf8(classname));
2085 frontend::Alert::error(_("Could not load class"), s);
2086 bcl.addEmptyClass(classname);
2089 pimpl_->baseClass_ = classname;
2090 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2095 LayoutFile const * BufferParams::baseClass() const
2097 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2098 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2104 LayoutFileIndex const & BufferParams::baseClassID() const
2106 return pimpl_->baseClass_;
2110 void BufferParams::makeDocumentClass(bool const clone)
2115 LayoutModuleList mods;
2116 LayoutModuleList::iterator it = layout_modules_.begin();
2117 LayoutModuleList::iterator en = layout_modules_.end();
2118 for (; it != en; ++it)
2119 mods.push_back(*it);
2121 it = cite_engine_.begin();
2122 en = cite_engine_.end();
2123 for (; it != en; ++it)
2124 mods.push_back(*it);
2126 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2128 TextClass::ReturnValues success = TextClass::OK;
2129 if (!forced_local_layout_.empty())
2130 success = doc_class_->read(forced_local_layout_, TextClass::MODULE);
2131 if (!local_layout_.empty() &&
2132 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2133 success = doc_class_->read(local_layout_, TextClass::MODULE);
2134 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2135 docstring const msg = _("Error reading internal layout information");
2136 frontend::Alert::warning(_("Read Error"), msg);
2141 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2143 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2147 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2149 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2153 std::string BufferParams::getLocalLayout(bool forced) const
2156 return doc_class_->forcedLayouts();
2158 return local_layout_;
2162 void BufferParams::setLocalLayout(string const & layout, bool forced)
2165 forced_local_layout_ = layout;
2167 local_layout_ = layout;
2171 bool BufferParams::addLayoutModule(string const & modName)
2173 LayoutModuleList::const_iterator it = layout_modules_.begin();
2174 LayoutModuleList::const_iterator end = layout_modules_.end();
2175 for (; it != end; ++it)
2178 layout_modules_.push_back(modName);
2183 string BufferParams::bufferFormat() const
2185 string format = documentClass().outputFormat();
2186 if (format == "latex") {
2189 if (encoding().package() == Encoding::japanese)
2196 bool BufferParams::isExportable(string const & format) const
2198 vector<string> backs = backends();
2199 for (vector<string>::const_iterator it = backs.begin();
2200 it != backs.end(); ++it)
2201 if (theConverters().isReachable(*it, format))
2207 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2209 vector<string> const backs = backends();
2210 set<string> excludes;
2211 if (useNonTeXFonts) {
2212 excludes.insert("latex");
2213 excludes.insert("pdflatex");
2215 vector<Format const *> result =
2216 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2217 for (vector<string>::const_iterator it = backs.begin() + 1;
2218 it != backs.end(); ++it) {
2219 vector<Format const *> r =
2220 theConverters().getReachable(*it, only_viewable, false, excludes);
2221 result.insert(result.end(), r.begin(), r.end());
2227 bool BufferParams::isExportableFormat(string const & format) const
2229 typedef vector<Format const *> Formats;
2231 formats = exportableFormats(true);
2232 Formats::const_iterator fit = formats.begin();
2233 Formats::const_iterator end = formats.end();
2234 for (; fit != end ; ++fit) {
2235 if ((*fit)->name() == format)
2242 vector<string> BufferParams::backends() const
2245 string const buffmt = bufferFormat();
2247 // FIXME: Don't hardcode format names here, but use a flag
2248 if (buffmt == "latex") {
2249 if (!useNonTeXFonts) {
2250 v.push_back("pdflatex");
2251 v.push_back("latex");
2253 v.push_back("luatex");
2254 v.push_back("dviluatex");
2255 v.push_back("xetex");
2256 } else if (buffmt == "xetex") {
2257 v.push_back("xetex");
2258 // FIXME: need to test all languages (bug 8205)
2259 if (!language || !language->isPolyglossiaExclusive()) {
2260 v.push_back("luatex");
2261 v.push_back("dviluatex");
2264 v.push_back(buffmt);
2266 v.push_back("xhtml");
2267 v.push_back("text");
2273 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const format) const
2275 string const dformat = (format.empty() || format == "default") ?
2276 getDefaultOutputFormat() : format;
2277 DefaultFlavorCache::const_iterator it =
2278 default_flavors_.find(dformat);
2280 if (it != default_flavors_.end())
2283 OutputParams::FLAVOR result = OutputParams::LATEX;
2285 // FIXME It'd be better not to hardcode this, but to do
2286 // something with formats.
2287 if (dformat == "xhtml")
2288 result = OutputParams::HTML;
2289 else if (dformat == "text")
2290 result = OutputParams::TEXT;
2291 else if (dformat == "lyx")
2292 result = OutputParams::LYX;
2293 else if (dformat == "pdflatex")
2294 result = OutputParams::PDFLATEX;
2295 else if (dformat == "xetex")
2296 result = OutputParams::XETEX;
2297 else if (dformat == "luatex")
2298 result = OutputParams::LUATEX;
2299 else if (dformat == "dviluatex")
2300 result = OutputParams::DVILUATEX;
2302 // Try to determine flavor of default output format
2303 vector<string> backs = backends();
2304 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2305 // Get shortest path to format
2306 Graph::EdgePath path;
2307 for (vector<string>::const_iterator it = backs.begin();
2308 it != backs.end(); ++it) {
2309 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2310 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2315 result = theConverters().getFlavor(path);
2318 // cache this flavor
2319 default_flavors_[dformat] = result;
2324 string BufferParams::getDefaultOutputFormat() const
2326 if (!default_output_format.empty()
2327 && default_output_format != "default")
2328 return default_output_format;
2330 || encoding().package() == Encoding::japanese) {
2331 vector<Format const *> const formats = exportableFormats(true);
2332 if (formats.empty())
2334 // return the first we find
2335 return formats.front()->name();
2338 return lyxrc.default_otf_view_format;
2339 return lyxrc.default_view_format;
2342 Font const BufferParams::getFont() const
2344 FontInfo f = documentClass().defaultfont();
2345 if (fonts_default_family == "rmdefault")
2346 f.setFamily(ROMAN_FAMILY);
2347 else if (fonts_default_family == "sfdefault")
2348 f.setFamily(SANS_FAMILY);
2349 else if (fonts_default_family == "ttdefault")
2350 f.setFamily(TYPEWRITER_FAMILY);
2351 return Font(f, language);
2355 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const qs) const
2357 return quoteslangtranslator().find(qs);
2361 bool BufferParams::isLatex() const
2363 return documentClass().outputType() == LATEX;
2367 bool BufferParams::isLiterate() const
2369 return documentClass().outputType() == LITERATE;
2373 bool BufferParams::isDocBook() const
2375 return documentClass().outputType() == DOCBOOK;
2379 void BufferParams::readPreamble(Lexer & lex)
2381 if (lex.getString() != "\\begin_preamble")
2382 lyxerr << "Error (BufferParams::readPreamble):"
2383 "consistency check failed." << endl;
2385 preamble = lex.getLongString("\\end_preamble");
2389 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2391 string const expected = forced ? "\\begin_forced_local_layout" :
2392 "\\begin_local_layout";
2393 if (lex.getString() != expected)
2394 lyxerr << "Error (BufferParams::readLocalLayout):"
2395 "consistency check failed." << endl;
2398 forced_local_layout_ =
2399 lex.getLongString("\\end_forced_local_layout");
2401 local_layout_ = lex.getLongString("\\end_local_layout");
2405 bool BufferParams::setLanguage(string const & lang)
2407 Language const *new_language = languages.getLanguage(lang);
2408 if (!new_language) {
2409 // Language lang was not found
2412 language = new_language;
2417 void BufferParams::readLanguage(Lexer & lex)
2419 if (!lex.next()) return;
2421 string const tmptok = lex.getString();
2423 // check if tmptok is part of tex_babel in tex-defs.h
2424 if (!setLanguage(tmptok)) {
2425 // Language tmptok was not found
2426 language = default_language;
2427 lyxerr << "Warning: Setting language `"
2428 << tmptok << "' to `" << language->lang()
2434 void BufferParams::readGraphicsDriver(Lexer & lex)
2439 string const tmptok = lex.getString();
2440 // check if tmptok is part of tex_graphics in tex_defs.h
2443 string const test = tex_graphics[n++];
2445 if (test == tmptok) {
2446 graphics_driver = tmptok;
2451 "Warning: graphics driver `$$Token' not recognized!\n"
2452 " Setting graphics driver to `default'.\n");
2453 graphics_driver = "default";
2460 void BufferParams::readBullets(Lexer & lex)
2465 int const index = lex.getInteger();
2467 int temp_int = lex.getInteger();
2468 user_defined_bullet(index).setFont(temp_int);
2469 temp_bullet(index).setFont(temp_int);
2471 user_defined_bullet(index).setCharacter(temp_int);
2472 temp_bullet(index).setCharacter(temp_int);
2474 user_defined_bullet(index).setSize(temp_int);
2475 temp_bullet(index).setSize(temp_int);
2479 void BufferParams::readBulletsLaTeX(Lexer & lex)
2481 // The bullet class should be able to read this.
2484 int const index = lex.getInteger();
2486 docstring const temp_str = lex.getDocString();
2488 user_defined_bullet(index).setText(temp_str);
2489 temp_bullet(index).setText(temp_str);
2493 void BufferParams::readModules(Lexer & lex)
2495 if (!lex.eatLine()) {
2496 lyxerr << "Error (BufferParams::readModules):"
2497 "Unexpected end of input." << endl;
2501 string mod = lex.getString();
2502 if (mod == "\\end_modules")
2504 addLayoutModule(mod);
2510 void BufferParams::readRemovedModules(Lexer & lex)
2512 if (!lex.eatLine()) {
2513 lyxerr << "Error (BufferParams::readRemovedModules):"
2514 "Unexpected end of input." << endl;
2518 string mod = lex.getString();
2519 if (mod == "\\end_removed_modules")
2521 removed_modules_.push_back(mod);
2524 // now we want to remove any removed modules that were previously
2525 // added. normally, that will be because default modules were added in
2526 // setBaseClass(), which gets called when \textclass is read at the
2527 // start of the read.
2528 list<string>::const_iterator rit = removed_modules_.begin();
2529 list<string>::const_iterator const ren = removed_modules_.end();
2530 for (; rit != ren; ++rit) {
2531 LayoutModuleList::iterator const mit = layout_modules_.begin();
2532 LayoutModuleList::iterator const men = layout_modules_.end();
2533 LayoutModuleList::iterator found = find(mit, men, *rit);
2536 layout_modules_.erase(found);
2541 void BufferParams::readIncludeonly(Lexer & lex)
2543 if (!lex.eatLine()) {
2544 lyxerr << "Error (BufferParams::readIncludeonly):"
2545 "Unexpected end of input." << endl;
2549 string child = lex.getString();
2550 if (child == "\\end_includeonly")
2552 included_children_.push_back(child);
2558 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2560 switch (papersize) {
2562 // could be anything, so don't guess
2564 case PAPER_CUSTOM: {
2565 if (purpose == XDVI && !paperwidth.empty() &&
2566 !paperheight.empty()) {
2567 // heightxwidth<unit>
2568 string first = paperwidth;
2569 string second = paperheight;
2570 if (orientation == ORIENTATION_LANDSCAPE)
2573 return first.erase(first.length() - 2)
2579 // dvips and dvipdfm do not know this
2580 if (purpose == DVIPS || purpose == DVIPDFM)
2584 if (purpose == DVIPS || purpose == DVIPDFM)
2588 if (purpose == DVIPS || purpose == DVIPDFM)
2598 if (purpose == DVIPS || purpose == DVIPDFM)
2602 if (purpose == DVIPS || purpose == DVIPDFM)
2606 if (purpose == DVIPS || purpose == DVIPDFM)
2610 if (purpose == DVIPS || purpose == DVIPDFM)
2614 if (purpose == DVIPS || purpose == DVIPDFM)
2618 // dvipdfm does not know this
2619 if (purpose == DVIPDFM)
2623 if (purpose == DVIPDFM)
2627 if (purpose == DVIPS || purpose == DVIPDFM)
2631 if (purpose == DVIPS || purpose == DVIPDFM)
2635 if (purpose == DVIPS || purpose == DVIPDFM)
2639 if (purpose == DVIPS || purpose == DVIPDFM)
2643 if (purpose == DVIPS || purpose == DVIPDFM)
2647 if (purpose == DVIPS || purpose == DVIPDFM)
2651 if (purpose == DVIPS || purpose == DVIPDFM)
2655 if (purpose == DVIPS || purpose == DVIPDFM)
2659 if (purpose == DVIPS || purpose == DVIPDFM)
2663 if (purpose == DVIPS || purpose == DVIPDFM)
2667 if (purpose == DVIPS || purpose == DVIPDFM)
2671 if (purpose == DVIPS || purpose == DVIPDFM)
2675 if (purpose == DVIPS || purpose == DVIPDFM)
2679 if (purpose == DVIPS || purpose == DVIPDFM)
2683 if (purpose == DVIPS || purpose == DVIPDFM)
2686 case PAPER_USEXECUTIVE:
2687 // dvipdfm does not know this
2688 if (purpose == DVIPDFM)
2693 case PAPER_USLETTER:
2695 if (purpose == XDVI)
2702 string const BufferParams::dvips_options() const
2706 // If the class loads the geometry package, we do not know which
2707 // paper size is used, since we do not set it (bug 7013).
2708 // Therefore we must not specify any argument here.
2709 // dvips gets the correct paper size via DVI specials in this case
2710 // (if the class uses the geometry package correctly).
2711 if (documentClass().provides("geometry"))
2715 && papersize == PAPER_CUSTOM
2716 && !lyxrc.print_paper_dimension_flag.empty()
2717 && !paperwidth.empty()
2718 && !paperheight.empty()) {
2719 // using a custom papersize
2720 result = lyxrc.print_paper_dimension_flag;
2721 result += ' ' + paperwidth;
2722 result += ',' + paperheight;
2724 string const paper_option = paperSizeName(DVIPS);
2725 if (!paper_option.empty() && (paper_option != "letter" ||
2726 orientation != ORIENTATION_LANDSCAPE)) {
2727 // dvips won't accept -t letter -t landscape.
2728 // In all other cases, include the paper size
2730 result = lyxrc.print_paper_flag;
2731 result += ' ' + paper_option;
2734 if (orientation == ORIENTATION_LANDSCAPE &&
2735 papersize != PAPER_CUSTOM)
2736 result += ' ' + lyxrc.print_landscape_flag;
2741 string const BufferParams::font_encoding() const
2743 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2747 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2749 // suppress the babel call if there is no BabelName defined
2750 // for the document language in the lib/languages file and if no
2751 // other languages are used (lang_opts is then empty)
2752 if (lang_opts.empty())
2754 // either a specific language (AsBabelOptions setting in
2755 // lib/languages) or the prefs require the languages to
2756 // be submitted to babel itself (not the class).
2758 return "\\usepackage[" + lang_opts + "]{babel}";
2759 return "\\usepackage{babel}";
2763 docstring BufferParams::getGraphicsDriver(string const & package) const
2767 if (package == "geometry") {
2768 if (graphics_driver == "dvips"
2769 || graphics_driver == "dvipdfm"
2770 || graphics_driver == "pdftex"
2771 || graphics_driver == "vtex")
2772 result = from_ascii(graphics_driver);
2773 else if (graphics_driver == "dvipdfmx")
2774 result = from_ascii("dvipdfm");
2781 void BufferParams::writeEncodingPreamble(otexstream & os,
2782 LaTeXFeatures & features) const
2784 // XeTeX does not need this
2785 if (features.runparams().flavor == OutputParams::XETEX)
2787 // LuaTeX neither, but with tex fonts, we need to load
2788 // the luainputenc package.
2789 if (features.runparams().flavor == OutputParams::LUATEX
2790 || features.runparams().flavor == OutputParams::DVILUATEX) {
2791 if (!useNonTeXFonts && inputenc != "default"
2792 && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc)
2793 || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) {
2794 os << "\\usepackage[utf8]{luainputenc}\n";
2798 if (inputenc == "auto") {
2799 string const doc_encoding =
2800 language->encoding()->latexName();
2801 Encoding::Package const package =
2802 language->encoding()->package();
2804 // Create a list with all the input encodings used
2806 set<string> encodings =
2807 features.getEncodingSet(doc_encoding);
2809 // If the "japanese" package (i.e. pLaTeX) is used,
2810 // inputenc must be omitted.
2811 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2812 if ((!encodings.empty() || package == Encoding::inputenc)
2813 && !features.isRequired("japanese")) {
2814 os << "\\usepackage[";
2815 set<string>::const_iterator it = encodings.begin();
2816 set<string>::const_iterator const end = encodings.end();
2818 os << from_ascii(*it);
2821 for (; it != end; ++it)
2822 os << ',' << from_ascii(*it);
2823 if (package == Encoding::inputenc) {
2824 if (!encodings.empty())
2826 os << from_ascii(doc_encoding);
2828 os << "]{inputenc}\n";
2830 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2831 if (language->encoding()->name() == "utf8-cjk"
2832 && LaTeXFeatures::isAvailable("CJKutf8"))
2833 os << "\\usepackage{CJKutf8}\n";
2835 os << "\\usepackage{CJK}\n";
2837 } else if (inputenc != "default") {
2838 switch (encoding().package()) {
2839 case Encoding::none:
2840 case Encoding::japanese:
2842 case Encoding::inputenc:
2843 // do not load inputenc if japanese is used
2844 if (features.isRequired("japanese"))
2846 os << "\\usepackage[" << from_ascii(encoding().latexName())
2850 if (encoding().name() == "utf8-cjk"
2851 && LaTeXFeatures::isAvailable("CJKutf8"))
2852 os << "\\usepackage{CJKutf8}\n";
2854 os << "\\usepackage{CJK}\n";
2857 // Load the CJK package if needed by a secondary language.
2858 // If the main encoding is some variant of UTF8, use CJKutf8.
2859 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
2860 if (encoding().iconvName() == "UTF-8"
2861 && LaTeXFeatures::isAvailable("CJKutf8"))
2862 os << "\\usepackage{CJKutf8}\n";
2864 os << "\\usepackage{CJK}\n";
2870 string const BufferParams::parseFontName(string const & name) const
2872 string mangled = name;
2873 size_t const idx = mangled.find('[');
2874 if (idx == string::npos || idx == 0)
2877 return mangled.substr(0, idx - 1);
2881 string const BufferParams::loadFonts(LaTeXFeatures & features) const
2883 if (fonts_roman == "default" && fonts_sans == "default"
2884 && fonts_typewriter == "default"
2885 && (fonts_math == "default" || fonts_math == "auto"))
2891 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
2892 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
2893 * Mapping=tex-text option assures TeX ligatures (such as "--")
2894 * are resolved. Note that tt does not use these ligatures.
2896 * -- add more GUI options?
2897 * -- add more fonts (fonts for other scripts)
2898 * -- if there's a way to find out if a font really supports
2899 * OldStyle, enable/disable the widget accordingly.
2901 if (useNonTeXFonts && features.isAvailable("fontspec")) {
2902 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
2903 // However, until v.2 (2010/07/11) fontspec only knew
2904 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
2905 // was introduced for both XeTeX and LuaTeX (LuaTeX
2906 // didn't understand "Mapping=tex-text", while XeTeX
2907 // understood both. With most recent versions, both
2908 // variants are understood by both engines. However,
2909 // we want to provide support for at least TeXLive 2009
2910 // (for XeTeX; LuaTeX is only supported as of v.2)
2911 string const texmapping =
2912 (features.runparams().flavor == OutputParams::XETEX) ?
2913 "Mapping=tex-text" : "Ligatures=TeX";
2914 if (fonts_roman != "default") {
2915 os << "\\setmainfont[" << texmapping;
2916 if (fonts_old_figures)
2917 os << ",Numbers=OldStyle";
2918 os << "]{" << parseFontName(fonts_roman) << "}\n";
2920 if (fonts_sans != "default") {
2921 string const sans = parseFontName(fonts_sans);
2922 if (fonts_sans_scale != 100)
2923 os << "\\setsansfont[Scale="
2924 << float(fonts_sans_scale) / 100
2925 << "," << texmapping << "]{"
2928 os << "\\setsansfont[" << texmapping << "]{"
2931 if (fonts_typewriter != "default") {
2932 string const mono = parseFontName(fonts_typewriter);
2933 if (fonts_typewriter_scale != 100)
2934 os << "\\setmonofont[Scale="
2935 << float(fonts_typewriter_scale) / 100
2939 os << "\\setmonofont{"
2946 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
2947 bool const dryrun = features.runparams().dryrun;
2948 bool const complete = (fonts_sans == "default" && fonts_typewriter == "default");
2949 bool const nomath = (fonts_math == "default");
2952 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_roman)).getLaTeXCode(
2953 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2957 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_sans)).getLaTeXCode(
2958 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2959 nomath, fonts_sans_scale);
2961 // MONOSPACED/TYPEWRITER
2962 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_typewriter)).getLaTeXCode(
2963 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2964 nomath, fonts_typewriter_scale);
2967 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getLaTeXCode(
2968 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2975 Encoding const & BufferParams::encoding() const
2977 // FIXME: actually, we should check for the flavor
2978 // or runparams.isFullyUnicode() here:
2979 // This check will not work with XeTeX/LuaTeX and tex fonts.
2980 // Thus we have to reset the encoding in Buffer::makeLaTeXFile.
2982 return *(encodings.fromLyXName("utf8-plain"));
2983 if (inputenc == "auto" || inputenc == "default")
2984 return *language->encoding();
2985 Encoding const * const enc = encodings.fromLyXName(inputenc);
2988 LYXERR0("Unknown inputenc value `" << inputenc
2989 << "'. Using `auto' instead.");
2990 return *language->encoding();
2994 bool BufferParams::addCiteEngine(string const & engine)
2996 LayoutModuleList::const_iterator it = cite_engine_.begin();
2997 LayoutModuleList::const_iterator en = cite_engine_.end();
2998 for (; it != en; ++it)
3001 cite_engine_.push_back(engine);
3006 bool BufferParams::addCiteEngine(vector<string> const & engine)
3008 vector<string>::const_iterator it = engine.begin();
3009 vector<string>::const_iterator en = engine.end();
3011 for (; it != en; ++it)
3012 if (!addCiteEngine(*it))
3018 string const & BufferParams::defaultBiblioStyle() const
3020 return documentClass().defaultBiblioStyle();
3024 bool const & BufferParams::fullAuthorList() const
3026 return documentClass().fullAuthorList();
3030 void BufferParams::setCiteEngine(string const & engine)
3033 addCiteEngine(engine);
3037 void BufferParams::setCiteEngine(vector<string> const & engine)
3040 addCiteEngine(engine);
3044 vector<string> BufferParams::citeCommands() const
3046 static CitationStyle const default_style;
3047 vector<string> commands =
3048 documentClass().citeCommands(citeEngineType());
3049 if (commands.empty())
3050 commands.push_back(default_style.cmd);
3055 vector<CitationStyle> BufferParams::citeStyles() const
3057 static CitationStyle const default_style;
3058 vector<CitationStyle> styles =
3059 documentClass().citeStyles(citeEngineType());
3061 styles.push_back(default_style);