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"
24 #include "buffer_funcs.h"
28 #include "Converter.h"
31 #include "IndicesList.h"
33 #include "LaTeXFeatures.h"
34 #include "LaTeXFonts.h"
35 #include "ModuleList.h"
39 #include "OutputParams.h"
43 #include "PDFOptions.h"
45 #include "frontends/alert.h"
47 #include "insets/InsetListingsParams.h"
49 #include "support/convert.h"
50 #include "support/debug.h"
51 #include "support/docstream.h"
52 #include "support/FileName.h"
53 #include "support/filetools.h"
54 #include "support/gettext.h"
55 #include "support/Messages.h"
56 #include "support/mutex.h"
57 #include "support/Package.h"
58 #include "support/Translator.h"
59 #include "support/lstrings.h"
65 using namespace lyx::support;
68 static char const * const string_paragraph_separation[] = {
73 static char const * const string_quotes_language[] = {
74 "english", "swedish", "german", "polish", "french", "danish", ""
78 static char const * const string_papersize[] = {
79 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
80 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
81 "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
82 "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
83 "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
88 static char const * const string_orientation[] = {
89 "portrait", "landscape", ""
93 static char const * const tex_graphics[] = {
94 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
95 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
96 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
97 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
108 // Paragraph separation
109 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
112 ParSepTranslator const init_parseptranslator()
114 ParSepTranslator translator
115 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
116 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
121 ParSepTranslator const & parseptranslator()
123 static ParSepTranslator const translator =
124 init_parseptranslator();
130 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
133 QuotesLangTranslator const init_quoteslangtranslator()
135 QuotesLangTranslator translator
136 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
137 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
138 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
139 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
140 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
141 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
146 QuotesLangTranslator const & quoteslangtranslator()
148 static QuotesLangTranslator const translator =
149 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 const translator =
200 initPaperSizeTranslator();
206 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
209 PaperOrientationTranslator const init_paperorientationtranslator()
211 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
212 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
217 PaperOrientationTranslator const & paperorientationtranslator()
219 static PaperOrientationTranslator const translator =
220 init_paperorientationtranslator();
226 typedef Translator<int, PageSides> SidesTranslator;
229 SidesTranslator const init_sidestranslator()
231 SidesTranslator translator(1, OneSide);
232 translator.addPair(2, TwoSides);
237 SidesTranslator const & sidestranslator()
239 static SidesTranslator const translator = init_sidestranslator();
245 typedef Translator<int, BufferParams::Package> PackageTranslator;
248 PackageTranslator const init_packagetranslator()
250 PackageTranslator translator(0, BufferParams::package_off);
251 translator.addPair(1, BufferParams::package_auto);
252 translator.addPair(2, BufferParams::package_on);
257 PackageTranslator const & packagetranslator()
259 static PackageTranslator const translator =
260 init_packagetranslator();
266 typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator;
269 CiteEngineTypeTranslator const init_citeenginetypetranslator()
271 CiteEngineTypeTranslator translator("authoryear", ENGINE_TYPE_AUTHORYEAR);
272 translator.addPair("numerical", ENGINE_TYPE_NUMERICAL);
273 translator.addPair("default", ENGINE_TYPE_DEFAULT);
278 CiteEngineTypeTranslator const & citeenginetypetranslator()
280 static CiteEngineTypeTranslator const translator =
281 init_citeenginetypetranslator();
287 typedef Translator<string, Spacing::Space> SpaceTranslator;
290 SpaceTranslator const init_spacetranslator()
292 SpaceTranslator translator("default", Spacing::Default);
293 translator.addPair("single", Spacing::Single);
294 translator.addPair("onehalf", Spacing::Onehalf);
295 translator.addPair("double", Spacing::Double);
296 translator.addPair("other", Spacing::Other);
301 SpaceTranslator const & spacetranslator()
303 static SpaceTranslator const translator = init_spacetranslator();
308 bool inSystemDir(FileName const & document_dir, string & system_dir)
310 // A document is assumed to be in a system LyX directory (not
311 // necessarily the system directory of the running instance)
312 // if both "configure.py" and "chkconfig.ltx" are found in
313 // either document_dir/../ or document_dir/../../.
314 // If true, the system directory path is returned in system_dir
315 // with a trailing path separator.
317 string const msg = "Checking whether document is in a system dir...";
319 string dir = document_dir.absFileName();
321 for (int i = 0; i < 2; ++i) {
322 dir = addPath(dir, "..");
323 if (!fileSearch(dir, "configure.py").empty() &&
324 !fileSearch(dir, "chkconfig.ltx").empty()) {
325 LYXERR(Debug::FILES, msg << " yes");
326 system_dir = addPath(FileName(dir).realPath(), "");
331 LYXERR(Debug::FILES, msg << " no");
332 system_dir = string();
339 class BufferParams::Impl
344 AuthorList authorlist;
345 BranchList branchlist;
346 Bullet temp_bullets[4];
347 Bullet user_defined_bullets[4];
348 IndicesList indiceslist;
350 /** This is the amount of space used for paragraph_separation "skip",
351 * and for detached paragraphs in "indented" documents.
355 PDFOptions pdfoptions;
356 LayoutFileIndex baseClass_;
360 BufferParams::Impl::Impl()
361 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
363 // set initial author
365 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
370 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
373 return new BufferParams::Impl(*ptr);
377 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
383 BufferParams::BufferParams()
386 setBaseClass(defaultBaseclass());
387 cite_engine_.push_back("basic");
388 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
390 paragraph_separation = ParagraphIndentSeparation;
391 quotes_language = InsetQuotes::EnglishQuotes;
392 fontsize = "default";
395 papersize = PAPER_DEFAULT;
396 orientation = ORIENTATION_PORTRAIT;
397 use_geometry = false;
398 biblio_style = "plain";
399 use_bibtopic = false;
401 save_transient_properties = true;
402 track_changes = false;
403 output_changes = false;
404 use_default_options = true;
405 maintain_unincluded_children = false;
408 language = default_language;
410 fonts_roman[0] = "default";
411 fonts_roman[1] = "default";
412 fonts_sans[0] = "default";
413 fonts_sans[1] = "default";
414 fonts_typewriter[0] = "default";
415 fonts_typewriter[1] = "default";
416 fonts_math[0] = "auto";
417 fonts_math[1] = "auto";
418 fonts_default_family = "default";
419 useNonTeXFonts = false;
420 fonts_expert_sc = false;
421 fonts_old_figures = false;
422 fonts_sans_scale[0] = 100;
423 fonts_sans_scale[1] = 100;
424 fonts_typewriter_scale[0] = 100;
425 fonts_typewriter_scale[1] = 100;
427 lang_package = "default";
428 graphics_driver = "default";
429 default_output_format = "default";
430 bibtex_command = "default";
431 index_command = "default";
434 listings_params = string();
435 pagestyle = "default";
436 suppress_date = false;
437 justification = true;
438 // no color is the default (white)
439 backgroundcolor = lyx::rgbFromHexName("#ffffff");
440 isbackgroundcolor = false;
441 // no color is the default (black)
442 fontcolor = lyx::rgbFromHexName("#000000");
444 // light gray is the default font color for greyed-out notes
445 notefontcolor = lyx::rgbFromHexName("#cccccc");
446 boxbgcolor = lyx::rgbFromHexName("#ff0000");
447 compressed = lyxrc.save_compressed;
448 for (int iter = 0; iter < 4; ++iter) {
449 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
450 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
453 indiceslist().addDefault(B_("Index"));
454 html_be_strict = false;
455 html_math_output = MathML;
456 html_math_img_scale = 1.0;
457 html_css_as_file = false;
458 display_pixel_ratio = 1.0;
463 // map current author
464 author_map_[pimpl_->authorlist.get(0).bufferId()] = 0;
468 docstring BufferParams::B_(string const & l10n) const
470 LASSERT(language, return from_utf8(l10n));
471 return getMessages(language->code()).get(l10n);
475 BufferParams::Package BufferParams::use_package(std::string const & p) const
477 PackageMap::const_iterator it = use_packages.find(p);
478 if (it == use_packages.end())
484 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
490 map<string, string> const & BufferParams::auto_packages()
492 static map<string, string> packages;
493 if (packages.empty()) {
494 // We could have a race condition here that two threads
495 // discover an empty map at the same time and want to fill
496 // it, but that is no problem, since the same contents is
497 // filled in twice then. Having the locker inside the
498 // packages.empty() condition has the advantage that we
499 // don't need the mutex overhead for simple reading.
501 Mutex::Locker locker(&mutex);
502 // adding a package here implies a file format change!
503 packages["amsmath"] =
504 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
505 packages["amssymb"] =
506 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
508 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
510 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
511 packages["mathdots"] =
512 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
513 packages["mathtools"] =
514 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
516 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
517 packages["stackrel"] =
518 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
519 packages["stmaryrd"] =
520 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");
521 packages["undertilde"] =
522 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
528 AuthorList & BufferParams::authors()
530 return pimpl_->authorlist;
534 AuthorList const & BufferParams::authors() const
536 return pimpl_->authorlist;
540 void BufferParams::addAuthor(Author a)
542 author_map_[a.bufferId()] = pimpl_->authorlist.record(a);
546 BranchList & BufferParams::branchlist()
548 return pimpl_->branchlist;
552 BranchList const & BufferParams::branchlist() const
554 return pimpl_->branchlist;
558 IndicesList & BufferParams::indiceslist()
560 return pimpl_->indiceslist;
564 IndicesList const & BufferParams::indiceslist() const
566 return pimpl_->indiceslist;
570 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
572 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
573 return pimpl_->temp_bullets[index];
577 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
579 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
580 return pimpl_->temp_bullets[index];
584 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
586 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
587 return pimpl_->user_defined_bullets[index];
591 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
593 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
594 return pimpl_->user_defined_bullets[index];
598 Spacing & BufferParams::spacing()
600 return pimpl_->spacing;
604 Spacing const & BufferParams::spacing() const
606 return pimpl_->spacing;
610 PDFOptions & BufferParams::pdfoptions()
612 return pimpl_->pdfoptions;
616 PDFOptions const & BufferParams::pdfoptions() const
618 return pimpl_->pdfoptions;
622 HSpace const & BufferParams::getIndentation() const
624 return pimpl_->indentation;
628 void BufferParams::setIndentation(HSpace const & indent)
630 pimpl_->indentation = indent;
634 VSpace const & BufferParams::getDefSkip() const
636 return pimpl_->defskip;
640 void BufferParams::setDefSkip(VSpace const & vs)
642 // DEFSKIP will cause an infinite loop
643 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
644 pimpl_->defskip = vs;
648 string BufferParams::readToken(Lexer & lex, string const & token,
649 FileName const & filepath)
653 if (token == "\\textclass") {
655 string const classname = lex.getString();
656 // if there exists a local layout file, ignore the system one
657 // NOTE: in this case, the textclass (.cls file) is assumed to
660 LayoutFileList & bcl = LayoutFileList::get();
661 if (!filepath.empty()) {
662 // If classname is an absolute path, the document is
663 // using a local layout file which could not be accessed
664 // by a relative path. In this case the path is correct
665 // even if the document was moved to a different
666 // location. However, we will have a problem if the
667 // document was generated on a different platform.
668 bool isabsolute = FileName::isAbsolute(classname);
669 string const classpath = onlyPath(classname);
670 string const path = isabsolute ? classpath
671 : FileName(addPath(filepath.absFileName(),
672 classpath)).realPath();
673 string const oldpath = isabsolute ? string()
674 : FileName(addPath(origin, classpath)).realPath();
675 tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
677 // that returns non-empty if a "local" layout file is found.
679 result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
680 from_utf8(filepath.absFileName())));
683 setBaseClass(onlyFileName(tcp));
685 setBaseClass(onlyFileName(classname));
686 // We assume that a tex class exists for local or unknown
687 // layouts so this warning, will only be given for system layouts.
688 if (!baseClass()->isTeXClassAvailable()) {
689 docstring const desc =
690 translateIfPossible(from_utf8(baseClass()->description()));
691 docstring const prereqs =
692 from_utf8(baseClass()->prerequisites());
693 docstring const msg =
694 bformat(_("The selected document class\n"
696 "requires external files that are not available.\n"
697 "The document class can still be used, but the\n"
698 "document cannot be compiled until the following\n"
699 "prerequisites are installed:\n"
701 "See section 3.1.2.2 (Class Availability) of the\n"
702 "User's Guide for more information."), desc, prereqs);
703 frontend::Alert::warning(_("Document class not available"),
706 } else if (token == "\\save_transient_properties") {
707 lex >> save_transient_properties;
708 } else if (token == "\\origin") {
710 origin = lex.getString();
711 string const sysdirprefix = "/systemlyxdir/";
712 if (prefixIs(origin, sysdirprefix)) {
714 if (inSystemDir(filepath, docsys))
715 origin.replace(0, sysdirprefix.length() - 1, docsys);
717 origin.replace(0, sysdirprefix.length() - 1,
718 package().system_support().absFileName());
720 } else if (token == "\\begin_preamble") {
722 } else if (token == "\\begin_local_layout") {
723 readLocalLayout(lex, false);
724 } else if (token == "\\begin_forced_local_layout") {
725 readLocalLayout(lex, true);
726 } else if (token == "\\begin_modules") {
728 } else if (token == "\\begin_removed_modules") {
729 readRemovedModules(lex);
730 } else if (token == "\\begin_includeonly") {
731 readIncludeonly(lex);
732 } else if (token == "\\maintain_unincluded_children") {
733 lex >> maintain_unincluded_children;
734 } else if (token == "\\options") {
736 options = lex.getString();
737 } else if (token == "\\use_default_options") {
738 lex >> use_default_options;
739 } else if (token == "\\master") {
741 master = lex.getString();
742 if (!filepath.empty() && FileName::isAbsolute(origin)) {
743 bool const isabs = FileName::isAbsolute(master);
744 FileName const abspath(isabs ? master : origin + master);
745 bool const moved = filepath != FileName(origin);
746 if (moved && abspath.exists()) {
747 docstring const path = isabs
749 : from_utf8(abspath.realPath());
750 docstring const refpath =
751 from_utf8(filepath.absFileName());
752 master = to_utf8(makeRelPath(path, refpath));
755 } else if (token == "\\suppress_date") {
756 lex >> suppress_date;
757 } else if (token == "\\justification") {
758 lex >> justification;
759 } else if (token == "\\language") {
761 } else if (token == "\\language_package") {
763 lang_package = lex.getString();
764 } else if (token == "\\inputencoding") {
766 } else if (token == "\\graphics") {
767 readGraphicsDriver(lex);
768 } else if (token == "\\default_output_format") {
769 lex >> default_output_format;
770 } else if (token == "\\bibtex_command") {
772 bibtex_command = lex.getString();
773 } else if (token == "\\index_command") {
775 index_command = lex.getString();
776 } else if (token == "\\fontencoding") {
778 fontenc = lex.getString();
779 } else if (token == "\\font_roman") {
780 lex >> fonts_roman[0];
781 lex >> fonts_roman[1];
782 } else if (token == "\\font_sans") {
783 lex >> fonts_sans[0];
784 lex >> fonts_sans[1];
785 } else if (token == "\\font_typewriter") {
786 lex >> fonts_typewriter[0];
787 lex >> fonts_typewriter[1];
788 } else if (token == "\\font_math") {
789 lex >> fonts_math[0];
790 lex >> fonts_math[1];
791 } else if (token == "\\font_default_family") {
792 lex >> fonts_default_family;
793 } else if (token == "\\use_non_tex_fonts") {
794 lex >> useNonTeXFonts;
795 } else if (token == "\\font_sc") {
796 lex >> fonts_expert_sc;
797 } else if (token == "\\font_osf") {
798 lex >> fonts_old_figures;
799 } else if (token == "\\font_sf_scale") {
800 lex >> fonts_sans_scale[0];
801 lex >> fonts_sans_scale[1];
802 } else if (token == "\\font_tt_scale") {
803 lex >> fonts_typewriter_scale[0];
804 lex >> fonts_typewriter_scale[1];
805 } else if (token == "\\font_cjk") {
807 } else if (token == "\\paragraph_separation") {
810 paragraph_separation = parseptranslator().find(parsep);
811 } else if (token == "\\paragraph_indentation") {
813 string indentation = lex.getString();
814 pimpl_->indentation = HSpace(indentation);
815 } else if (token == "\\defskip") {
817 string const defskip = lex.getString();
818 pimpl_->defskip = VSpace(defskip);
819 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
821 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
822 } else if (token == "\\quotes_language") {
825 quotes_language = quoteslangtranslator().find(quotes_lang);
826 } else if (token == "\\papersize") {
829 papersize = papersizetranslator().find(ppsize);
830 } else if (token == "\\use_geometry") {
832 } else if (token == "\\use_package") {
837 use_package(package, packagetranslator().find(use));
838 } else if (token == "\\cite_engine") {
840 vector<string> engine = getVectorFromString(lex.getString());
841 setCiteEngine(engine);
842 } else if (token == "\\cite_engine_type") {
845 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
846 } else if (token == "\\biblio_style") {
848 biblio_style = lex.getString();
849 } else if (token == "\\use_bibtopic") {
851 } else if (token == "\\use_indices") {
853 } else if (token == "\\tracking_changes") {
854 lex >> track_changes;
855 } else if (token == "\\output_changes") {
856 lex >> output_changes;
857 } else if (token == "\\branch") {
859 docstring branch = lex.getDocString();
860 branchlist().add(branch);
863 string const tok = lex.getString();
864 if (tok == "\\end_branch")
866 Branch * branch_ptr = branchlist().find(branch);
867 if (tok == "\\selected") {
870 branch_ptr->setSelected(lex.getInteger());
872 if (tok == "\\filename_suffix") {
875 branch_ptr->setFileNameSuffix(lex.getInteger());
877 if (tok == "\\color") {
879 string color = lex.getString();
881 branch_ptr->setColor(color);
882 // Update also the Color table:
884 color = lcolor.getX11Name(Color_background);
886 lcolor.setColor(to_utf8(branch), color);
889 } else if (token == "\\index") {
891 docstring index = lex.getDocString();
893 indiceslist().add(index);
896 string const tok = lex.getString();
897 if (tok == "\\end_index")
899 Index * index_ptr = indiceslist().find(index);
900 if (tok == "\\shortcut") {
902 shortcut = lex.getDocString();
904 index_ptr->setShortcut(shortcut);
906 if (tok == "\\color") {
908 string color = lex.getString();
910 index_ptr->setColor(color);
911 // Update also the Color table:
913 color = lcolor.getX11Name(Color_background);
915 if (!shortcut.empty())
916 lcolor.setColor(to_utf8(shortcut), color);
919 } else if (token == "\\author") {
921 istringstream ss(lex.getString());
925 } else if (token == "\\paperorientation") {
928 orientation = paperorientationtranslator().find(orient);
929 } else if (token == "\\backgroundcolor") {
931 backgroundcolor = lyx::rgbFromHexName(lex.getString());
932 isbackgroundcolor = true;
933 } else if (token == "\\fontcolor") {
935 fontcolor = lyx::rgbFromHexName(lex.getString());
937 } else if (token == "\\notefontcolor") {
939 string color = lex.getString();
940 notefontcolor = lyx::rgbFromHexName(color);
941 lcolor.setColor("notefontcolor", color);
942 } else if (token == "\\boxbgcolor") {
944 string color = lex.getString();
945 boxbgcolor = lyx::rgbFromHexName(color);
946 lcolor.setColor("boxbgcolor", color);
947 } else if (token == "\\paperwidth") {
949 } else if (token == "\\paperheight") {
951 } else if (token == "\\leftmargin") {
953 } else if (token == "\\topmargin") {
955 } else if (token == "\\rightmargin") {
957 } else if (token == "\\bottommargin") {
959 } else if (token == "\\headheight") {
961 } else if (token == "\\headsep") {
963 } else if (token == "\\footskip") {
965 } else if (token == "\\columnsep") {
967 } else if (token == "\\paperfontsize") {
969 } else if (token == "\\papercolumns") {
971 } else if (token == "\\listings_params") {
974 listings_params = InsetListingsParams(par).params();
975 } else if (token == "\\papersides") {
978 sides = sidestranslator().find(psides);
979 } else if (token == "\\paperpagestyle") {
981 } else if (token == "\\bullet") {
983 } else if (token == "\\bulletLaTeX") {
984 readBulletsLaTeX(lex);
985 } else if (token == "\\secnumdepth") {
987 } else if (token == "\\tocdepth") {
989 } else if (token == "\\spacing") {
993 if (nspacing == "other") {
996 spacing().set(spacetranslator().find(nspacing), tmp_val);
997 } else if (token == "\\float_placement") {
998 lex >> float_placement;
1000 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
1001 string toktmp = pdfoptions().readToken(lex, token);
1002 if (!toktmp.empty()) {
1003 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
1007 } else if (token == "\\html_math_output") {
1010 html_math_output = static_cast<MathOutput>(temp);
1011 } else if (token == "\\html_be_strict") {
1012 lex >> html_be_strict;
1013 } else if (token == "\\html_css_as_file") {
1014 lex >> html_css_as_file;
1015 } else if (token == "\\html_math_img_scale") {
1016 lex >> html_math_img_scale;
1017 } else if (token == "\\html_latex_start") {
1019 html_latex_start = lex.getString();
1020 } else if (token == "\\html_latex_end") {
1022 html_latex_end = lex.getString();
1023 } else if (token == "\\output_sync") {
1025 } else if (token == "\\output_sync_macro") {
1026 lex >> output_sync_macro;
1027 } else if (token == "\\use_refstyle") {
1028 lex >> use_refstyle;
1030 lyxerr << "BufferParams::readToken(): Unknown token: " <<
1040 // Quote argument if it contains spaces
1041 string quoteIfNeeded(string const & str) {
1042 if (contains(str, ' '))
1043 return "\"" + str + "\"";
1049 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
1051 // The top of the file is written by the buffer.
1052 // Prints out the buffer info into the .lyx file given by file
1054 os << "\\save_transient_properties "
1055 << convert<string>(save_transient_properties) << '\n';
1057 // the document directory (must end with a path separator)
1058 // realPath() is used to resolve symlinks, while addPath(..., "")
1059 // ensures a trailing path separator.
1061 string filepath = addPath(buf->fileName().onlyPath().realPath(), "");
1062 string const sysdir = inSystemDir(FileName(filepath), docsys) ? docsys
1063 : addPath(package().system_support().realPath(), "");
1064 string const relpath =
1065 to_utf8(makeRelPath(from_utf8(filepath), from_utf8(sysdir)));
1066 if (!prefixIs(relpath, "../") && !FileName::isAbsolute(relpath))
1067 filepath = addPath("/systemlyxdir", relpath);
1068 else if (!save_transient_properties || !lyxrc.save_origin)
1069 filepath = "unavailable";
1070 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1073 os << "\\textclass "
1074 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1075 baseClass()->name()), "layout"))
1078 // then the preamble
1079 if (!preamble.empty()) {
1080 // remove '\n' from the end of preamble
1081 string const tmppreamble = rtrim(preamble, "\n");
1082 os << "\\begin_preamble\n"
1084 << "\n\\end_preamble\n";
1088 if (!options.empty()) {
1089 os << "\\options " << options << '\n';
1092 // use the class options defined in the layout?
1093 os << "\\use_default_options "
1094 << convert<string>(use_default_options) << "\n";
1096 // the master document
1097 if (!master.empty()) {
1098 os << "\\master " << master << '\n';
1102 if (!removed_modules_.empty()) {
1103 os << "\\begin_removed_modules" << '\n';
1104 list<string>::const_iterator it = removed_modules_.begin();
1105 list<string>::const_iterator en = removed_modules_.end();
1106 for (; it != en; ++it)
1108 os << "\\end_removed_modules" << '\n';
1112 if (!layout_modules_.empty()) {
1113 os << "\\begin_modules" << '\n';
1114 LayoutModuleList::const_iterator it = layout_modules_.begin();
1115 LayoutModuleList::const_iterator en = layout_modules_.end();
1116 for (; it != en; ++it)
1118 os << "\\end_modules" << '\n';
1122 if (!included_children_.empty()) {
1123 os << "\\begin_includeonly" << '\n';
1124 list<string>::const_iterator it = included_children_.begin();
1125 list<string>::const_iterator en = included_children_.end();
1126 for (; it != en; ++it)
1128 os << "\\end_includeonly" << '\n';
1130 os << "\\maintain_unincluded_children "
1131 << convert<string>(maintain_unincluded_children) << '\n';
1133 // local layout information
1134 string const local_layout = getLocalLayout(false);
1135 if (!local_layout.empty()) {
1136 // remove '\n' from the end
1137 string const tmplocal = rtrim(local_layout, "\n");
1138 os << "\\begin_local_layout\n"
1140 << "\n\\end_local_layout\n";
1142 string const forced_local_layout = getLocalLayout(true);
1143 if (!forced_local_layout.empty()) {
1144 // remove '\n' from the end
1145 string const tmplocal = rtrim(forced_local_layout, "\n");
1146 os << "\\begin_forced_local_layout\n"
1148 << "\n\\end_forced_local_layout\n";
1151 // then the text parameters
1152 if (language != ignore_language)
1153 os << "\\language " << language->lang() << '\n';
1154 os << "\\language_package " << lang_package
1155 << "\n\\inputencoding " << inputenc
1156 << "\n\\fontencoding " << fontenc
1157 << "\n\\font_roman \"" << fonts_roman[0]
1158 << "\" \"" << fonts_roman[1] << '"'
1159 << "\n\\font_sans \"" << fonts_sans[0]
1160 << "\" \"" << fonts_sans[1] << '"'
1161 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1162 << "\" \"" << fonts_typewriter[1] << '"'
1163 << "\n\\font_math \"" << fonts_math[0]
1164 << "\" \"" << fonts_math[1] << '"'
1165 << "\n\\font_default_family " << fonts_default_family
1166 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1167 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1168 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1169 << "\n\\font_sf_scale " << fonts_sans_scale[0]
1170 << ' ' << fonts_sans_scale[1]
1171 << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1172 << ' ' << fonts_typewriter_scale[1]
1174 if (!fonts_cjk.empty()) {
1175 os << "\\font_cjk " << fonts_cjk << '\n';
1177 os << "\\graphics " << graphics_driver << '\n';
1178 os << "\\default_output_format " << default_output_format << '\n';
1179 os << "\\output_sync " << output_sync << '\n';
1180 if (!output_sync_macro.empty())
1181 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1182 os << "\\bibtex_command " << bibtex_command << '\n';
1183 os << "\\index_command " << index_command << '\n';
1185 if (!float_placement.empty()) {
1186 os << "\\float_placement " << float_placement << '\n';
1188 os << "\\paperfontsize " << fontsize << '\n';
1190 spacing().writeFile(os);
1191 pdfoptions().writeFile(os);
1193 os << "\\papersize " << string_papersize[papersize]
1194 << "\n\\use_geometry " << convert<string>(use_geometry);
1195 map<string, string> const & packages = auto_packages();
1196 for (map<string, string>::const_iterator it = packages.begin();
1197 it != packages.end(); ++it)
1198 os << "\n\\use_package " << it->first << ' '
1199 << use_package(it->first);
1201 os << "\n\\cite_engine ";
1203 if (!cite_engine_.empty()) {
1204 LayoutModuleList::const_iterator be = cite_engine_.begin();
1205 LayoutModuleList::const_iterator en = cite_engine_.end();
1206 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1215 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1216 << "\n\\biblio_style " << biblio_style
1217 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1218 << "\n\\use_indices " << convert<string>(use_indices)
1219 << "\n\\paperorientation " << string_orientation[orientation]
1220 << "\n\\suppress_date " << convert<string>(suppress_date)
1221 << "\n\\justification " << convert<string>(justification)
1222 << "\n\\use_refstyle " << use_refstyle
1224 if (isbackgroundcolor == true)
1225 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1226 if (isfontcolor == true)
1227 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1228 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1229 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1230 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1231 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1233 BranchList::const_iterator it = branchlist().begin();
1234 BranchList::const_iterator end = branchlist().end();
1235 for (; it != end; ++it) {
1236 os << "\\branch " << to_utf8(it->branch())
1237 << "\n\\selected " << it->isSelected()
1238 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1239 << "\n\\color " << lyx::X11hexname(it->color())
1244 IndicesList::const_iterator iit = indiceslist().begin();
1245 IndicesList::const_iterator iend = indiceslist().end();
1246 for (; iit != iend; ++iit) {
1247 os << "\\index " << to_utf8(iit->index())
1248 << "\n\\shortcut " << to_utf8(iit->shortcut())
1249 << "\n\\color " << lyx::X11hexname(iit->color())
1254 if (!paperwidth.empty())
1255 os << "\\paperwidth "
1256 << VSpace(paperwidth).asLyXCommand() << '\n';
1257 if (!paperheight.empty())
1258 os << "\\paperheight "
1259 << VSpace(paperheight).asLyXCommand() << '\n';
1260 if (!leftmargin.empty())
1261 os << "\\leftmargin "
1262 << VSpace(leftmargin).asLyXCommand() << '\n';
1263 if (!topmargin.empty())
1264 os << "\\topmargin "
1265 << VSpace(topmargin).asLyXCommand() << '\n';
1266 if (!rightmargin.empty())
1267 os << "\\rightmargin "
1268 << VSpace(rightmargin).asLyXCommand() << '\n';
1269 if (!bottommargin.empty())
1270 os << "\\bottommargin "
1271 << VSpace(bottommargin).asLyXCommand() << '\n';
1272 if (!headheight.empty())
1273 os << "\\headheight "
1274 << VSpace(headheight).asLyXCommand() << '\n';
1275 if (!headsep.empty())
1277 << VSpace(headsep).asLyXCommand() << '\n';
1278 if (!footskip.empty())
1280 << VSpace(footskip).asLyXCommand() << '\n';
1281 if (!columnsep.empty())
1282 os << "\\columnsep "
1283 << VSpace(columnsep).asLyXCommand() << '\n';
1284 os << "\\secnumdepth " << secnumdepth
1285 << "\n\\tocdepth " << tocdepth
1286 << "\n\\paragraph_separation "
1287 << string_paragraph_separation[paragraph_separation];
1288 if (!paragraph_separation)
1289 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1291 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1292 os << "\n\\quotes_language "
1293 << string_quotes_language[quotes_language]
1294 << "\n\\papercolumns " << columns
1295 << "\n\\papersides " << sides
1296 << "\n\\paperpagestyle " << pagestyle << '\n';
1297 if (!listings_params.empty())
1298 os << "\\listings_params \"" <<
1299 InsetListingsParams(listings_params).encodedString() << "\"\n";
1300 for (int i = 0; i < 4; ++i) {
1301 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1302 if (user_defined_bullet(i).getFont() != -1) {
1303 os << "\\bullet " << i << " "
1304 << user_defined_bullet(i).getFont() << " "
1305 << user_defined_bullet(i).getCharacter() << " "
1306 << user_defined_bullet(i).getSize() << "\n";
1310 os << "\\bulletLaTeX " << i << " \""
1311 << lyx::to_ascii(user_defined_bullet(i).getText())
1317 os << "\\tracking_changes "
1318 << (save_transient_properties ? convert<string>(track_changes) : "false")
1321 os << "\\output_changes "
1322 << (save_transient_properties ? convert<string>(output_changes) : "false")
1325 os << "\\html_math_output " << html_math_output << '\n'
1326 << "\\html_css_as_file " << html_css_as_file << '\n'
1327 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1329 if (html_math_img_scale != 1.0)
1330 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1331 if (!html_latex_start.empty())
1332 os << "\\html_latex_start " << html_latex_start << '\n';
1333 if (!html_latex_end.empty())
1334 os << "\\html_latex_end " << html_latex_end << '\n';
1336 os << pimpl_->authorlist;
1340 void BufferParams::validate(LaTeXFeatures & features) const
1342 features.require(documentClass().requires());
1344 if (columns > 1 && language->rightToLeft())
1345 features.require("rtloutputdblcol");
1347 if (output_changes) {
1348 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1349 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1350 LaTeXFeatures::isAvailable("xcolor");
1352 switch (features.runparams().flavor) {
1353 case OutputParams::LATEX:
1354 case OutputParams::DVILUATEX:
1356 features.require("ct-dvipost");
1357 features.require("dvipost");
1358 } else if (xcolorulem) {
1359 features.require("ct-xcolor-ulem");
1360 features.require("ulem");
1361 features.require("xcolor");
1363 features.require("ct-none");
1366 case OutputParams::LUATEX:
1367 case OutputParams::PDFLATEX:
1368 case OutputParams::XETEX:
1370 features.require("ct-xcolor-ulem");
1371 features.require("ulem");
1372 features.require("xcolor");
1373 // improves color handling in PDF output
1374 features.require("pdfcolmk");
1376 features.require("ct-none");
1384 // Floats with 'Here definitely' as default setting.
1385 if (float_placement.find('H') != string::npos)
1386 features.require("float");
1388 for (PackageMap::const_iterator it = use_packages.begin();
1389 it != use_packages.end(); ++it) {
1390 if (it->first == "amsmath") {
1391 // AMS Style is at document level
1392 if (it->second == package_on ||
1393 features.isProvided("amsmath"))
1394 features.require(it->first);
1395 } else if (it->second == package_on)
1396 features.require(it->first);
1399 // Document-level line spacing
1400 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1401 features.require("setspace");
1403 // the bullet shapes are buffer level not paragraph level
1404 // so they are tested here
1405 for (int i = 0; i < 4; ++i) {
1406 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1408 int const font = user_defined_bullet(i).getFont();
1410 int const c = user_defined_bullet(i).getCharacter();
1416 features.require("latexsym");
1418 } else if (font == 1) {
1419 features.require("amssymb");
1420 } else if (font >= 2 && font <= 5) {
1421 features.require("pifont");
1425 if (pdfoptions().use_hyperref) {
1426 features.require("hyperref");
1427 // due to interferences with babel and hyperref, the color package has to
1428 // be loaded after hyperref when hyperref is used with the colorlinks
1429 // option, see http://www.lyx.org/trac/ticket/5291
1430 if (pdfoptions().colorlinks)
1431 features.require("color");
1433 if (!listings_params.empty()) {
1434 // do not test validity because listings_params is
1435 // supposed to be valid
1437 InsetListingsParams(listings_params).separatedParams(true);
1438 // we can't support all packages, but we should load the color package
1439 if (par.find("\\color", 0) != string::npos)
1440 features.require("color");
1443 // some languages are only available via polyglossia
1444 if (features.hasPolyglossiaExclusiveLanguages())
1445 features.require("polyglossia");
1447 if (useNonTeXFonts && fontsMath() != "auto")
1448 features.require("unicode-math");
1450 if (!language->requires().empty())
1451 features.require(language->requires());
1455 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1456 FileName const & filepath) const
1458 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1459 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1460 // \RequirePackage to do so, rather than the normal \usepackage
1461 // Do not try to load any other package before the document class, unless you
1462 // have a thorough understanding of the LATEX internals and know exactly what you
1464 if (features.mustProvide("fix-cm"))
1465 os << "\\RequirePackage{fix-cm}\n";
1466 // Likewise for fixltx2e. If other packages conflict with this policy,
1467 // treat it as a package bug (and report it!)
1468 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1469 if (features.mustProvide("fixltx2e"))
1470 os << "\\RequirePackage{fixltx2e}\n";
1472 os << "\\documentclass";
1474 DocumentClass const & tclass = documentClass();
1476 ostringstream clsoptions; // the document class options.
1478 if (tokenPos(tclass.opt_fontsize(),
1479 '|', fontsize) >= 0) {
1480 // only write if existing in list (and not default)
1481 clsoptions << fontsize << "pt,";
1484 // all paper sizes except of A4, A5, B5 and the US sizes need the
1486 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1487 && papersize != PAPER_USLETTER
1488 && papersize != PAPER_USLEGAL
1489 && papersize != PAPER_USEXECUTIVE
1490 && papersize != PAPER_A4
1491 && papersize != PAPER_A5
1492 && papersize != PAPER_B5;
1494 if (!use_geometry) {
1495 switch (papersize) {
1497 clsoptions << "a4paper,";
1499 case PAPER_USLETTER:
1500 clsoptions << "letterpaper,";
1503 clsoptions << "a5paper,";
1506 clsoptions << "b5paper,";
1508 case PAPER_USEXECUTIVE:
1509 clsoptions << "executivepaper,";
1512 clsoptions << "legalpaper,";
1546 if (sides != tclass.sides()) {
1549 clsoptions << "oneside,";
1552 clsoptions << "twoside,";
1558 if (columns != tclass.columns()) {
1560 clsoptions << "twocolumn,";
1562 clsoptions << "onecolumn,";
1566 && orientation == ORIENTATION_LANDSCAPE)
1567 clsoptions << "landscape,";
1569 // language should be a parameter to \documentclass
1570 if (language->babel() == "hebrew"
1571 && default_language->babel() != "hebrew")
1572 // This seems necessary
1573 features.useLanguage(default_language);
1575 ostringstream language_options;
1576 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1577 bool const use_polyglossia = features.usePolyglossia();
1578 bool const global = lyxrc.language_global_options;
1579 if (use_babel || (use_polyglossia && global)) {
1580 language_options << features.getBabelLanguages();
1581 if (!language->babel().empty()) {
1582 if (!language_options.str().empty())
1583 language_options << ',';
1584 language_options << language->babel();
1586 if (global && !features.needBabelLangOptions()
1587 && !language_options.str().empty())
1588 clsoptions << language_options.str() << ',';
1591 // the predefined options from the layout
1592 if (use_default_options && !tclass.options().empty())
1593 clsoptions << tclass.options() << ',';
1595 // the user-defined options
1596 if (!options.empty()) {
1597 clsoptions << options << ',';
1600 string strOptions(clsoptions.str());
1601 if (!strOptions.empty()) {
1602 strOptions = rtrim(strOptions, ",");
1604 os << '[' << from_utf8(strOptions) << ']';
1607 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1608 // end of \documentclass defs
1610 // if we use fontspec or newtxmath, we have to load the AMS packages here
1611 string const ams = features.loadAMSPackages();
1612 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1613 bool const use_newtxmath =
1614 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1615 ot1, false, false) == "newtxmath";
1616 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1617 os << from_ascii(ams);
1619 if (useNonTeXFonts) {
1620 if (!features.isProvided("fontspec"))
1621 os << "\\usepackage{fontspec}\n";
1622 if (features.mustProvide("unicode-math")
1623 && features.isAvailable("unicode-math"))
1624 os << "\\usepackage{unicode-math}\n";
1627 // font selection must be done before loading fontenc.sty
1628 string const fonts = loadFonts(features);
1630 os << from_utf8(fonts);
1632 if (fonts_default_family != "default")
1633 os << "\\renewcommand{\\familydefault}{\\"
1634 << from_ascii(fonts_default_family) << "}\n";
1636 // set font encoding
1637 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1638 if (!useNonTeXFonts && !features.isProvided("fontenc")
1639 && font_encoding() != "default") {
1640 // get main font encodings
1641 vector<string> fontencs = font_encodings();
1642 // get font encodings of secondary languages
1643 features.getFontEncodings(fontencs);
1644 if (!fontencs.empty()) {
1645 os << "\\usepackage["
1646 << from_ascii(getStringFromVector(fontencs))
1651 // handle inputenc etc.
1652 writeEncodingPreamble(os, features);
1655 if (!features.runparams().includeall && !included_children_.empty()) {
1656 os << "\\includeonly{";
1657 list<string>::const_iterator it = included_children_.begin();
1658 list<string>::const_iterator en = included_children_.end();
1660 for (; it != en; ++it) {
1661 string incfile = *it;
1662 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1663 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1665 if (!features.runparams().nice)
1667 // \includeonly doesn't want an extension
1668 incfile = changeExtension(incfile, string());
1669 incfile = support::latex_path(incfile);
1670 if (!incfile.empty()) {
1673 os << from_utf8(incfile);
1680 if (!features.isProvided("geometry")
1681 && (use_geometry || nonstandard_papersize)) {
1682 odocstringstream ods;
1683 if (!getGraphicsDriver("geometry").empty())
1684 ods << getGraphicsDriver("geometry");
1685 if (orientation == ORIENTATION_LANDSCAPE)
1686 ods << ",landscape";
1687 switch (papersize) {
1689 if (!paperwidth.empty())
1690 ods << ",paperwidth="
1691 << from_ascii(paperwidth);
1692 if (!paperheight.empty())
1693 ods << ",paperheight="
1694 << from_ascii(paperheight);
1696 case PAPER_USLETTER:
1697 ods << ",letterpaper";
1700 ods << ",legalpaper";
1702 case PAPER_USEXECUTIVE:
1703 ods << ",executivepaper";
1792 docstring const g_options = trim(ods.str(), ",");
1793 os << "\\usepackage";
1794 if (!g_options.empty())
1795 os << '[' << g_options << ']';
1796 os << "{geometry}\n";
1797 // output this only if use_geometry is true
1799 os << "\\geometry{verbose";
1800 if (!topmargin.empty())
1801 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1802 if (!bottommargin.empty())
1803 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1804 if (!leftmargin.empty())
1805 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1806 if (!rightmargin.empty())
1807 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1808 if (!headheight.empty())
1809 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1810 if (!headsep.empty())
1811 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1812 if (!footskip.empty())
1813 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1814 if (!columnsep.empty())
1815 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1818 } else if (orientation == ORIENTATION_LANDSCAPE
1819 || papersize != PAPER_DEFAULT) {
1820 features.require("papersize");
1823 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1824 if (pagestyle == "fancy")
1825 os << "\\usepackage{fancyhdr}\n";
1826 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1829 // only output when the background color is not default
1830 if (isbackgroundcolor == true) {
1831 // only require color here, the background color will be defined
1832 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1834 features.require("color");
1835 features.require("pagecolor");
1838 // only output when the font color is not default
1839 if (isfontcolor == true) {
1840 // only require color here, the font color will be defined
1841 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1843 features.require("color");
1844 features.require("fontcolor");
1847 // Only if class has a ToC hierarchy
1848 if (tclass.hasTocLevels()) {
1849 if (secnumdepth != tclass.secnumdepth()) {
1850 os << "\\setcounter{secnumdepth}{"
1854 if (tocdepth != tclass.tocdepth()) {
1855 os << "\\setcounter{tocdepth}{"
1861 if (paragraph_separation) {
1862 // when skip separation
1863 switch (getDefSkip().kind()) {
1864 case VSpace::SMALLSKIP:
1865 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1867 case VSpace::MEDSKIP:
1868 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1870 case VSpace::BIGSKIP:
1871 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1873 case VSpace::LENGTH:
1874 os << "\\setlength{\\parskip}{"
1875 << from_utf8(getDefSkip().length().asLatexString())
1878 default: // should never happen // Then delete it.
1879 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1882 os << "\\setlength{\\parindent}{0pt}\n";
1884 // when separation by indentation
1885 // only output something when a width is given
1886 if (getIndentation().asLyXCommand() != "default") {
1887 os << "\\setlength{\\parindent}{"
1888 << from_utf8(getIndentation().asLatexCommand())
1893 // Now insert the LyX specific LaTeX commands...
1894 docstring lyxpreamble;
1895 features.resolveAlternatives();
1898 if (!output_sync_macro.empty())
1899 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1900 else if (features.runparams().flavor == OutputParams::LATEX)
1901 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1902 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1903 lyxpreamble += "\\synctex=-1\n";
1906 // The package options (via \PassOptionsToPackage)
1907 lyxpreamble += from_ascii(features.getPackageOptions());
1909 // due to interferences with babel and hyperref, the color package has to
1910 // be loaded (when it is not already loaded) before babel when hyperref
1911 // is used with the colorlinks option, see
1912 // http://www.lyx.org/trac/ticket/5291
1913 // we decided therefore to load color always before babel, see
1914 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1915 lyxpreamble += from_ascii(features.getColorOptions());
1917 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1918 // we have to call babel before
1920 && (features.isRequired("jurabib")
1921 || features.isRequired("hyperref")
1922 || features.isRequired("varioref")
1923 || features.isRequired("vietnamese")
1924 || features.isRequired("japanese"))) {
1926 lyxpreamble += from_utf8(features.getBabelPresettings());
1927 lyxpreamble += from_utf8(babelCall(language_options.str(),
1928 features.needBabelLangOptions())) + '\n';
1929 lyxpreamble += from_utf8(features.getBabelPostsettings());
1932 // The optional packages;
1933 lyxpreamble += from_ascii(features.getPackages());
1935 // Additional Indices
1936 if (features.isRequired("splitidx")) {
1937 IndicesList::const_iterator iit = indiceslist().begin();
1938 IndicesList::const_iterator iend = indiceslist().end();
1939 for (; iit != iend; ++iit) {
1940 pair<docstring, docstring> indexname_latex =
1941 features.runparams().encoding->latexString(iit->index(),
1942 features.runparams().dryrun);
1943 if (!indexname_latex.second.empty()) {
1944 // issue a warning about omitted characters
1945 // FIXME: should be passed to the error dialog
1946 frontend::Alert::warning(_("Uncodable characters"),
1947 bformat(_("The following characters that are used in an index name are not\n"
1948 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1949 indexname_latex.second));
1951 lyxpreamble += "\\newindex[";
1952 lyxpreamble += indexname_latex.first;
1953 lyxpreamble += "]{";
1954 lyxpreamble += escape(iit->shortcut());
1955 lyxpreamble += "}\n";
1960 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1963 // * Hyperref manual: "Make sure it comes last of your loaded
1964 // packages, to give it a fighting chance of not being over-written,
1965 // since its job is to redefine many LaTeX commands."
1966 // * Email from Heiko Oberdiek: "It is usually better to load babel
1967 // before hyperref. Then hyperref has a chance to detect babel.
1968 // * Has to be loaded before the "LyX specific LaTeX commands" to
1969 // avoid errors with algorithm floats.
1970 // use hyperref explicitly if it is required
1971 if (features.isRequired("hyperref")) {
1972 // pass what we have to stream here, since we need
1973 // to access the stream itself in PDFOptions.
1976 OutputParams tmp_params = features.runparams();
1977 pdfoptions().writeLaTeX(tmp_params, os,
1978 features.isProvided("hyperref"));
1979 // set back for the rest
1980 lyxpreamble.clear();
1981 // correctly break URLs with hyperref and dvi output
1982 if (features.runparams().flavor == OutputParams::LATEX
1983 && features.isAvailable("breakurl"))
1984 lyxpreamble += "\\usepackage{breakurl}\n";
1985 } else if (features.isRequired("nameref"))
1986 // hyperref loads this automatically
1987 lyxpreamble += "\\usepackage{nameref}\n";
1989 // bibtopic needs to be loaded after hyperref.
1990 // the dot provides the aux file naming which LyX can detect.
1991 if (features.mustProvide("bibtopic"))
1992 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1994 // Will be surrounded by \makeatletter and \makeatother when not empty
1995 docstring atlyxpreamble;
1997 // Some macros LyX will need
1998 docstring tmppreamble(features.getMacros());
2000 if (!tmppreamble.empty())
2001 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2002 "LyX specific LaTeX commands.\n"
2003 + tmppreamble + '\n';
2005 // the text class specific preamble
2006 tmppreamble = features.getTClassPreamble();
2007 if (!tmppreamble.empty())
2008 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2009 "Textclass specific LaTeX commands.\n"
2010 + tmppreamble + '\n';
2012 // suppress date if selected
2013 // use \@ifundefined because we cannot be sure that every document class
2014 // has a \date command
2016 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
2018 /* the user-defined preamble */
2019 if (!containsOnly(preamble, " \n\t")) {
2021 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
2022 "User specified LaTeX commands.\n";
2024 // Check if the user preamble contains uncodable glyphs
2025 docstring const u_preamble = from_utf8(preamble);
2026 odocstringstream user_preamble;
2027 docstring uncodable_glyphs;
2028 Encoding const * const enc = features.runparams().encoding;
2030 for (size_t n = 0; n < u_preamble.size(); ++n) {
2031 char_type c = u_preamble[n];
2032 if (!enc->encodable(c)) {
2033 docstring const glyph(1, c);
2034 LYXERR0("Uncodable character '"
2036 << "' in user preamble!");
2037 uncodable_glyphs += glyph;
2038 if (features.runparams().dryrun) {
2039 user_preamble << "<" << _("LyX Warning: ")
2040 << _("uncodable character") << " '";
2041 user_preamble.put(c);
2042 user_preamble << "'>";
2045 user_preamble.put(c);
2048 user_preamble << u_preamble;
2050 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2051 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2052 frontend::Alert::warning(
2053 _("Uncodable character in user preamble"),
2055 _("The user preamble of your document contains glyphs "
2056 "that are unknown in the current document encoding "
2057 "(namely %1$s).\nThese glyphs are omitted "
2058 " from the output, which may result in "
2059 "incomplete output."
2060 "\n\nPlease select an appropriate "
2061 "document encoding\n"
2062 "(such as utf8) or change the "
2063 "preamble code accordingly."),
2066 atlyxpreamble += user_preamble.str() + '\n';
2069 // footmisc must be loaded after setspace
2070 // Load it here to avoid clashes with footmisc loaded in the user
2071 // preamble. For that reason we also pass the options via
2072 // \PassOptionsToPackage in getPreamble() and not here.
2073 if (features.mustProvide("footmisc"))
2074 atlyxpreamble += "\\usepackage{footmisc}\n";
2076 // subfig loads internally the LaTeX package "caption". As
2077 // caption is a very popular package, users will load it in
2078 // the preamble. Therefore we must load subfig behind the
2079 // user-defined preamble and check if the caption package was
2080 // loaded or not. For the case that caption is loaded before
2081 // subfig, there is the subfig option "caption=false". This
2082 // option also works when a koma-script class is used and
2083 // koma's own caption commands are used instead of caption. We
2084 // use \PassOptionsToPackage here because the user could have
2085 // already loaded subfig in the preamble.
2086 if (features.mustProvide("subfig")) {
2087 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
2088 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2089 "\\usepackage{subfig}\n";
2092 // Itemize bullet settings need to be last in case the user
2093 // defines their own bullets that use a package included
2094 // in the user-defined preamble -- ARRae
2095 // Actually it has to be done much later than that
2096 // since some packages like frenchb make modifications
2097 // at \begin{document} time -- JMarc
2098 docstring bullets_def;
2099 for (int i = 0; i < 4; ++i) {
2100 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2101 if (bullets_def.empty())
2102 bullets_def += "\\AtBeginDocument{\n";
2103 bullets_def += " \\def\\labelitemi";
2105 // `i' is one less than the item to modify
2112 bullets_def += "ii";
2118 bullets_def += '{' +
2119 user_defined_bullet(i).getText()
2124 if (!bullets_def.empty())
2125 atlyxpreamble += bullets_def + "}\n\n";
2127 if (!atlyxpreamble.empty())
2128 lyxpreamble += "\n\\makeatletter\n"
2129 + atlyxpreamble + "\\makeatother\n\n";
2131 // We try to load babel late, in case it interferes with other packages.
2132 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
2133 // called after babel, though.
2134 if (use_babel && !features.isRequired("jurabib")
2135 && !features.isRequired("hyperref")
2136 && !features.isRequired("varioref")
2137 && !features.isRequired("vietnamese")
2138 && !features.isRequired("japanese")) {
2140 lyxpreamble += from_utf8(features.getBabelPresettings());
2141 lyxpreamble += from_utf8(babelCall(language_options.str(),
2142 features.needBabelLangOptions())) + '\n';
2143 lyxpreamble += from_utf8(features.getBabelPostsettings());
2145 if (features.isRequired("bicaption"))
2146 lyxpreamble += "\\usepackage{bicaption}\n";
2147 if (!listings_params.empty() || features.mustProvide("listings"))
2148 lyxpreamble += "\\usepackage{listings}\n";
2149 if (!listings_params.empty()) {
2150 lyxpreamble += "\\lstset{";
2151 // do not test validity because listings_params is
2152 // supposed to be valid
2154 InsetListingsParams(listings_params).separatedParams(true);
2155 lyxpreamble += from_utf8(par);
2156 lyxpreamble += "}\n";
2159 // xunicode needs to be loaded at least after amsmath, amssymb,
2160 // esint and the other packages that provide special glyphs
2161 // The package only supports XeTeX currently.
2162 if (features.runparams().flavor == OutputParams::XETEX
2164 lyxpreamble += "\\usepackage{xunicode}\n";
2166 // Polyglossia must be loaded last
2167 if (use_polyglossia) {
2169 lyxpreamble += "\\usepackage{polyglossia}\n";
2170 // set the main language
2171 lyxpreamble += "\\setdefaultlanguage";
2172 if (!language->polyglossiaOpts().empty())
2173 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
2174 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
2175 // now setup the other languages
2176 std::map<std::string, std::string> const polylangs =
2177 features.getPolyglossiaLanguages();
2178 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
2179 mit != polylangs.end() ; ++mit) {
2180 lyxpreamble += "\\setotherlanguage";
2181 if (!mit->second.empty())
2182 lyxpreamble += "[" + from_ascii(mit->second) + "]";
2183 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
2187 // Load custom language package here
2188 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2189 if (lang_package == "default")
2190 lyxpreamble += from_utf8(lyxrc.language_custom_package);
2192 lyxpreamble += from_utf8(lang_package);
2193 lyxpreamble += '\n';
2196 docstring const i18npreamble =
2197 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2198 if (!i18npreamble.empty())
2199 lyxpreamble += i18npreamble + '\n';
2207 void BufferParams::useClassDefaults()
2209 DocumentClass const & tclass = documentClass();
2211 sides = tclass.sides();
2212 columns = tclass.columns();
2213 pagestyle = tclass.pagestyle();
2214 use_default_options = true;
2215 // Only if class has a ToC hierarchy
2216 if (tclass.hasTocLevels()) {
2217 secnumdepth = tclass.secnumdepth();
2218 tocdepth = tclass.tocdepth();
2223 bool BufferParams::hasClassDefaults() const
2225 DocumentClass const & tclass = documentClass();
2227 return sides == tclass.sides()
2228 && columns == tclass.columns()
2229 && pagestyle == tclass.pagestyle()
2230 && use_default_options
2231 && secnumdepth == tclass.secnumdepth()
2232 && tocdepth == tclass.tocdepth();
2236 DocumentClass const & BufferParams::documentClass() const
2238 return *doc_class_.get();
2242 DocumentClassConstPtr BufferParams::documentClassPtr() const
2248 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2250 // evil, but this function is evil
2251 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2255 bool BufferParams::setBaseClass(string const & classname)
2257 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2258 LayoutFileList & bcl = LayoutFileList::get();
2259 if (!bcl.haveClass(classname)) {
2261 bformat(_("The layout file:\n"
2263 "could not be found. A default textclass with default\n"
2264 "layouts will be used. LyX will not be able to produce\n"
2266 from_utf8(classname));
2267 frontend::Alert::error(_("Document class not found"), s);
2268 bcl.addEmptyClass(classname);
2271 bool const success = bcl[classname].load();
2274 bformat(_("Due to some error in it, the layout file:\n"
2276 "could not be loaded. A default textclass with default\n"
2277 "layouts will be used. LyX will not be able to produce\n"
2279 from_utf8(classname));
2280 frontend::Alert::error(_("Could not load class"), s);
2281 bcl.addEmptyClass(classname);
2284 pimpl_->baseClass_ = classname;
2285 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2290 LayoutFile const * BufferParams::baseClass() const
2292 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2293 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2299 LayoutFileIndex const & BufferParams::baseClassID() const
2301 return pimpl_->baseClass_;
2305 void BufferParams::makeDocumentClass(bool const clone)
2310 LayoutModuleList mods;
2311 LayoutModuleList::iterator it = layout_modules_.begin();
2312 LayoutModuleList::iterator en = layout_modules_.end();
2313 for (; it != en; ++it)
2314 mods.push_back(*it);
2316 it = cite_engine_.begin();
2317 en = cite_engine_.end();
2318 for (; it != en; ++it)
2319 mods.push_back(*it);
2321 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2323 TextClass::ReturnValues success = TextClass::OK;
2324 if (!forced_local_layout_.empty())
2325 success = doc_class_->read(forced_local_layout_, TextClass::MODULE);
2326 if (!local_layout_.empty() &&
2327 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2328 success = doc_class_->read(local_layout_, TextClass::MODULE);
2329 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2330 docstring const msg = _("Error reading internal layout information");
2331 frontend::Alert::warning(_("Read Error"), msg);
2336 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2338 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2342 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2344 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2348 std::string BufferParams::getLocalLayout(bool forced) const
2351 return doc_class_->forcedLayouts();
2353 return local_layout_;
2357 void BufferParams::setLocalLayout(string const & layout, bool forced)
2360 forced_local_layout_ = layout;
2362 local_layout_ = layout;
2366 bool BufferParams::addLayoutModule(string const & modName)
2368 LayoutModuleList::const_iterator it = layout_modules_.begin();
2369 LayoutModuleList::const_iterator end = layout_modules_.end();
2370 for (; it != end; ++it)
2373 layout_modules_.push_back(modName);
2378 string BufferParams::bufferFormat() const
2380 string format = documentClass().outputFormat();
2381 if (format == "latex") {
2383 // FIXME: In this context, this means "xetex or luatex"
2384 // with fontspec. We cannot differentiate further here.
2385 // But maybe use a more appropriate string.
2387 if (encoding().package() == Encoding::japanese)
2394 bool BufferParams::isExportable(string const & format) const
2396 vector<string> backs = backends();
2397 for (vector<string>::const_iterator it = backs.begin();
2398 it != backs.end(); ++it)
2399 if (theConverters().isReachable(*it, format))
2405 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2407 vector<string> const backs = backends();
2408 set<string> excludes;
2409 if (useNonTeXFonts) {
2410 excludes.insert("latex");
2411 excludes.insert("pdflatex");
2413 vector<Format const *> result =
2414 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2415 for (vector<string>::const_iterator it = backs.begin() + 1;
2416 it != backs.end(); ++it) {
2417 vector<Format const *> r =
2418 theConverters().getReachable(*it, only_viewable, false, excludes);
2419 result.insert(result.end(), r.begin(), r.end());
2425 bool BufferParams::isExportableFormat(string const & format) const
2427 typedef vector<Format const *> Formats;
2429 formats = exportableFormats(true);
2430 Formats::const_iterator fit = formats.begin();
2431 Formats::const_iterator end = formats.end();
2432 for (; fit != end ; ++fit) {
2433 if ((*fit)->name() == format)
2440 vector<string> BufferParams::backends() const
2443 string const buffmt = bufferFormat();
2445 // FIXME: Don't hardcode format names here, but use a flag
2446 if (buffmt == "latex") {
2447 if (!useNonTeXFonts) {
2448 v.push_back("pdflatex");
2449 v.push_back("latex");
2451 v.push_back("luatex");
2452 v.push_back("dviluatex");
2453 v.push_back("xetex");
2454 } else if (buffmt == "xetex") {
2455 v.push_back("xetex");
2456 v.push_back("luatex");
2457 v.push_back("dviluatex");
2459 v.push_back(buffmt);
2461 v.push_back("xhtml");
2462 v.push_back("text");
2468 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2470 string const dformat = (format.empty() || format == "default") ?
2471 getDefaultOutputFormat() : format;
2472 DefaultFlavorCache::const_iterator it =
2473 default_flavors_.find(dformat);
2475 if (it != default_flavors_.end())
2478 OutputParams::FLAVOR result = OutputParams::LATEX;
2480 // FIXME It'd be better not to hardcode this, but to do
2481 // something with formats.
2482 if (dformat == "xhtml")
2483 result = OutputParams::HTML;
2484 else if (dformat == "text")
2485 result = OutputParams::TEXT;
2486 else if (dformat == "lyx")
2487 result = OutputParams::LYX;
2488 else if (dformat == "pdflatex")
2489 result = OutputParams::PDFLATEX;
2490 else if (dformat == "xetex")
2491 result = OutputParams::XETEX;
2492 else if (dformat == "luatex")
2493 result = OutputParams::LUATEX;
2494 else if (dformat == "dviluatex")
2495 result = OutputParams::DVILUATEX;
2497 // Try to determine flavor of default output format
2498 vector<string> backs = backends();
2499 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2500 // Get shortest path to format
2501 Graph::EdgePath path;
2502 for (vector<string>::const_iterator it = backs.begin();
2503 it != backs.end(); ++it) {
2504 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2505 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2510 result = theConverters().getFlavor(path);
2513 // cache this flavor
2514 default_flavors_[dformat] = result;
2519 string BufferParams::getDefaultOutputFormat() const
2521 if (!default_output_format.empty()
2522 && default_output_format != "default")
2523 return default_output_format;
2525 || encoding().package() == Encoding::japanese) {
2526 vector<Format const *> const formats = exportableFormats(true);
2527 if (formats.empty())
2529 // return the first we find
2530 return formats.front()->name();
2533 return lyxrc.default_otf_view_format;
2534 return lyxrc.default_view_format;
2537 Font const BufferParams::getFont() const
2539 FontInfo f = documentClass().defaultfont();
2540 if (fonts_default_family == "rmdefault")
2541 f.setFamily(ROMAN_FAMILY);
2542 else if (fonts_default_family == "sfdefault")
2543 f.setFamily(SANS_FAMILY);
2544 else if (fonts_default_family == "ttdefault")
2545 f.setFamily(TYPEWRITER_FAMILY);
2546 return Font(f, language);
2550 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const & qs) const
2552 return quoteslangtranslator().find(qs);
2556 bool BufferParams::isLatex() const
2558 return documentClass().outputType() == LATEX;
2562 bool BufferParams::isLiterate() const
2564 return documentClass().outputType() == LITERATE;
2568 bool BufferParams::isDocBook() const
2570 return documentClass().outputType() == DOCBOOK;
2574 void BufferParams::readPreamble(Lexer & lex)
2576 if (lex.getString() != "\\begin_preamble")
2577 lyxerr << "Error (BufferParams::readPreamble):"
2578 "consistency check failed." << endl;
2580 preamble = lex.getLongString("\\end_preamble");
2584 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2586 string const expected = forced ? "\\begin_forced_local_layout" :
2587 "\\begin_local_layout";
2588 if (lex.getString() != expected)
2589 lyxerr << "Error (BufferParams::readLocalLayout):"
2590 "consistency check failed." << endl;
2593 forced_local_layout_ =
2594 lex.getLongString("\\end_forced_local_layout");
2596 local_layout_ = lex.getLongString("\\end_local_layout");
2600 bool BufferParams::setLanguage(string const & lang)
2602 Language const *new_language = languages.getLanguage(lang);
2603 if (!new_language) {
2604 // Language lang was not found
2607 language = new_language;
2612 void BufferParams::readLanguage(Lexer & lex)
2614 if (!lex.next()) return;
2616 string const tmptok = lex.getString();
2618 // check if tmptok is part of tex_babel in tex-defs.h
2619 if (!setLanguage(tmptok)) {
2620 // Language tmptok was not found
2621 language = default_language;
2622 lyxerr << "Warning: Setting language `"
2623 << tmptok << "' to `" << language->lang()
2629 void BufferParams::readGraphicsDriver(Lexer & lex)
2634 string const tmptok = lex.getString();
2635 // check if tmptok is part of tex_graphics in tex_defs.h
2638 string const test = tex_graphics[n++];
2640 if (test == tmptok) {
2641 graphics_driver = tmptok;
2646 "Warning: graphics driver `$$Token' not recognized!\n"
2647 " Setting graphics driver to `default'.\n");
2648 graphics_driver = "default";
2655 void BufferParams::readBullets(Lexer & lex)
2660 int const index = lex.getInteger();
2662 int temp_int = lex.getInteger();
2663 user_defined_bullet(index).setFont(temp_int);
2664 temp_bullet(index).setFont(temp_int);
2666 user_defined_bullet(index).setCharacter(temp_int);
2667 temp_bullet(index).setCharacter(temp_int);
2669 user_defined_bullet(index).setSize(temp_int);
2670 temp_bullet(index).setSize(temp_int);
2674 void BufferParams::readBulletsLaTeX(Lexer & lex)
2676 // The bullet class should be able to read this.
2679 int const index = lex.getInteger();
2681 docstring const temp_str = lex.getDocString();
2683 user_defined_bullet(index).setText(temp_str);
2684 temp_bullet(index).setText(temp_str);
2688 void BufferParams::readModules(Lexer & lex)
2690 if (!lex.eatLine()) {
2691 lyxerr << "Error (BufferParams::readModules):"
2692 "Unexpected end of input." << endl;
2696 string mod = lex.getString();
2697 if (mod == "\\end_modules")
2699 addLayoutModule(mod);
2705 void BufferParams::readRemovedModules(Lexer & lex)
2707 if (!lex.eatLine()) {
2708 lyxerr << "Error (BufferParams::readRemovedModules):"
2709 "Unexpected end of input." << endl;
2713 string mod = lex.getString();
2714 if (mod == "\\end_removed_modules")
2716 removed_modules_.push_back(mod);
2719 // now we want to remove any removed modules that were previously
2720 // added. normally, that will be because default modules were added in
2721 // setBaseClass(), which gets called when \textclass is read at the
2722 // start of the read.
2723 list<string>::const_iterator rit = removed_modules_.begin();
2724 list<string>::const_iterator const ren = removed_modules_.end();
2725 for (; rit != ren; ++rit) {
2726 LayoutModuleList::iterator const mit = layout_modules_.begin();
2727 LayoutModuleList::iterator const men = layout_modules_.end();
2728 LayoutModuleList::iterator found = find(mit, men, *rit);
2731 layout_modules_.erase(found);
2736 void BufferParams::readIncludeonly(Lexer & lex)
2738 if (!lex.eatLine()) {
2739 lyxerr << "Error (BufferParams::readIncludeonly):"
2740 "Unexpected end of input." << endl;
2744 string child = lex.getString();
2745 if (child == "\\end_includeonly")
2747 included_children_.push_back(child);
2753 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2755 switch (papersize) {
2757 // could be anything, so don't guess
2759 case PAPER_CUSTOM: {
2760 if (purpose == XDVI && !paperwidth.empty() &&
2761 !paperheight.empty()) {
2762 // heightxwidth<unit>
2763 string first = paperwidth;
2764 string second = paperheight;
2765 if (orientation == ORIENTATION_LANDSCAPE)
2768 return first.erase(first.length() - 2)
2774 // dvips and dvipdfm do not know this
2775 if (purpose == DVIPS || purpose == DVIPDFM)
2779 if (purpose == DVIPS || purpose == DVIPDFM)
2783 if (purpose == DVIPS || purpose == DVIPDFM)
2793 if (purpose == DVIPS || purpose == DVIPDFM)
2797 if (purpose == DVIPS || purpose == DVIPDFM)
2801 if (purpose == DVIPS || purpose == DVIPDFM)
2805 if (purpose == DVIPS || purpose == DVIPDFM)
2809 if (purpose == DVIPS || purpose == DVIPDFM)
2813 // dvipdfm does not know this
2814 if (purpose == DVIPDFM)
2818 if (purpose == DVIPDFM)
2822 if (purpose == DVIPS || purpose == DVIPDFM)
2826 if (purpose == DVIPS || purpose == DVIPDFM)
2830 if (purpose == DVIPS || purpose == DVIPDFM)
2834 if (purpose == DVIPS || purpose == DVIPDFM)
2838 if (purpose == DVIPS || purpose == DVIPDFM)
2842 if (purpose == DVIPS || purpose == DVIPDFM)
2846 if (purpose == DVIPS || purpose == DVIPDFM)
2850 if (purpose == DVIPS || purpose == DVIPDFM)
2854 if (purpose == DVIPS || purpose == DVIPDFM)
2858 if (purpose == DVIPS || purpose == DVIPDFM)
2862 if (purpose == DVIPS || purpose == DVIPDFM)
2866 if (purpose == DVIPS || purpose == DVIPDFM)
2870 if (purpose == DVIPS || purpose == DVIPDFM)
2874 if (purpose == DVIPS || purpose == DVIPDFM)
2878 if (purpose == DVIPS || purpose == DVIPDFM)
2881 case PAPER_USEXECUTIVE:
2882 // dvipdfm does not know this
2883 if (purpose == DVIPDFM)
2888 case PAPER_USLETTER:
2890 if (purpose == XDVI)
2897 string const BufferParams::dvips_options() const
2901 // If the class loads the geometry package, we do not know which
2902 // paper size is used, since we do not set it (bug 7013).
2903 // Therefore we must not specify any argument here.
2904 // dvips gets the correct paper size via DVI specials in this case
2905 // (if the class uses the geometry package correctly).
2906 if (documentClass().provides("geometry"))
2910 && papersize == PAPER_CUSTOM
2911 && !lyxrc.print_paper_dimension_flag.empty()
2912 && !paperwidth.empty()
2913 && !paperheight.empty()) {
2914 // using a custom papersize
2915 result = lyxrc.print_paper_dimension_flag;
2916 result += ' ' + paperwidth;
2917 result += ',' + paperheight;
2919 string const paper_option = paperSizeName(DVIPS);
2920 if (!paper_option.empty() && (paper_option != "letter" ||
2921 orientation != ORIENTATION_LANDSCAPE)) {
2922 // dvips won't accept -t letter -t landscape.
2923 // In all other cases, include the paper size
2925 result = lyxrc.print_paper_flag;
2926 result += ' ' + paper_option;
2929 if (orientation == ORIENTATION_LANDSCAPE &&
2930 papersize != PAPER_CUSTOM)
2931 result += ' ' + lyxrc.print_landscape_flag;
2936 string const BufferParams::font_encoding() const
2938 return font_encodings().empty() ? "default" : font_encodings().back();
2942 vector<string> const BufferParams::font_encodings() const
2944 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2946 vector<string> fontencs;
2948 // "default" means "no explicit font encoding"
2949 if (doc_fontenc != "default") {
2950 fontencs = getVectorFromString(doc_fontenc);
2951 if (!language->fontenc().empty()
2952 && ascii_lowercase(language->fontenc()) != "none") {
2953 vector<string> fencs = getVectorFromString(language->fontenc());
2954 vector<string>::const_iterator fit = fencs.begin();
2955 for (; fit != fencs.end(); ++fit) {
2956 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
2957 fontencs.push_back(*fit);
2966 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2968 // suppress the babel call if there is no BabelName defined
2969 // for the document language in the lib/languages file and if no
2970 // other languages are used (lang_opts is then empty)
2971 if (lang_opts.empty())
2973 // either a specific language (AsBabelOptions setting in
2974 // lib/languages) or the prefs require the languages to
2975 // be submitted to babel itself (not the class).
2977 return "\\usepackage[" + lang_opts + "]{babel}";
2978 return "\\usepackage{babel}";
2982 docstring BufferParams::getGraphicsDriver(string const & package) const
2986 if (package == "geometry") {
2987 if (graphics_driver == "dvips"
2988 || graphics_driver == "dvipdfm"
2989 || graphics_driver == "pdftex"
2990 || graphics_driver == "vtex")
2991 result = from_ascii(graphics_driver);
2992 else if (graphics_driver == "dvipdfmx")
2993 result = from_ascii("dvipdfm");
3000 void BufferParams::writeEncodingPreamble(otexstream & os,
3001 LaTeXFeatures & features) const
3003 // XeTeX/LuaTeX: (see also #9740)
3004 // With Unicode fonts we use utf8-plain without encoding package.
3005 // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails.
3006 // XeTeX must use ASCII encoding (see Buffer.cpp),
3007 // for LuaTeX, we load "luainputenc" (see below).
3008 if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
3011 if (inputenc == "auto") {
3012 string const doc_encoding =
3013 language->encoding()->latexName();
3014 Encoding::Package const package =
3015 language->encoding()->package();
3017 // Create list of inputenc options:
3018 set<string> encodings;
3019 // luainputenc fails with more than one encoding
3020 if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts
3021 // list all input encodings used in the document
3022 encodings = features.getEncodingSet(doc_encoding);
3024 // If the "japanese" package (i.e. pLaTeX) is used,
3025 // inputenc must be omitted.
3026 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
3027 if ((!encodings.empty() || package == Encoding::inputenc)
3028 && !features.isRequired("japanese")
3029 && !features.isProvided("inputenc")) {
3030 os << "\\usepackage[";
3031 set<string>::const_iterator it = encodings.begin();
3032 set<string>::const_iterator const end = encodings.end();
3034 os << from_ascii(*it);
3037 for (; it != end; ++it)
3038 os << ',' << from_ascii(*it);
3039 if (package == Encoding::inputenc) {
3040 if (!encodings.empty())
3042 os << from_ascii(doc_encoding);
3044 if (features.runparams().flavor == OutputParams::LUATEX
3045 || features.runparams().flavor == OutputParams::DVILUATEX)
3046 os << "]{luainputenc}\n";
3048 os << "]{inputenc}\n";
3050 if (package == Encoding::CJK || features.mustProvide("CJK")) {
3051 if (language->encoding()->name() == "utf8-cjk"
3052 && LaTeXFeatures::isAvailable("CJKutf8"))
3053 os << "\\usepackage{CJKutf8}\n";
3055 os << "\\usepackage{CJK}\n";
3057 } else if (inputenc != "default") {
3058 switch (encoding().package()) {
3059 case Encoding::none:
3060 case Encoding::japanese:
3062 case Encoding::inputenc:
3063 // do not load inputenc if japanese is used
3064 // or if the class provides inputenc
3065 if (features.isRequired("japanese")
3066 || features.isProvided("inputenc"))
3068 os << "\\usepackage[" << from_ascii(encoding().latexName());
3069 if (features.runparams().flavor == OutputParams::LUATEX
3070 || features.runparams().flavor == OutputParams::DVILUATEX)
3071 os << "]{luainputenc}\n";
3073 os << "]{inputenc}\n";
3076 if (encoding().name() == "utf8-cjk"
3077 && LaTeXFeatures::isAvailable("CJKutf8"))
3078 os << "\\usepackage{CJKutf8}\n";
3080 os << "\\usepackage{CJK}\n";
3083 // Load the CJK package if needed by a secondary language.
3084 // If the main encoding is some variant of UTF8, use CJKutf8.
3085 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
3086 if (encoding().iconvName() == "UTF-8"
3087 && LaTeXFeatures::isAvailable("CJKutf8"))
3088 os << "\\usepackage{CJKutf8}\n";
3090 os << "\\usepackage{CJK}\n";
3096 string const BufferParams::parseFontName(string const & name) const
3098 string mangled = name;
3099 size_t const idx = mangled.find('[');
3100 if (idx == string::npos || idx == 0)
3103 return mangled.substr(0, idx - 1);
3107 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3109 if (fontsRoman() == "default" && fontsSans() == "default"
3110 && fontsTypewriter() == "default"
3111 && (fontsMath() == "default" || fontsMath() == "auto"))
3117 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3118 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3119 * Mapping=tex-text option assures TeX ligatures (such as "--")
3120 * are resolved. Note that tt does not use these ligatures.
3122 * -- add more GUI options?
3123 * -- add more fonts (fonts for other scripts)
3124 * -- if there's a way to find out if a font really supports
3125 * OldStyle, enable/disable the widget accordingly.
3127 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3128 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3129 // However, until v.2 (2010/07/11) fontspec only knew
3130 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3131 // was introduced for both XeTeX and LuaTeX (LuaTeX
3132 // didn't understand "Mapping=tex-text", while XeTeX
3133 // understood both. With most recent versions, both
3134 // variants are understood by both engines. However,
3135 // we want to provide support for at least TeXLive 2009
3136 // (for XeTeX; LuaTeX is only supported as of v.2)
3137 string const texmapping =
3138 (features.runparams().flavor == OutputParams::XETEX) ?
3139 "Mapping=tex-text" : "Ligatures=TeX";
3140 if (fontsRoman() != "default") {
3141 os << "\\setmainfont[" << texmapping;
3142 if (fonts_old_figures)
3143 os << ",Numbers=OldStyle";
3144 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3146 if (fontsSans() != "default") {
3147 string const sans = parseFontName(fontsSans());
3148 if (fontsSansScale() != 100)
3149 os << "\\setsansfont[Scale="
3150 << float(fontsSansScale()) / 100
3151 << "," << texmapping << "]{"
3154 os << "\\setsansfont[" << texmapping << "]{"
3157 if (fontsTypewriter() != "default") {
3158 string const mono = parseFontName(fontsTypewriter());
3159 if (fontsTypewriterScale() != 100)
3160 os << "\\setmonofont[Scale="
3161 << float(fontsTypewriterScale()) / 100
3165 os << "\\setmonofont{"
3172 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
3173 bool const dryrun = features.runparams().dryrun;
3174 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3175 bool const nomath = (fontsMath() == "default");
3178 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3179 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3183 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3184 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3185 nomath, fontsSansScale());
3187 // MONOSPACED/TYPEWRITER
3188 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3189 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3190 nomath, fontsTypewriterScale());
3193 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3194 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3201 Encoding const & BufferParams::encoding() const
3203 // Main encoding for LaTeX output.
3205 // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740).
3206 // As the "flavor" is only known once export started, this
3207 // cannot be handled here. Instead, runparams.encoding is set
3208 // to ASCII in Buffer::makeLaTeXFile (for export)
3209 // and Buffer::writeLaTeXSource (for preview).
3211 return *(encodings.fromLyXName("utf8-plain"));
3212 if (inputenc == "auto" || inputenc == "default")
3213 return *language->encoding();
3214 Encoding const * const enc = encodings.fromLyXName(inputenc);
3217 LYXERR0("Unknown inputenc value `" << inputenc
3218 << "'. Using `auto' instead.");
3219 return *language->encoding();
3223 bool BufferParams::addCiteEngine(string const & engine)
3225 LayoutModuleList::const_iterator it = cite_engine_.begin();
3226 LayoutModuleList::const_iterator en = cite_engine_.end();
3227 for (; it != en; ++it)
3230 cite_engine_.push_back(engine);
3235 bool BufferParams::addCiteEngine(vector<string> const & engine)
3237 vector<string>::const_iterator it = engine.begin();
3238 vector<string>::const_iterator en = engine.end();
3240 for (; it != en; ++it)
3241 if (!addCiteEngine(*it))
3247 string const & BufferParams::defaultBiblioStyle() const
3249 return documentClass().defaultBiblioStyle();
3253 bool const & BufferParams::fullAuthorList() const
3255 return documentClass().fullAuthorList();
3259 void BufferParams::setCiteEngine(string const & engine)
3262 addCiteEngine(engine);
3266 void BufferParams::setCiteEngine(vector<string> const & engine)
3269 addCiteEngine(engine);
3273 vector<string> BufferParams::citeCommands() const
3275 static CitationStyle const default_style;
3276 vector<string> commands =
3277 documentClass().citeCommands(citeEngineType());
3278 if (commands.empty())
3279 commands.push_back(default_style.cmd);
3284 vector<CitationStyle> BufferParams::citeStyles() const
3286 static CitationStyle const default_style;
3287 vector<CitationStyle> styles =
3288 documentClass().citeStyles(citeEngineType());
3290 styles.push_back(default_style);