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();
310 class BufferParams::Impl
315 AuthorList authorlist;
316 BranchList branchlist;
317 Bullet temp_bullets[4];
318 Bullet user_defined_bullets[4];
319 IndicesList indiceslist;
321 /** This is the amount of space used for paragraph_separation "skip",
322 * and for detached paragraphs in "indented" documents.
326 PDFOptions pdfoptions;
327 LayoutFileIndex baseClass_;
331 BufferParams::Impl::Impl()
332 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
334 // set initial author
336 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
341 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
344 return new BufferParams::Impl(*ptr);
348 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
354 BufferParams::BufferParams()
357 setBaseClass(defaultBaseclass());
358 cite_engine_.push_back("basic");
359 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
361 paragraph_separation = ParagraphIndentSeparation;
362 quotes_language = InsetQuotes::EnglishQuotes;
363 fontsize = "default";
366 papersize = PAPER_DEFAULT;
367 orientation = ORIENTATION_PORTRAIT;
368 use_geometry = false;
369 biblio_style = "plain";
370 use_bibtopic = false;
372 track_changes = false;
373 output_changes = false;
374 use_default_options = true;
375 maintain_unincluded_children = false;
378 language = default_language;
380 fonts_roman[0] = "default";
381 fonts_roman[1] = "default";
382 fonts_sans[0] = "default";
383 fonts_sans[1] = "default";
384 fonts_typewriter[0] = "default";
385 fonts_typewriter[1] = "default";
386 fonts_math[0] = "auto";
387 fonts_math[1] = "auto";
388 fonts_default_family = "default";
389 useNonTeXFonts = false;
390 fonts_expert_sc = false;
391 fonts_old_figures = false;
392 fonts_sans_scale[0] = 100;
393 fonts_sans_scale[1] = 100;
394 fonts_typewriter_scale[0] = 100;
395 fonts_typewriter_scale[1] = 100;
397 lang_package = "default";
398 graphics_driver = "default";
399 default_output_format = "default";
400 bibtex_command = "default";
401 index_command = "default";
404 listings_params = string();
405 pagestyle = "default";
406 suppress_date = false;
407 justification = true;
408 // no color is the default (white)
409 backgroundcolor = lyx::rgbFromHexName("#ffffff");
410 isbackgroundcolor = false;
411 // no color is the default (black)
412 fontcolor = lyx::rgbFromHexName("#000000");
414 // light gray is the default font color for greyed-out notes
415 notefontcolor = lyx::rgbFromHexName("#cccccc");
416 boxbgcolor = lyx::rgbFromHexName("#ff0000");
417 compressed = lyxrc.save_compressed;
418 for (int iter = 0; iter < 4; ++iter) {
419 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
420 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
423 indiceslist().addDefault(B_("Index"));
424 html_be_strict = false;
425 html_math_output = MathML;
426 html_math_img_scale = 1.0;
427 html_css_as_file = false;
428 display_pixel_ratio = 1.0;
433 // map current author
434 author_map_[pimpl_->authorlist.get(0).bufferId()] = 0;
438 docstring BufferParams::B_(string const & l10n) const
440 LASSERT(language, return from_utf8(l10n));
441 return getMessages(language->code()).get(l10n);
445 BufferParams::Package BufferParams::use_package(std::string const & p) const
447 PackageMap::const_iterator it = use_packages.find(p);
448 if (it == use_packages.end())
454 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
460 map<string, string> const & BufferParams::auto_packages()
462 static map<string, string> packages;
463 if (packages.empty()) {
464 // We could have a race condition here that two threads
465 // discover an empty map at the same time and want to fill
466 // it, but that is no problem, since the same contents is
467 // filled in twice then. Having the locker inside the
468 // packages.empty() condition has the advantage that we
469 // don't need the mutex overhead for simple reading.
471 Mutex::Locker locker(&mutex);
472 // adding a package here implies a file format change!
473 packages["amsmath"] =
474 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
475 packages["amssymb"] =
476 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
478 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
480 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
481 packages["mathdots"] =
482 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
483 packages["mathtools"] =
484 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
486 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
487 packages["stackrel"] =
488 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
489 packages["stmaryrd"] =
490 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");
491 packages["undertilde"] =
492 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
498 AuthorList & BufferParams::authors()
500 return pimpl_->authorlist;
504 AuthorList const & BufferParams::authors() const
506 return pimpl_->authorlist;
510 void BufferParams::addAuthor(Author a)
512 author_map_[a.bufferId()] = pimpl_->authorlist.record(a);
516 BranchList & BufferParams::branchlist()
518 return pimpl_->branchlist;
522 BranchList const & BufferParams::branchlist() const
524 return pimpl_->branchlist;
528 IndicesList & BufferParams::indiceslist()
530 return pimpl_->indiceslist;
534 IndicesList const & BufferParams::indiceslist() const
536 return pimpl_->indiceslist;
540 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
542 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
543 return pimpl_->temp_bullets[index];
547 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
549 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
550 return pimpl_->temp_bullets[index];
554 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
556 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
557 return pimpl_->user_defined_bullets[index];
561 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
563 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
564 return pimpl_->user_defined_bullets[index];
568 Spacing & BufferParams::spacing()
570 return pimpl_->spacing;
574 Spacing const & BufferParams::spacing() const
576 return pimpl_->spacing;
580 PDFOptions & BufferParams::pdfoptions()
582 return pimpl_->pdfoptions;
586 PDFOptions const & BufferParams::pdfoptions() const
588 return pimpl_->pdfoptions;
592 HSpace const & BufferParams::getIndentation() const
594 return pimpl_->indentation;
598 void BufferParams::setIndentation(HSpace const & indent)
600 pimpl_->indentation = indent;
604 VSpace const & BufferParams::getDefSkip() const
606 return pimpl_->defskip;
610 void BufferParams::setDefSkip(VSpace const & vs)
612 // DEFSKIP will cause an infinite loop
613 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
614 pimpl_->defskip = vs;
618 string BufferParams::readToken(Lexer & lex, string const & token,
619 FileName const & filepath)
623 if (token == "\\textclass") {
625 string const classname = lex.getString();
626 // if there exists a local layout file, ignore the system one
627 // NOTE: in this case, the textclass (.cls file) is assumed to
630 LayoutFileList & bcl = LayoutFileList::get();
631 if (!filepath.empty()) {
632 // If classname is an absolute path, the document is
633 // using a local layout file which could not be accessed
634 // by a relative path. In this case the path is correct
635 // even if the document was moved to a different
636 // location. However, we will have a problem if the
637 // document was generated on a different platform.
638 bool isabsolute = FileName::isAbsolute(classname);
639 string const classpath = onlyPath(classname);
640 string const path = isabsolute ? classpath
641 : FileName(addPath(filepath.absFileName(),
642 classpath)).realPath();
643 string const oldpath = isabsolute ? string()
644 : FileName(addPath(origin, classpath)).realPath();
645 tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
647 // that returns non-empty if a "local" layout file is found.
649 result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
650 from_utf8(filepath.absFileName())));
653 setBaseClass(onlyFileName(tcp));
655 setBaseClass(onlyFileName(classname));
656 // We assume that a tex class exists for local or unknown
657 // layouts so this warning, will only be given for system layouts.
658 if (!baseClass()->isTeXClassAvailable()) {
659 docstring const desc =
660 translateIfPossible(from_utf8(baseClass()->description()));
661 docstring const prereqs =
662 from_utf8(baseClass()->prerequisites());
663 docstring const msg =
664 bformat(_("The selected document class\n"
666 "requires external files that are not available.\n"
667 "The document class can still be used, but the\n"
668 "document cannot be compiled until the following\n"
669 "prerequisites are installed:\n"
671 "See section 3.1.2.2 (Class Availability) of the\n"
672 "User's Guide for more information."), desc, prereqs);
673 frontend::Alert::warning(_("Document class not available"),
676 } else if (token == "\\origin") {
678 origin = lex.getString();
679 string const sysdirprefix = "/systemlyxdir/";
680 if (prefixIs(origin, sysdirprefix)) {
681 origin.replace(0, sysdirprefix.length() - 1,
682 package().system_support().absFileName());
684 } else if (token == "\\begin_preamble") {
686 } else if (token == "\\begin_local_layout") {
687 readLocalLayout(lex, false);
688 } else if (token == "\\begin_forced_local_layout") {
689 readLocalLayout(lex, true);
690 } else if (token == "\\begin_modules") {
692 } else if (token == "\\begin_removed_modules") {
693 readRemovedModules(lex);
694 } else if (token == "\\begin_includeonly") {
695 readIncludeonly(lex);
696 } else if (token == "\\maintain_unincluded_children") {
697 lex >> maintain_unincluded_children;
698 } else if (token == "\\options") {
700 options = lex.getString();
701 } else if (token == "\\use_default_options") {
702 lex >> use_default_options;
703 } else if (token == "\\master") {
705 master = lex.getString();
706 if (!filepath.empty() && FileName::isAbsolute(origin)) {
707 bool const isabs = FileName::isAbsolute(master);
708 FileName const abspath(isabs ? master : origin + master);
709 bool const moved = filepath != FileName(origin);
710 if (moved && abspath.exists()) {
711 docstring const path = isabs
713 : from_utf8(abspath.realPath());
714 docstring const refpath =
715 from_utf8(filepath.absFileName());
716 master = to_utf8(makeRelPath(path, refpath));
719 } else if (token == "\\suppress_date") {
720 lex >> suppress_date;
721 } else if (token == "\\justification") {
722 lex >> justification;
723 } else if (token == "\\language") {
725 } else if (token == "\\language_package") {
727 lang_package = lex.getString();
728 } else if (token == "\\inputencoding") {
730 } else if (token == "\\graphics") {
731 readGraphicsDriver(lex);
732 } else if (token == "\\default_output_format") {
733 lex >> default_output_format;
734 } else if (token == "\\bibtex_command") {
736 bibtex_command = lex.getString();
737 } else if (token == "\\index_command") {
739 index_command = lex.getString();
740 } else if (token == "\\fontencoding") {
742 fontenc = lex.getString();
743 } else if (token == "\\font_roman") {
744 lex >> fonts_roman[0];
745 lex >> fonts_roman[1];
746 } else if (token == "\\font_sans") {
747 lex >> fonts_sans[0];
748 lex >> fonts_sans[1];
749 } else if (token == "\\font_typewriter") {
750 lex >> fonts_typewriter[0];
751 lex >> fonts_typewriter[1];
752 } else if (token == "\\font_math") {
753 lex >> fonts_math[0];
754 lex >> fonts_math[1];
755 } else if (token == "\\font_default_family") {
756 lex >> fonts_default_family;
757 } else if (token == "\\use_non_tex_fonts") {
758 lex >> useNonTeXFonts;
759 } else if (token == "\\font_sc") {
760 lex >> fonts_expert_sc;
761 } else if (token == "\\font_osf") {
762 lex >> fonts_old_figures;
763 } else if (token == "\\font_sf_scale") {
764 lex >> fonts_sans_scale[0];
765 lex >> fonts_sans_scale[1];
766 } else if (token == "\\font_tt_scale") {
767 lex >> fonts_typewriter_scale[0];
768 lex >> fonts_typewriter_scale[1];
769 } else if (token == "\\font_cjk") {
771 } else if (token == "\\paragraph_separation") {
774 paragraph_separation = parseptranslator().find(parsep);
775 } else if (token == "\\paragraph_indentation") {
777 string indentation = lex.getString();
778 pimpl_->indentation = HSpace(indentation);
779 } else if (token == "\\defskip") {
781 string const defskip = lex.getString();
782 pimpl_->defskip = VSpace(defskip);
783 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
785 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
786 } else if (token == "\\quotes_language") {
789 quotes_language = quoteslangtranslator().find(quotes_lang);
790 } else if (token == "\\papersize") {
793 papersize = papersizetranslator().find(ppsize);
794 } else if (token == "\\use_geometry") {
796 } else if (token == "\\use_package") {
801 use_package(package, packagetranslator().find(use));
802 } else if (token == "\\cite_engine") {
804 vector<string> engine = getVectorFromString(lex.getString());
805 setCiteEngine(engine);
806 } else if (token == "\\cite_engine_type") {
809 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
810 } else if (token == "\\biblio_style") {
812 biblio_style = lex.getString();
813 } else if (token == "\\use_bibtopic") {
815 } else if (token == "\\use_indices") {
817 } else if (token == "\\tracking_changes") {
818 lex >> track_changes;
819 } else if (token == "\\output_changes") {
820 lex >> output_changes;
821 } else if (token == "\\branch") {
823 docstring branch = lex.getDocString();
824 branchlist().add(branch);
827 string const tok = lex.getString();
828 if (tok == "\\end_branch")
830 Branch * branch_ptr = branchlist().find(branch);
831 if (tok == "\\selected") {
834 branch_ptr->setSelected(lex.getInteger());
836 if (tok == "\\filename_suffix") {
839 branch_ptr->setFileNameSuffix(lex.getInteger());
841 if (tok == "\\color") {
843 string color = lex.getString();
845 branch_ptr->setColor(color);
846 // Update also the Color table:
848 color = lcolor.getX11Name(Color_background);
850 lcolor.setColor(to_utf8(branch), color);
853 } else if (token == "\\index") {
855 docstring index = lex.getDocString();
857 indiceslist().add(index);
860 string const tok = lex.getString();
861 if (tok == "\\end_index")
863 Index * index_ptr = indiceslist().find(index);
864 if (tok == "\\shortcut") {
866 shortcut = lex.getDocString();
868 index_ptr->setShortcut(shortcut);
870 if (tok == "\\color") {
872 string color = lex.getString();
874 index_ptr->setColor(color);
875 // Update also the Color table:
877 color = lcolor.getX11Name(Color_background);
879 if (!shortcut.empty())
880 lcolor.setColor(to_utf8(shortcut), color);
883 } else if (token == "\\author") {
885 istringstream ss(lex.getString());
889 } else if (token == "\\paperorientation") {
892 orientation = paperorientationtranslator().find(orient);
893 } else if (token == "\\backgroundcolor") {
895 backgroundcolor = lyx::rgbFromHexName(lex.getString());
896 isbackgroundcolor = true;
897 } else if (token == "\\fontcolor") {
899 fontcolor = lyx::rgbFromHexName(lex.getString());
901 } else if (token == "\\notefontcolor") {
903 string color = lex.getString();
904 notefontcolor = lyx::rgbFromHexName(color);
905 lcolor.setColor("notefontcolor", color);
906 } else if (token == "\\boxbgcolor") {
908 string color = lex.getString();
909 boxbgcolor = lyx::rgbFromHexName(color);
910 lcolor.setColor("boxbgcolor", color);
911 } else if (token == "\\paperwidth") {
913 } else if (token == "\\paperheight") {
915 } else if (token == "\\leftmargin") {
917 } else if (token == "\\topmargin") {
919 } else if (token == "\\rightmargin") {
921 } else if (token == "\\bottommargin") {
923 } else if (token == "\\headheight") {
925 } else if (token == "\\headsep") {
927 } else if (token == "\\footskip") {
929 } else if (token == "\\columnsep") {
931 } else if (token == "\\paperfontsize") {
933 } else if (token == "\\papercolumns") {
935 } else if (token == "\\listings_params") {
938 listings_params = InsetListingsParams(par).params();
939 } else if (token == "\\papersides") {
942 sides = sidestranslator().find(psides);
943 } else if (token == "\\paperpagestyle") {
945 } else if (token == "\\bullet") {
947 } else if (token == "\\bulletLaTeX") {
948 readBulletsLaTeX(lex);
949 } else if (token == "\\secnumdepth") {
951 } else if (token == "\\tocdepth") {
953 } else if (token == "\\spacing") {
957 if (nspacing == "other") {
960 spacing().set(spacetranslator().find(nspacing), tmp_val);
961 } else if (token == "\\float_placement") {
962 lex >> float_placement;
964 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
965 string toktmp = pdfoptions().readToken(lex, token);
966 if (!toktmp.empty()) {
967 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
971 } else if (token == "\\html_math_output") {
974 html_math_output = static_cast<MathOutput>(temp);
975 } else if (token == "\\html_be_strict") {
976 lex >> html_be_strict;
977 } else if (token == "\\html_css_as_file") {
978 lex >> html_css_as_file;
979 } else if (token == "\\html_math_img_scale") {
980 lex >> html_math_img_scale;
981 } else if (token == "\\html_latex_start") {
983 html_latex_start = lex.getString();
984 } else if (token == "\\html_latex_end") {
986 html_latex_end = lex.getString();
987 } else if (token == "\\output_sync") {
989 } else if (token == "\\output_sync_macro") {
990 lex >> output_sync_macro;
991 } else if (token == "\\use_refstyle") {
994 lyxerr << "BufferParams::readToken(): Unknown token: " <<
1004 // Quote argument if it contains spaces
1005 string quoteIfNeeded(string const & str) {
1006 if (contains(str, ' '))
1007 return "\"" + str + "\"";
1013 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
1015 // The top of the file is written by the buffer.
1016 // Prints out the buffer info into the .lyx file given by file
1018 // the document directory
1019 // use realPath() instead of absFileName() for comparing
1020 // so we can catch also eventually used symbolic parts of the path.
1021 string filepath = buf->fileName().onlyPath().realPath();
1022 string const sysdir = package().system_support().realPath();
1023 if (prefixIs(filepath, sysdir)) {
1024 filepath.replace(0, sysdir.length(), "/systemlyxdir/");
1025 // Remove eventually added superfluous "/"
1026 filepath = subst(filepath, "//", "/");
1028 else if (!lyxrc.save_origin)
1029 filepath = "unavailable";
1030 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1033 os << "\\textclass "
1034 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1035 baseClass()->name()), "layout"))
1038 // then the preamble
1039 if (!preamble.empty()) {
1040 // remove '\n' from the end of preamble
1041 string const tmppreamble = rtrim(preamble, "\n");
1042 os << "\\begin_preamble\n"
1044 << "\n\\end_preamble\n";
1048 if (!options.empty()) {
1049 os << "\\options " << options << '\n';
1052 // use the class options defined in the layout?
1053 os << "\\use_default_options "
1054 << convert<string>(use_default_options) << "\n";
1056 // the master document
1057 if (!master.empty()) {
1058 os << "\\master " << master << '\n';
1062 if (!removed_modules_.empty()) {
1063 os << "\\begin_removed_modules" << '\n';
1064 list<string>::const_iterator it = removed_modules_.begin();
1065 list<string>::const_iterator en = removed_modules_.end();
1066 for (; it != en; ++it)
1068 os << "\\end_removed_modules" << '\n';
1072 if (!layout_modules_.empty()) {
1073 os << "\\begin_modules" << '\n';
1074 LayoutModuleList::const_iterator it = layout_modules_.begin();
1075 LayoutModuleList::const_iterator en = layout_modules_.end();
1076 for (; it != en; ++it)
1078 os << "\\end_modules" << '\n';
1082 if (!included_children_.empty()) {
1083 os << "\\begin_includeonly" << '\n';
1084 list<string>::const_iterator it = included_children_.begin();
1085 list<string>::const_iterator en = included_children_.end();
1086 for (; it != en; ++it)
1088 os << "\\end_includeonly" << '\n';
1090 os << "\\maintain_unincluded_children "
1091 << convert<string>(maintain_unincluded_children) << '\n';
1093 // local layout information
1094 string const local_layout = getLocalLayout(false);
1095 if (!local_layout.empty()) {
1096 // remove '\n' from the end
1097 string const tmplocal = rtrim(local_layout, "\n");
1098 os << "\\begin_local_layout\n"
1100 << "\n\\end_local_layout\n";
1102 string const forced_local_layout = getLocalLayout(true);
1103 if (!forced_local_layout.empty()) {
1104 // remove '\n' from the end
1105 string const tmplocal = rtrim(forced_local_layout, "\n");
1106 os << "\\begin_forced_local_layout\n"
1108 << "\n\\end_forced_local_layout\n";
1111 // then the text parameters
1112 if (language != ignore_language)
1113 os << "\\language " << language->lang() << '\n';
1114 os << "\\language_package " << lang_package
1115 << "\n\\inputencoding " << inputenc
1116 << "\n\\fontencoding " << fontenc
1117 << "\n\\font_roman \"" << fonts_roman[0]
1118 << "\" \"" << fonts_roman[1] << '"'
1119 << "\n\\font_sans \"" << fonts_sans[0]
1120 << "\" \"" << fonts_sans[1] << '"'
1121 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1122 << "\" \"" << fonts_typewriter[1] << '"'
1123 << "\n\\font_math \"" << fonts_math[0]
1124 << "\" \"" << fonts_math[1] << '"'
1125 << "\n\\font_default_family " << fonts_default_family
1126 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1127 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1128 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1129 << "\n\\font_sf_scale " << fonts_sans_scale[0]
1130 << ' ' << fonts_sans_scale[1]
1131 << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1132 << ' ' << fonts_typewriter_scale[1]
1134 if (!fonts_cjk.empty()) {
1135 os << "\\font_cjk " << fonts_cjk << '\n';
1137 os << "\\graphics " << graphics_driver << '\n';
1138 os << "\\default_output_format " << default_output_format << '\n';
1139 os << "\\output_sync " << output_sync << '\n';
1140 if (!output_sync_macro.empty())
1141 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1142 os << "\\bibtex_command " << bibtex_command << '\n';
1143 os << "\\index_command " << index_command << '\n';
1145 if (!float_placement.empty()) {
1146 os << "\\float_placement " << float_placement << '\n';
1148 os << "\\paperfontsize " << fontsize << '\n';
1150 spacing().writeFile(os);
1151 pdfoptions().writeFile(os);
1153 os << "\\papersize " << string_papersize[papersize]
1154 << "\n\\use_geometry " << convert<string>(use_geometry);
1155 map<string, string> const & packages = auto_packages();
1156 for (map<string, string>::const_iterator it = packages.begin();
1157 it != packages.end(); ++it)
1158 os << "\n\\use_package " << it->first << ' '
1159 << use_package(it->first);
1161 os << "\n\\cite_engine ";
1163 if (!cite_engine_.empty()) {
1164 LayoutModuleList::const_iterator be = cite_engine_.begin();
1165 LayoutModuleList::const_iterator en = cite_engine_.end();
1166 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1175 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1176 << "\n\\biblio_style " << biblio_style
1177 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1178 << "\n\\use_indices " << convert<string>(use_indices)
1179 << "\n\\paperorientation " << string_orientation[orientation]
1180 << "\n\\suppress_date " << convert<string>(suppress_date)
1181 << "\n\\justification " << convert<string>(justification)
1182 << "\n\\use_refstyle " << use_refstyle
1184 if (isbackgroundcolor == true)
1185 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1186 if (isfontcolor == true)
1187 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1188 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1189 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1190 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1191 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1193 BranchList::const_iterator it = branchlist().begin();
1194 BranchList::const_iterator end = branchlist().end();
1195 for (; it != end; ++it) {
1196 os << "\\branch " << to_utf8(it->branch())
1197 << "\n\\selected " << it->isSelected()
1198 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1199 << "\n\\color " << lyx::X11hexname(it->color())
1204 IndicesList::const_iterator iit = indiceslist().begin();
1205 IndicesList::const_iterator iend = indiceslist().end();
1206 for (; iit != iend; ++iit) {
1207 os << "\\index " << to_utf8(iit->index())
1208 << "\n\\shortcut " << to_utf8(iit->shortcut())
1209 << "\n\\color " << lyx::X11hexname(iit->color())
1214 if (!paperwidth.empty())
1215 os << "\\paperwidth "
1216 << VSpace(paperwidth).asLyXCommand() << '\n';
1217 if (!paperheight.empty())
1218 os << "\\paperheight "
1219 << VSpace(paperheight).asLyXCommand() << '\n';
1220 if (!leftmargin.empty())
1221 os << "\\leftmargin "
1222 << VSpace(leftmargin).asLyXCommand() << '\n';
1223 if (!topmargin.empty())
1224 os << "\\topmargin "
1225 << VSpace(topmargin).asLyXCommand() << '\n';
1226 if (!rightmargin.empty())
1227 os << "\\rightmargin "
1228 << VSpace(rightmargin).asLyXCommand() << '\n';
1229 if (!bottommargin.empty())
1230 os << "\\bottommargin "
1231 << VSpace(bottommargin).asLyXCommand() << '\n';
1232 if (!headheight.empty())
1233 os << "\\headheight "
1234 << VSpace(headheight).asLyXCommand() << '\n';
1235 if (!headsep.empty())
1237 << VSpace(headsep).asLyXCommand() << '\n';
1238 if (!footskip.empty())
1240 << VSpace(footskip).asLyXCommand() << '\n';
1241 if (!columnsep.empty())
1242 os << "\\columnsep "
1243 << VSpace(columnsep).asLyXCommand() << '\n';
1244 os << "\\secnumdepth " << secnumdepth
1245 << "\n\\tocdepth " << tocdepth
1246 << "\n\\paragraph_separation "
1247 << string_paragraph_separation[paragraph_separation];
1248 if (!paragraph_separation)
1249 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1251 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1252 os << "\n\\quotes_language "
1253 << string_quotes_language[quotes_language]
1254 << "\n\\papercolumns " << columns
1255 << "\n\\papersides " << sides
1256 << "\n\\paperpagestyle " << pagestyle << '\n';
1257 if (!listings_params.empty())
1258 os << "\\listings_params \"" <<
1259 InsetListingsParams(listings_params).encodedString() << "\"\n";
1260 for (int i = 0; i < 4; ++i) {
1261 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1262 if (user_defined_bullet(i).getFont() != -1) {
1263 os << "\\bullet " << i << " "
1264 << user_defined_bullet(i).getFont() << " "
1265 << user_defined_bullet(i).getCharacter() << " "
1266 << user_defined_bullet(i).getSize() << "\n";
1270 os << "\\bulletLaTeX " << i << " \""
1271 << lyx::to_ascii(user_defined_bullet(i).getText())
1277 os << "\\tracking_changes " << convert<string>(track_changes) << '\n'
1278 << "\\output_changes " << convert<string>(output_changes) << '\n'
1279 << "\\html_math_output " << html_math_output << '\n'
1280 << "\\html_css_as_file " << html_css_as_file << '\n'
1281 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1283 if (html_math_img_scale != 1.0)
1284 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1285 if (!html_latex_start.empty())
1286 os << "\\html_latex_start " << html_latex_start << '\n';
1287 if (!html_latex_end.empty())
1288 os << "\\html_latex_end " << html_latex_end << '\n';
1290 os << pimpl_->authorlist;
1294 void BufferParams::validate(LaTeXFeatures & features) const
1296 features.require(documentClass().requires());
1298 if (columns > 1 && language->rightToLeft())
1299 features.require("rtloutputdblcol");
1301 if (output_changes) {
1302 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1303 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1304 LaTeXFeatures::isAvailable("xcolor");
1306 switch (features.runparams().flavor) {
1307 case OutputParams::LATEX:
1308 case OutputParams::DVILUATEX:
1310 features.require("ct-dvipost");
1311 features.require("dvipost");
1312 } else if (xcolorulem) {
1313 features.require("ct-xcolor-ulem");
1314 features.require("ulem");
1315 features.require("xcolor");
1317 features.require("ct-none");
1320 case OutputParams::LUATEX:
1321 case OutputParams::PDFLATEX:
1322 case OutputParams::XETEX:
1324 features.require("ct-xcolor-ulem");
1325 features.require("ulem");
1326 features.require("xcolor");
1327 // improves color handling in PDF output
1328 features.require("pdfcolmk");
1330 features.require("ct-none");
1338 // Floats with 'Here definitely' as default setting.
1339 if (float_placement.find('H') != string::npos)
1340 features.require("float");
1342 for (PackageMap::const_iterator it = use_packages.begin();
1343 it != use_packages.end(); ++it) {
1344 if (it->first == "amsmath") {
1345 // AMS Style is at document level
1346 if (it->second == package_on ||
1347 features.isProvided("amsmath"))
1348 features.require(it->first);
1349 } else if (it->second == package_on)
1350 features.require(it->first);
1353 // Document-level line spacing
1354 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1355 features.require("setspace");
1357 // the bullet shapes are buffer level not paragraph level
1358 // so they are tested here
1359 for (int i = 0; i < 4; ++i) {
1360 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1362 int const font = user_defined_bullet(i).getFont();
1364 int const c = user_defined_bullet(i).getCharacter();
1370 features.require("latexsym");
1372 } else if (font == 1) {
1373 features.require("amssymb");
1374 } else if (font >= 2 && font <= 5) {
1375 features.require("pifont");
1379 if (pdfoptions().use_hyperref) {
1380 features.require("hyperref");
1381 // due to interferences with babel and hyperref, the color package has to
1382 // be loaded after hyperref when hyperref is used with the colorlinks
1383 // option, see http://www.lyx.org/trac/ticket/5291
1384 if (pdfoptions().colorlinks)
1385 features.require("color");
1387 if (!listings_params.empty()) {
1388 // do not test validity because listings_params is
1389 // supposed to be valid
1391 InsetListingsParams(listings_params).separatedParams(true);
1392 // we can't support all packages, but we should load the color package
1393 if (par.find("\\color", 0) != string::npos)
1394 features.require("color");
1397 // some languages are only available via polyglossia
1398 if ((features.runparams().flavor == OutputParams::XETEX
1399 || features.runparams().flavor == OutputParams::LUATEX)
1400 && (features.hasPolyglossiaExclusiveLanguages()
1402 features.require("polyglossia");
1404 if (useNonTeXFonts && fontsMath() != "auto")
1405 features.require("unicode-math");
1407 if (!language->requires().empty())
1408 features.require(language->requires());
1412 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1413 FileName const & filepath) const
1415 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1416 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1417 // \RequirePackage to do so, rather than the normal \usepackage
1418 // Do not try to load any other package before the document class, unless you
1419 // have a thorough understanding of the LATEX internals and know exactly what you
1421 if (features.mustProvide("fix-cm"))
1422 os << "\\RequirePackage{fix-cm}\n";
1423 // Likewise for fixltx2e. If other packages conflict with this policy,
1424 // treat it as a package bug (and report it!)
1425 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1426 if (features.mustProvide("fixltx2e"))
1427 os << "\\RequirePackage{fixltx2e}\n";
1429 os << "\\documentclass";
1431 DocumentClass const & tclass = documentClass();
1433 ostringstream clsoptions; // the document class options.
1435 if (tokenPos(tclass.opt_fontsize(),
1436 '|', fontsize) >= 0) {
1437 // only write if existing in list (and not default)
1438 clsoptions << fontsize << "pt,";
1441 // all paper sizes except of A4, A5, B5 and the US sizes need the
1443 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1444 && papersize != PAPER_USLETTER
1445 && papersize != PAPER_USLEGAL
1446 && papersize != PAPER_USEXECUTIVE
1447 && papersize != PAPER_A4
1448 && papersize != PAPER_A5
1449 && papersize != PAPER_B5;
1451 if (!use_geometry) {
1452 switch (papersize) {
1454 clsoptions << "a4paper,";
1456 case PAPER_USLETTER:
1457 clsoptions << "letterpaper,";
1460 clsoptions << "a5paper,";
1463 clsoptions << "b5paper,";
1465 case PAPER_USEXECUTIVE:
1466 clsoptions << "executivepaper,";
1469 clsoptions << "legalpaper,";
1503 if (sides != tclass.sides()) {
1506 clsoptions << "oneside,";
1509 clsoptions << "twoside,";
1515 if (columns != tclass.columns()) {
1517 clsoptions << "twocolumn,";
1519 clsoptions << "onecolumn,";
1523 && orientation == ORIENTATION_LANDSCAPE)
1524 clsoptions << "landscape,";
1526 // language should be a parameter to \documentclass
1527 if (language->babel() == "hebrew"
1528 && default_language->babel() != "hebrew")
1529 // This seems necessary
1530 features.useLanguage(default_language);
1532 ostringstream language_options;
1533 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1534 bool const use_polyglossia = features.usePolyglossia();
1535 bool const global = lyxrc.language_global_options;
1536 if (use_babel || (use_polyglossia && global)) {
1537 language_options << features.getBabelLanguages();
1538 if (!language->babel().empty()) {
1539 if (!language_options.str().empty())
1540 language_options << ',';
1541 language_options << language->babel();
1543 if (global && !features.needBabelLangOptions()
1544 && !language_options.str().empty())
1545 clsoptions << language_options.str() << ',';
1548 // the predefined options from the layout
1549 if (use_default_options && !tclass.options().empty())
1550 clsoptions << tclass.options() << ',';
1552 // the user-defined options
1553 if (!options.empty()) {
1554 clsoptions << options << ',';
1557 string strOptions(clsoptions.str());
1558 if (!strOptions.empty()) {
1559 strOptions = rtrim(strOptions, ",");
1561 os << '[' << from_utf8(strOptions) << ']';
1564 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1565 // end of \documentclass defs
1567 // if we use fontspec or newtxmath, we have to load the AMS packages here
1568 string const ams = features.loadAMSPackages();
1569 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1570 bool const use_newtxmath =
1571 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1572 ot1, false, false) == "newtxmath";
1573 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1574 os << from_ascii(ams);
1576 if (useNonTeXFonts) {
1577 os << "\\usepackage{fontspec}\n";
1578 if (features.mustProvide("unicode-math")
1579 && features.isAvailable("unicode-math"))
1580 os << "\\usepackage{unicode-math}\n";
1583 // font selection must be done before loading fontenc.sty
1584 string const fonts = loadFonts(features);
1586 os << from_utf8(fonts);
1588 if (fonts_default_family != "default")
1589 os << "\\renewcommand{\\familydefault}{\\"
1590 << from_ascii(fonts_default_family) << "}\n";
1592 // set font encoding
1593 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1594 if (!useNonTeXFonts && !features.isProvided("fontenc")
1595 && font_encoding() != "default") {
1596 // get main font encodings
1597 vector<string> fontencs = font_encodings();
1598 // get font encodings of secondary languages
1599 features.getFontEncodings(fontencs);
1600 if (!fontencs.empty()) {
1601 os << "\\usepackage["
1602 << from_ascii(getStringFromVector(fontencs))
1607 // handle inputenc etc.
1608 writeEncodingPreamble(os, features);
1611 if (!features.runparams().includeall && !included_children_.empty()) {
1612 os << "\\includeonly{";
1613 list<string>::const_iterator it = included_children_.begin();
1614 list<string>::const_iterator en = included_children_.end();
1616 for (; it != en; ++it) {
1617 string incfile = *it;
1618 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1619 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1621 if (!features.runparams().nice)
1623 // \includeonly doesn't want an extension
1624 incfile = changeExtension(incfile, string());
1625 incfile = support::latex_path(incfile);
1626 if (!incfile.empty()) {
1629 os << from_utf8(incfile);
1636 if (!features.isProvided("geometry")
1637 && (use_geometry || nonstandard_papersize)) {
1638 odocstringstream ods;
1639 if (!getGraphicsDriver("geometry").empty())
1640 ods << getGraphicsDriver("geometry");
1641 if (orientation == ORIENTATION_LANDSCAPE)
1642 ods << ",landscape";
1643 switch (papersize) {
1645 if (!paperwidth.empty())
1646 ods << ",paperwidth="
1647 << from_ascii(paperwidth);
1648 if (!paperheight.empty())
1649 ods << ",paperheight="
1650 << from_ascii(paperheight);
1652 case PAPER_USLETTER:
1653 ods << ",letterpaper";
1656 ods << ",legalpaper";
1658 case PAPER_USEXECUTIVE:
1659 ods << ",executivepaper";
1748 docstring const g_options = trim(ods.str(), ",");
1749 os << "\\usepackage";
1750 if (!g_options.empty())
1751 os << '[' << g_options << ']';
1752 os << "{geometry}\n";
1753 // output this only if use_geometry is true
1755 os << "\\geometry{verbose";
1756 if (!topmargin.empty())
1757 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1758 if (!bottommargin.empty())
1759 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1760 if (!leftmargin.empty())
1761 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1762 if (!rightmargin.empty())
1763 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1764 if (!headheight.empty())
1765 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1766 if (!headsep.empty())
1767 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1768 if (!footskip.empty())
1769 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1770 if (!columnsep.empty())
1771 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1774 } else if (orientation == ORIENTATION_LANDSCAPE
1775 || papersize != PAPER_DEFAULT) {
1776 features.require("papersize");
1779 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1780 if (pagestyle == "fancy")
1781 os << "\\usepackage{fancyhdr}\n";
1782 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1785 // only output when the background color is not default
1786 if (isbackgroundcolor == true) {
1787 // only require color here, the background color will be defined
1788 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1790 features.require("color");
1791 features.require("pagecolor");
1794 // only output when the font color is not default
1795 if (isfontcolor == true) {
1796 // only require color here, the font color will be defined
1797 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1799 features.require("color");
1800 features.require("fontcolor");
1803 // Only if class has a ToC hierarchy
1804 if (tclass.hasTocLevels()) {
1805 if (secnumdepth != tclass.secnumdepth()) {
1806 os << "\\setcounter{secnumdepth}{"
1810 if (tocdepth != tclass.tocdepth()) {
1811 os << "\\setcounter{tocdepth}{"
1817 if (paragraph_separation) {
1818 // when skip separation
1819 switch (getDefSkip().kind()) {
1820 case VSpace::SMALLSKIP:
1821 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1823 case VSpace::MEDSKIP:
1824 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1826 case VSpace::BIGSKIP:
1827 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1829 case VSpace::LENGTH:
1830 os << "\\setlength{\\parskip}{"
1831 << from_utf8(getDefSkip().length().asLatexString())
1834 default: // should never happen // Then delete it.
1835 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1838 os << "\\setlength{\\parindent}{0pt}\n";
1840 // when separation by indentation
1841 // only output something when a width is given
1842 if (getIndentation().asLyXCommand() != "default") {
1843 os << "\\setlength{\\parindent}{"
1844 << from_utf8(getIndentation().asLatexCommand())
1849 // Now insert the LyX specific LaTeX commands...
1850 docstring lyxpreamble;
1851 features.resolveAlternatives();
1854 if (!output_sync_macro.empty())
1855 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1856 else if (features.runparams().flavor == OutputParams::LATEX)
1857 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1858 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1859 lyxpreamble += "\\synctex=-1\n";
1862 // The package options (via \PassOptionsToPackage)
1863 lyxpreamble += from_ascii(features.getPackageOptions());
1865 // due to interferences with babel and hyperref, the color package has to
1866 // be loaded (when it is not already loaded) before babel when hyperref
1867 // is used with the colorlinks option, see
1868 // http://www.lyx.org/trac/ticket/5291
1869 // we decided therefore to load color always before babel, see
1870 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1871 lyxpreamble += from_ascii(features.getColorOptions());
1873 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1874 // we have to call babel before
1876 && (features.isRequired("jurabib")
1877 || features.isRequired("hyperref")
1878 || features.isRequired("varioref")
1879 || features.isRequired("vietnamese")
1880 || features.isRequired("japanese"))) {
1882 lyxpreamble += from_utf8(features.getBabelPresettings());
1883 lyxpreamble += from_utf8(babelCall(language_options.str(),
1884 features.needBabelLangOptions())) + '\n';
1885 lyxpreamble += from_utf8(features.getBabelPostsettings());
1888 // The optional packages;
1889 lyxpreamble += from_ascii(features.getPackages());
1891 // Additional Indices
1892 if (features.isRequired("splitidx")) {
1893 IndicesList::const_iterator iit = indiceslist().begin();
1894 IndicesList::const_iterator iend = indiceslist().end();
1895 for (; iit != iend; ++iit) {
1896 pair<docstring, docstring> indexname_latex =
1897 features.runparams().encoding->latexString(iit->index(),
1898 features.runparams().dryrun);
1899 if (!indexname_latex.second.empty()) {
1900 // issue a warning about omitted characters
1901 // FIXME: should be passed to the error dialog
1902 frontend::Alert::warning(_("Uncodable characters"),
1903 bformat(_("The following characters that are used in an index name are not\n"
1904 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1905 indexname_latex.second));
1907 lyxpreamble += "\\newindex[";
1908 lyxpreamble += indexname_latex.first;
1909 lyxpreamble += "]{";
1910 lyxpreamble += escape(iit->shortcut());
1911 lyxpreamble += "}\n";
1916 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1919 // * Hyperref manual: "Make sure it comes last of your loaded
1920 // packages, to give it a fighting chance of not being over-written,
1921 // since its job is to redefine many LaTeX commands."
1922 // * Email from Heiko Oberdiek: "It is usually better to load babel
1923 // before hyperref. Then hyperref has a chance to detect babel.
1924 // * Has to be loaded before the "LyX specific LaTeX commands" to
1925 // avoid errors with algorithm floats.
1926 // use hyperref explicitly if it is required
1927 if (features.isRequired("hyperref")) {
1928 // pass what we have to stream here, since we need
1929 // to access the stream itself in PDFOptions.
1932 OutputParams tmp_params = features.runparams();
1933 pdfoptions().writeLaTeX(tmp_params, os,
1934 features.isProvided("hyperref"));
1935 // set back for the rest
1936 lyxpreamble.clear();
1937 // correctly break URLs with hyperref and dvi output
1938 if (features.runparams().flavor == OutputParams::LATEX
1939 && features.isAvailable("breakurl"))
1940 lyxpreamble += "\\usepackage{breakurl}\n";
1941 } else if (features.isRequired("nameref"))
1942 // hyperref loads this automatically
1943 lyxpreamble += "\\usepackage{nameref}\n";
1945 // bibtopic needs to be loaded after hyperref.
1946 // the dot provides the aux file naming which LyX can detect.
1947 if (features.mustProvide("bibtopic"))
1948 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1950 // Will be surrounded by \makeatletter and \makeatother when not empty
1951 docstring atlyxpreamble;
1953 // Some macros LyX will need
1954 docstring tmppreamble(features.getMacros());
1956 if (!tmppreamble.empty())
1957 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1958 "LyX specific LaTeX commands.\n"
1959 + tmppreamble + '\n';
1961 // the text class specific preamble
1962 tmppreamble = features.getTClassPreamble();
1963 if (!tmppreamble.empty())
1964 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1965 "Textclass specific LaTeX commands.\n"
1966 + tmppreamble + '\n';
1968 // suppress date if selected
1969 // use \@ifundefined because we cannot be sure that every document class
1970 // has a \date command
1972 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1974 /* the user-defined preamble */
1975 if (!containsOnly(preamble, " \n\t")) {
1977 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1978 "User specified LaTeX commands.\n";
1980 // Check if the user preamble contains uncodable glyphs
1981 docstring const u_preamble = from_utf8(preamble);
1982 odocstringstream user_preamble;
1983 docstring uncodable_glyphs;
1984 Encoding const * const enc = features.runparams().encoding;
1986 for (size_t n = 0; n < u_preamble.size(); ++n) {
1987 char_type c = u_preamble[n];
1988 if (!enc->encodable(c)) {
1989 docstring const glyph(1, c);
1990 LYXERR0("Uncodable character '"
1992 << "' in user preamble!");
1993 uncodable_glyphs += glyph;
1994 if (features.runparams().dryrun) {
1995 user_preamble << "<" << _("LyX Warning: ")
1996 << _("uncodable character") << " '";
1997 user_preamble.put(c);
1998 user_preamble << "'>";
2001 user_preamble.put(c);
2004 user_preamble << u_preamble;
2006 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2007 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2008 frontend::Alert::warning(
2009 _("Uncodable character in user preamble"),
2011 _("The user preamble of your document contains glyphs "
2012 "that are unknown in the current document encoding "
2013 "(namely %1$s).\nThese glyphs are omitted "
2014 " from the output, which may result in "
2015 "incomplete output."
2016 "\n\nPlease select an appropriate "
2017 "document encoding\n"
2018 "(such as utf8) or change the "
2019 "preamble code accordingly."),
2022 atlyxpreamble += user_preamble.str() + '\n';
2025 // footmisc must be loaded after setspace
2026 // Load it here to avoid clashes with footmisc loaded in the user
2027 // preamble. For that reason we also pass the options via
2028 // \PassOptionsToPackage in getPreamble() and not here.
2029 if (features.mustProvide("footmisc"))
2030 atlyxpreamble += "\\usepackage{footmisc}\n";
2032 // subfig loads internally the LaTeX package "caption". As
2033 // caption is a very popular package, users will load it in
2034 // the preamble. Therefore we must load subfig behind the
2035 // user-defined preamble and check if the caption package was
2036 // loaded or not. For the case that caption is loaded before
2037 // subfig, there is the subfig option "caption=false". This
2038 // option also works when a koma-script class is used and
2039 // koma's own caption commands are used instead of caption. We
2040 // use \PassOptionsToPackage here because the user could have
2041 // already loaded subfig in the preamble.
2042 if (features.isRequired("subfig")) {
2043 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
2044 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2045 "\\usepackage{subfig}\n";
2048 // Itemize bullet settings need to be last in case the user
2049 // defines their own bullets that use a package included
2050 // in the user-defined preamble -- ARRae
2051 // Actually it has to be done much later than that
2052 // since some packages like frenchb make modifications
2053 // at \begin{document} time -- JMarc
2054 docstring bullets_def;
2055 for (int i = 0; i < 4; ++i) {
2056 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2057 if (bullets_def.empty())
2058 bullets_def += "\\AtBeginDocument{\n";
2059 bullets_def += " \\def\\labelitemi";
2061 // `i' is one less than the item to modify
2068 bullets_def += "ii";
2074 bullets_def += '{' +
2075 user_defined_bullet(i).getText()
2080 if (!bullets_def.empty())
2081 atlyxpreamble += bullets_def + "}\n\n";
2083 if (!atlyxpreamble.empty())
2084 lyxpreamble += "\n\\makeatletter\n"
2085 + atlyxpreamble + "\\makeatother\n\n";
2087 // We try to load babel late, in case it interferes with other packages.
2088 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
2089 // called after babel, though.
2090 if (use_babel && !features.isRequired("jurabib")
2091 && !features.isRequired("hyperref")
2092 && !features.isRequired("varioref")
2093 && !features.isRequired("vietnamese")
2094 && !features.isRequired("japanese")) {
2096 lyxpreamble += from_utf8(features.getBabelPresettings());
2097 lyxpreamble += from_utf8(babelCall(language_options.str(),
2098 features.needBabelLangOptions())) + '\n';
2099 lyxpreamble += from_utf8(features.getBabelPostsettings());
2101 if (features.isRequired("bicaption"))
2102 lyxpreamble += "\\usepackage{bicaption}\n";
2103 if (!listings_params.empty() || features.isRequired("listings"))
2104 lyxpreamble += "\\usepackage{listings}\n";
2105 if (!listings_params.empty()) {
2106 lyxpreamble += "\\lstset{";
2107 // do not test validity because listings_params is
2108 // supposed to be valid
2110 InsetListingsParams(listings_params).separatedParams(true);
2111 lyxpreamble += from_utf8(par);
2112 lyxpreamble += "}\n";
2115 // xunicode needs to be loaded at least after amsmath, amssymb,
2116 // esint and the other packages that provide special glyphs
2117 if (features.runparams().flavor == OutputParams::XETEX
2119 lyxpreamble += "\\usepackage{xunicode}\n";
2121 // Polyglossia must be loaded last
2122 if (use_polyglossia) {
2124 lyxpreamble += "\\usepackage{polyglossia}\n";
2125 // set the main language
2126 lyxpreamble += "\\setdefaultlanguage";
2127 if (!language->polyglossiaOpts().empty())
2128 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
2129 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
2130 // now setup the other languages
2131 std::map<std::string, std::string> const polylangs =
2132 features.getPolyglossiaLanguages();
2133 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
2134 mit != polylangs.end() ; ++mit) {
2135 lyxpreamble += "\\setotherlanguage";
2136 if (!mit->second.empty())
2137 lyxpreamble += "[" + from_ascii(mit->second) + "]";
2138 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
2142 // Load custom language package here
2143 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2144 if (lang_package == "default")
2145 lyxpreamble += from_utf8(lyxrc.language_custom_package);
2147 lyxpreamble += from_utf8(lang_package);
2148 lyxpreamble += '\n';
2151 docstring const i18npreamble =
2152 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2153 if (!i18npreamble.empty())
2154 lyxpreamble += i18npreamble + '\n';
2162 void BufferParams::useClassDefaults()
2164 DocumentClass const & tclass = documentClass();
2166 sides = tclass.sides();
2167 columns = tclass.columns();
2168 pagestyle = tclass.pagestyle();
2169 use_default_options = true;
2170 // Only if class has a ToC hierarchy
2171 if (tclass.hasTocLevels()) {
2172 secnumdepth = tclass.secnumdepth();
2173 tocdepth = tclass.tocdepth();
2178 bool BufferParams::hasClassDefaults() const
2180 DocumentClass const & tclass = documentClass();
2182 return sides == tclass.sides()
2183 && columns == tclass.columns()
2184 && pagestyle == tclass.pagestyle()
2185 && use_default_options
2186 && secnumdepth == tclass.secnumdepth()
2187 && tocdepth == tclass.tocdepth();
2191 DocumentClass const & BufferParams::documentClass() const
2193 return *doc_class_.get();
2197 DocumentClassConstPtr BufferParams::documentClassPtr() const
2203 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2205 // evil, but this function is evil
2206 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2210 bool BufferParams::setBaseClass(string const & classname)
2212 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2213 LayoutFileList & bcl = LayoutFileList::get();
2214 if (!bcl.haveClass(classname)) {
2216 bformat(_("The layout file:\n"
2218 "could not be found. A default textclass with default\n"
2219 "layouts will be used. LyX will not be able to produce\n"
2221 from_utf8(classname));
2222 frontend::Alert::error(_("Document class not found"), s);
2223 bcl.addEmptyClass(classname);
2226 bool const success = bcl[classname].load();
2229 bformat(_("Due to some error in it, the layout file:\n"
2231 "could not be loaded. A default textclass with default\n"
2232 "layouts will be used. LyX will not be able to produce\n"
2234 from_utf8(classname));
2235 frontend::Alert::error(_("Could not load class"), s);
2236 bcl.addEmptyClass(classname);
2239 pimpl_->baseClass_ = classname;
2240 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2245 LayoutFile const * BufferParams::baseClass() const
2247 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2248 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2254 LayoutFileIndex const & BufferParams::baseClassID() const
2256 return pimpl_->baseClass_;
2260 void BufferParams::makeDocumentClass(bool const clone)
2265 LayoutModuleList mods;
2266 LayoutModuleList::iterator it = layout_modules_.begin();
2267 LayoutModuleList::iterator en = layout_modules_.end();
2268 for (; it != en; ++it)
2269 mods.push_back(*it);
2271 it = cite_engine_.begin();
2272 en = cite_engine_.end();
2273 for (; it != en; ++it)
2274 mods.push_back(*it);
2276 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2278 TextClass::ReturnValues success = TextClass::OK;
2279 if (!forced_local_layout_.empty())
2280 success = doc_class_->read(forced_local_layout_, TextClass::MODULE);
2281 if (!local_layout_.empty() &&
2282 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2283 success = doc_class_->read(local_layout_, TextClass::MODULE);
2284 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2285 docstring const msg = _("Error reading internal layout information");
2286 frontend::Alert::warning(_("Read Error"), msg);
2291 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2293 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2297 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2299 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2303 std::string BufferParams::getLocalLayout(bool forced) const
2306 return doc_class_->forcedLayouts();
2308 return local_layout_;
2312 void BufferParams::setLocalLayout(string const & layout, bool forced)
2315 forced_local_layout_ = layout;
2317 local_layout_ = layout;
2321 bool BufferParams::addLayoutModule(string const & modName)
2323 LayoutModuleList::const_iterator it = layout_modules_.begin();
2324 LayoutModuleList::const_iterator end = layout_modules_.end();
2325 for (; it != end; ++it)
2328 layout_modules_.push_back(modName);
2333 string BufferParams::bufferFormat() const
2335 string format = documentClass().outputFormat();
2336 if (format == "latex") {
2338 return "xetex"; // actually "xetex or luatex"
2339 if (encoding().package() == Encoding::japanese)
2346 bool BufferParams::isExportable(string const & format) const
2348 vector<string> backs = backends();
2349 for (vector<string>::const_iterator it = backs.begin();
2350 it != backs.end(); ++it)
2351 if (theConverters().isReachable(*it, format))
2357 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2359 vector<string> const backs = backends();
2360 set<string> excludes;
2361 if (useNonTeXFonts) {
2362 excludes.insert("latex");
2363 excludes.insert("pdflatex");
2365 vector<Format const *> result =
2366 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2367 for (vector<string>::const_iterator it = backs.begin() + 1;
2368 it != backs.end(); ++it) {
2369 vector<Format const *> r =
2370 theConverters().getReachable(*it, only_viewable, false, excludes);
2371 result.insert(result.end(), r.begin(), r.end());
2377 bool BufferParams::isExportableFormat(string const & format) const
2379 typedef vector<Format const *> Formats;
2381 formats = exportableFormats(true);
2382 Formats::const_iterator fit = formats.begin();
2383 Formats::const_iterator end = formats.end();
2384 for (; fit != end ; ++fit) {
2385 if ((*fit)->name() == format)
2392 vector<string> BufferParams::backends() const
2395 string const buffmt = bufferFormat();
2397 // FIXME: Don't hardcode format names here, but use a flag
2398 if (buffmt == "latex") {
2399 if (!useNonTeXFonts) {
2400 v.push_back("pdflatex");
2401 v.push_back("latex");
2403 v.push_back("luatex");
2404 v.push_back("dviluatex");
2405 v.push_back("xetex");
2406 } else if (buffmt == "xetex") {
2407 v.push_back("xetex");
2408 // FIXME: need to test all languages (bug 8205)
2409 if (!language || !language->isPolyglossiaExclusive()) {
2410 v.push_back("luatex");
2411 v.push_back("dviluatex");
2414 v.push_back(buffmt);
2416 v.push_back("xhtml");
2417 v.push_back("text");
2423 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2425 string const dformat = (format.empty() || format == "default") ?
2426 getDefaultOutputFormat() : format;
2427 DefaultFlavorCache::const_iterator it =
2428 default_flavors_.find(dformat);
2430 if (it != default_flavors_.end())
2433 OutputParams::FLAVOR result = OutputParams::LATEX;
2435 // FIXME It'd be better not to hardcode this, but to do
2436 // something with formats.
2437 if (dformat == "xhtml")
2438 result = OutputParams::HTML;
2439 else if (dformat == "text")
2440 result = OutputParams::TEXT;
2441 else if (dformat == "lyx")
2442 result = OutputParams::LYX;
2443 else if (dformat == "pdflatex")
2444 result = OutputParams::PDFLATEX;
2445 else if (dformat == "xetex")
2446 result = OutputParams::XETEX;
2447 else if (dformat == "luatex")
2448 result = OutputParams::LUATEX;
2449 else if (dformat == "dviluatex")
2450 result = OutputParams::DVILUATEX;
2452 // Try to determine flavor of default output format
2453 vector<string> backs = backends();
2454 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2455 // Get shortest path to format
2456 Graph::EdgePath path;
2457 for (vector<string>::const_iterator it = backs.begin();
2458 it != backs.end(); ++it) {
2459 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2460 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2465 result = theConverters().getFlavor(path);
2468 // cache this flavor
2469 default_flavors_[dformat] = result;
2474 string BufferParams::getDefaultOutputFormat() const
2476 if (!default_output_format.empty()
2477 && default_output_format != "default")
2478 return default_output_format;
2480 || encoding().package() == Encoding::japanese) {
2481 vector<Format const *> const formats = exportableFormats(true);
2482 if (formats.empty())
2484 // return the first we find
2485 return formats.front()->name();
2488 return lyxrc.default_otf_view_format;
2489 return lyxrc.default_view_format;
2492 Font const BufferParams::getFont() const
2494 FontInfo f = documentClass().defaultfont();
2495 if (fonts_default_family == "rmdefault")
2496 f.setFamily(ROMAN_FAMILY);
2497 else if (fonts_default_family == "sfdefault")
2498 f.setFamily(SANS_FAMILY);
2499 else if (fonts_default_family == "ttdefault")
2500 f.setFamily(TYPEWRITER_FAMILY);
2501 return Font(f, language);
2505 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const & qs) const
2507 return quoteslangtranslator().find(qs);
2511 bool BufferParams::isLatex() const
2513 return documentClass().outputType() == LATEX;
2517 bool BufferParams::isLiterate() const
2519 return documentClass().outputType() == LITERATE;
2523 bool BufferParams::isDocBook() const
2525 return documentClass().outputType() == DOCBOOK;
2529 void BufferParams::readPreamble(Lexer & lex)
2531 if (lex.getString() != "\\begin_preamble")
2532 lyxerr << "Error (BufferParams::readPreamble):"
2533 "consistency check failed." << endl;
2535 preamble = lex.getLongString("\\end_preamble");
2539 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2541 string const expected = forced ? "\\begin_forced_local_layout" :
2542 "\\begin_local_layout";
2543 if (lex.getString() != expected)
2544 lyxerr << "Error (BufferParams::readLocalLayout):"
2545 "consistency check failed." << endl;
2548 forced_local_layout_ =
2549 lex.getLongString("\\end_forced_local_layout");
2551 local_layout_ = lex.getLongString("\\end_local_layout");
2555 bool BufferParams::setLanguage(string const & lang)
2557 Language const *new_language = languages.getLanguage(lang);
2558 if (!new_language) {
2559 // Language lang was not found
2562 language = new_language;
2567 void BufferParams::readLanguage(Lexer & lex)
2569 if (!lex.next()) return;
2571 string const tmptok = lex.getString();
2573 // check if tmptok is part of tex_babel in tex-defs.h
2574 if (!setLanguage(tmptok)) {
2575 // Language tmptok was not found
2576 language = default_language;
2577 lyxerr << "Warning: Setting language `"
2578 << tmptok << "' to `" << language->lang()
2584 void BufferParams::readGraphicsDriver(Lexer & lex)
2589 string const tmptok = lex.getString();
2590 // check if tmptok is part of tex_graphics in tex_defs.h
2593 string const test = tex_graphics[n++];
2595 if (test == tmptok) {
2596 graphics_driver = tmptok;
2601 "Warning: graphics driver `$$Token' not recognized!\n"
2602 " Setting graphics driver to `default'.\n");
2603 graphics_driver = "default";
2610 void BufferParams::readBullets(Lexer & lex)
2615 int const index = lex.getInteger();
2617 int temp_int = lex.getInteger();
2618 user_defined_bullet(index).setFont(temp_int);
2619 temp_bullet(index).setFont(temp_int);
2621 user_defined_bullet(index).setCharacter(temp_int);
2622 temp_bullet(index).setCharacter(temp_int);
2624 user_defined_bullet(index).setSize(temp_int);
2625 temp_bullet(index).setSize(temp_int);
2629 void BufferParams::readBulletsLaTeX(Lexer & lex)
2631 // The bullet class should be able to read this.
2634 int const index = lex.getInteger();
2636 docstring const temp_str = lex.getDocString();
2638 user_defined_bullet(index).setText(temp_str);
2639 temp_bullet(index).setText(temp_str);
2643 void BufferParams::readModules(Lexer & lex)
2645 if (!lex.eatLine()) {
2646 lyxerr << "Error (BufferParams::readModules):"
2647 "Unexpected end of input." << endl;
2651 string mod = lex.getString();
2652 if (mod == "\\end_modules")
2654 addLayoutModule(mod);
2660 void BufferParams::readRemovedModules(Lexer & lex)
2662 if (!lex.eatLine()) {
2663 lyxerr << "Error (BufferParams::readRemovedModules):"
2664 "Unexpected end of input." << endl;
2668 string mod = lex.getString();
2669 if (mod == "\\end_removed_modules")
2671 removed_modules_.push_back(mod);
2674 // now we want to remove any removed modules that were previously
2675 // added. normally, that will be because default modules were added in
2676 // setBaseClass(), which gets called when \textclass is read at the
2677 // start of the read.
2678 list<string>::const_iterator rit = removed_modules_.begin();
2679 list<string>::const_iterator const ren = removed_modules_.end();
2680 for (; rit != ren; ++rit) {
2681 LayoutModuleList::iterator const mit = layout_modules_.begin();
2682 LayoutModuleList::iterator const men = layout_modules_.end();
2683 LayoutModuleList::iterator found = find(mit, men, *rit);
2686 layout_modules_.erase(found);
2691 void BufferParams::readIncludeonly(Lexer & lex)
2693 if (!lex.eatLine()) {
2694 lyxerr << "Error (BufferParams::readIncludeonly):"
2695 "Unexpected end of input." << endl;
2699 string child = lex.getString();
2700 if (child == "\\end_includeonly")
2702 included_children_.push_back(child);
2708 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2710 switch (papersize) {
2712 // could be anything, so don't guess
2714 case PAPER_CUSTOM: {
2715 if (purpose == XDVI && !paperwidth.empty() &&
2716 !paperheight.empty()) {
2717 // heightxwidth<unit>
2718 string first = paperwidth;
2719 string second = paperheight;
2720 if (orientation == ORIENTATION_LANDSCAPE)
2723 return first.erase(first.length() - 2)
2729 // dvips and dvipdfm do not know this
2730 if (purpose == DVIPS || purpose == DVIPDFM)
2734 if (purpose == DVIPS || purpose == DVIPDFM)
2738 if (purpose == DVIPS || purpose == DVIPDFM)
2748 if (purpose == DVIPS || purpose == DVIPDFM)
2752 if (purpose == DVIPS || purpose == DVIPDFM)
2756 if (purpose == DVIPS || purpose == DVIPDFM)
2760 if (purpose == DVIPS || purpose == DVIPDFM)
2764 if (purpose == DVIPS || purpose == DVIPDFM)
2768 // dvipdfm does not know this
2769 if (purpose == DVIPDFM)
2773 if (purpose == DVIPDFM)
2777 if (purpose == DVIPS || purpose == DVIPDFM)
2781 if (purpose == DVIPS || purpose == DVIPDFM)
2785 if (purpose == DVIPS || purpose == DVIPDFM)
2789 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 if (purpose == DVIPS || purpose == DVIPDFM)
2817 if (purpose == DVIPS || purpose == DVIPDFM)
2821 if (purpose == DVIPS || purpose == DVIPDFM)
2825 if (purpose == DVIPS || purpose == DVIPDFM)
2829 if (purpose == DVIPS || purpose == DVIPDFM)
2833 if (purpose == DVIPS || purpose == DVIPDFM)
2836 case PAPER_USEXECUTIVE:
2837 // dvipdfm does not know this
2838 if (purpose == DVIPDFM)
2843 case PAPER_USLETTER:
2845 if (purpose == XDVI)
2852 string const BufferParams::dvips_options() const
2856 // If the class loads the geometry package, we do not know which
2857 // paper size is used, since we do not set it (bug 7013).
2858 // Therefore we must not specify any argument here.
2859 // dvips gets the correct paper size via DVI specials in this case
2860 // (if the class uses the geometry package correctly).
2861 if (documentClass().provides("geometry"))
2865 && papersize == PAPER_CUSTOM
2866 && !lyxrc.print_paper_dimension_flag.empty()
2867 && !paperwidth.empty()
2868 && !paperheight.empty()) {
2869 // using a custom papersize
2870 result = lyxrc.print_paper_dimension_flag;
2871 result += ' ' + paperwidth;
2872 result += ',' + paperheight;
2874 string const paper_option = paperSizeName(DVIPS);
2875 if (!paper_option.empty() && (paper_option != "letter" ||
2876 orientation != ORIENTATION_LANDSCAPE)) {
2877 // dvips won't accept -t letter -t landscape.
2878 // In all other cases, include the paper size
2880 result = lyxrc.print_paper_flag;
2881 result += ' ' + paper_option;
2884 if (orientation == ORIENTATION_LANDSCAPE &&
2885 papersize != PAPER_CUSTOM)
2886 result += ' ' + lyxrc.print_landscape_flag;
2891 string const BufferParams::font_encoding() const
2893 return font_encodings().empty() ? "default" : font_encodings().back();
2897 vector<string> const BufferParams::font_encodings() const
2899 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2901 vector<string> fontencs;
2903 // "default" means "no explicit font encoding"
2904 if (doc_fontenc != "default") {
2905 fontencs = getVectorFromString(doc_fontenc);
2906 if (!language->fontenc().empty()
2907 && ascii_lowercase(language->fontenc()) != "none") {
2908 vector<string> fencs = getVectorFromString(language->fontenc());
2909 vector<string>::const_iterator fit = fencs.begin();
2910 for (; fit != fencs.end(); ++fit) {
2911 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
2912 fontencs.push_back(*fit);
2921 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2923 // suppress the babel call if there is no BabelName defined
2924 // for the document language in the lib/languages file and if no
2925 // other languages are used (lang_opts is then empty)
2926 if (lang_opts.empty())
2928 // either a specific language (AsBabelOptions setting in
2929 // lib/languages) or the prefs require the languages to
2930 // be submitted to babel itself (not the class).
2932 return "\\usepackage[" + lang_opts + "]{babel}";
2933 return "\\usepackage{babel}";
2937 docstring BufferParams::getGraphicsDriver(string const & package) const
2941 if (package == "geometry") {
2942 if (graphics_driver == "dvips"
2943 || graphics_driver == "dvipdfm"
2944 || graphics_driver == "pdftex"
2945 || graphics_driver == "vtex")
2946 result = from_ascii(graphics_driver);
2947 else if (graphics_driver == "dvipdfmx")
2948 result = from_ascii("dvipdfm");
2955 void BufferParams::writeEncodingPreamble(otexstream & os,
2956 LaTeXFeatures & features) const
2958 // XeTeX/LuaTeX: (see also #9740)
2959 // With Unicode fonts we use utf8-plain without encoding package.
2960 // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails.
2961 // XeTeX must use ASCII encoding, for LuaTeX, we load
2962 // "luainputenc" (see below).
2963 if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
2966 if (inputenc == "auto") {
2967 string const doc_encoding =
2968 language->encoding()->latexName();
2969 Encoding::Package const package =
2970 language->encoding()->package();
2972 // Create list of inputenc options:
2973 set<string> encodings;
2974 // luainputenc fails with more than one encoding
2975 if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts
2976 // list all input encodings used in the document
2977 encodings = features.getEncodingSet(doc_encoding);
2979 // If the "japanese" package (i.e. pLaTeX) is used,
2980 // inputenc must be omitted.
2981 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2982 if ((!encodings.empty() || package == Encoding::inputenc)
2983 && !features.isRequired("japanese")
2984 && !features.isProvided("inputenc")) {
2985 os << "\\usepackage[";
2986 set<string>::const_iterator it = encodings.begin();
2987 set<string>::const_iterator const end = encodings.end();
2989 os << from_ascii(*it);
2992 for (; it != end; ++it)
2993 os << ',' << from_ascii(*it);
2994 if (package == Encoding::inputenc) {
2995 if (!encodings.empty())
2997 os << from_ascii(doc_encoding);
2999 if (features.runparams().flavor == OutputParams::LUATEX
3000 || features.runparams().flavor == OutputParams::DVILUATEX)
3001 os << "]{luainputenc}\n";
3003 os << "]{inputenc}\n";
3005 if (package == Encoding::CJK || features.mustProvide("CJK")) {
3006 if (language->encoding()->name() == "utf8-cjk"
3007 && LaTeXFeatures::isAvailable("CJKutf8"))
3008 os << "\\usepackage{CJKutf8}\n";
3010 os << "\\usepackage{CJK}\n";
3012 } else if (inputenc != "default") {
3013 switch (encoding().package()) {
3014 case Encoding::none:
3015 case Encoding::japanese:
3017 case Encoding::inputenc:
3018 // do not load inputenc if japanese is used
3019 // or if the class provides inputenc
3020 if (features.isRequired("japanese")
3021 || features.isProvided("inputenc"))
3023 os << "\\usepackage[" << from_ascii(encoding().latexName());
3024 if (features.runparams().flavor == OutputParams::LUATEX
3025 || features.runparams().flavor == OutputParams::DVILUATEX)
3026 os << "]{luainputenc}\n";
3028 os << "]{inputenc}\n";
3031 if (encoding().name() == "utf8-cjk"
3032 && LaTeXFeatures::isAvailable("CJKutf8"))
3033 os << "\\usepackage{CJKutf8}\n";
3035 os << "\\usepackage{CJK}\n";
3038 // Load the CJK package if needed by a secondary language.
3039 // If the main encoding is some variant of UTF8, use CJKutf8.
3040 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
3041 if (encoding().iconvName() == "UTF-8"
3042 && LaTeXFeatures::isAvailable("CJKutf8"))
3043 os << "\\usepackage{CJKutf8}\n";
3045 os << "\\usepackage{CJK}\n";
3051 string const BufferParams::parseFontName(string const & name) const
3053 string mangled = name;
3054 size_t const idx = mangled.find('[');
3055 if (idx == string::npos || idx == 0)
3058 return mangled.substr(0, idx - 1);
3062 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3064 if (fontsRoman() == "default" && fontsSans() == "default"
3065 && fontsTypewriter() == "default"
3066 && (fontsMath() == "default" || fontsMath() == "auto"))
3072 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3073 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3074 * Mapping=tex-text option assures TeX ligatures (such as "--")
3075 * are resolved. Note that tt does not use these ligatures.
3077 * -- add more GUI options?
3078 * -- add more fonts (fonts for other scripts)
3079 * -- if there's a way to find out if a font really supports
3080 * OldStyle, enable/disable the widget accordingly.
3082 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3083 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3084 // However, until v.2 (2010/07/11) fontspec only knew
3085 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3086 // was introduced for both XeTeX and LuaTeX (LuaTeX
3087 // didn't understand "Mapping=tex-text", while XeTeX
3088 // understood both. With most recent versions, both
3089 // variants are understood by both engines. However,
3090 // we want to provide support for at least TeXLive 2009
3091 // (for XeTeX; LuaTeX is only supported as of v.2)
3092 string const texmapping =
3093 (features.runparams().flavor == OutputParams::XETEX) ?
3094 "Mapping=tex-text" : "Ligatures=TeX";
3095 if (fontsRoman() != "default") {
3096 os << "\\setmainfont[" << texmapping;
3097 if (fonts_old_figures)
3098 os << ",Numbers=OldStyle";
3099 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3101 if (fontsSans() != "default") {
3102 string const sans = parseFontName(fontsSans());
3103 if (fontsSansScale() != 100)
3104 os << "\\setsansfont[Scale="
3105 << float(fontsSansScale()) / 100
3106 << "," << texmapping << "]{"
3109 os << "\\setsansfont[" << texmapping << "]{"
3112 if (fontsTypewriter() != "default") {
3113 string const mono = parseFontName(fontsTypewriter());
3114 if (fontsTypewriterScale() != 100)
3115 os << "\\setmonofont[Scale="
3116 << float(fontsTypewriterScale()) / 100
3120 os << "\\setmonofont{"
3127 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
3128 bool const dryrun = features.runparams().dryrun;
3129 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3130 bool const nomath = (fontsMath() == "default");
3133 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3134 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3138 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3139 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3140 nomath, fontsSansScale());
3142 // MONOSPACED/TYPEWRITER
3143 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3144 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3145 nomath, fontsTypewriterScale());
3148 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3149 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3156 Encoding const & BufferParams::encoding() const
3158 // Main encoding for LaTeX output.
3160 // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740).
3161 // As the "flavor" is only known once export started, this
3162 // cannot be handled here. Instead, runparams.encoding is set
3163 // to ASCII in Buffer::makeLaTeXFile (for export)
3164 // and Buffer::writeLaTeXSource (for preview).
3166 return *(encodings.fromLyXName("utf8-plain"));
3167 if (inputenc == "auto" || inputenc == "default")
3168 return *language->encoding();
3169 Encoding const * const enc = encodings.fromLyXName(inputenc);
3172 LYXERR0("Unknown inputenc value `" << inputenc
3173 << "'. Using `auto' instead.");
3174 return *language->encoding();
3178 bool BufferParams::addCiteEngine(string const & engine)
3180 LayoutModuleList::const_iterator it = cite_engine_.begin();
3181 LayoutModuleList::const_iterator en = cite_engine_.end();
3182 for (; it != en; ++it)
3185 cite_engine_.push_back(engine);
3190 bool BufferParams::addCiteEngine(vector<string> const & engine)
3192 vector<string>::const_iterator it = engine.begin();
3193 vector<string>::const_iterator en = engine.end();
3195 for (; it != en; ++it)
3196 if (!addCiteEngine(*it))
3202 string const & BufferParams::defaultBiblioStyle() const
3204 return documentClass().defaultBiblioStyle();
3208 bool const & BufferParams::fullAuthorList() const
3210 return documentClass().fullAuthorList();
3214 void BufferParams::setCiteEngine(string const & engine)
3217 addCiteEngine(engine);
3221 void BufferParams::setCiteEngine(vector<string> const & engine)
3224 addCiteEngine(engine);
3228 vector<string> BufferParams::citeCommands() const
3230 static CitationStyle const default_style;
3231 vector<string> commands =
3232 documentClass().citeCommands(citeEngineType());
3233 if (commands.empty())
3234 commands.push_back(default_style.cmd);
3239 vector<CitationStyle> BufferParams::citeStyles() const
3241 static CitationStyle const default_style;
3242 vector<CitationStyle> styles =
3243 documentClass().citeStyles(citeEngineType());
3245 styles.push_back(default_style);