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 string filepath = buf->filePath();
1020 string const sysdir = package().system_support().absFileName();
1021 if (prefixIs(filepath, sysdir))
1022 filepath.replace(0, sysdir.length(), "/systemlyxdir/");
1023 else if (!lyxrc.save_origin)
1024 filepath = "unavailable";
1025 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1028 os << "\\textclass "
1029 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1030 baseClass()->name()), "layout"))
1033 // then the preamble
1034 if (!preamble.empty()) {
1035 // remove '\n' from the end of preamble
1036 string const tmppreamble = rtrim(preamble, "\n");
1037 os << "\\begin_preamble\n"
1039 << "\n\\end_preamble\n";
1043 if (!options.empty()) {
1044 os << "\\options " << options << '\n';
1047 // use the class options defined in the layout?
1048 os << "\\use_default_options "
1049 << convert<string>(use_default_options) << "\n";
1051 // the master document
1052 if (!master.empty()) {
1053 os << "\\master " << master << '\n';
1057 if (!removed_modules_.empty()) {
1058 os << "\\begin_removed_modules" << '\n';
1059 list<string>::const_iterator it = removed_modules_.begin();
1060 list<string>::const_iterator en = removed_modules_.end();
1061 for (; it != en; ++it)
1063 os << "\\end_removed_modules" << '\n';
1067 if (!layout_modules_.empty()) {
1068 os << "\\begin_modules" << '\n';
1069 LayoutModuleList::const_iterator it = layout_modules_.begin();
1070 LayoutModuleList::const_iterator en = layout_modules_.end();
1071 for (; it != en; ++it)
1073 os << "\\end_modules" << '\n';
1077 if (!included_children_.empty()) {
1078 os << "\\begin_includeonly" << '\n';
1079 list<string>::const_iterator it = included_children_.begin();
1080 list<string>::const_iterator en = included_children_.end();
1081 for (; it != en; ++it)
1083 os << "\\end_includeonly" << '\n';
1085 os << "\\maintain_unincluded_children "
1086 << convert<string>(maintain_unincluded_children) << '\n';
1088 // local layout information
1089 string const local_layout = getLocalLayout(false);
1090 if (!local_layout.empty()) {
1091 // remove '\n' from the end
1092 string const tmplocal = rtrim(local_layout, "\n");
1093 os << "\\begin_local_layout\n"
1095 << "\n\\end_local_layout\n";
1097 string const forced_local_layout = getLocalLayout(true);
1098 if (!forced_local_layout.empty()) {
1099 // remove '\n' from the end
1100 string const tmplocal = rtrim(forced_local_layout, "\n");
1101 os << "\\begin_forced_local_layout\n"
1103 << "\n\\end_forced_local_layout\n";
1106 // then the text parameters
1107 if (language != ignore_language)
1108 os << "\\language " << language->lang() << '\n';
1109 os << "\\language_package " << lang_package
1110 << "\n\\inputencoding " << inputenc
1111 << "\n\\fontencoding " << fontenc
1112 << "\n\\font_roman \"" << fonts_roman[0]
1113 << "\" \"" << fonts_roman[1] << '"'
1114 << "\n\\font_sans \"" << fonts_sans[0]
1115 << "\" \"" << fonts_sans[1] << '"'
1116 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1117 << "\" \"" << fonts_typewriter[1] << '"'
1118 << "\n\\font_math \"" << fonts_math[0]
1119 << "\" \"" << fonts_math[1] << '"'
1120 << "\n\\font_default_family " << fonts_default_family
1121 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1122 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1123 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1124 << "\n\\font_sf_scale " << fonts_sans_scale[0]
1125 << ' ' << fonts_sans_scale[1]
1126 << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1127 << ' ' << fonts_typewriter_scale[1]
1129 if (!fonts_cjk.empty()) {
1130 os << "\\font_cjk " << fonts_cjk << '\n';
1132 os << "\\graphics " << graphics_driver << '\n';
1133 os << "\\default_output_format " << default_output_format << '\n';
1134 os << "\\output_sync " << output_sync << '\n';
1135 if (!output_sync_macro.empty())
1136 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1137 os << "\\bibtex_command " << bibtex_command << '\n';
1138 os << "\\index_command " << index_command << '\n';
1140 if (!float_placement.empty()) {
1141 os << "\\float_placement " << float_placement << '\n';
1143 os << "\\paperfontsize " << fontsize << '\n';
1145 spacing().writeFile(os);
1146 pdfoptions().writeFile(os);
1148 os << "\\papersize " << string_papersize[papersize]
1149 << "\n\\use_geometry " << convert<string>(use_geometry);
1150 map<string, string> const & packages = auto_packages();
1151 for (map<string, string>::const_iterator it = packages.begin();
1152 it != packages.end(); ++it)
1153 os << "\n\\use_package " << it->first << ' '
1154 << use_package(it->first);
1156 os << "\n\\cite_engine ";
1158 if (!cite_engine_.empty()) {
1159 LayoutModuleList::const_iterator be = cite_engine_.begin();
1160 LayoutModuleList::const_iterator en = cite_engine_.end();
1161 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1170 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1171 << "\n\\biblio_style " << biblio_style
1172 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1173 << "\n\\use_indices " << convert<string>(use_indices)
1174 << "\n\\paperorientation " << string_orientation[orientation]
1175 << "\n\\suppress_date " << convert<string>(suppress_date)
1176 << "\n\\justification " << convert<string>(justification)
1177 << "\n\\use_refstyle " << use_refstyle
1179 if (isbackgroundcolor == true)
1180 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1181 if (isfontcolor == true)
1182 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1183 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1184 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1185 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1186 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1188 BranchList::const_iterator it = branchlist().begin();
1189 BranchList::const_iterator end = branchlist().end();
1190 for (; it != end; ++it) {
1191 os << "\\branch " << to_utf8(it->branch())
1192 << "\n\\selected " << it->isSelected()
1193 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1194 << "\n\\color " << lyx::X11hexname(it->color())
1199 IndicesList::const_iterator iit = indiceslist().begin();
1200 IndicesList::const_iterator iend = indiceslist().end();
1201 for (; iit != iend; ++iit) {
1202 os << "\\index " << to_utf8(iit->index())
1203 << "\n\\shortcut " << to_utf8(iit->shortcut())
1204 << "\n\\color " << lyx::X11hexname(iit->color())
1209 if (!paperwidth.empty())
1210 os << "\\paperwidth "
1211 << VSpace(paperwidth).asLyXCommand() << '\n';
1212 if (!paperheight.empty())
1213 os << "\\paperheight "
1214 << VSpace(paperheight).asLyXCommand() << '\n';
1215 if (!leftmargin.empty())
1216 os << "\\leftmargin "
1217 << VSpace(leftmargin).asLyXCommand() << '\n';
1218 if (!topmargin.empty())
1219 os << "\\topmargin "
1220 << VSpace(topmargin).asLyXCommand() << '\n';
1221 if (!rightmargin.empty())
1222 os << "\\rightmargin "
1223 << VSpace(rightmargin).asLyXCommand() << '\n';
1224 if (!bottommargin.empty())
1225 os << "\\bottommargin "
1226 << VSpace(bottommargin).asLyXCommand() << '\n';
1227 if (!headheight.empty())
1228 os << "\\headheight "
1229 << VSpace(headheight).asLyXCommand() << '\n';
1230 if (!headsep.empty())
1232 << VSpace(headsep).asLyXCommand() << '\n';
1233 if (!footskip.empty())
1235 << VSpace(footskip).asLyXCommand() << '\n';
1236 if (!columnsep.empty())
1237 os << "\\columnsep "
1238 << VSpace(columnsep).asLyXCommand() << '\n';
1239 os << "\\secnumdepth " << secnumdepth
1240 << "\n\\tocdepth " << tocdepth
1241 << "\n\\paragraph_separation "
1242 << string_paragraph_separation[paragraph_separation];
1243 if (!paragraph_separation)
1244 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1246 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1247 os << "\n\\quotes_language "
1248 << string_quotes_language[quotes_language]
1249 << "\n\\papercolumns " << columns
1250 << "\n\\papersides " << sides
1251 << "\n\\paperpagestyle " << pagestyle << '\n';
1252 if (!listings_params.empty())
1253 os << "\\listings_params \"" <<
1254 InsetListingsParams(listings_params).encodedString() << "\"\n";
1255 for (int i = 0; i < 4; ++i) {
1256 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1257 if (user_defined_bullet(i).getFont() != -1) {
1258 os << "\\bullet " << i << " "
1259 << user_defined_bullet(i).getFont() << " "
1260 << user_defined_bullet(i).getCharacter() << " "
1261 << user_defined_bullet(i).getSize() << "\n";
1265 os << "\\bulletLaTeX " << i << " \""
1266 << lyx::to_ascii(user_defined_bullet(i).getText())
1272 os << "\\tracking_changes " << convert<string>(track_changes) << '\n'
1273 << "\\output_changes " << convert<string>(output_changes) << '\n'
1274 << "\\html_math_output " << html_math_output << '\n'
1275 << "\\html_css_as_file " << html_css_as_file << '\n'
1276 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1278 if (html_math_img_scale != 1.0)
1279 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1280 if (!html_latex_start.empty())
1281 os << "\\html_latex_start " << html_latex_start << '\n';
1282 if (!html_latex_end.empty())
1283 os << "\\html_latex_end " << html_latex_end << '\n';
1285 os << pimpl_->authorlist;
1289 void BufferParams::validate(LaTeXFeatures & features) const
1291 features.require(documentClass().requires());
1293 if (columns > 1 && language->rightToLeft())
1294 features.require("rtloutputdblcol");
1296 if (output_changes) {
1297 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1298 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1299 LaTeXFeatures::isAvailable("xcolor");
1301 switch (features.runparams().flavor) {
1302 case OutputParams::LATEX:
1303 case OutputParams::DVILUATEX:
1305 features.require("ct-dvipost");
1306 features.require("dvipost");
1307 } else if (xcolorulem) {
1308 features.require("ct-xcolor-ulem");
1309 features.require("ulem");
1310 features.require("xcolor");
1312 features.require("ct-none");
1315 case OutputParams::LUATEX:
1316 case OutputParams::PDFLATEX:
1317 case OutputParams::XETEX:
1319 features.require("ct-xcolor-ulem");
1320 features.require("ulem");
1321 features.require("xcolor");
1322 // improves color handling in PDF output
1323 features.require("pdfcolmk");
1325 features.require("ct-none");
1333 // Floats with 'Here definitely' as default setting.
1334 if (float_placement.find('H') != string::npos)
1335 features.require("float");
1337 for (PackageMap::const_iterator it = use_packages.begin();
1338 it != use_packages.end(); ++it) {
1339 if (it->first == "amsmath") {
1340 // AMS Style is at document level
1341 if (it->second == package_on ||
1342 features.isProvided("amsmath"))
1343 features.require(it->first);
1344 } else if (it->second == package_on)
1345 features.require(it->first);
1348 // Document-level line spacing
1349 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1350 features.require("setspace");
1352 // the bullet shapes are buffer level not paragraph level
1353 // so they are tested here
1354 for (int i = 0; i < 4; ++i) {
1355 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1357 int const font = user_defined_bullet(i).getFont();
1359 int const c = user_defined_bullet(i).getCharacter();
1365 features.require("latexsym");
1367 } else if (font == 1) {
1368 features.require("amssymb");
1369 } else if (font >= 2 && font <= 5) {
1370 features.require("pifont");
1374 if (pdfoptions().use_hyperref) {
1375 features.require("hyperref");
1376 // due to interferences with babel and hyperref, the color package has to
1377 // be loaded after hyperref when hyperref is used with the colorlinks
1378 // option, see http://www.lyx.org/trac/ticket/5291
1379 if (pdfoptions().colorlinks)
1380 features.require("color");
1382 if (!listings_params.empty()) {
1383 // do not test validity because listings_params is
1384 // supposed to be valid
1386 InsetListingsParams(listings_params).separatedParams(true);
1387 // we can't support all packages, but we should load the color package
1388 if (par.find("\\color", 0) != string::npos)
1389 features.require("color");
1392 // some languages are only available via polyglossia
1393 if ((features.runparams().flavor == OutputParams::XETEX
1394 || features.runparams().flavor == OutputParams::LUATEX)
1395 && (features.hasPolyglossiaExclusiveLanguages()
1397 features.require("polyglossia");
1399 if (useNonTeXFonts && fontsMath() != "auto")
1400 features.require("unicode-math");
1402 if (!language->requires().empty())
1403 features.require(language->requires());
1407 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1408 FileName const & filepath) const
1410 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1411 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1412 // \RequirePackage to do so, rather than the normal \usepackage
1413 // Do not try to load any other package before the document class, unless you
1414 // have a thorough understanding of the LATEX internals and know exactly what you
1416 if (features.mustProvide("fix-cm"))
1417 os << "\\RequirePackage{fix-cm}\n";
1418 // Likewise for fixltx2e. If other packages conflict with this policy,
1419 // treat it as a package bug (and report it!)
1420 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1421 if (features.mustProvide("fixltx2e"))
1422 os << "\\RequirePackage{fixltx2e}\n";
1424 os << "\\documentclass";
1426 DocumentClass const & tclass = documentClass();
1428 ostringstream clsoptions; // the document class options.
1430 if (tokenPos(tclass.opt_fontsize(),
1431 '|', fontsize) >= 0) {
1432 // only write if existing in list (and not default)
1433 clsoptions << fontsize << "pt,";
1436 // all paper sizes except of A4, A5, B5 and the US sizes need the
1438 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1439 && papersize != PAPER_USLETTER
1440 && papersize != PAPER_USLEGAL
1441 && papersize != PAPER_USEXECUTIVE
1442 && papersize != PAPER_A4
1443 && papersize != PAPER_A5
1444 && papersize != PAPER_B5;
1446 if (!use_geometry) {
1447 switch (papersize) {
1449 clsoptions << "a4paper,";
1451 case PAPER_USLETTER:
1452 clsoptions << "letterpaper,";
1455 clsoptions << "a5paper,";
1458 clsoptions << "b5paper,";
1460 case PAPER_USEXECUTIVE:
1461 clsoptions << "executivepaper,";
1464 clsoptions << "legalpaper,";
1498 if (sides != tclass.sides()) {
1501 clsoptions << "oneside,";
1504 clsoptions << "twoside,";
1510 if (columns != tclass.columns()) {
1512 clsoptions << "twocolumn,";
1514 clsoptions << "onecolumn,";
1518 && orientation == ORIENTATION_LANDSCAPE)
1519 clsoptions << "landscape,";
1521 // language should be a parameter to \documentclass
1522 if (language->babel() == "hebrew"
1523 && default_language->babel() != "hebrew")
1524 // This seems necessary
1525 features.useLanguage(default_language);
1527 ostringstream language_options;
1528 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1529 bool const use_polyglossia = features.usePolyglossia();
1530 bool const global = lyxrc.language_global_options;
1531 if (use_babel || (use_polyglossia && global)) {
1532 language_options << features.getBabelLanguages();
1533 if (!language->babel().empty()) {
1534 if (!language_options.str().empty())
1535 language_options << ',';
1536 language_options << language->babel();
1538 if (global && !features.needBabelLangOptions()
1539 && !language_options.str().empty())
1540 clsoptions << language_options.str() << ',';
1543 // the predefined options from the layout
1544 if (use_default_options && !tclass.options().empty())
1545 clsoptions << tclass.options() << ',';
1547 // the user-defined options
1548 if (!options.empty()) {
1549 clsoptions << options << ',';
1552 string strOptions(clsoptions.str());
1553 if (!strOptions.empty()) {
1554 strOptions = rtrim(strOptions, ",");
1556 os << '[' << from_utf8(strOptions) << ']';
1559 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1560 // end of \documentclass defs
1562 // if we use fontspec or newtxmath, we have to load the AMS packages here
1563 string const ams = features.loadAMSPackages();
1564 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1565 bool const use_newtxmath =
1566 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1567 ot1, false, false) == "newtxmath";
1568 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1569 os << from_ascii(ams);
1571 if (useNonTeXFonts) {
1572 os << "\\usepackage{fontspec}\n";
1573 if (features.mustProvide("unicode-math")
1574 && features.isAvailable("unicode-math"))
1575 os << "\\usepackage{unicode-math}\n";
1578 // font selection must be done before loading fontenc.sty
1579 string const fonts = loadFonts(features);
1581 os << from_utf8(fonts);
1583 if (fonts_default_family != "default")
1584 os << "\\renewcommand{\\familydefault}{\\"
1585 << from_ascii(fonts_default_family) << "}\n";
1587 // set font encoding
1588 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1589 if (!useNonTeXFonts && !features.isProvided("fontenc")
1590 && font_encoding() != "default") {
1591 // get main font encodings
1592 vector<string> fontencs = font_encodings();
1593 // get font encodings of secondary languages
1594 features.getFontEncodings(fontencs);
1595 if (!fontencs.empty()) {
1596 os << "\\usepackage["
1597 << from_ascii(getStringFromVector(fontencs))
1602 // handle inputenc etc.
1603 writeEncodingPreamble(os, features);
1606 if (!features.runparams().includeall && !included_children_.empty()) {
1607 os << "\\includeonly{";
1608 list<string>::const_iterator it = included_children_.begin();
1609 list<string>::const_iterator en = included_children_.end();
1611 for (; it != en; ++it) {
1612 string incfile = *it;
1613 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1614 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1616 if (!features.runparams().nice)
1618 // \includeonly doesn't want an extension
1619 incfile = changeExtension(incfile, string());
1620 incfile = support::latex_path(incfile);
1621 if (!incfile.empty()) {
1624 os << from_utf8(incfile);
1631 if (!features.isProvided("geometry")
1632 && (use_geometry || nonstandard_papersize)) {
1633 odocstringstream ods;
1634 if (!getGraphicsDriver("geometry").empty())
1635 ods << getGraphicsDriver("geometry");
1636 if (orientation == ORIENTATION_LANDSCAPE)
1637 ods << ",landscape";
1638 switch (papersize) {
1640 if (!paperwidth.empty())
1641 ods << ",paperwidth="
1642 << from_ascii(paperwidth);
1643 if (!paperheight.empty())
1644 ods << ",paperheight="
1645 << from_ascii(paperheight);
1647 case PAPER_USLETTER:
1648 ods << ",letterpaper";
1651 ods << ",legalpaper";
1653 case PAPER_USEXECUTIVE:
1654 ods << ",executivepaper";
1743 docstring const g_options = trim(ods.str(), ",");
1744 os << "\\usepackage";
1745 if (!g_options.empty())
1746 os << '[' << g_options << ']';
1747 os << "{geometry}\n";
1748 // output this only if use_geometry is true
1750 os << "\\geometry{verbose";
1751 if (!topmargin.empty())
1752 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1753 if (!bottommargin.empty())
1754 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1755 if (!leftmargin.empty())
1756 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1757 if (!rightmargin.empty())
1758 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1759 if (!headheight.empty())
1760 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1761 if (!headsep.empty())
1762 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1763 if (!footskip.empty())
1764 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1765 if (!columnsep.empty())
1766 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1769 } else if (orientation == ORIENTATION_LANDSCAPE
1770 || papersize != PAPER_DEFAULT) {
1771 features.require("papersize");
1774 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1775 if (pagestyle == "fancy")
1776 os << "\\usepackage{fancyhdr}\n";
1777 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1780 // only output when the background color is not default
1781 if (isbackgroundcolor == true) {
1782 // only require color here, the background color will be defined
1783 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1785 features.require("color");
1786 features.require("pagecolor");
1789 // only output when the font color is not default
1790 if (isfontcolor == true) {
1791 // only require color here, the font color will be defined
1792 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1794 features.require("color");
1795 features.require("fontcolor");
1798 // Only if class has a ToC hierarchy
1799 if (tclass.hasTocLevels()) {
1800 if (secnumdepth != tclass.secnumdepth()) {
1801 os << "\\setcounter{secnumdepth}{"
1805 if (tocdepth != tclass.tocdepth()) {
1806 os << "\\setcounter{tocdepth}{"
1812 if (paragraph_separation) {
1813 // when skip separation
1814 switch (getDefSkip().kind()) {
1815 case VSpace::SMALLSKIP:
1816 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1818 case VSpace::MEDSKIP:
1819 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1821 case VSpace::BIGSKIP:
1822 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1824 case VSpace::LENGTH:
1825 os << "\\setlength{\\parskip}{"
1826 << from_utf8(getDefSkip().length().asLatexString())
1829 default: // should never happen // Then delete it.
1830 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1833 os << "\\setlength{\\parindent}{0pt}\n";
1835 // when separation by indentation
1836 // only output something when a width is given
1837 if (getIndentation().asLyXCommand() != "default") {
1838 os << "\\setlength{\\parindent}{"
1839 << from_utf8(getIndentation().asLatexCommand())
1844 // Now insert the LyX specific LaTeX commands...
1845 docstring lyxpreamble;
1846 features.resolveAlternatives();
1849 if (!output_sync_macro.empty())
1850 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1851 else if (features.runparams().flavor == OutputParams::LATEX)
1852 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1853 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1854 lyxpreamble += "\\synctex=-1\n";
1857 // The package options (via \PassOptionsToPackage)
1858 lyxpreamble += from_ascii(features.getPackageOptions());
1860 // due to interferences with babel and hyperref, the color package has to
1861 // be loaded (when it is not already loaded) before babel when hyperref
1862 // is used with the colorlinks option, see
1863 // http://www.lyx.org/trac/ticket/5291
1864 // we decided therefore to load color always before babel, see
1865 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1866 lyxpreamble += from_ascii(features.getColorOptions());
1868 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1869 // we have to call babel before
1871 && (features.isRequired("jurabib")
1872 || features.isRequired("hyperref")
1873 || features.isRequired("varioref")
1874 || features.isRequired("vietnamese")
1875 || features.isRequired("japanese"))) {
1877 lyxpreamble += from_utf8(features.getBabelPresettings());
1878 lyxpreamble += from_utf8(babelCall(language_options.str(),
1879 features.needBabelLangOptions())) + '\n';
1880 lyxpreamble += from_utf8(features.getBabelPostsettings());
1883 // The optional packages;
1884 lyxpreamble += from_ascii(features.getPackages());
1886 // Additional Indices
1887 if (features.isRequired("splitidx")) {
1888 IndicesList::const_iterator iit = indiceslist().begin();
1889 IndicesList::const_iterator iend = indiceslist().end();
1890 for (; iit != iend; ++iit) {
1891 pair<docstring, docstring> indexname_latex =
1892 features.runparams().encoding->latexString(iit->index(),
1893 features.runparams().dryrun);
1894 if (!indexname_latex.second.empty()) {
1895 // issue a warning about omitted characters
1896 // FIXME: should be passed to the error dialog
1897 frontend::Alert::warning(_("Uncodable characters"),
1898 bformat(_("The following characters that are used in an index name are not\n"
1899 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1900 indexname_latex.second));
1902 lyxpreamble += "\\newindex[";
1903 lyxpreamble += indexname_latex.first;
1904 lyxpreamble += "]{";
1905 lyxpreamble += escape(iit->shortcut());
1906 lyxpreamble += "}\n";
1911 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1914 // * Hyperref manual: "Make sure it comes last of your loaded
1915 // packages, to give it a fighting chance of not being over-written,
1916 // since its job is to redefine many LaTeX commands."
1917 // * Email from Heiko Oberdiek: "It is usually better to load babel
1918 // before hyperref. Then hyperref has a chance to detect babel.
1919 // * Has to be loaded before the "LyX specific LaTeX commands" to
1920 // avoid errors with algorithm floats.
1921 // use hyperref explicitly if it is required
1922 if (features.isRequired("hyperref")) {
1923 // pass what we have to stream here, since we need
1924 // to access the stream itself in PDFOptions.
1927 OutputParams tmp_params = features.runparams();
1928 pdfoptions().writeLaTeX(tmp_params, os,
1929 features.isProvided("hyperref"));
1930 // set back for the rest
1931 lyxpreamble.clear();
1932 // correctly break URLs with hyperref and dvi output
1933 if (features.runparams().flavor == OutputParams::LATEX
1934 && features.isAvailable("breakurl"))
1935 lyxpreamble += "\\usepackage{breakurl}\n";
1936 } else if (features.isRequired("nameref"))
1937 // hyperref loads this automatically
1938 lyxpreamble += "\\usepackage{nameref}\n";
1940 // bibtopic needs to be loaded after hyperref.
1941 // the dot provides the aux file naming which LyX can detect.
1942 if (features.mustProvide("bibtopic"))
1943 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1945 // Will be surrounded by \makeatletter and \makeatother when not empty
1946 docstring atlyxpreamble;
1948 // Some macros LyX will need
1949 docstring tmppreamble(features.getMacros());
1951 if (!tmppreamble.empty())
1952 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1953 "LyX specific LaTeX commands.\n"
1954 + tmppreamble + '\n';
1956 // the text class specific preamble
1957 tmppreamble = features.getTClassPreamble();
1958 if (!tmppreamble.empty())
1959 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1960 "Textclass specific LaTeX commands.\n"
1961 + tmppreamble + '\n';
1963 // suppress date if selected
1964 // use \@ifundefined because we cannot be sure that every document class
1965 // has a \date command
1967 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1969 /* the user-defined preamble */
1970 if (!containsOnly(preamble, " \n\t")) {
1972 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1973 "User specified LaTeX commands.\n";
1975 // Check if the user preamble contains uncodable glyphs
1976 docstring const u_preamble = from_utf8(preamble);
1977 odocstringstream user_preamble;
1978 docstring uncodable_glyphs;
1979 Encoding const * const enc = features.runparams().encoding;
1981 for (size_t n = 0; n < u_preamble.size(); ++n) {
1982 char_type c = u_preamble[n];
1983 if (!enc->encodable(c)) {
1984 docstring const glyph(1, c);
1985 LYXERR0("Uncodable character '"
1987 << "' in user preamble!");
1988 uncodable_glyphs += glyph;
1989 if (features.runparams().dryrun) {
1990 user_preamble << "<" << _("LyX Warning: ")
1991 << _("uncodable character") << " '";
1992 user_preamble.put(c);
1993 user_preamble << "'>";
1996 user_preamble.put(c);
1999 user_preamble << u_preamble;
2001 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2002 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2003 frontend::Alert::warning(
2004 _("Uncodable character in user preamble"),
2006 _("The user preamble of your document contains glyphs "
2007 "that are unknown in the current document encoding "
2008 "(namely %1$s).\nThese glyphs are omitted "
2009 " from the output, which may result in "
2010 "incomplete output."
2011 "\n\nPlease select an appropriate "
2012 "document encoding\n"
2013 "(such as utf8) or change the "
2014 "preamble code accordingly."),
2017 atlyxpreamble += user_preamble.str() + '\n';
2020 // footmisc must be loaded after setspace
2021 // Load it here to avoid clashes with footmisc loaded in the user
2022 // preamble. For that reason we also pass the options via
2023 // \PassOptionsToPackage in getPreamble() and not here.
2024 if (features.mustProvide("footmisc"))
2025 atlyxpreamble += "\\usepackage{footmisc}\n";
2027 // subfig loads internally the LaTeX package "caption". As
2028 // caption is a very popular package, users will load it in
2029 // the preamble. Therefore we must load subfig behind the
2030 // user-defined preamble and check if the caption package was
2031 // loaded or not. For the case that caption is loaded before
2032 // subfig, there is the subfig option "caption=false". This
2033 // option also works when a koma-script class is used and
2034 // koma's own caption commands are used instead of caption. We
2035 // use \PassOptionsToPackage here because the user could have
2036 // already loaded subfig in the preamble.
2037 if (features.isRequired("subfig")) {
2038 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
2039 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2040 "\\usepackage{subfig}\n";
2043 // Itemize bullet settings need to be last in case the user
2044 // defines their own bullets that use a package included
2045 // in the user-defined preamble -- ARRae
2046 // Actually it has to be done much later than that
2047 // since some packages like frenchb make modifications
2048 // at \begin{document} time -- JMarc
2049 docstring bullets_def;
2050 for (int i = 0; i < 4; ++i) {
2051 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2052 if (bullets_def.empty())
2053 bullets_def += "\\AtBeginDocument{\n";
2054 bullets_def += " \\def\\labelitemi";
2056 // `i' is one less than the item to modify
2063 bullets_def += "ii";
2069 bullets_def += '{' +
2070 user_defined_bullet(i).getText()
2075 if (!bullets_def.empty())
2076 atlyxpreamble += bullets_def + "}\n\n";
2078 if (!atlyxpreamble.empty())
2079 lyxpreamble += "\n\\makeatletter\n"
2080 + atlyxpreamble + "\\makeatother\n\n";
2082 // We try to load babel late, in case it interferes with other packages.
2083 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
2084 // called after babel, though.
2085 if (use_babel && !features.isRequired("jurabib")
2086 && !features.isRequired("hyperref")
2087 && !features.isRequired("varioref")
2088 && !features.isRequired("vietnamese")
2089 && !features.isRequired("japanese")) {
2091 lyxpreamble += from_utf8(features.getBabelPresettings());
2092 lyxpreamble += from_utf8(babelCall(language_options.str(),
2093 features.needBabelLangOptions())) + '\n';
2094 lyxpreamble += from_utf8(features.getBabelPostsettings());
2096 if (features.isRequired("bicaption"))
2097 lyxpreamble += "\\usepackage{bicaption}\n";
2098 if (!listings_params.empty() || features.isRequired("listings"))
2099 lyxpreamble += "\\usepackage{listings}\n";
2100 if (!listings_params.empty()) {
2101 lyxpreamble += "\\lstset{";
2102 // do not test validity because listings_params is
2103 // supposed to be valid
2105 InsetListingsParams(listings_params).separatedParams(true);
2106 lyxpreamble += from_utf8(par);
2107 lyxpreamble += "}\n";
2110 // xunicode needs to be loaded at least after amsmath, amssymb,
2111 // esint and the other packages that provide special glyphs
2112 if (features.runparams().flavor == OutputParams::XETEX
2114 lyxpreamble += "\\usepackage{xunicode}\n";
2116 // Polyglossia must be loaded last
2117 if (use_polyglossia) {
2119 lyxpreamble += "\\usepackage{polyglossia}\n";
2120 // set the main language
2121 lyxpreamble += "\\setdefaultlanguage";
2122 if (!language->polyglossiaOpts().empty())
2123 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
2124 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
2125 // now setup the other languages
2126 std::map<std::string, std::string> const polylangs =
2127 features.getPolyglossiaLanguages();
2128 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
2129 mit != polylangs.end() ; ++mit) {
2130 lyxpreamble += "\\setotherlanguage";
2131 if (!mit->second.empty())
2132 lyxpreamble += "[" + from_ascii(mit->second) + "]";
2133 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
2137 // Load custom language package here
2138 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2139 if (lang_package == "default")
2140 lyxpreamble += from_utf8(lyxrc.language_custom_package);
2142 lyxpreamble += from_utf8(lang_package);
2143 lyxpreamble += '\n';
2146 docstring const i18npreamble =
2147 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2148 if (!i18npreamble.empty())
2149 lyxpreamble += i18npreamble + '\n';
2157 void BufferParams::useClassDefaults()
2159 DocumentClass const & tclass = documentClass();
2161 sides = tclass.sides();
2162 columns = tclass.columns();
2163 pagestyle = tclass.pagestyle();
2164 use_default_options = true;
2165 // Only if class has a ToC hierarchy
2166 if (tclass.hasTocLevels()) {
2167 secnumdepth = tclass.secnumdepth();
2168 tocdepth = tclass.tocdepth();
2173 bool BufferParams::hasClassDefaults() const
2175 DocumentClass const & tclass = documentClass();
2177 return sides == tclass.sides()
2178 && columns == tclass.columns()
2179 && pagestyle == tclass.pagestyle()
2180 && use_default_options
2181 && secnumdepth == tclass.secnumdepth()
2182 && tocdepth == tclass.tocdepth();
2186 DocumentClass const & BufferParams::documentClass() const
2188 return *doc_class_.get();
2192 DocumentClassConstPtr BufferParams::documentClassPtr() const
2198 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2200 // evil, but this function is evil
2201 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2205 bool BufferParams::setBaseClass(string const & classname)
2207 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2208 LayoutFileList & bcl = LayoutFileList::get();
2209 if (!bcl.haveClass(classname)) {
2211 bformat(_("The layout file:\n"
2213 "could not be found. A default textclass with default\n"
2214 "layouts will be used. LyX will not be able to produce\n"
2216 from_utf8(classname));
2217 frontend::Alert::error(_("Document class not found"), s);
2218 bcl.addEmptyClass(classname);
2221 bool const success = bcl[classname].load();
2224 bformat(_("Due to some error in it, the layout file:\n"
2226 "could not be loaded. A default textclass with default\n"
2227 "layouts will be used. LyX will not be able to produce\n"
2229 from_utf8(classname));
2230 frontend::Alert::error(_("Could not load class"), s);
2231 bcl.addEmptyClass(classname);
2234 pimpl_->baseClass_ = classname;
2235 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2240 LayoutFile const * BufferParams::baseClass() const
2242 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2243 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2249 LayoutFileIndex const & BufferParams::baseClassID() const
2251 return pimpl_->baseClass_;
2255 void BufferParams::makeDocumentClass(bool const clone)
2260 LayoutModuleList mods;
2261 LayoutModuleList::iterator it = layout_modules_.begin();
2262 LayoutModuleList::iterator en = layout_modules_.end();
2263 for (; it != en; ++it)
2264 mods.push_back(*it);
2266 it = cite_engine_.begin();
2267 en = cite_engine_.end();
2268 for (; it != en; ++it)
2269 mods.push_back(*it);
2271 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2273 TextClass::ReturnValues success = TextClass::OK;
2274 if (!forced_local_layout_.empty())
2275 success = doc_class_->read(forced_local_layout_, TextClass::MODULE);
2276 if (!local_layout_.empty() &&
2277 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2278 success = doc_class_->read(local_layout_, TextClass::MODULE);
2279 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2280 docstring const msg = _("Error reading internal layout information");
2281 frontend::Alert::warning(_("Read Error"), msg);
2286 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2288 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2292 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2294 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2298 std::string BufferParams::getLocalLayout(bool forced) const
2301 return doc_class_->forcedLayouts();
2303 return local_layout_;
2307 void BufferParams::setLocalLayout(string const & layout, bool forced)
2310 forced_local_layout_ = layout;
2312 local_layout_ = layout;
2316 bool BufferParams::addLayoutModule(string const & modName)
2318 LayoutModuleList::const_iterator it = layout_modules_.begin();
2319 LayoutModuleList::const_iterator end = layout_modules_.end();
2320 for (; it != end; ++it)
2323 layout_modules_.push_back(modName);
2328 string BufferParams::bufferFormat() const
2330 string format = documentClass().outputFormat();
2331 if (format == "latex") {
2333 return "xetex"; // actually "xetex or luatex"
2334 if (encoding().package() == Encoding::japanese)
2341 bool BufferParams::isExportable(string const & format) const
2343 vector<string> backs = backends();
2344 for (vector<string>::const_iterator it = backs.begin();
2345 it != backs.end(); ++it)
2346 if (theConverters().isReachable(*it, format))
2352 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2354 vector<string> const backs = backends();
2355 set<string> excludes;
2356 if (useNonTeXFonts) {
2357 excludes.insert("latex");
2358 excludes.insert("pdflatex");
2360 vector<Format const *> result =
2361 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2362 for (vector<string>::const_iterator it = backs.begin() + 1;
2363 it != backs.end(); ++it) {
2364 vector<Format const *> r =
2365 theConverters().getReachable(*it, only_viewable, false, excludes);
2366 result.insert(result.end(), r.begin(), r.end());
2372 bool BufferParams::isExportableFormat(string const & format) const
2374 typedef vector<Format const *> Formats;
2376 formats = exportableFormats(true);
2377 Formats::const_iterator fit = formats.begin();
2378 Formats::const_iterator end = formats.end();
2379 for (; fit != end ; ++fit) {
2380 if ((*fit)->name() == format)
2387 vector<string> BufferParams::backends() const
2390 string const buffmt = bufferFormat();
2392 // FIXME: Don't hardcode format names here, but use a flag
2393 if (buffmt == "latex") {
2394 if (!useNonTeXFonts) {
2395 v.push_back("pdflatex");
2396 v.push_back("latex");
2398 v.push_back("luatex");
2399 v.push_back("dviluatex");
2400 v.push_back("xetex");
2401 } else if (buffmt == "xetex") {
2402 v.push_back("xetex");
2403 // FIXME: need to test all languages (bug 8205)
2404 if (!language || !language->isPolyglossiaExclusive()) {
2405 v.push_back("luatex");
2406 v.push_back("dviluatex");
2409 v.push_back(buffmt);
2411 v.push_back("xhtml");
2412 v.push_back("text");
2418 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2420 string const dformat = (format.empty() || format == "default") ?
2421 getDefaultOutputFormat() : format;
2422 DefaultFlavorCache::const_iterator it =
2423 default_flavors_.find(dformat);
2425 if (it != default_flavors_.end())
2428 OutputParams::FLAVOR result = OutputParams::LATEX;
2430 // FIXME It'd be better not to hardcode this, but to do
2431 // something with formats.
2432 if (dformat == "xhtml")
2433 result = OutputParams::HTML;
2434 else if (dformat == "text")
2435 result = OutputParams::TEXT;
2436 else if (dformat == "lyx")
2437 result = OutputParams::LYX;
2438 else if (dformat == "pdflatex")
2439 result = OutputParams::PDFLATEX;
2440 else if (dformat == "xetex")
2441 result = OutputParams::XETEX;
2442 else if (dformat == "luatex")
2443 result = OutputParams::LUATEX;
2444 else if (dformat == "dviluatex")
2445 result = OutputParams::DVILUATEX;
2447 // Try to determine flavor of default output format
2448 vector<string> backs = backends();
2449 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2450 // Get shortest path to format
2451 Graph::EdgePath path;
2452 for (vector<string>::const_iterator it = backs.begin();
2453 it != backs.end(); ++it) {
2454 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2455 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2460 result = theConverters().getFlavor(path);
2463 // cache this flavor
2464 default_flavors_[dformat] = result;
2469 string BufferParams::getDefaultOutputFormat() const
2471 if (!default_output_format.empty()
2472 && default_output_format != "default")
2473 return default_output_format;
2475 || encoding().package() == Encoding::japanese) {
2476 vector<Format const *> const formats = exportableFormats(true);
2477 if (formats.empty())
2479 // return the first we find
2480 return formats.front()->name();
2483 return lyxrc.default_otf_view_format;
2484 return lyxrc.default_view_format;
2487 Font const BufferParams::getFont() const
2489 FontInfo f = documentClass().defaultfont();
2490 if (fonts_default_family == "rmdefault")
2491 f.setFamily(ROMAN_FAMILY);
2492 else if (fonts_default_family == "sfdefault")
2493 f.setFamily(SANS_FAMILY);
2494 else if (fonts_default_family == "ttdefault")
2495 f.setFamily(TYPEWRITER_FAMILY);
2496 return Font(f, language);
2500 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const & qs) const
2502 return quoteslangtranslator().find(qs);
2506 bool BufferParams::isLatex() const
2508 return documentClass().outputType() == LATEX;
2512 bool BufferParams::isLiterate() const
2514 return documentClass().outputType() == LITERATE;
2518 bool BufferParams::isDocBook() const
2520 return documentClass().outputType() == DOCBOOK;
2524 void BufferParams::readPreamble(Lexer & lex)
2526 if (lex.getString() != "\\begin_preamble")
2527 lyxerr << "Error (BufferParams::readPreamble):"
2528 "consistency check failed." << endl;
2530 preamble = lex.getLongString("\\end_preamble");
2534 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2536 string const expected = forced ? "\\begin_forced_local_layout" :
2537 "\\begin_local_layout";
2538 if (lex.getString() != expected)
2539 lyxerr << "Error (BufferParams::readLocalLayout):"
2540 "consistency check failed." << endl;
2543 forced_local_layout_ =
2544 lex.getLongString("\\end_forced_local_layout");
2546 local_layout_ = lex.getLongString("\\end_local_layout");
2550 bool BufferParams::setLanguage(string const & lang)
2552 Language const *new_language = languages.getLanguage(lang);
2553 if (!new_language) {
2554 // Language lang was not found
2557 language = new_language;
2562 void BufferParams::readLanguage(Lexer & lex)
2564 if (!lex.next()) return;
2566 string const tmptok = lex.getString();
2568 // check if tmptok is part of tex_babel in tex-defs.h
2569 if (!setLanguage(tmptok)) {
2570 // Language tmptok was not found
2571 language = default_language;
2572 lyxerr << "Warning: Setting language `"
2573 << tmptok << "' to `" << language->lang()
2579 void BufferParams::readGraphicsDriver(Lexer & lex)
2584 string const tmptok = lex.getString();
2585 // check if tmptok is part of tex_graphics in tex_defs.h
2588 string const test = tex_graphics[n++];
2590 if (test == tmptok) {
2591 graphics_driver = tmptok;
2596 "Warning: graphics driver `$$Token' not recognized!\n"
2597 " Setting graphics driver to `default'.\n");
2598 graphics_driver = "default";
2605 void BufferParams::readBullets(Lexer & lex)
2610 int const index = lex.getInteger();
2612 int temp_int = lex.getInteger();
2613 user_defined_bullet(index).setFont(temp_int);
2614 temp_bullet(index).setFont(temp_int);
2616 user_defined_bullet(index).setCharacter(temp_int);
2617 temp_bullet(index).setCharacter(temp_int);
2619 user_defined_bullet(index).setSize(temp_int);
2620 temp_bullet(index).setSize(temp_int);
2624 void BufferParams::readBulletsLaTeX(Lexer & lex)
2626 // The bullet class should be able to read this.
2629 int const index = lex.getInteger();
2631 docstring const temp_str = lex.getDocString();
2633 user_defined_bullet(index).setText(temp_str);
2634 temp_bullet(index).setText(temp_str);
2638 void BufferParams::readModules(Lexer & lex)
2640 if (!lex.eatLine()) {
2641 lyxerr << "Error (BufferParams::readModules):"
2642 "Unexpected end of input." << endl;
2646 string mod = lex.getString();
2647 if (mod == "\\end_modules")
2649 addLayoutModule(mod);
2655 void BufferParams::readRemovedModules(Lexer & lex)
2657 if (!lex.eatLine()) {
2658 lyxerr << "Error (BufferParams::readRemovedModules):"
2659 "Unexpected end of input." << endl;
2663 string mod = lex.getString();
2664 if (mod == "\\end_removed_modules")
2666 removed_modules_.push_back(mod);
2669 // now we want to remove any removed modules that were previously
2670 // added. normally, that will be because default modules were added in
2671 // setBaseClass(), which gets called when \textclass is read at the
2672 // start of the read.
2673 list<string>::const_iterator rit = removed_modules_.begin();
2674 list<string>::const_iterator const ren = removed_modules_.end();
2675 for (; rit != ren; ++rit) {
2676 LayoutModuleList::iterator const mit = layout_modules_.begin();
2677 LayoutModuleList::iterator const men = layout_modules_.end();
2678 LayoutModuleList::iterator found = find(mit, men, *rit);
2681 layout_modules_.erase(found);
2686 void BufferParams::readIncludeonly(Lexer & lex)
2688 if (!lex.eatLine()) {
2689 lyxerr << "Error (BufferParams::readIncludeonly):"
2690 "Unexpected end of input." << endl;
2694 string child = lex.getString();
2695 if (child == "\\end_includeonly")
2697 included_children_.push_back(child);
2703 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2705 switch (papersize) {
2707 // could be anything, so don't guess
2709 case PAPER_CUSTOM: {
2710 if (purpose == XDVI && !paperwidth.empty() &&
2711 !paperheight.empty()) {
2712 // heightxwidth<unit>
2713 string first = paperwidth;
2714 string second = paperheight;
2715 if (orientation == ORIENTATION_LANDSCAPE)
2718 return first.erase(first.length() - 2)
2724 // dvips and dvipdfm do not know this
2725 if (purpose == DVIPS || purpose == DVIPDFM)
2729 if (purpose == DVIPS || purpose == DVIPDFM)
2733 if (purpose == DVIPS || purpose == DVIPDFM)
2743 if (purpose == DVIPS || purpose == DVIPDFM)
2747 if (purpose == DVIPS || purpose == DVIPDFM)
2751 if (purpose == DVIPS || purpose == DVIPDFM)
2755 if (purpose == DVIPS || purpose == DVIPDFM)
2759 if (purpose == DVIPS || purpose == DVIPDFM)
2763 // dvipdfm does not know this
2764 if (purpose == DVIPDFM)
2768 if (purpose == DVIPDFM)
2772 if (purpose == DVIPS || purpose == DVIPDFM)
2776 if (purpose == DVIPS || purpose == DVIPDFM)
2780 if (purpose == DVIPS || purpose == DVIPDFM)
2784 if (purpose == DVIPS || purpose == DVIPDFM)
2788 if (purpose == DVIPS || purpose == DVIPDFM)
2792 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 if (purpose == DVIPS || purpose == DVIPDFM)
2820 if (purpose == DVIPS || purpose == DVIPDFM)
2824 if (purpose == DVIPS || purpose == DVIPDFM)
2828 if (purpose == DVIPS || purpose == DVIPDFM)
2831 case PAPER_USEXECUTIVE:
2832 // dvipdfm does not know this
2833 if (purpose == DVIPDFM)
2838 case PAPER_USLETTER:
2840 if (purpose == XDVI)
2847 string const BufferParams::dvips_options() const
2851 // If the class loads the geometry package, we do not know which
2852 // paper size is used, since we do not set it (bug 7013).
2853 // Therefore we must not specify any argument here.
2854 // dvips gets the correct paper size via DVI specials in this case
2855 // (if the class uses the geometry package correctly).
2856 if (documentClass().provides("geometry"))
2860 && papersize == PAPER_CUSTOM
2861 && !lyxrc.print_paper_dimension_flag.empty()
2862 && !paperwidth.empty()
2863 && !paperheight.empty()) {
2864 // using a custom papersize
2865 result = lyxrc.print_paper_dimension_flag;
2866 result += ' ' + paperwidth;
2867 result += ',' + paperheight;
2869 string const paper_option = paperSizeName(DVIPS);
2870 if (!paper_option.empty() && (paper_option != "letter" ||
2871 orientation != ORIENTATION_LANDSCAPE)) {
2872 // dvips won't accept -t letter -t landscape.
2873 // In all other cases, include the paper size
2875 result = lyxrc.print_paper_flag;
2876 result += ' ' + paper_option;
2879 if (orientation == ORIENTATION_LANDSCAPE &&
2880 papersize != PAPER_CUSTOM)
2881 result += ' ' + lyxrc.print_landscape_flag;
2886 string const BufferParams::font_encoding() const
2888 return font_encodings().empty() ? "default" : font_encodings().back();
2892 vector<string> const BufferParams::font_encodings() const
2894 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2896 vector<string> fontencs;
2898 // "default" means "no explicit font encoding"
2899 if (doc_fontenc != "default") {
2900 fontencs = getVectorFromString(doc_fontenc);
2901 if (!language->fontenc().empty()
2902 && ascii_lowercase(language->fontenc()) != "none") {
2903 vector<string> fencs = getVectorFromString(language->fontenc());
2904 vector<string>::const_iterator fit = fencs.begin();
2905 for (; fit != fencs.end(); ++fit) {
2906 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
2907 fontencs.push_back(*fit);
2916 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2918 // suppress the babel call if there is no BabelName defined
2919 // for the document language in the lib/languages file and if no
2920 // other languages are used (lang_opts is then empty)
2921 if (lang_opts.empty())
2923 // either a specific language (AsBabelOptions setting in
2924 // lib/languages) or the prefs require the languages to
2925 // be submitted to babel itself (not the class).
2927 return "\\usepackage[" + lang_opts + "]{babel}";
2928 return "\\usepackage{babel}";
2932 docstring BufferParams::getGraphicsDriver(string const & package) const
2936 if (package == "geometry") {
2937 if (graphics_driver == "dvips"
2938 || graphics_driver == "dvipdfm"
2939 || graphics_driver == "pdftex"
2940 || graphics_driver == "vtex")
2941 result = from_ascii(graphics_driver);
2942 else if (graphics_driver == "dvipdfmx")
2943 result = from_ascii("dvipdfm");
2950 void BufferParams::writeEncodingPreamble(otexstream & os,
2951 LaTeXFeatures & features) const
2953 // XeTeX/LuaTeX: (see also #9740)
2954 // With Unicode fonts we use utf8-plain without encoding package.
2955 // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails.
2956 // XeTeX must use ASCII encoding, for LuaTeX, we load
2957 // "luainputenc" (see below).
2958 if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
2961 if (inputenc == "auto") {
2962 string const doc_encoding =
2963 language->encoding()->latexName();
2964 Encoding::Package const package =
2965 language->encoding()->package();
2967 // Create list of inputenc options:
2968 set<string> encodings;
2969 // luainputenc fails with more than one encoding
2970 if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts
2971 // list all input encodings used in the document
2972 encodings = features.getEncodingSet(doc_encoding);
2974 // If the "japanese" package (i.e. pLaTeX) is used,
2975 // inputenc must be omitted.
2976 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2977 if ((!encodings.empty() || package == Encoding::inputenc)
2978 && !features.isRequired("japanese")
2979 && !features.isProvided("inputenc")) {
2980 os << "\\usepackage[";
2981 set<string>::const_iterator it = encodings.begin();
2982 set<string>::const_iterator const end = encodings.end();
2984 os << from_ascii(*it);
2987 for (; it != end; ++it)
2988 os << ',' << from_ascii(*it);
2989 if (package == Encoding::inputenc) {
2990 if (!encodings.empty())
2992 os << from_ascii(doc_encoding);
2994 if (features.runparams().flavor == OutputParams::LUATEX
2995 || features.runparams().flavor == OutputParams::DVILUATEX)
2996 os << "]{luainputenc}\n";
2998 os << "]{inputenc}\n";
3000 if (package == Encoding::CJK || features.mustProvide("CJK")) {
3001 if (language->encoding()->name() == "utf8-cjk"
3002 && LaTeXFeatures::isAvailable("CJKutf8"))
3003 os << "\\usepackage{CJKutf8}\n";
3005 os << "\\usepackage{CJK}\n";
3007 } else if (inputenc != "default") {
3008 switch (encoding().package()) {
3009 case Encoding::none:
3010 case Encoding::japanese:
3012 case Encoding::inputenc:
3013 // do not load inputenc if japanese is used
3014 // or if the class provides inputenc
3015 if (features.isRequired("japanese")
3016 || features.isProvided("inputenc"))
3018 os << "\\usepackage[" << from_ascii(encoding().latexName());
3019 if (features.runparams().flavor == OutputParams::LUATEX
3020 || features.runparams().flavor == OutputParams::DVILUATEX)
3021 os << "]{luainputenc}\n";
3023 os << "]{inputenc}\n";
3026 if (encoding().name() == "utf8-cjk"
3027 && LaTeXFeatures::isAvailable("CJKutf8"))
3028 os << "\\usepackage{CJKutf8}\n";
3030 os << "\\usepackage{CJK}\n";
3033 // Load the CJK package if needed by a secondary language.
3034 // If the main encoding is some variant of UTF8, use CJKutf8.
3035 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
3036 if (encoding().iconvName() == "UTF-8"
3037 && LaTeXFeatures::isAvailable("CJKutf8"))
3038 os << "\\usepackage{CJKutf8}\n";
3040 os << "\\usepackage{CJK}\n";
3046 string const BufferParams::parseFontName(string const & name) const
3048 string mangled = name;
3049 size_t const idx = mangled.find('[');
3050 if (idx == string::npos || idx == 0)
3053 return mangled.substr(0, idx - 1);
3057 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3059 if (fontsRoman() == "default" && fontsSans() == "default"
3060 && fontsTypewriter() == "default"
3061 && (fontsMath() == "default" || fontsMath() == "auto"))
3067 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3068 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3069 * Mapping=tex-text option assures TeX ligatures (such as "--")
3070 * are resolved. Note that tt does not use these ligatures.
3072 * -- add more GUI options?
3073 * -- add more fonts (fonts for other scripts)
3074 * -- if there's a way to find out if a font really supports
3075 * OldStyle, enable/disable the widget accordingly.
3077 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3078 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3079 // However, until v.2 (2010/07/11) fontspec only knew
3080 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3081 // was introduced for both XeTeX and LuaTeX (LuaTeX
3082 // didn't understand "Mapping=tex-text", while XeTeX
3083 // understood both. With most recent versions, both
3084 // variants are understood by both engines. However,
3085 // we want to provide support for at least TeXLive 2009
3086 // (for XeTeX; LuaTeX is only supported as of v.2)
3087 string const texmapping =
3088 (features.runparams().flavor == OutputParams::XETEX) ?
3089 "Mapping=tex-text" : "Ligatures=TeX";
3090 if (fontsRoman() != "default") {
3091 os << "\\setmainfont[" << texmapping;
3092 if (fonts_old_figures)
3093 os << ",Numbers=OldStyle";
3094 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3096 if (fontsSans() != "default") {
3097 string const sans = parseFontName(fontsSans());
3098 if (fontsSansScale() != 100)
3099 os << "\\setsansfont[Scale="
3100 << float(fontsSansScale()) / 100
3101 << "," << texmapping << "]{"
3104 os << "\\setsansfont[" << texmapping << "]{"
3107 if (fontsTypewriter() != "default") {
3108 string const mono = parseFontName(fontsTypewriter());
3109 if (fontsTypewriterScale() != 100)
3110 os << "\\setmonofont[Scale="
3111 << float(fontsTypewriterScale()) / 100
3115 os << "\\setmonofont{"
3122 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
3123 bool const dryrun = features.runparams().dryrun;
3124 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3125 bool const nomath = (fontsMath() == "default");
3128 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3129 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3133 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3134 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3135 nomath, fontsSansScale());
3137 // MONOSPACED/TYPEWRITER
3138 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3139 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3140 nomath, fontsTypewriterScale());
3143 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3144 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3151 Encoding const & BufferParams::encoding() const
3153 // Main encoding for LaTeX output.
3155 // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740).
3156 // As the "flavor" is only known once export started, this
3157 // cannot be handled here. Instead, runparams.encoding is set
3158 // to ASCII in Buffer::makeLaTeXFile (for export)
3159 // and Buffer::writeLaTeXSource (for preview).
3161 return *(encodings.fromLyXName("utf8-plain"));
3162 if (inputenc == "auto" || inputenc == "default")
3163 return *language->encoding();
3164 Encoding const * const enc = encodings.fromLyXName(inputenc);
3167 LYXERR0("Unknown inputenc value `" << inputenc
3168 << "'. Using `auto' instead.");
3169 return *language->encoding();
3173 bool BufferParams::addCiteEngine(string const & engine)
3175 LayoutModuleList::const_iterator it = cite_engine_.begin();
3176 LayoutModuleList::const_iterator en = cite_engine_.end();
3177 for (; it != en; ++it)
3180 cite_engine_.push_back(engine);
3185 bool BufferParams::addCiteEngine(vector<string> const & engine)
3187 vector<string>::const_iterator it = engine.begin();
3188 vector<string>::const_iterator en = engine.end();
3190 for (; it != en; ++it)
3191 if (!addCiteEngine(*it))
3197 string const & BufferParams::defaultBiblioStyle() const
3199 return documentClass().defaultBiblioStyle();
3203 bool const & BufferParams::fullAuthorList() const
3205 return documentClass().fullAuthorList();
3209 void BufferParams::setCiteEngine(string const & engine)
3212 addCiteEngine(engine);
3216 void BufferParams::setCiteEngine(vector<string> const & engine)
3219 addCiteEngine(engine);
3223 vector<string> BufferParams::citeCommands() const
3225 static CitationStyle const default_style;
3226 vector<string> commands =
3227 documentClass().citeCommands(citeEngineType());
3228 if (commands.empty())
3229 commands.push_back(default_style.cmd);
3234 vector<CitationStyle> BufferParams::citeStyles() const
3236 static CitationStyle const default_style;
3237 vector<CitationStyle> styles =
3238 documentClass().citeStyles(citeEngineType());
3240 styles.push_back(default_style);