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/mutex.h"
56 #include "support/Translator.h"
57 #include "support/lstrings.h"
63 using namespace lyx::support;
66 static char const * const string_paragraph_separation[] = {
71 static char const * const string_quotes_language[] = {
72 "english", "swedish", "german", "polish", "french", "danish", ""
76 static char const * const string_papersize[] = {
77 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
78 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
79 "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
80 "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
81 "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
86 static char const * const string_orientation[] = {
87 "portrait", "landscape", ""
91 static char const * const tex_graphics[] = {
92 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
93 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
94 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
95 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
106 // Paragraph separation
107 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
110 ParSepTranslator const init_parseptranslator()
112 ParSepTranslator translator
113 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
114 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
119 ParSepTranslator const & parseptranslator()
121 static ParSepTranslator const translator =
122 init_parseptranslator();
128 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
131 QuotesLangTranslator const init_quoteslangtranslator()
133 QuotesLangTranslator translator
134 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
135 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
136 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
137 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
138 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
139 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
144 QuotesLangTranslator const & quoteslangtranslator()
146 static QuotesLangTranslator const translator =
147 init_quoteslangtranslator();
153 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
156 static PaperSizeTranslator initPaperSizeTranslator()
158 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
159 translator.addPair(string_papersize[1], PAPER_CUSTOM);
160 translator.addPair(string_papersize[2], PAPER_USLETTER);
161 translator.addPair(string_papersize[3], PAPER_USLEGAL);
162 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
163 translator.addPair(string_papersize[5], PAPER_A0);
164 translator.addPair(string_papersize[6], PAPER_A1);
165 translator.addPair(string_papersize[7], PAPER_A2);
166 translator.addPair(string_papersize[8], PAPER_A3);
167 translator.addPair(string_papersize[9], PAPER_A4);
168 translator.addPair(string_papersize[10], PAPER_A5);
169 translator.addPair(string_papersize[11], PAPER_A6);
170 translator.addPair(string_papersize[12], PAPER_B0);
171 translator.addPair(string_papersize[13], PAPER_B1);
172 translator.addPair(string_papersize[14], PAPER_B2);
173 translator.addPair(string_papersize[15], PAPER_B3);
174 translator.addPair(string_papersize[16], PAPER_B4);
175 translator.addPair(string_papersize[17], PAPER_B5);
176 translator.addPair(string_papersize[18], PAPER_B6);
177 translator.addPair(string_papersize[19], PAPER_C0);
178 translator.addPair(string_papersize[20], PAPER_C1);
179 translator.addPair(string_papersize[21], PAPER_C2);
180 translator.addPair(string_papersize[22], PAPER_C3);
181 translator.addPair(string_papersize[23], PAPER_C4);
182 translator.addPair(string_papersize[24], PAPER_C5);
183 translator.addPair(string_papersize[25], PAPER_C6);
184 translator.addPair(string_papersize[26], PAPER_JISB0);
185 translator.addPair(string_papersize[27], PAPER_JISB1);
186 translator.addPair(string_papersize[28], PAPER_JISB2);
187 translator.addPair(string_papersize[29], PAPER_JISB3);
188 translator.addPair(string_papersize[30], PAPER_JISB4);
189 translator.addPair(string_papersize[31], PAPER_JISB5);
190 translator.addPair(string_papersize[32], PAPER_JISB6);
195 PaperSizeTranslator const & papersizetranslator()
197 static PaperSizeTranslator const translator =
198 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 const translator =
218 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 const 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 const translator =
258 init_packagetranslator();
264 typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator;
267 CiteEngineTypeTranslator const init_citeenginetypetranslator()
269 CiteEngineTypeTranslator translator("authoryear", ENGINE_TYPE_AUTHORYEAR);
270 translator.addPair("numerical", ENGINE_TYPE_NUMERICAL);
271 translator.addPair("default", ENGINE_TYPE_DEFAULT);
276 CiteEngineTypeTranslator const & citeenginetypetranslator()
278 static CiteEngineTypeTranslator const translator =
279 init_citeenginetypetranslator();
285 typedef Translator<string, Spacing::Space> SpaceTranslator;
288 SpaceTranslator const init_spacetranslator()
290 SpaceTranslator translator("default", Spacing::Default);
291 translator.addPair("single", Spacing::Single);
292 translator.addPair("onehalf", Spacing::Onehalf);
293 translator.addPair("double", Spacing::Double);
294 translator.addPair("other", Spacing::Other);
299 SpaceTranslator const & spacetranslator()
301 static SpaceTranslator const translator = init_spacetranslator();
308 class BufferParams::Impl
313 AuthorList authorlist;
314 BranchList branchlist;
315 Bullet temp_bullets[4];
316 Bullet user_defined_bullets[4];
317 IndicesList indiceslist;
319 /** This is the amount of space used for paragraph_separation "skip",
320 * and for detached paragraphs in "indented" documents.
324 PDFOptions pdfoptions;
325 LayoutFileIndex baseClass_;
329 BufferParams::Impl::Impl()
330 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
332 // set initial author
334 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
339 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
342 return new BufferParams::Impl(*ptr);
346 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
352 BufferParams::BufferParams()
355 setBaseClass(defaultBaseclass());
357 paragraph_separation = ParagraphIndentSeparation;
358 quotes_language = InsetQuotes::EnglishQuotes;
359 fontsize = "default";
362 papersize = PAPER_DEFAULT;
363 orientation = ORIENTATION_PORTRAIT;
364 use_geometry = false;
365 cite_engine_.push_back("basic");
366 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
367 biblio_style = "plain";
368 use_bibtopic = false;
370 track_changes = false;
371 output_changes = false;
372 use_default_options = true;
373 maintain_unincluded_children = false;
376 language = default_language;
378 fonts_roman = "default";
379 fonts_sans = "default";
380 fonts_typewriter = "default";
382 fonts_default_family = "default";
383 useNonTeXFonts = false;
384 fonts_expert_sc = false;
385 fonts_old_figures = false;
386 fonts_sans_scale = 100;
387 fonts_typewriter_scale = 100;
389 lang_package = "default";
390 graphics_driver = "default";
391 default_output_format = "default";
392 bibtex_command = "default";
393 index_command = "default";
396 listings_params = string();
397 pagestyle = "default";
398 suppress_date = false;
399 justification = true;
400 // no color is the default (white)
401 backgroundcolor = lyx::rgbFromHexName("#ffffff");
402 isbackgroundcolor = false;
403 // no color is the default (black)
404 fontcolor = lyx::rgbFromHexName("#000000");
406 // light gray is the default font color for greyed-out notes
407 notefontcolor = lyx::rgbFromHexName("#cccccc");
408 boxbgcolor = lyx::rgbFromHexName("#ff0000");
409 compressed = lyxrc.save_compressed;
410 for (int iter = 0; iter < 4; ++iter) {
411 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
412 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
415 indiceslist().addDefault(B_("Index"));
416 html_be_strict = false;
417 html_math_output = MathML;
418 html_math_img_scale = 1.0;
419 html_css_as_file = false;
426 docstring BufferParams::B_(string const & l10n) const
428 LASSERT(language, return from_utf8(l10n));
429 return getMessages(language->code()).get(l10n);
433 BufferParams::Package BufferParams::use_package(std::string const & p) const
435 PackageMap::const_iterator it = use_packages.find(p);
436 if (it == use_packages.end())
442 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
448 map<string, string> const & BufferParams::auto_packages()
450 static map<string, string> packages;
451 if (packages.empty()) {
452 // We could have a race condition here that two threads
453 // discover an empty map at the same time and want to fill
454 // it, but that is no problem, since the same contents is
455 // filled in twice then. Having the locker inside the
456 // packages.empty() condition has the advantage that we
457 // don't need the mutex overhead for simple reading.
459 Mutex::Locker locker(&mutex);
460 // adding a package here implies a file format change!
461 packages["amsmath"] =
462 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
463 packages["amssymb"] =
464 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
466 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
468 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
469 packages["mathdots"] =
470 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
471 packages["mathtools"] =
472 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
474 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
475 packages["stackrel"] =
476 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
477 packages["stmaryrd"] =
478 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");
479 packages["undertilde"] =
480 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
486 AuthorList & BufferParams::authors()
488 return pimpl_->authorlist;
492 AuthorList const & BufferParams::authors() const
494 return pimpl_->authorlist;
498 BranchList & BufferParams::branchlist()
500 return pimpl_->branchlist;
504 BranchList const & BufferParams::branchlist() const
506 return pimpl_->branchlist;
510 IndicesList & BufferParams::indiceslist()
512 return pimpl_->indiceslist;
516 IndicesList const & BufferParams::indiceslist() const
518 return pimpl_->indiceslist;
522 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
524 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
525 return pimpl_->temp_bullets[index];
529 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
531 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
532 return pimpl_->temp_bullets[index];
536 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
538 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
539 return pimpl_->user_defined_bullets[index];
543 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
545 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
546 return pimpl_->user_defined_bullets[index];
550 Spacing & BufferParams::spacing()
552 return pimpl_->spacing;
556 Spacing const & BufferParams::spacing() const
558 return pimpl_->spacing;
562 PDFOptions & BufferParams::pdfoptions()
564 return pimpl_->pdfoptions;
568 PDFOptions const & BufferParams::pdfoptions() const
570 return pimpl_->pdfoptions;
574 HSpace const & BufferParams::getIndentation() const
576 return pimpl_->indentation;
580 void BufferParams::setIndentation(HSpace const & indent)
582 pimpl_->indentation = indent;
586 VSpace const & BufferParams::getDefSkip() const
588 return pimpl_->defskip;
592 void BufferParams::setDefSkip(VSpace const & vs)
594 // DEFSKIP will cause an infinite loop
595 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
596 pimpl_->defskip = vs;
600 string BufferParams::readToken(Lexer & lex, string const & token,
601 FileName const & filepath)
603 if (token == "\\textclass") {
605 string const classname = lex.getString();
606 // if there exists a local layout file, ignore the system one
607 // NOTE: in this case, the textclass (.cls file) is assumed to
610 LayoutFileList & bcl = LayoutFileList::get();
611 if (!filepath.empty())
612 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
613 // that returns non-empty if a "local" layout file is found.
617 setBaseClass(classname);
618 // We assume that a tex class exists for local or unknown
619 // layouts so this warning, will only be given for system layouts.
620 if (!baseClass()->isTeXClassAvailable()) {
621 docstring const desc =
622 translateIfPossible(from_utf8(baseClass()->description()));
623 docstring const prereqs =
624 from_utf8(baseClass()->prerequisites());
625 docstring const msg =
626 bformat(_("The selected document class\n"
628 "requires external files that are not available.\n"
629 "The document class can still be used, but the\n"
630 "document cannot be compiled until the following\n"
631 "prerequisites are installed:\n"
633 "See section 3.1.2.2 (Class Availability) of the\n"
634 "User's Guide for more information."), desc, prereqs);
635 frontend::Alert::warning(_("Document class not available"),
638 } else if (token == "\\begin_preamble") {
640 } else if (token == "\\begin_local_layout") {
641 readLocalLayout(lex, false);
642 } else if (token == "\\begin_forced_local_layout") {
643 readLocalLayout(lex, true);
644 } else if (token == "\\begin_modules") {
646 } else if (token == "\\begin_removed_modules") {
647 readRemovedModules(lex);
648 } else if (token == "\\begin_includeonly") {
649 readIncludeonly(lex);
650 } else if (token == "\\maintain_unincluded_children") {
651 lex >> maintain_unincluded_children;
652 } else if (token == "\\options") {
654 options = lex.getString();
655 } else if (token == "\\use_default_options") {
656 lex >> use_default_options;
657 } else if (token == "\\master") {
659 master = lex.getString();
660 } else if (token == "\\suppress_date") {
661 lex >> suppress_date;
662 } else if (token == "\\justification") {
663 lex >> justification;
664 } else if (token == "\\language") {
666 } else if (token == "\\language_package") {
668 lang_package = lex.getString();
669 } else if (token == "\\inputencoding") {
671 } else if (token == "\\graphics") {
672 readGraphicsDriver(lex);
673 } else if (token == "\\default_output_format") {
674 lex >> default_output_format;
675 } else if (token == "\\bibtex_command") {
677 bibtex_command = lex.getString();
678 } else if (token == "\\index_command") {
680 index_command = lex.getString();
681 } else if (token == "\\fontencoding") {
683 fontenc = lex.getString();
684 } else if (token == "\\font_roman") {
686 fonts_roman = lex.getString();
687 } else if (token == "\\font_sans") {
689 fonts_sans = lex.getString();
690 } else if (token == "\\font_typewriter") {
692 fonts_typewriter = lex.getString();
693 } else if (token == "\\font_math") {
695 fonts_math = lex.getString();
696 } else if (token == "\\font_default_family") {
697 lex >> fonts_default_family;
698 } else if (token == "\\use_non_tex_fonts") {
699 lex >> useNonTeXFonts;
700 } else if (token == "\\font_sc") {
701 lex >> fonts_expert_sc;
702 } else if (token == "\\font_osf") {
703 lex >> fonts_old_figures;
704 } else if (token == "\\font_sf_scale") {
705 lex >> fonts_sans_scale;
706 } else if (token == "\\font_tt_scale") {
707 lex >> fonts_typewriter_scale;
708 } else if (token == "\\font_cjk") {
710 } else if (token == "\\paragraph_separation") {
713 paragraph_separation = parseptranslator().find(parsep);
714 } else if (token == "\\paragraph_indentation") {
716 string indentation = lex.getString();
717 pimpl_->indentation = HSpace(indentation);
718 } else if (token == "\\defskip") {
720 string const defskip = lex.getString();
721 pimpl_->defskip = VSpace(defskip);
722 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
724 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
725 } else if (token == "\\quotes_language") {
728 quotes_language = quoteslangtranslator().find(quotes_lang);
729 } else if (token == "\\papersize") {
732 papersize = papersizetranslator().find(ppsize);
733 } else if (token == "\\use_geometry") {
735 } else if (token == "\\use_package") {
740 use_package(package, packagetranslator().find(use));
741 } else if (token == "\\cite_engine") {
743 vector<string> engine = getVectorFromString(lex.getString());
744 setCiteEngine(engine);
745 } else if (token == "\\cite_engine_type") {
748 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
749 } else if (token == "\\biblio_style") {
751 biblio_style = lex.getString();
752 } else if (token == "\\use_bibtopic") {
754 } else if (token == "\\use_indices") {
756 } else if (token == "\\tracking_changes") {
757 lex >> track_changes;
758 } else if (token == "\\output_changes") {
759 lex >> output_changes;
760 } else if (token == "\\branch") {
762 docstring branch = lex.getDocString();
763 branchlist().add(branch);
766 string const tok = lex.getString();
767 if (tok == "\\end_branch")
769 Branch * branch_ptr = branchlist().find(branch);
770 if (tok == "\\selected") {
773 branch_ptr->setSelected(lex.getInteger());
775 if (tok == "\\filename_suffix") {
778 branch_ptr->setFileNameSuffix(lex.getInteger());
780 if (tok == "\\color") {
782 string color = lex.getString();
784 branch_ptr->setColor(color);
785 // Update also the Color table:
787 color = lcolor.getX11Name(Color_background);
789 lcolor.setColor(to_utf8(branch), color);
792 } else if (token == "\\index") {
794 docstring index = lex.getDocString();
796 indiceslist().add(index);
799 string const tok = lex.getString();
800 if (tok == "\\end_index")
802 Index * index_ptr = indiceslist().find(index);
803 if (tok == "\\shortcut") {
805 shortcut = lex.getDocString();
807 index_ptr->setShortcut(shortcut);
809 if (tok == "\\color") {
811 string color = lex.getString();
813 index_ptr->setColor(color);
814 // Update also the Color table:
816 color = lcolor.getX11Name(Color_background);
818 if (!shortcut.empty())
819 lcolor.setColor(to_utf8(shortcut), color);
822 } else if (token == "\\author") {
824 istringstream ss(lex.getString());
827 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
828 } else if (token == "\\paperorientation") {
831 orientation = paperorientationtranslator().find(orient);
832 } else if (token == "\\backgroundcolor") {
834 backgroundcolor = lyx::rgbFromHexName(lex.getString());
835 isbackgroundcolor = true;
836 } else if (token == "\\fontcolor") {
838 fontcolor = lyx::rgbFromHexName(lex.getString());
840 } else if (token == "\\notefontcolor") {
842 string color = lex.getString();
843 notefontcolor = lyx::rgbFromHexName(color);
844 lcolor.setColor("notefontcolor", color);
845 } else if (token == "\\boxbgcolor") {
847 string color = lex.getString();
848 boxbgcolor = lyx::rgbFromHexName(color);
849 lcolor.setColor("boxbgcolor", color);
850 } else if (token == "\\paperwidth") {
852 } else if (token == "\\paperheight") {
854 } else if (token == "\\leftmargin") {
856 } else if (token == "\\topmargin") {
858 } else if (token == "\\rightmargin") {
860 } else if (token == "\\bottommargin") {
862 } else if (token == "\\headheight") {
864 } else if (token == "\\headsep") {
866 } else if (token == "\\footskip") {
868 } else if (token == "\\columnsep") {
870 } else if (token == "\\paperfontsize") {
872 } else if (token == "\\papercolumns") {
874 } else if (token == "\\listings_params") {
877 listings_params = InsetListingsParams(par).params();
878 } else if (token == "\\papersides") {
881 sides = sidestranslator().find(psides);
882 } else if (token == "\\paperpagestyle") {
884 } else if (token == "\\bullet") {
886 } else if (token == "\\bulletLaTeX") {
887 readBulletsLaTeX(lex);
888 } else if (token == "\\secnumdepth") {
890 } else if (token == "\\tocdepth") {
892 } else if (token == "\\spacing") {
896 if (nspacing == "other") {
899 spacing().set(spacetranslator().find(nspacing), tmp_val);
900 } else if (token == "\\float_placement") {
901 lex >> float_placement;
903 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
904 string toktmp = pdfoptions().readToken(lex, token);
905 if (!toktmp.empty()) {
906 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
910 } else if (token == "\\html_math_output") {
913 html_math_output = static_cast<MathOutput>(temp);
914 } else if (token == "\\html_be_strict") {
915 lex >> html_be_strict;
916 } else if (token == "\\html_css_as_file") {
917 lex >> html_css_as_file;
918 } else if (token == "\\html_math_img_scale") {
919 lex >> html_math_img_scale;
920 } else if (token == "\\html_latex_start") {
922 html_latex_start = lex.getString();
923 } else if (token == "\\html_latex_end") {
925 html_latex_end = lex.getString();
926 } else if (token == "\\output_sync") {
928 } else if (token == "\\output_sync_macro") {
929 lex >> output_sync_macro;
930 } else if (token == "\\use_refstyle") {
933 lyxerr << "BufferParams::readToken(): Unknown token: " <<
942 void BufferParams::writeFile(ostream & os) const
944 // The top of the file is written by the buffer.
945 // Prints out the buffer info into the .lyx file given by file
948 os << "\\textclass " << baseClass()->name() << '\n';
951 if (!preamble.empty()) {
952 // remove '\n' from the end of preamble
953 string const tmppreamble = rtrim(preamble, "\n");
954 os << "\\begin_preamble\n"
956 << "\n\\end_preamble\n";
960 if (!options.empty()) {
961 os << "\\options " << options << '\n';
964 // use the class options defined in the layout?
965 os << "\\use_default_options "
966 << convert<string>(use_default_options) << "\n";
968 // the master document
969 if (!master.empty()) {
970 os << "\\master " << master << '\n';
974 if (!removed_modules_.empty()) {
975 os << "\\begin_removed_modules" << '\n';
976 list<string>::const_iterator it = removed_modules_.begin();
977 list<string>::const_iterator en = removed_modules_.end();
978 for (; it != en; ++it)
980 os << "\\end_removed_modules" << '\n';
984 if (!layout_modules_.empty()) {
985 os << "\\begin_modules" << '\n';
986 LayoutModuleList::const_iterator it = layout_modules_.begin();
987 LayoutModuleList::const_iterator en = layout_modules_.end();
988 for (; it != en; ++it)
990 os << "\\end_modules" << '\n';
994 if (!included_children_.empty()) {
995 os << "\\begin_includeonly" << '\n';
996 list<string>::const_iterator it = included_children_.begin();
997 list<string>::const_iterator en = included_children_.end();
998 for (; it != en; ++it)
1000 os << "\\end_includeonly" << '\n';
1002 os << "\\maintain_unincluded_children "
1003 << convert<string>(maintain_unincluded_children) << '\n';
1005 // local layout information
1006 string const local_layout = getLocalLayout(false);
1007 if (!local_layout.empty()) {
1008 // remove '\n' from the end
1009 string const tmplocal = rtrim(local_layout, "\n");
1010 os << "\\begin_local_layout\n"
1012 << "\n\\end_local_layout\n";
1014 string const forced_local_layout = getLocalLayout(true);
1015 if (!forced_local_layout.empty()) {
1016 // remove '\n' from the end
1017 string const tmplocal = rtrim(forced_local_layout, "\n");
1018 os << "\\begin_forced_local_layout\n"
1020 << "\n\\end_forced_local_layout\n";
1023 // then the text parameters
1024 if (language != ignore_language)
1025 os << "\\language " << language->lang() << '\n';
1026 os << "\\language_package " << lang_package
1027 << "\n\\inputencoding " << inputenc
1028 << "\n\\fontencoding " << fontenc
1029 << "\n\\font_roman " << fonts_roman
1030 << "\n\\font_sans " << fonts_sans
1031 << "\n\\font_typewriter " << fonts_typewriter
1032 << "\n\\font_math " << fonts_math
1033 << "\n\\font_default_family " << fonts_default_family
1034 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1035 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1036 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1037 << "\n\\font_sf_scale " << fonts_sans_scale
1038 << "\n\\font_tt_scale " << fonts_typewriter_scale
1040 if (!fonts_cjk.empty()) {
1041 os << "\\font_cjk " << fonts_cjk << '\n';
1043 os << "\\graphics " << graphics_driver << '\n';
1044 os << "\\default_output_format " << default_output_format << '\n';
1045 os << "\\output_sync " << output_sync << '\n';
1046 if (!output_sync_macro.empty())
1047 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1048 os << "\\bibtex_command " << bibtex_command << '\n';
1049 os << "\\index_command " << index_command << '\n';
1051 if (!float_placement.empty()) {
1052 os << "\\float_placement " << float_placement << '\n';
1054 os << "\\paperfontsize " << fontsize << '\n';
1056 spacing().writeFile(os);
1057 pdfoptions().writeFile(os);
1059 os << "\\papersize " << string_papersize[papersize]
1060 << "\n\\use_geometry " << convert<string>(use_geometry);
1061 map<string, string> const & packages = auto_packages();
1062 for (map<string, string>::const_iterator it = packages.begin();
1063 it != packages.end(); ++it)
1064 os << "\n\\use_package " << it->first << ' '
1065 << use_package(it->first);
1067 os << "\n\\cite_engine ";
1069 if (!cite_engine_.empty()) {
1070 LayoutModuleList::const_iterator be = cite_engine_.begin();
1071 LayoutModuleList::const_iterator en = cite_engine_.end();
1072 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1081 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1082 << "\n\\biblio_style " << biblio_style
1083 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1084 << "\n\\use_indices " << convert<string>(use_indices)
1085 << "\n\\paperorientation " << string_orientation[orientation]
1086 << "\n\\suppress_date " << convert<string>(suppress_date)
1087 << "\n\\justification " << convert<string>(justification)
1088 << "\n\\use_refstyle " << use_refstyle
1090 if (isbackgroundcolor == true)
1091 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1092 if (isfontcolor == true)
1093 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1094 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1095 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1096 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1097 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1099 BranchList::const_iterator it = branchlist().begin();
1100 BranchList::const_iterator end = branchlist().end();
1101 for (; it != end; ++it) {
1102 os << "\\branch " << to_utf8(it->branch())
1103 << "\n\\selected " << it->isSelected()
1104 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1105 << "\n\\color " << lyx::X11hexname(it->color())
1110 IndicesList::const_iterator iit = indiceslist().begin();
1111 IndicesList::const_iterator iend = indiceslist().end();
1112 for (; iit != iend; ++iit) {
1113 os << "\\index " << to_utf8(iit->index())
1114 << "\n\\shortcut " << to_utf8(iit->shortcut())
1115 << "\n\\color " << lyx::X11hexname(iit->color())
1120 if (!paperwidth.empty())
1121 os << "\\paperwidth "
1122 << VSpace(paperwidth).asLyXCommand() << '\n';
1123 if (!paperheight.empty())
1124 os << "\\paperheight "
1125 << VSpace(paperheight).asLyXCommand() << '\n';
1126 if (!leftmargin.empty())
1127 os << "\\leftmargin "
1128 << VSpace(leftmargin).asLyXCommand() << '\n';
1129 if (!topmargin.empty())
1130 os << "\\topmargin "
1131 << VSpace(topmargin).asLyXCommand() << '\n';
1132 if (!rightmargin.empty())
1133 os << "\\rightmargin "
1134 << VSpace(rightmargin).asLyXCommand() << '\n';
1135 if (!bottommargin.empty())
1136 os << "\\bottommargin "
1137 << VSpace(bottommargin).asLyXCommand() << '\n';
1138 if (!headheight.empty())
1139 os << "\\headheight "
1140 << VSpace(headheight).asLyXCommand() << '\n';
1141 if (!headsep.empty())
1143 << VSpace(headsep).asLyXCommand() << '\n';
1144 if (!footskip.empty())
1146 << VSpace(footskip).asLyXCommand() << '\n';
1147 if (!columnsep.empty())
1148 os << "\\columnsep "
1149 << VSpace(columnsep).asLyXCommand() << '\n';
1150 os << "\\secnumdepth " << secnumdepth
1151 << "\n\\tocdepth " << tocdepth
1152 << "\n\\paragraph_separation "
1153 << string_paragraph_separation[paragraph_separation];
1154 if (!paragraph_separation)
1155 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1157 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1158 os << "\n\\quotes_language "
1159 << string_quotes_language[quotes_language]
1160 << "\n\\papercolumns " << columns
1161 << "\n\\papersides " << sides
1162 << "\n\\paperpagestyle " << pagestyle << '\n';
1163 if (!listings_params.empty())
1164 os << "\\listings_params \"" <<
1165 InsetListingsParams(listings_params).encodedString() << "\"\n";
1166 for (int i = 0; i < 4; ++i) {
1167 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1168 if (user_defined_bullet(i).getFont() != -1) {
1169 os << "\\bullet " << i << " "
1170 << user_defined_bullet(i).getFont() << " "
1171 << user_defined_bullet(i).getCharacter() << " "
1172 << user_defined_bullet(i).getSize() << "\n";
1176 os << "\\bulletLaTeX " << i << " \""
1177 << lyx::to_ascii(user_defined_bullet(i).getText())
1183 os << "\\tracking_changes " << convert<string>(track_changes) << '\n'
1184 << "\\output_changes " << convert<string>(output_changes) << '\n'
1185 << "\\html_math_output " << html_math_output << '\n'
1186 << "\\html_css_as_file " << html_css_as_file << '\n'
1187 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1189 if (html_math_img_scale != 1.0)
1190 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1191 if (!html_latex_start.empty())
1192 os << "\\html_latex_start " << html_latex_start << '\n';
1193 if (!html_latex_end.empty())
1194 os << "\\html_latex_end " << html_latex_end << '\n';
1196 os << pimpl_->authorlist;
1200 void BufferParams::validate(LaTeXFeatures & features) const
1202 features.require(documentClass().requires());
1204 if (columns > 1 && language->rightToLeft())
1205 features.require("rtloutputdblcol");
1207 if (output_changes) {
1208 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1209 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1210 LaTeXFeatures::isAvailable("xcolor");
1212 switch (features.runparams().flavor) {
1213 case OutputParams::LATEX:
1214 case OutputParams::DVILUATEX:
1216 features.require("ct-dvipost");
1217 features.require("dvipost");
1218 } else if (xcolorulem) {
1219 features.require("ct-xcolor-ulem");
1220 features.require("ulem");
1221 features.require("xcolor");
1223 features.require("ct-none");
1226 case OutputParams::LUATEX:
1227 case OutputParams::PDFLATEX:
1228 case OutputParams::XETEX:
1230 features.require("ct-xcolor-ulem");
1231 features.require("ulem");
1232 features.require("xcolor");
1233 // improves color handling in PDF output
1234 features.require("pdfcolmk");
1236 features.require("ct-none");
1244 // Floats with 'Here definitely' as default setting.
1245 if (float_placement.find('H') != string::npos)
1246 features.require("float");
1248 for (PackageMap::const_iterator it = use_packages.begin();
1249 it != use_packages.end(); ++it) {
1250 if (it->first == "amsmath") {
1251 // AMS Style is at document level
1252 if (it->second == package_on ||
1253 features.isProvided("amsmath"))
1254 features.require(it->first);
1255 } else if (it->second == package_on)
1256 features.require(it->first);
1259 // Document-level line spacing
1260 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1261 features.require("setspace");
1263 // the bullet shapes are buffer level not paragraph level
1264 // so they are tested here
1265 for (int i = 0; i < 4; ++i) {
1266 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1268 int const font = user_defined_bullet(i).getFont();
1270 int const c = user_defined_bullet(i).getCharacter();
1276 features.require("latexsym");
1278 } else if (font == 1) {
1279 features.require("amssymb");
1280 } else if (font >= 2 && font <= 5) {
1281 features.require("pifont");
1285 if (pdfoptions().use_hyperref) {
1286 features.require("hyperref");
1287 // due to interferences with babel and hyperref, the color package has to
1288 // be loaded after hyperref when hyperref is used with the colorlinks
1289 // option, see http://www.lyx.org/trac/ticket/5291
1290 if (pdfoptions().colorlinks)
1291 features.require("color");
1293 if (!listings_params.empty()) {
1294 // do not test validity because listings_params is
1295 // supposed to be valid
1297 InsetListingsParams(listings_params).separatedParams(true);
1298 // we can't support all packages, but we should load the color package
1299 if (par.find("\\color", 0) != string::npos)
1300 features.require("color");
1303 // some languages are only available via polyglossia
1304 if (features.runparams().flavor == OutputParams::XETEX
1305 && (features.hasPolyglossiaExclusiveLanguages()
1307 features.require("polyglossia");
1309 if (useNonTeXFonts && fonts_math != "auto")
1310 features.require("unicode-math");
1312 if (!language->requires().empty())
1313 features.require(language->requires());
1317 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1318 FileName const & filepath) const
1320 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1321 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1322 // \RequirePackage to do so, rather than the normal \usepackage
1323 // Do not try to load any other package before the document class, unless you
1324 // have a thorough understanding of the LATEX internals and know exactly what you
1326 if (features.mustProvide("fix-cm"))
1327 os << "\\RequirePackage{fix-cm}\n";
1329 os << "\\documentclass";
1331 DocumentClass const & tclass = documentClass();
1333 ostringstream clsoptions; // the document class options.
1335 if (tokenPos(tclass.opt_fontsize(),
1336 '|', fontsize) >= 0) {
1337 // only write if existing in list (and not default)
1338 clsoptions << fontsize << "pt,";
1341 // all paper sizes except of A4, A5, B5 and the US sizes need the
1343 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1344 && papersize != PAPER_USLETTER
1345 && papersize != PAPER_USLEGAL
1346 && papersize != PAPER_USEXECUTIVE
1347 && papersize != PAPER_A4
1348 && papersize != PAPER_A5
1349 && papersize != PAPER_B5;
1351 if (!use_geometry) {
1352 switch (papersize) {
1354 clsoptions << "a4paper,";
1356 case PAPER_USLETTER:
1357 clsoptions << "letterpaper,";
1360 clsoptions << "a5paper,";
1363 clsoptions << "b5paper,";
1365 case PAPER_USEXECUTIVE:
1366 clsoptions << "executivepaper,";
1369 clsoptions << "legalpaper,";
1403 if (sides != tclass.sides()) {
1406 clsoptions << "oneside,";
1409 clsoptions << "twoside,";
1415 if (columns != tclass.columns()) {
1417 clsoptions << "twocolumn,";
1419 clsoptions << "onecolumn,";
1423 && orientation == ORIENTATION_LANDSCAPE)
1424 clsoptions << "landscape,";
1426 // language should be a parameter to \documentclass
1427 if (language->babel() == "hebrew"
1428 && default_language->babel() != "hebrew")
1429 // This seems necessary
1430 features.useLanguage(default_language);
1432 ostringstream language_options;
1433 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1434 bool const use_polyglossia = features.usePolyglossia();
1435 bool const global = lyxrc.language_global_options;
1436 if (use_babel || (use_polyglossia && global)) {
1437 language_options << features.getBabelLanguages();
1438 if (!language->babel().empty()) {
1439 if (!language_options.str().empty())
1440 language_options << ',';
1441 language_options << language->babel();
1443 if (global && !features.needBabelLangOptions()
1444 && !language_options.str().empty())
1445 clsoptions << language_options.str() << ',';
1448 // the predefined options from the layout
1449 if (use_default_options && !tclass.options().empty())
1450 clsoptions << tclass.options() << ',';
1452 // the user-defined options
1453 if (!options.empty()) {
1454 clsoptions << options << ',';
1457 string strOptions(clsoptions.str());
1458 if (!strOptions.empty()) {
1459 strOptions = rtrim(strOptions, ",");
1461 os << '[' << from_utf8(strOptions) << ']';
1464 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1465 // end of \documentclass defs
1467 // if we use fontspec or newtxmath, we have to load the AMS packages here
1468 string const ams = features.loadAMSPackages();
1469 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1470 bool const use_newtxmath =
1471 theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getUsedPackage(
1472 ot1, false, false) == "newtxmath";
1473 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1474 os << from_ascii(ams);
1476 if (useNonTeXFonts) {
1477 os << "\\usepackage{fontspec}\n";
1478 if (features.mustProvide("unicode-math")
1479 && features.isAvailable("unicode-math"))
1480 os << "\\usepackage{unicode-math}\n";
1483 // font selection must be done before loading fontenc.sty
1484 string const fonts = loadFonts(features);
1486 os << from_utf8(fonts);
1488 if (fonts_default_family != "default")
1489 os << "\\renewcommand{\\familydefault}{\\"
1490 << from_ascii(fonts_default_family) << "}\n";
1492 // set font encoding
1493 // for arabic_arabi and farsi we also need to load the LAE and
1495 // XeTeX and LuaTeX (with OS fonts) work without fontenc
1496 if (font_encoding() != "default" && language->lang() != "japanese"
1497 && !useNonTeXFonts && !features.isProvided("fontenc")) {
1498 docstring extra_encoding;
1499 if (features.mustProvide("textgreek"))
1500 extra_encoding += from_ascii("LGR");
1501 if (features.mustProvide("textcyr")) {
1502 if (!extra_encoding.empty())
1503 extra_encoding.push_back(',');
1504 extra_encoding += from_ascii("T2A");
1506 if (!extra_encoding.empty() && !font_encoding().empty())
1507 extra_encoding.push_back(',');
1508 size_t fars = language_options.str().find("farsi");
1509 size_t arab = language_options.str().find("arabic");
1510 if (language->lang() == "arabic_arabi"
1511 || language->lang() == "farsi" || fars != string::npos
1512 || arab != string::npos) {
1513 os << "\\usepackage[" << extra_encoding
1514 << from_ascii(font_encoding())
1515 << ",LFE,LAE]{fontenc}\n";
1517 os << "\\usepackage[" << extra_encoding
1518 << from_ascii(font_encoding())
1523 // handle inputenc etc.
1524 writeEncodingPreamble(os, features);
1527 if (!features.runparams().includeall && !included_children_.empty()) {
1528 os << "\\includeonly{";
1529 list<string>::const_iterator it = included_children_.begin();
1530 list<string>::const_iterator en = included_children_.end();
1532 for (; it != en; ++it) {
1533 string incfile = *it;
1534 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1535 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1537 if (!features.runparams().nice)
1539 // \includeonly doesn't want an extension
1540 incfile = changeExtension(incfile, string());
1541 incfile = support::latex_path(incfile);
1542 if (!incfile.empty()) {
1545 os << from_utf8(incfile);
1552 if (!features.isProvided("geometry")
1553 && (use_geometry || nonstandard_papersize)) {
1554 odocstringstream ods;
1555 if (!getGraphicsDriver("geometry").empty())
1556 ods << getGraphicsDriver("geometry");
1557 if (orientation == ORIENTATION_LANDSCAPE)
1558 ods << ",landscape";
1559 switch (papersize) {
1561 if (!paperwidth.empty())
1562 ods << ",paperwidth="
1563 << from_ascii(paperwidth);
1564 if (!paperheight.empty())
1565 ods << ",paperheight="
1566 << from_ascii(paperheight);
1568 case PAPER_USLETTER:
1569 ods << ",letterpaper";
1572 ods << ",legalpaper";
1574 case PAPER_USEXECUTIVE:
1575 ods << ",executivepaper";
1664 docstring const g_options = trim(ods.str(), ",");
1665 os << "\\usepackage";
1666 if (!g_options.empty())
1667 os << '[' << g_options << ']';
1668 os << "{geometry}\n";
1669 // output this only if use_geometry is true
1671 os << "\\geometry{verbose";
1672 if (!topmargin.empty())
1673 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1674 if (!bottommargin.empty())
1675 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1676 if (!leftmargin.empty())
1677 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1678 if (!rightmargin.empty())
1679 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1680 if (!headheight.empty())
1681 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1682 if (!headsep.empty())
1683 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1684 if (!footskip.empty())
1685 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1686 if (!columnsep.empty())
1687 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1690 } else if (orientation == ORIENTATION_LANDSCAPE
1691 || papersize != PAPER_DEFAULT) {
1692 features.require("papersize");
1695 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1696 if (pagestyle == "fancy")
1697 os << "\\usepackage{fancyhdr}\n";
1698 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1701 // only output when the background color is not default
1702 if (isbackgroundcolor == true) {
1703 // only require color here, the background color will be defined
1704 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1706 features.require("color");
1707 features.require("pagecolor");
1710 // only output when the font color is not default
1711 if (isfontcolor == true) {
1712 // only require color here, the font color will be defined
1713 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1715 features.require("color");
1716 features.require("fontcolor");
1719 // Only if class has a ToC hierarchy
1720 if (tclass.hasTocLevels()) {
1721 if (secnumdepth != tclass.secnumdepth()) {
1722 os << "\\setcounter{secnumdepth}{"
1726 if (tocdepth != tclass.tocdepth()) {
1727 os << "\\setcounter{tocdepth}{"
1733 if (paragraph_separation) {
1734 // when skip separation
1735 switch (getDefSkip().kind()) {
1736 case VSpace::SMALLSKIP:
1737 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1739 case VSpace::MEDSKIP:
1740 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1742 case VSpace::BIGSKIP:
1743 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1745 case VSpace::LENGTH:
1746 os << "\\setlength{\\parskip}{"
1747 << from_utf8(getDefSkip().length().asLatexString())
1750 default: // should never happen // Then delete it.
1751 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1754 os << "\\setlength{\\parindent}{0pt}\n";
1756 // when separation by indentation
1757 // only output something when a width is given
1758 if (getIndentation().asLyXCommand() != "default") {
1759 os << "\\setlength{\\parindent}{"
1760 << from_utf8(getIndentation().asLatexCommand())
1765 // Now insert the LyX specific LaTeX commands...
1766 docstring lyxpreamble;
1767 features.resolveAlternatives();
1770 if (!output_sync_macro.empty())
1771 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1772 else if (features.runparams().flavor == OutputParams::LATEX)
1773 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1774 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1775 lyxpreamble += "\\synctex=-1\n";
1778 // due to interferences with babel and hyperref, the color package has to
1779 // be loaded (when it is not already loaded) before babel when hyperref
1780 // is used with the colorlinks option, see
1781 // http://www.lyx.org/trac/ticket/5291
1782 // we decided therefore to load color always before babel, see
1783 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1784 lyxpreamble += from_ascii(features.getColorOptions());
1786 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1787 // we have to call babel before
1789 && (features.isRequired("jurabib")
1790 || features.isRequired("hyperref")
1791 || features.isRequired("varioref")
1792 || features.isRequired("vietnamese")
1793 || features.isRequired("japanese"))) {
1795 lyxpreamble += from_utf8(features.getBabelPresettings());
1796 lyxpreamble += from_utf8(babelCall(language_options.str(),
1797 features.needBabelLangOptions())) + '\n';
1798 lyxpreamble += from_utf8(features.getBabelPostsettings());
1801 // The optional packages;
1802 lyxpreamble += from_ascii(features.getPackages());
1804 // Additional Indices
1805 if (features.isRequired("splitidx")) {
1806 IndicesList::const_iterator iit = indiceslist().begin();
1807 IndicesList::const_iterator iend = indiceslist().end();
1808 for (; iit != iend; ++iit) {
1809 pair<docstring, docstring> indexname_latex =
1810 features.runparams().encoding->latexString(iit->index(),
1811 features.runparams().dryrun);
1812 if (!indexname_latex.second.empty()) {
1813 // issue a warning about omitted characters
1814 // FIXME: should be passed to the error dialog
1815 frontend::Alert::warning(_("Uncodable characters"),
1816 bformat(_("The following characters that are used in an index name are not\n"
1817 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1818 indexname_latex.second));
1820 lyxpreamble += "\\newindex[";
1821 lyxpreamble += indexname_latex.first;
1822 lyxpreamble += "]{";
1823 lyxpreamble += escape(iit->shortcut());
1824 lyxpreamble += "}\n";
1829 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1832 // * Hyperref manual: "Make sure it comes last of your loaded
1833 // packages, to give it a fighting chance of not being over-written,
1834 // since its job is to redefine many LaTeX commands."
1835 // * Email from Heiko Oberdiek: "It is usually better to load babel
1836 // before hyperref. Then hyperref has a chance to detect babel.
1837 // * Has to be loaded before the "LyX specific LaTeX commands" to
1838 // avoid errors with algorithm floats.
1839 // use hyperref explicitly if it is required
1840 if (features.isRequired("hyperref")) {
1841 // pass what we have to stream here, since we need
1842 // to access the stream itself in PDFOptions.
1845 OutputParams tmp_params = features.runparams();
1846 pdfoptions().writeLaTeX(tmp_params, os,
1847 features.isProvided("hyperref"));
1848 // set back for the rest
1849 lyxpreamble.clear();
1850 // correctly break URLs with hyperref and dvi output
1851 if (features.runparams().flavor == OutputParams::LATEX
1852 && features.isAvailable("breakurl"))
1853 lyxpreamble += "\\usepackage{breakurl}\n";
1854 } else if (features.isRequired("nameref"))
1855 // hyperref loads this automatically
1856 lyxpreamble += "\\usepackage{nameref}\n";
1858 // bibtopic needs to be loaded after hyperref.
1859 // the dot provides the aux file naming which LyX can detect.
1860 if (features.mustProvide("bibtopic"))
1861 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1863 // Will be surrounded by \makeatletter and \makeatother when not empty
1864 docstring atlyxpreamble;
1866 // Some macros LyX will need
1867 docstring tmppreamble(features.getMacros());
1869 if (!tmppreamble.empty())
1870 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1871 "LyX specific LaTeX commands.\n"
1872 + tmppreamble + '\n';
1874 // the text class specific preamble
1875 tmppreamble = features.getTClassPreamble();
1876 if (!tmppreamble.empty())
1877 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1878 "Textclass specific LaTeX commands.\n"
1879 + tmppreamble + '\n';
1881 // suppress date if selected
1882 // use \@ifundefined because we cannot be sure that every document class
1883 // has a \date command
1885 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1887 /* the user-defined preamble */
1888 if (!containsOnly(preamble, " \n\t"))
1890 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1891 "User specified LaTeX commands.\n"
1892 + from_utf8(preamble) + '\n';
1894 // subfig loads internally the LaTeX package "caption". As
1895 // caption is a very popular package, users will load it in
1896 // the preamble. Therefore we must load subfig behind the
1897 // user-defined preamble and check if the caption package was
1898 // loaded or not. For the case that caption is loaded before
1899 // subfig, there is the subfig option "caption=false". This
1900 // option also works when a koma-script class is used and
1901 // koma's own caption commands are used instead of caption. We
1902 // use \PassOptionsToPackage here because the user could have
1903 // already loaded subfig in the preamble.
1904 if (features.isRequired("subfig")) {
1905 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1906 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1907 "\\usepackage{subfig}\n";
1910 // Itemize bullet settings need to be last in case the user
1911 // defines their own bullets that use a package included
1912 // in the user-defined preamble -- ARRae
1913 // Actually it has to be done much later than that
1914 // since some packages like frenchb make modifications
1915 // at \begin{document} time -- JMarc
1916 docstring bullets_def;
1917 for (int i = 0; i < 4; ++i) {
1918 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1919 if (bullets_def.empty())
1920 bullets_def += "\\AtBeginDocument{\n";
1921 bullets_def += " \\def\\labelitemi";
1923 // `i' is one less than the item to modify
1930 bullets_def += "ii";
1936 bullets_def += '{' +
1937 user_defined_bullet(i).getText()
1942 if (!bullets_def.empty())
1943 atlyxpreamble += bullets_def + "}\n\n";
1945 if (!atlyxpreamble.empty())
1946 lyxpreamble += "\n\\makeatletter\n"
1947 + atlyxpreamble + "\\makeatother\n\n";
1949 // We try to load babel late, in case it interferes with other packages.
1950 // Jurabib, hyperref, varioref and listings (bug 8995) have to be
1951 // called after babel, though.
1952 if (use_babel && !features.isRequired("jurabib")
1953 && !features.isRequired("hyperref")
1954 && !features.isRequired("varioref")
1955 && !features.isRequired("vietnamese")
1956 && !features.isRequired("japanese")) {
1958 lyxpreamble += from_utf8(features.getBabelPresettings());
1959 lyxpreamble += from_utf8(babelCall(language_options.str(),
1960 features.needBabelLangOptions())) + '\n';
1961 lyxpreamble += from_utf8(features.getBabelPostsettings());
1963 if (!listings_params.empty() || features.isRequired("listings"))
1964 lyxpreamble += "\\usepackage{listings}\n";
1965 if (!listings_params.empty()) {
1966 lyxpreamble += "\\lstset{";
1967 // do not test validity because listings_params is
1968 // supposed to be valid
1970 InsetListingsParams(listings_params).separatedParams(true);
1971 lyxpreamble += from_utf8(par);
1972 lyxpreamble += "}\n";
1975 // xunicode needs to be loaded at least after amsmath, amssymb,
1976 // esint and the other packages that provide special glyphs
1977 if (features.runparams().flavor == OutputParams::XETEX
1979 lyxpreamble += "\\usepackage{xunicode}\n";
1981 // Polyglossia must be loaded last
1982 if (use_polyglossia) {
1984 lyxpreamble += "\\usepackage{polyglossia}\n";
1985 // set the main language
1986 lyxpreamble += "\\setdefaultlanguage";
1987 if (!language->polyglossiaOpts().empty())
1988 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
1989 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
1990 // now setup the other languages
1991 std::map<std::string, std::string> const polylangs =
1992 features.getPolyglossiaLanguages();
1993 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
1994 mit != polylangs.end() ; ++mit) {
1995 lyxpreamble += "\\setotherlanguage";
1996 if (!mit->second.empty())
1997 lyxpreamble += "[" + from_ascii(mit->second) + "]";
1998 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
2002 // Load custom language package here
2003 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2004 if (lang_package == "default")
2005 lyxpreamble += from_utf8(lyxrc.language_custom_package);
2007 lyxpreamble += from_utf8(lang_package);
2008 lyxpreamble += '\n';
2011 docstring const i18npreamble =
2012 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2013 if (!i18npreamble.empty())
2014 lyxpreamble += i18npreamble + '\n';
2022 void BufferParams::useClassDefaults()
2024 DocumentClass const & tclass = documentClass();
2026 sides = tclass.sides();
2027 columns = tclass.columns();
2028 pagestyle = tclass.pagestyle();
2029 use_default_options = true;
2030 // Only if class has a ToC hierarchy
2031 if (tclass.hasTocLevels()) {
2032 secnumdepth = tclass.secnumdepth();
2033 tocdepth = tclass.tocdepth();
2038 bool BufferParams::hasClassDefaults() const
2040 DocumentClass const & tclass = documentClass();
2042 return sides == tclass.sides()
2043 && columns == tclass.columns()
2044 && pagestyle == tclass.pagestyle()
2045 && use_default_options
2046 && secnumdepth == tclass.secnumdepth()
2047 && tocdepth == tclass.tocdepth();
2051 DocumentClass const & BufferParams::documentClass() const
2053 return *doc_class_.get();
2057 DocumentClassConstPtr BufferParams::documentClassPtr() const
2063 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2065 // evil, but this function is evil
2066 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2070 bool BufferParams::setBaseClass(string const & classname)
2072 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2073 LayoutFileList & bcl = LayoutFileList::get();
2074 if (!bcl.haveClass(classname)) {
2076 bformat(_("The layout file:\n"
2078 "could not be found. A default textclass with default\n"
2079 "layouts will be used. LyX will not be able to produce\n"
2081 from_utf8(classname));
2082 frontend::Alert::error(_("Document class not found"), s);
2083 bcl.addEmptyClass(classname);
2086 bool const success = bcl[classname].load();
2089 bformat(_("Due to some error in it, the layout file:\n"
2091 "could not be loaded. A default textclass with default\n"
2092 "layouts will be used. LyX will not be able to produce\n"
2094 from_utf8(classname));
2095 frontend::Alert::error(_("Could not load class"), s);
2096 bcl.addEmptyClass(classname);
2099 pimpl_->baseClass_ = classname;
2100 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2105 LayoutFile const * BufferParams::baseClass() const
2107 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2108 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2114 LayoutFileIndex const & BufferParams::baseClassID() const
2116 return pimpl_->baseClass_;
2120 void BufferParams::makeDocumentClass(bool const clone)
2125 LayoutModuleList mods;
2126 LayoutModuleList::iterator it = layout_modules_.begin();
2127 LayoutModuleList::iterator en = layout_modules_.end();
2128 for (; it != en; ++it)
2129 mods.push_back(*it);
2131 it = cite_engine_.begin();
2132 en = cite_engine_.end();
2133 for (; it != en; ++it)
2134 mods.push_back(*it);
2136 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2138 TextClass::ReturnValues success = TextClass::OK;
2139 if (!forced_local_layout_.empty())
2140 success = doc_class_->read(forced_local_layout_, TextClass::MODULE);
2141 if (!local_layout_.empty() &&
2142 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2143 success = doc_class_->read(local_layout_, TextClass::MODULE);
2144 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2145 docstring const msg = _("Error reading internal layout information");
2146 frontend::Alert::warning(_("Read Error"), msg);
2151 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2153 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2157 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2159 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2163 std::string BufferParams::getLocalLayout(bool forced) const
2166 return doc_class_->forcedLayouts();
2168 return local_layout_;
2172 void BufferParams::setLocalLayout(string const & layout, bool forced)
2175 forced_local_layout_ = layout;
2177 local_layout_ = layout;
2181 bool BufferParams::addLayoutModule(string const & modName)
2183 LayoutModuleList::const_iterator it = layout_modules_.begin();
2184 LayoutModuleList::const_iterator end = layout_modules_.end();
2185 for (; it != end; ++it)
2188 layout_modules_.push_back(modName);
2193 string BufferParams::bufferFormat() const
2195 string format = documentClass().outputFormat();
2196 if (format == "latex") {
2199 if (encoding().package() == Encoding::japanese)
2206 bool BufferParams::isExportable(string const & format) const
2208 vector<string> backs = backends();
2209 for (vector<string>::const_iterator it = backs.begin();
2210 it != backs.end(); ++it)
2211 if (theConverters().isReachable(*it, format))
2217 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2219 vector<string> const backs = backends();
2220 set<string> excludes;
2221 if (useNonTeXFonts) {
2222 excludes.insert("latex");
2223 excludes.insert("pdflatex");
2225 vector<Format const *> result =
2226 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2227 for (vector<string>::const_iterator it = backs.begin() + 1;
2228 it != backs.end(); ++it) {
2229 vector<Format const *> r =
2230 theConverters().getReachable(*it, only_viewable, false, excludes);
2231 result.insert(result.end(), r.begin(), r.end());
2237 bool BufferParams::isExportableFormat(string const & format) const
2239 typedef vector<Format const *> Formats;
2241 formats = exportableFormats(true);
2242 Formats::const_iterator fit = formats.begin();
2243 Formats::const_iterator end = formats.end();
2244 for (; fit != end ; ++fit) {
2245 if ((*fit)->name() == format)
2252 vector<string> BufferParams::backends() const
2255 string const buffmt = bufferFormat();
2257 // FIXME: Don't hardcode format names here, but use a flag
2258 if (buffmt == "latex") {
2259 if (!useNonTeXFonts) {
2260 v.push_back("pdflatex");
2261 v.push_back("latex");
2263 v.push_back("luatex");
2264 v.push_back("dviluatex");
2265 v.push_back("xetex");
2266 } else if (buffmt == "xetex") {
2267 v.push_back("xetex");
2268 // FIXME: need to test all languages (bug 8205)
2269 if (!language || !language->isPolyglossiaExclusive()) {
2270 v.push_back("luatex");
2271 v.push_back("dviluatex");
2274 v.push_back(buffmt);
2276 v.push_back("xhtml");
2277 v.push_back("text");
2283 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2285 string const dformat = (format.empty() || format == "default") ?
2286 getDefaultOutputFormat() : format;
2287 DefaultFlavorCache::const_iterator it =
2288 default_flavors_.find(dformat);
2290 if (it != default_flavors_.end())
2293 OutputParams::FLAVOR result = OutputParams::LATEX;
2295 // FIXME It'd be better not to hardcode this, but to do
2296 // something with formats.
2297 if (dformat == "xhtml")
2298 result = OutputParams::HTML;
2299 else if (dformat == "text")
2300 result = OutputParams::TEXT;
2301 else if (dformat == "lyx")
2302 result = OutputParams::LYX;
2303 else if (dformat == "pdflatex")
2304 result = OutputParams::PDFLATEX;
2305 else if (dformat == "xetex")
2306 result = OutputParams::XETEX;
2307 else if (dformat == "luatex")
2308 result = OutputParams::LUATEX;
2309 else if (dformat == "dviluatex")
2310 result = OutputParams::DVILUATEX;
2312 // Try to determine flavor of default output format
2313 vector<string> backs = backends();
2314 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2315 // Get shortest path to format
2316 Graph::EdgePath path;
2317 for (vector<string>::const_iterator it = backs.begin();
2318 it != backs.end(); ++it) {
2319 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2320 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2325 result = theConverters().getFlavor(path);
2328 // cache this flavor
2329 default_flavors_[dformat] = result;
2334 string BufferParams::getDefaultOutputFormat() const
2336 if (!default_output_format.empty()
2337 && default_output_format != "default")
2338 return default_output_format;
2340 || encoding().package() == Encoding::japanese) {
2341 vector<Format const *> const formats = exportableFormats(true);
2342 if (formats.empty())
2344 // return the first we find
2345 return formats.front()->name();
2348 return lyxrc.default_otf_view_format;
2349 return lyxrc.default_view_format;
2352 Font const BufferParams::getFont() const
2354 FontInfo f = documentClass().defaultfont();
2355 if (fonts_default_family == "rmdefault")
2356 f.setFamily(ROMAN_FAMILY);
2357 else if (fonts_default_family == "sfdefault")
2358 f.setFamily(SANS_FAMILY);
2359 else if (fonts_default_family == "ttdefault")
2360 f.setFamily(TYPEWRITER_FAMILY);
2361 return Font(f, language);
2365 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const & qs) const
2367 return quoteslangtranslator().find(qs);
2371 bool BufferParams::isLatex() const
2373 return documentClass().outputType() == LATEX;
2377 bool BufferParams::isLiterate() const
2379 return documentClass().outputType() == LITERATE;
2383 bool BufferParams::isDocBook() const
2385 return documentClass().outputType() == DOCBOOK;
2389 void BufferParams::readPreamble(Lexer & lex)
2391 if (lex.getString() != "\\begin_preamble")
2392 lyxerr << "Error (BufferParams::readPreamble):"
2393 "consistency check failed." << endl;
2395 preamble = lex.getLongString("\\end_preamble");
2399 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2401 string const expected = forced ? "\\begin_forced_local_layout" :
2402 "\\begin_local_layout";
2403 if (lex.getString() != expected)
2404 lyxerr << "Error (BufferParams::readLocalLayout):"
2405 "consistency check failed." << endl;
2408 forced_local_layout_ =
2409 lex.getLongString("\\end_forced_local_layout");
2411 local_layout_ = lex.getLongString("\\end_local_layout");
2415 bool BufferParams::setLanguage(string const & lang)
2417 Language const *new_language = languages.getLanguage(lang);
2418 if (!new_language) {
2419 // Language lang was not found
2422 language = new_language;
2427 void BufferParams::readLanguage(Lexer & lex)
2429 if (!lex.next()) return;
2431 string const tmptok = lex.getString();
2433 // check if tmptok is part of tex_babel in tex-defs.h
2434 if (!setLanguage(tmptok)) {
2435 // Language tmptok was not found
2436 language = default_language;
2437 lyxerr << "Warning: Setting language `"
2438 << tmptok << "' to `" << language->lang()
2444 void BufferParams::readGraphicsDriver(Lexer & lex)
2449 string const tmptok = lex.getString();
2450 // check if tmptok is part of tex_graphics in tex_defs.h
2453 string const test = tex_graphics[n++];
2455 if (test == tmptok) {
2456 graphics_driver = tmptok;
2461 "Warning: graphics driver `$$Token' not recognized!\n"
2462 " Setting graphics driver to `default'.\n");
2463 graphics_driver = "default";
2470 void BufferParams::readBullets(Lexer & lex)
2475 int const index = lex.getInteger();
2477 int temp_int = lex.getInteger();
2478 user_defined_bullet(index).setFont(temp_int);
2479 temp_bullet(index).setFont(temp_int);
2481 user_defined_bullet(index).setCharacter(temp_int);
2482 temp_bullet(index).setCharacter(temp_int);
2484 user_defined_bullet(index).setSize(temp_int);
2485 temp_bullet(index).setSize(temp_int);
2489 void BufferParams::readBulletsLaTeX(Lexer & lex)
2491 // The bullet class should be able to read this.
2494 int const index = lex.getInteger();
2496 docstring const temp_str = lex.getDocString();
2498 user_defined_bullet(index).setText(temp_str);
2499 temp_bullet(index).setText(temp_str);
2503 void BufferParams::readModules(Lexer & lex)
2505 if (!lex.eatLine()) {
2506 lyxerr << "Error (BufferParams::readModules):"
2507 "Unexpected end of input." << endl;
2511 string mod = lex.getString();
2512 if (mod == "\\end_modules")
2514 addLayoutModule(mod);
2520 void BufferParams::readRemovedModules(Lexer & lex)
2522 if (!lex.eatLine()) {
2523 lyxerr << "Error (BufferParams::readRemovedModules):"
2524 "Unexpected end of input." << endl;
2528 string mod = lex.getString();
2529 if (mod == "\\end_removed_modules")
2531 removed_modules_.push_back(mod);
2534 // now we want to remove any removed modules that were previously
2535 // added. normally, that will be because default modules were added in
2536 // setBaseClass(), which gets called when \textclass is read at the
2537 // start of the read.
2538 list<string>::const_iterator rit = removed_modules_.begin();
2539 list<string>::const_iterator const ren = removed_modules_.end();
2540 for (; rit != ren; ++rit) {
2541 LayoutModuleList::iterator const mit = layout_modules_.begin();
2542 LayoutModuleList::iterator const men = layout_modules_.end();
2543 LayoutModuleList::iterator found = find(mit, men, *rit);
2546 layout_modules_.erase(found);
2551 void BufferParams::readIncludeonly(Lexer & lex)
2553 if (!lex.eatLine()) {
2554 lyxerr << "Error (BufferParams::readIncludeonly):"
2555 "Unexpected end of input." << endl;
2559 string child = lex.getString();
2560 if (child == "\\end_includeonly")
2562 included_children_.push_back(child);
2568 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2570 switch (papersize) {
2572 // could be anything, so don't guess
2574 case PAPER_CUSTOM: {
2575 if (purpose == XDVI && !paperwidth.empty() &&
2576 !paperheight.empty()) {
2577 // heightxwidth<unit>
2578 string first = paperwidth;
2579 string second = paperheight;
2580 if (orientation == ORIENTATION_LANDSCAPE)
2583 return first.erase(first.length() - 2)
2589 // dvips and dvipdfm do not know this
2590 if (purpose == DVIPS || purpose == DVIPDFM)
2594 if (purpose == DVIPS || purpose == DVIPDFM)
2598 if (purpose == DVIPS || purpose == DVIPDFM)
2608 if (purpose == DVIPS || purpose == DVIPDFM)
2612 if (purpose == DVIPS || purpose == DVIPDFM)
2616 if (purpose == DVIPS || purpose == DVIPDFM)
2620 if (purpose == DVIPS || purpose == DVIPDFM)
2624 if (purpose == DVIPS || purpose == DVIPDFM)
2628 // dvipdfm does not know this
2629 if (purpose == DVIPDFM)
2633 if (purpose == DVIPDFM)
2637 if (purpose == DVIPS || purpose == DVIPDFM)
2641 if (purpose == DVIPS || purpose == DVIPDFM)
2645 if (purpose == DVIPS || purpose == DVIPDFM)
2649 if (purpose == DVIPS || purpose == DVIPDFM)
2653 if (purpose == DVIPS || purpose == DVIPDFM)
2657 if (purpose == DVIPS || purpose == DVIPDFM)
2661 if (purpose == DVIPS || purpose == DVIPDFM)
2665 if (purpose == DVIPS || purpose == DVIPDFM)
2669 if (purpose == DVIPS || purpose == DVIPDFM)
2673 if (purpose == DVIPS || purpose == DVIPDFM)
2677 if (purpose == DVIPS || purpose == DVIPDFM)
2681 if (purpose == DVIPS || purpose == DVIPDFM)
2685 if (purpose == DVIPS || purpose == DVIPDFM)
2689 if (purpose == DVIPS || purpose == DVIPDFM)
2693 if (purpose == DVIPS || purpose == DVIPDFM)
2696 case PAPER_USEXECUTIVE:
2697 // dvipdfm does not know this
2698 if (purpose == DVIPDFM)
2703 case PAPER_USLETTER:
2705 if (purpose == XDVI)
2712 string const BufferParams::dvips_options() const
2716 // If the class loads the geometry package, we do not know which
2717 // paper size is used, since we do not set it (bug 7013).
2718 // Therefore we must not specify any argument here.
2719 // dvips gets the correct paper size via DVI specials in this case
2720 // (if the class uses the geometry package correctly).
2721 if (documentClass().provides("geometry"))
2725 && papersize == PAPER_CUSTOM
2726 && !lyxrc.print_paper_dimension_flag.empty()
2727 && !paperwidth.empty()
2728 && !paperheight.empty()) {
2729 // using a custom papersize
2730 result = lyxrc.print_paper_dimension_flag;
2731 result += ' ' + paperwidth;
2732 result += ',' + paperheight;
2734 string const paper_option = paperSizeName(DVIPS);
2735 if (!paper_option.empty() && (paper_option != "letter" ||
2736 orientation != ORIENTATION_LANDSCAPE)) {
2737 // dvips won't accept -t letter -t landscape.
2738 // In all other cases, include the paper size
2740 result = lyxrc.print_paper_flag;
2741 result += ' ' + paper_option;
2744 if (orientation == ORIENTATION_LANDSCAPE &&
2745 papersize != PAPER_CUSTOM)
2746 result += ' ' + lyxrc.print_landscape_flag;
2751 string const BufferParams::font_encoding() const
2753 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2757 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2759 // suppress the babel call if there is no BabelName defined
2760 // for the document language in the lib/languages file and if no
2761 // other languages are used (lang_opts is then empty)
2762 if (lang_opts.empty())
2764 // either a specific language (AsBabelOptions setting in
2765 // lib/languages) or the prefs require the languages to
2766 // be submitted to babel itself (not the class).
2768 return "\\usepackage[" + lang_opts + "]{babel}";
2769 return "\\usepackage{babel}";
2773 docstring BufferParams::getGraphicsDriver(string const & package) const
2777 if (package == "geometry") {
2778 if (graphics_driver == "dvips"
2779 || graphics_driver == "dvipdfm"
2780 || graphics_driver == "pdftex"
2781 || graphics_driver == "vtex")
2782 result = from_ascii(graphics_driver);
2783 else if (graphics_driver == "dvipdfmx")
2784 result = from_ascii("dvipdfm");
2791 void BufferParams::writeEncodingPreamble(otexstream & os,
2792 LaTeXFeatures & features) const
2794 // XeTeX does not need this
2795 if (features.runparams().flavor == OutputParams::XETEX)
2797 // LuaTeX neither, but with tex fonts, we need to load
2798 // the luainputenc package.
2799 if (features.runparams().flavor == OutputParams::LUATEX
2800 || features.runparams().flavor == OutputParams::DVILUATEX) {
2801 if (!useNonTeXFonts && inputenc != "default"
2802 && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc)
2803 || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) {
2804 os << "\\usepackage[utf8]{luainputenc}\n";
2808 if (inputenc == "auto") {
2809 string const doc_encoding =
2810 language->encoding()->latexName();
2811 Encoding::Package const package =
2812 language->encoding()->package();
2814 // Create a list with all the input encodings used
2816 set<string> encodings =
2817 features.getEncodingSet(doc_encoding);
2819 // If the "japanese" package (i.e. pLaTeX) is used,
2820 // inputenc must be omitted.
2821 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2822 if ((!encodings.empty() || package == Encoding::inputenc)
2823 && !features.isRequired("japanese")) {
2824 os << "\\usepackage[";
2825 set<string>::const_iterator it = encodings.begin();
2826 set<string>::const_iterator const end = encodings.end();
2828 os << from_ascii(*it);
2831 for (; it != end; ++it)
2832 os << ',' << from_ascii(*it);
2833 if (package == Encoding::inputenc) {
2834 if (!encodings.empty())
2836 os << from_ascii(doc_encoding);
2838 os << "]{inputenc}\n";
2840 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2841 if (language->encoding()->name() == "utf8-cjk"
2842 && LaTeXFeatures::isAvailable("CJKutf8"))
2843 os << "\\usepackage{CJKutf8}\n";
2845 os << "\\usepackage{CJK}\n";
2847 } else if (inputenc != "default") {
2848 switch (encoding().package()) {
2849 case Encoding::none:
2850 case Encoding::japanese:
2852 case Encoding::inputenc:
2853 // do not load inputenc if japanese is used
2854 if (features.isRequired("japanese"))
2856 os << "\\usepackage[" << from_ascii(encoding().latexName())
2860 if (encoding().name() == "utf8-cjk"
2861 && LaTeXFeatures::isAvailable("CJKutf8"))
2862 os << "\\usepackage{CJKutf8}\n";
2864 os << "\\usepackage{CJK}\n";
2867 // Load the CJK package if needed by a secondary language.
2868 // If the main encoding is some variant of UTF8, use CJKutf8.
2869 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
2870 if (encoding().iconvName() == "UTF-8"
2871 && LaTeXFeatures::isAvailable("CJKutf8"))
2872 os << "\\usepackage{CJKutf8}\n";
2874 os << "\\usepackage{CJK}\n";
2880 string const BufferParams::parseFontName(string const & name) const
2882 string mangled = name;
2883 size_t const idx = mangled.find('[');
2884 if (idx == string::npos || idx == 0)
2887 return mangled.substr(0, idx - 1);
2891 string const BufferParams::loadFonts(LaTeXFeatures & features) const
2893 if (fonts_roman == "default" && fonts_sans == "default"
2894 && fonts_typewriter == "default"
2895 && (fonts_math == "default" || fonts_math == "auto"))
2901 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
2902 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
2903 * Mapping=tex-text option assures TeX ligatures (such as "--")
2904 * are resolved. Note that tt does not use these ligatures.
2906 * -- add more GUI options?
2907 * -- add more fonts (fonts for other scripts)
2908 * -- if there's a way to find out if a font really supports
2909 * OldStyle, enable/disable the widget accordingly.
2911 if (useNonTeXFonts && features.isAvailable("fontspec")) {
2912 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
2913 // However, until v.2 (2010/07/11) fontspec only knew
2914 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
2915 // was introduced for both XeTeX and LuaTeX (LuaTeX
2916 // didn't understand "Mapping=tex-text", while XeTeX
2917 // understood both. With most recent versions, both
2918 // variants are understood by both engines. However,
2919 // we want to provide support for at least TeXLive 2009
2920 // (for XeTeX; LuaTeX is only supported as of v.2)
2921 string const texmapping =
2922 (features.runparams().flavor == OutputParams::XETEX) ?
2923 "Mapping=tex-text" : "Ligatures=TeX";
2924 if (fonts_roman != "default") {
2925 os << "\\setmainfont[" << texmapping;
2926 if (fonts_old_figures)
2927 os << ",Numbers=OldStyle";
2928 os << "]{" << parseFontName(fonts_roman) << "}\n";
2930 if (fonts_sans != "default") {
2931 string const sans = parseFontName(fonts_sans);
2932 if (fonts_sans_scale != 100)
2933 os << "\\setsansfont[Scale="
2934 << float(fonts_sans_scale) / 100
2935 << "," << texmapping << "]{"
2938 os << "\\setsansfont[" << texmapping << "]{"
2941 if (fonts_typewriter != "default") {
2942 string const mono = parseFontName(fonts_typewriter);
2943 if (fonts_typewriter_scale != 100)
2944 os << "\\setmonofont[Scale="
2945 << float(fonts_typewriter_scale) / 100
2949 os << "\\setmonofont{"
2956 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
2957 bool const dryrun = features.runparams().dryrun;
2958 bool const complete = (fonts_sans == "default" && fonts_typewriter == "default");
2959 bool const nomath = (fonts_math == "default");
2962 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_roman)).getLaTeXCode(
2963 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2967 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_sans)).getLaTeXCode(
2968 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2969 nomath, fonts_sans_scale);
2971 // MONOSPACED/TYPEWRITER
2972 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_typewriter)).getLaTeXCode(
2973 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2974 nomath, fonts_typewriter_scale);
2977 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getLaTeXCode(
2978 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2985 Encoding const & BufferParams::encoding() const
2987 // FIXME: actually, we should check for the flavor
2988 // or runparams.isFullyUnicode() here:
2989 // This check will not work with XeTeX/LuaTeX and tex fonts.
2990 // Thus we have to reset the encoding in Buffer::makeLaTeXFile.
2992 return *(encodings.fromLyXName("utf8-plain"));
2993 if (inputenc == "auto" || inputenc == "default")
2994 return *language->encoding();
2995 Encoding const * const enc = encodings.fromLyXName(inputenc);
2998 LYXERR0("Unknown inputenc value `" << inputenc
2999 << "'. Using `auto' instead.");
3000 return *language->encoding();
3004 bool BufferParams::addCiteEngine(string const & engine)
3006 LayoutModuleList::const_iterator it = cite_engine_.begin();
3007 LayoutModuleList::const_iterator en = cite_engine_.end();
3008 for (; it != en; ++it)
3011 cite_engine_.push_back(engine);
3016 bool BufferParams::addCiteEngine(vector<string> const & engine)
3018 vector<string>::const_iterator it = engine.begin();
3019 vector<string>::const_iterator en = engine.end();
3021 for (; it != en; ++it)
3022 if (!addCiteEngine(*it))
3028 string const & BufferParams::defaultBiblioStyle() const
3030 return documentClass().defaultBiblioStyle();
3034 bool const & BufferParams::fullAuthorList() const
3036 return documentClass().fullAuthorList();
3040 void BufferParams::setCiteEngine(string const & engine)
3043 addCiteEngine(engine);
3047 void BufferParams::setCiteEngine(vector<string> const & engine)
3050 addCiteEngine(engine);
3054 vector<string> BufferParams::citeCommands() const
3056 static CitationStyle const default_style;
3057 vector<string> commands =
3058 documentClass().citeCommands(citeEngineType());
3059 if (commands.empty())
3060 commands.push_back(default_style.cmd);
3065 vector<CitationStyle> BufferParams::citeStyles() const
3067 static CitationStyle const default_style;
3068 vector<CitationStyle> styles =
3069 documentClass().citeStyles(citeEngineType());
3071 styles.push_back(default_style);