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 set<string> const polylangs =
2177 features.getPolyglossiaLanguages();
2178 for (set<string>::const_iterator mit = polylangs.begin();
2179 mit != polylangs.end() ; ++mit) {
2180 // We do not output the options here; they are output in
2181 // the language switch commands. This is safer if multiple
2182 // varieties are used.
2183 if (*mit == language->polyglossia())
2185 lyxpreamble += "\\setotherlanguage";
2186 lyxpreamble += "{" + from_ascii(*mit) + "}\n";
2190 // Load custom language package here
2191 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2192 if (lang_package == "default")
2193 lyxpreamble += from_utf8(lyxrc.language_custom_package);
2195 lyxpreamble += from_utf8(lang_package);
2196 lyxpreamble += '\n';
2199 docstring const i18npreamble =
2200 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2201 if (!i18npreamble.empty())
2202 lyxpreamble += i18npreamble + '\n';
2210 void BufferParams::useClassDefaults()
2212 DocumentClass const & tclass = documentClass();
2214 sides = tclass.sides();
2215 columns = tclass.columns();
2216 pagestyle = tclass.pagestyle();
2217 use_default_options = true;
2218 // Only if class has a ToC hierarchy
2219 if (tclass.hasTocLevels()) {
2220 secnumdepth = tclass.secnumdepth();
2221 tocdepth = tclass.tocdepth();
2226 bool BufferParams::hasClassDefaults() const
2228 DocumentClass const & tclass = documentClass();
2230 return sides == tclass.sides()
2231 && columns == tclass.columns()
2232 && pagestyle == tclass.pagestyle()
2233 && use_default_options
2234 && secnumdepth == tclass.secnumdepth()
2235 && tocdepth == tclass.tocdepth();
2239 DocumentClass const & BufferParams::documentClass() const
2241 return *doc_class_.get();
2245 DocumentClassConstPtr BufferParams::documentClassPtr() const
2251 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2253 // evil, but this function is evil
2254 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2258 bool BufferParams::setBaseClass(string const & classname)
2260 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2261 LayoutFileList & bcl = LayoutFileList::get();
2262 if (!bcl.haveClass(classname)) {
2264 bformat(_("The layout file:\n"
2266 "could not be found. A default textclass with default\n"
2267 "layouts will be used. LyX will not be able to produce\n"
2269 from_utf8(classname));
2270 frontend::Alert::error(_("Document class not found"), s);
2271 bcl.addEmptyClass(classname);
2274 bool const success = bcl[classname].load();
2277 bformat(_("Due to some error in it, the layout file:\n"
2279 "could not be loaded. A default textclass with default\n"
2280 "layouts will be used. LyX will not be able to produce\n"
2282 from_utf8(classname));
2283 frontend::Alert::error(_("Could not load class"), s);
2284 bcl.addEmptyClass(classname);
2287 pimpl_->baseClass_ = classname;
2288 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2293 LayoutFile const * BufferParams::baseClass() const
2295 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2296 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2302 LayoutFileIndex const & BufferParams::baseClassID() const
2304 return pimpl_->baseClass_;
2308 void BufferParams::makeDocumentClass(bool const clone)
2313 LayoutModuleList mods;
2314 LayoutModuleList::iterator it = layout_modules_.begin();
2315 LayoutModuleList::iterator en = layout_modules_.end();
2316 for (; it != en; ++it)
2317 mods.push_back(*it);
2319 it = cite_engine_.begin();
2320 en = cite_engine_.end();
2321 for (; it != en; ++it)
2322 mods.push_back(*it);
2324 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2326 TextClass::ReturnValues success = TextClass::OK;
2327 if (!forced_local_layout_.empty())
2328 success = doc_class_->read(forced_local_layout_, TextClass::MODULE);
2329 if (!local_layout_.empty() &&
2330 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2331 success = doc_class_->read(local_layout_, TextClass::MODULE);
2332 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2333 docstring const msg = _("Error reading internal layout information");
2334 frontend::Alert::warning(_("Read Error"), msg);
2339 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2341 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2345 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2347 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2351 std::string BufferParams::getLocalLayout(bool forced) const
2354 return doc_class_->forcedLayouts();
2356 return local_layout_;
2360 void BufferParams::setLocalLayout(string const & layout, bool forced)
2363 forced_local_layout_ = layout;
2365 local_layout_ = layout;
2369 bool BufferParams::addLayoutModule(string const & modName)
2371 LayoutModuleList::const_iterator it = layout_modules_.begin();
2372 LayoutModuleList::const_iterator end = layout_modules_.end();
2373 for (; it != end; ++it)
2376 layout_modules_.push_back(modName);
2381 string BufferParams::bufferFormat() const
2383 string format = documentClass().outputFormat();
2384 if (format == "latex") {
2386 // FIXME: In this context, this means "xetex or luatex"
2387 // with fontspec. We cannot differentiate further here.
2388 // But maybe use a more appropriate string.
2390 if (encoding().package() == Encoding::japanese)
2397 bool BufferParams::isExportable(string const & format) const
2399 vector<string> backs = backends();
2400 for (vector<string>::const_iterator it = backs.begin();
2401 it != backs.end(); ++it)
2402 if (theConverters().isReachable(*it, format))
2408 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2410 vector<string> const backs = backends();
2411 set<string> excludes;
2412 if (useNonTeXFonts) {
2413 excludes.insert("latex");
2414 excludes.insert("pdflatex");
2416 vector<Format const *> result =
2417 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2418 for (vector<string>::const_iterator it = backs.begin() + 1;
2419 it != backs.end(); ++it) {
2420 vector<Format const *> r =
2421 theConverters().getReachable(*it, only_viewable, false, excludes);
2422 result.insert(result.end(), r.begin(), r.end());
2428 bool BufferParams::isExportableFormat(string const & format) const
2430 typedef vector<Format const *> Formats;
2432 formats = exportableFormats(true);
2433 Formats::const_iterator fit = formats.begin();
2434 Formats::const_iterator end = formats.end();
2435 for (; fit != end ; ++fit) {
2436 if ((*fit)->name() == format)
2443 vector<string> BufferParams::backends() const
2446 string const buffmt = bufferFormat();
2448 // FIXME: Don't hardcode format names here, but use a flag
2449 if (buffmt == "latex") {
2450 if (!useNonTeXFonts) {
2451 v.push_back("pdflatex");
2452 v.push_back("latex");
2454 v.push_back("luatex");
2455 v.push_back("dviluatex");
2456 v.push_back("xetex");
2457 } else if (buffmt == "xetex") {
2458 v.push_back("xetex");
2459 v.push_back("luatex");
2460 v.push_back("dviluatex");
2462 v.push_back(buffmt);
2464 v.push_back("xhtml");
2465 v.push_back("text");
2471 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2473 string const dformat = (format.empty() || format == "default") ?
2474 getDefaultOutputFormat() : format;
2475 DefaultFlavorCache::const_iterator it =
2476 default_flavors_.find(dformat);
2478 if (it != default_flavors_.end())
2481 OutputParams::FLAVOR result = OutputParams::LATEX;
2483 // FIXME It'd be better not to hardcode this, but to do
2484 // something with formats.
2485 if (dformat == "xhtml")
2486 result = OutputParams::HTML;
2487 else if (dformat == "text")
2488 result = OutputParams::TEXT;
2489 else if (dformat == "lyx")
2490 result = OutputParams::LYX;
2491 else if (dformat == "pdflatex")
2492 result = OutputParams::PDFLATEX;
2493 else if (dformat == "xetex")
2494 result = OutputParams::XETEX;
2495 else if (dformat == "luatex")
2496 result = OutputParams::LUATEX;
2497 else if (dformat == "dviluatex")
2498 result = OutputParams::DVILUATEX;
2500 // Try to determine flavor of default output format
2501 vector<string> backs = backends();
2502 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2503 // Get shortest path to format
2504 Graph::EdgePath path;
2505 for (vector<string>::const_iterator it = backs.begin();
2506 it != backs.end(); ++it) {
2507 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2508 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2513 result = theConverters().getFlavor(path);
2516 // cache this flavor
2517 default_flavors_[dformat] = result;
2522 string BufferParams::getDefaultOutputFormat() const
2524 if (!default_output_format.empty()
2525 && default_output_format != "default")
2526 return default_output_format;
2528 || encoding().package() == Encoding::japanese) {
2529 vector<Format const *> const formats = exportableFormats(true);
2530 if (formats.empty())
2532 // return the first we find
2533 return formats.front()->name();
2536 return lyxrc.default_otf_view_format;
2537 return lyxrc.default_view_format;
2540 Font const BufferParams::getFont() const
2542 FontInfo f = documentClass().defaultfont();
2543 if (fonts_default_family == "rmdefault")
2544 f.setFamily(ROMAN_FAMILY);
2545 else if (fonts_default_family == "sfdefault")
2546 f.setFamily(SANS_FAMILY);
2547 else if (fonts_default_family == "ttdefault")
2548 f.setFamily(TYPEWRITER_FAMILY);
2549 return Font(f, language);
2553 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const & qs) const
2555 return quoteslangtranslator().find(qs);
2559 bool BufferParams::isLatex() const
2561 return documentClass().outputType() == LATEX;
2565 bool BufferParams::isLiterate() const
2567 return documentClass().outputType() == LITERATE;
2571 bool BufferParams::isDocBook() const
2573 return documentClass().outputType() == DOCBOOK;
2577 void BufferParams::readPreamble(Lexer & lex)
2579 if (lex.getString() != "\\begin_preamble")
2580 lyxerr << "Error (BufferParams::readPreamble):"
2581 "consistency check failed." << endl;
2583 preamble = lex.getLongString("\\end_preamble");
2587 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2589 string const expected = forced ? "\\begin_forced_local_layout" :
2590 "\\begin_local_layout";
2591 if (lex.getString() != expected)
2592 lyxerr << "Error (BufferParams::readLocalLayout):"
2593 "consistency check failed." << endl;
2596 forced_local_layout_ =
2597 lex.getLongString("\\end_forced_local_layout");
2599 local_layout_ = lex.getLongString("\\end_local_layout");
2603 bool BufferParams::setLanguage(string const & lang)
2605 Language const *new_language = languages.getLanguage(lang);
2606 if (!new_language) {
2607 // Language lang was not found
2610 language = new_language;
2615 void BufferParams::readLanguage(Lexer & lex)
2617 if (!lex.next()) return;
2619 string const tmptok = lex.getString();
2621 // check if tmptok is part of tex_babel in tex-defs.h
2622 if (!setLanguage(tmptok)) {
2623 // Language tmptok was not found
2624 language = default_language;
2625 lyxerr << "Warning: Setting language `"
2626 << tmptok << "' to `" << language->lang()
2632 void BufferParams::readGraphicsDriver(Lexer & lex)
2637 string const tmptok = lex.getString();
2638 // check if tmptok is part of tex_graphics in tex_defs.h
2641 string const test = tex_graphics[n++];
2643 if (test == tmptok) {
2644 graphics_driver = tmptok;
2649 "Warning: graphics driver `$$Token' not recognized!\n"
2650 " Setting graphics driver to `default'.\n");
2651 graphics_driver = "default";
2658 void BufferParams::readBullets(Lexer & lex)
2663 int const index = lex.getInteger();
2665 int temp_int = lex.getInteger();
2666 user_defined_bullet(index).setFont(temp_int);
2667 temp_bullet(index).setFont(temp_int);
2669 user_defined_bullet(index).setCharacter(temp_int);
2670 temp_bullet(index).setCharacter(temp_int);
2672 user_defined_bullet(index).setSize(temp_int);
2673 temp_bullet(index).setSize(temp_int);
2677 void BufferParams::readBulletsLaTeX(Lexer & lex)
2679 // The bullet class should be able to read this.
2682 int const index = lex.getInteger();
2684 docstring const temp_str = lex.getDocString();
2686 user_defined_bullet(index).setText(temp_str);
2687 temp_bullet(index).setText(temp_str);
2691 void BufferParams::readModules(Lexer & lex)
2693 if (!lex.eatLine()) {
2694 lyxerr << "Error (BufferParams::readModules):"
2695 "Unexpected end of input." << endl;
2699 string mod = lex.getString();
2700 if (mod == "\\end_modules")
2702 addLayoutModule(mod);
2708 void BufferParams::readRemovedModules(Lexer & lex)
2710 if (!lex.eatLine()) {
2711 lyxerr << "Error (BufferParams::readRemovedModules):"
2712 "Unexpected end of input." << endl;
2716 string mod = lex.getString();
2717 if (mod == "\\end_removed_modules")
2719 removed_modules_.push_back(mod);
2722 // now we want to remove any removed modules that were previously
2723 // added. normally, that will be because default modules were added in
2724 // setBaseClass(), which gets called when \textclass is read at the
2725 // start of the read.
2726 list<string>::const_iterator rit = removed_modules_.begin();
2727 list<string>::const_iterator const ren = removed_modules_.end();
2728 for (; rit != ren; ++rit) {
2729 LayoutModuleList::iterator const mit = layout_modules_.begin();
2730 LayoutModuleList::iterator const men = layout_modules_.end();
2731 LayoutModuleList::iterator found = find(mit, men, *rit);
2734 layout_modules_.erase(found);
2739 void BufferParams::readIncludeonly(Lexer & lex)
2741 if (!lex.eatLine()) {
2742 lyxerr << "Error (BufferParams::readIncludeonly):"
2743 "Unexpected end of input." << endl;
2747 string child = lex.getString();
2748 if (child == "\\end_includeonly")
2750 included_children_.push_back(child);
2756 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2758 switch (papersize) {
2760 // could be anything, so don't guess
2762 case PAPER_CUSTOM: {
2763 if (purpose == XDVI && !paperwidth.empty() &&
2764 !paperheight.empty()) {
2765 // heightxwidth<unit>
2766 string first = paperwidth;
2767 string second = paperheight;
2768 if (orientation == ORIENTATION_LANDSCAPE)
2771 return first.erase(first.length() - 2)
2777 // dvips and dvipdfm do not know this
2778 if (purpose == DVIPS || purpose == DVIPDFM)
2782 if (purpose == DVIPS || purpose == DVIPDFM)
2786 if (purpose == DVIPS || purpose == DVIPDFM)
2796 if (purpose == DVIPS || purpose == DVIPDFM)
2800 if (purpose == DVIPS || purpose == DVIPDFM)
2804 if (purpose == DVIPS || purpose == DVIPDFM)
2808 if (purpose == DVIPS || purpose == DVIPDFM)
2812 if (purpose == DVIPS || purpose == DVIPDFM)
2816 // dvipdfm does not know this
2817 if (purpose == DVIPDFM)
2821 if (purpose == DVIPDFM)
2825 if (purpose == DVIPS || purpose == DVIPDFM)
2829 if (purpose == DVIPS || purpose == DVIPDFM)
2833 if (purpose == DVIPS || purpose == DVIPDFM)
2837 if (purpose == DVIPS || purpose == DVIPDFM)
2841 if (purpose == DVIPS || purpose == DVIPDFM)
2845 if (purpose == DVIPS || purpose == DVIPDFM)
2849 if (purpose == DVIPS || purpose == DVIPDFM)
2853 if (purpose == DVIPS || purpose == DVIPDFM)
2857 if (purpose == DVIPS || purpose == DVIPDFM)
2861 if (purpose == DVIPS || purpose == DVIPDFM)
2865 if (purpose == DVIPS || purpose == DVIPDFM)
2869 if (purpose == DVIPS || purpose == DVIPDFM)
2873 if (purpose == DVIPS || purpose == DVIPDFM)
2877 if (purpose == DVIPS || purpose == DVIPDFM)
2881 if (purpose == DVIPS || purpose == DVIPDFM)
2884 case PAPER_USEXECUTIVE:
2885 // dvipdfm does not know this
2886 if (purpose == DVIPDFM)
2891 case PAPER_USLETTER:
2893 if (purpose == XDVI)
2900 string const BufferParams::dvips_options() const
2904 // If the class loads the geometry package, we do not know which
2905 // paper size is used, since we do not set it (bug 7013).
2906 // Therefore we must not specify any argument here.
2907 // dvips gets the correct paper size via DVI specials in this case
2908 // (if the class uses the geometry package correctly).
2909 if (documentClass().provides("geometry"))
2913 && papersize == PAPER_CUSTOM
2914 && !lyxrc.print_paper_dimension_flag.empty()
2915 && !paperwidth.empty()
2916 && !paperheight.empty()) {
2917 // using a custom papersize
2918 result = lyxrc.print_paper_dimension_flag;
2919 result += ' ' + paperwidth;
2920 result += ',' + paperheight;
2922 string const paper_option = paperSizeName(DVIPS);
2923 if (!paper_option.empty() && (paper_option != "letter" ||
2924 orientation != ORIENTATION_LANDSCAPE)) {
2925 // dvips won't accept -t letter -t landscape.
2926 // In all other cases, include the paper size
2928 result = lyxrc.print_paper_flag;
2929 result += ' ' + paper_option;
2932 if (orientation == ORIENTATION_LANDSCAPE &&
2933 papersize != PAPER_CUSTOM)
2934 result += ' ' + lyxrc.print_landscape_flag;
2939 string const BufferParams::font_encoding() const
2941 return font_encodings().empty() ? "default" : font_encodings().back();
2945 vector<string> const BufferParams::font_encodings() const
2947 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2949 vector<string> fontencs;
2951 // "default" means "no explicit font encoding"
2952 if (doc_fontenc != "default") {
2953 fontencs = getVectorFromString(doc_fontenc);
2954 if (!language->fontenc().empty()
2955 && ascii_lowercase(language->fontenc()) != "none") {
2956 vector<string> fencs = getVectorFromString(language->fontenc());
2957 vector<string>::const_iterator fit = fencs.begin();
2958 for (; fit != fencs.end(); ++fit) {
2959 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
2960 fontencs.push_back(*fit);
2969 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2971 // suppress the babel call if there is no BabelName defined
2972 // for the document language in the lib/languages file and if no
2973 // other languages are used (lang_opts is then empty)
2974 if (lang_opts.empty())
2976 // either a specific language (AsBabelOptions setting in
2977 // lib/languages) or the prefs require the languages to
2978 // be submitted to babel itself (not the class).
2980 return "\\usepackage[" + lang_opts + "]{babel}";
2981 return "\\usepackage{babel}";
2985 docstring BufferParams::getGraphicsDriver(string const & package) const
2989 if (package == "geometry") {
2990 if (graphics_driver == "dvips"
2991 || graphics_driver == "dvipdfm"
2992 || graphics_driver == "pdftex"
2993 || graphics_driver == "vtex")
2994 result = from_ascii(graphics_driver);
2995 else if (graphics_driver == "dvipdfmx")
2996 result = from_ascii("dvipdfm");
3003 void BufferParams::writeEncodingPreamble(otexstream & os,
3004 LaTeXFeatures & features) const
3006 // XeTeX/LuaTeX: (see also #9740)
3007 // With Unicode fonts we use utf8-plain without encoding package.
3008 // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails.
3009 // XeTeX must use ASCII encoding (see Buffer.cpp),
3010 // for LuaTeX, we load "luainputenc" (see below).
3011 if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
3014 if (inputenc == "auto") {
3015 string const doc_encoding =
3016 language->encoding()->latexName();
3017 Encoding::Package const package =
3018 language->encoding()->package();
3020 // Create list of inputenc options:
3021 set<string> encodings;
3022 // luainputenc fails with more than one encoding
3023 if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts
3024 // list all input encodings used in the document
3025 encodings = features.getEncodingSet(doc_encoding);
3027 // If the "japanese" package (i.e. pLaTeX) is used,
3028 // inputenc must be omitted.
3029 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
3030 if ((!encodings.empty() || package == Encoding::inputenc)
3031 && !features.isRequired("japanese")
3032 && !features.isProvided("inputenc")) {
3033 os << "\\usepackage[";
3034 set<string>::const_iterator it = encodings.begin();
3035 set<string>::const_iterator const end = encodings.end();
3037 os << from_ascii(*it);
3040 for (; it != end; ++it)
3041 os << ',' << from_ascii(*it);
3042 if (package == Encoding::inputenc) {
3043 if (!encodings.empty())
3045 os << from_ascii(doc_encoding);
3047 if (features.runparams().flavor == OutputParams::LUATEX
3048 || features.runparams().flavor == OutputParams::DVILUATEX)
3049 os << "]{luainputenc}\n";
3051 os << "]{inputenc}\n";
3053 if (package == Encoding::CJK || features.mustProvide("CJK")) {
3054 if (language->encoding()->name() == "utf8-cjk"
3055 && LaTeXFeatures::isAvailable("CJKutf8"))
3056 os << "\\usepackage{CJKutf8}\n";
3058 os << "\\usepackage{CJK}\n";
3060 } else if (inputenc != "default") {
3061 switch (encoding().package()) {
3062 case Encoding::none:
3063 case Encoding::japanese:
3065 case Encoding::inputenc:
3066 // do not load inputenc if japanese is used
3067 // or if the class provides inputenc
3068 if (features.isRequired("japanese")
3069 || features.isProvided("inputenc"))
3071 os << "\\usepackage[" << from_ascii(encoding().latexName());
3072 if (features.runparams().flavor == OutputParams::LUATEX
3073 || features.runparams().flavor == OutputParams::DVILUATEX)
3074 os << "]{luainputenc}\n";
3076 os << "]{inputenc}\n";
3079 if (encoding().name() == "utf8-cjk"
3080 && LaTeXFeatures::isAvailable("CJKutf8"))
3081 os << "\\usepackage{CJKutf8}\n";
3083 os << "\\usepackage{CJK}\n";
3086 // Load the CJK package if needed by a secondary language.
3087 // If the main encoding is some variant of UTF8, use CJKutf8.
3088 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
3089 if (encoding().iconvName() == "UTF-8"
3090 && LaTeXFeatures::isAvailable("CJKutf8"))
3091 os << "\\usepackage{CJKutf8}\n";
3093 os << "\\usepackage{CJK}\n";
3099 string const BufferParams::parseFontName(string const & name) const
3101 string mangled = name;
3102 size_t const idx = mangled.find('[');
3103 if (idx == string::npos || idx == 0)
3106 return mangled.substr(0, idx - 1);
3110 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3112 if (fontsRoman() == "default" && fontsSans() == "default"
3113 && fontsTypewriter() == "default"
3114 && (fontsMath() == "default" || fontsMath() == "auto"))
3120 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3121 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3122 * Mapping=tex-text option assures TeX ligatures (such as "--")
3123 * are resolved. Note that tt does not use these ligatures.
3125 * -- add more GUI options?
3126 * -- add more fonts (fonts for other scripts)
3127 * -- if there's a way to find out if a font really supports
3128 * OldStyle, enable/disable the widget accordingly.
3130 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3131 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3132 // However, until v.2 (2010/07/11) fontspec only knew
3133 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3134 // was introduced for both XeTeX and LuaTeX (LuaTeX
3135 // didn't understand "Mapping=tex-text", while XeTeX
3136 // understood both. With most recent versions, both
3137 // variants are understood by both engines. However,
3138 // we want to provide support for at least TeXLive 2009
3139 // (for XeTeX; LuaTeX is only supported as of v.2)
3140 string const texmapping =
3141 (features.runparams().flavor == OutputParams::XETEX) ?
3142 "Mapping=tex-text" : "Ligatures=TeX";
3143 if (fontsRoman() != "default") {
3144 os << "\\setmainfont[" << texmapping;
3145 if (fonts_old_figures)
3146 os << ",Numbers=OldStyle";
3147 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3149 if (fontsSans() != "default") {
3150 string const sans = parseFontName(fontsSans());
3151 if (fontsSansScale() != 100)
3152 os << "\\setsansfont[Scale="
3153 << float(fontsSansScale()) / 100
3154 << "," << texmapping << "]{"
3157 os << "\\setsansfont[" << texmapping << "]{"
3160 if (fontsTypewriter() != "default") {
3161 string const mono = parseFontName(fontsTypewriter());
3162 if (fontsTypewriterScale() != 100)
3163 os << "\\setmonofont[Scale="
3164 << float(fontsTypewriterScale()) / 100
3168 os << "\\setmonofont{"
3175 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
3176 bool const dryrun = features.runparams().dryrun;
3177 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3178 bool const nomath = (fontsMath() == "default");
3181 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3182 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3186 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3187 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3188 nomath, fontsSansScale());
3190 // MONOSPACED/TYPEWRITER
3191 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3192 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3193 nomath, fontsTypewriterScale());
3196 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3197 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3204 Encoding const & BufferParams::encoding() const
3206 // Main encoding for LaTeX output.
3208 // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740).
3209 // As the "flavor" is only known once export started, this
3210 // cannot be handled here. Instead, runparams.encoding is set
3211 // to ASCII in Buffer::makeLaTeXFile (for export)
3212 // and Buffer::writeLaTeXSource (for preview).
3214 return *(encodings.fromLyXName("utf8-plain"));
3215 if (inputenc == "auto" || inputenc == "default")
3216 return *language->encoding();
3217 Encoding const * const enc = encodings.fromLyXName(inputenc);
3220 LYXERR0("Unknown inputenc value `" << inputenc
3221 << "'. Using `auto' instead.");
3222 return *language->encoding();
3226 bool BufferParams::addCiteEngine(string const & engine)
3228 LayoutModuleList::const_iterator it = cite_engine_.begin();
3229 LayoutModuleList::const_iterator en = cite_engine_.end();
3230 for (; it != en; ++it)
3233 cite_engine_.push_back(engine);
3238 bool BufferParams::addCiteEngine(vector<string> const & engine)
3240 vector<string>::const_iterator it = engine.begin();
3241 vector<string>::const_iterator en = engine.end();
3243 for (; it != en; ++it)
3244 if (!addCiteEngine(*it))
3250 string const & BufferParams::defaultBiblioStyle() const
3252 return documentClass().defaultBiblioStyle();
3256 bool const & BufferParams::fullAuthorList() const
3258 return documentClass().fullAuthorList();
3262 void BufferParams::setCiteEngine(string const & engine)
3265 addCiteEngine(engine);
3269 void BufferParams::setCiteEngine(vector<string> const & engine)
3272 addCiteEngine(engine);
3276 vector<string> BufferParams::citeCommands() const
3278 static CitationStyle const default_style;
3279 vector<string> commands =
3280 documentClass().citeCommands(citeEngineType());
3281 if (commands.empty())
3282 commands.push_back(default_style.cmd);
3287 vector<CitationStyle> BufferParams::citeStyles() const
3289 static CitationStyle const default_style;
3290 vector<CitationStyle> styles =
3291 documentClass().citeStyles(citeEngineType());
3293 styles.push_back(default_style);