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 save_transient_properties = true;
373 track_changes = false;
374 output_changes = false;
375 use_default_options = true;
376 maintain_unincluded_children = false;
379 language = default_language;
381 fonts_roman[0] = "default";
382 fonts_roman[1] = "default";
383 fonts_sans[0] = "default";
384 fonts_sans[1] = "default";
385 fonts_typewriter[0] = "default";
386 fonts_typewriter[1] = "default";
387 fonts_math[0] = "auto";
388 fonts_math[1] = "auto";
389 fonts_default_family = "default";
390 useNonTeXFonts = false;
391 use_microtype = false;
392 fonts_expert_sc = false;
393 fonts_old_figures = false;
394 fonts_sans_scale[0] = 100;
395 fonts_sans_scale[1] = 100;
396 fonts_typewriter_scale[0] = 100;
397 fonts_typewriter_scale[1] = 100;
399 lang_package = "default";
400 graphics_driver = "default";
401 default_output_format = "default";
402 bibtex_command = "default";
403 index_command = "default";
406 listings_params = string();
407 pagestyle = "default";
408 suppress_date = false;
409 justification = true;
410 // no color is the default (white)
411 backgroundcolor = lyx::rgbFromHexName("#ffffff");
412 isbackgroundcolor = false;
413 // no color is the default (black)
414 fontcolor = lyx::rgbFromHexName("#000000");
416 // light gray is the default font color for greyed-out notes
417 notefontcolor = lyx::rgbFromHexName("#cccccc");
418 boxbgcolor = lyx::rgbFromHexName("#ff0000");
419 compressed = lyxrc.save_compressed;
420 for (int iter = 0; iter < 4; ++iter) {
421 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
422 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
425 indiceslist().addDefault(B_("Index"));
426 html_be_strict = false;
427 html_math_output = MathML;
428 html_math_img_scale = 1.0;
429 html_css_as_file = false;
430 display_pixel_ratio = 1.0;
435 // map current author
436 author_map_[pimpl_->authorlist.get(0).bufferId()] = 0;
440 docstring BufferParams::B_(string const & l10n) const
442 LASSERT(language, return from_utf8(l10n));
443 return getMessages(language->code()).get(l10n);
447 BufferParams::Package BufferParams::use_package(std::string const & p) const
449 PackageMap::const_iterator it = use_packages.find(p);
450 if (it == use_packages.end())
456 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
462 map<string, string> const & BufferParams::auto_packages()
464 static map<string, string> packages;
465 if (packages.empty()) {
466 // We could have a race condition here that two threads
467 // discover an empty map at the same time and want to fill
468 // it, but that is no problem, since the same contents is
469 // filled in twice then. Having the locker inside the
470 // packages.empty() condition has the advantage that we
471 // don't need the mutex overhead for simple reading.
473 Mutex::Locker locker(&mutex);
474 // adding a package here implies a file format change!
475 packages["amsmath"] =
476 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
477 packages["amssymb"] =
478 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
480 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
482 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
483 packages["mathdots"] =
484 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
485 packages["mathtools"] =
486 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
488 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
489 packages["stackrel"] =
490 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
491 packages["stmaryrd"] =
492 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");
493 packages["undertilde"] =
494 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
500 AuthorList & BufferParams::authors()
502 return pimpl_->authorlist;
506 AuthorList const & BufferParams::authors() const
508 return pimpl_->authorlist;
512 void BufferParams::addAuthor(Author a)
514 author_map_[a.bufferId()] = pimpl_->authorlist.record(a);
518 BranchList & BufferParams::branchlist()
520 return pimpl_->branchlist;
524 BranchList const & BufferParams::branchlist() const
526 return pimpl_->branchlist;
530 IndicesList & BufferParams::indiceslist()
532 return pimpl_->indiceslist;
536 IndicesList const & BufferParams::indiceslist() const
538 return pimpl_->indiceslist;
542 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
544 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
545 return pimpl_->temp_bullets[index];
549 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
551 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
552 return pimpl_->temp_bullets[index];
556 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
558 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
559 return pimpl_->user_defined_bullets[index];
563 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
565 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
566 return pimpl_->user_defined_bullets[index];
570 Spacing & BufferParams::spacing()
572 return pimpl_->spacing;
576 Spacing const & BufferParams::spacing() const
578 return pimpl_->spacing;
582 PDFOptions & BufferParams::pdfoptions()
584 return pimpl_->pdfoptions;
588 PDFOptions const & BufferParams::pdfoptions() const
590 return pimpl_->pdfoptions;
594 HSpace const & BufferParams::getIndentation() const
596 return pimpl_->indentation;
600 void BufferParams::setIndentation(HSpace const & indent)
602 pimpl_->indentation = indent;
606 VSpace const & BufferParams::getDefSkip() const
608 return pimpl_->defskip;
612 void BufferParams::setDefSkip(VSpace const & vs)
614 // DEFSKIP will cause an infinite loop
615 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
616 pimpl_->defskip = vs;
620 string BufferParams::readToken(Lexer & lex, string const & token,
621 FileName const & filepath)
625 if (token == "\\textclass") {
627 string const classname = lex.getString();
628 // if there exists a local layout file, ignore the system one
629 // NOTE: in this case, the textclass (.cls file) is assumed to
632 LayoutFileList & bcl = LayoutFileList::get();
633 if (!filepath.empty()) {
634 // If classname is an absolute path, the document is
635 // using a local layout file which could not be accessed
636 // by a relative path. In this case the path is correct
637 // even if the document was moved to a different
638 // location. However, we will have a problem if the
639 // document was generated on a different platform.
640 bool isabsolute = FileName::isAbsolute(classname);
641 string const classpath = onlyPath(classname);
642 string const path = isabsolute ? classpath
643 : FileName(addPath(filepath.absFileName(),
644 classpath)).realPath();
645 string const oldpath = isabsolute ? string()
646 : FileName(addPath(origin, classpath)).realPath();
647 tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
649 // that returns non-empty if a "local" layout file is found.
651 result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
652 from_utf8(filepath.absFileName())));
655 setBaseClass(onlyFileName(tcp));
657 setBaseClass(onlyFileName(classname));
658 // We assume that a tex class exists for local or unknown
659 // layouts so this warning, will only be given for system layouts.
660 if (!baseClass()->isTeXClassAvailable()) {
661 docstring const desc =
662 translateIfPossible(from_utf8(baseClass()->description()));
663 docstring const prereqs =
664 from_utf8(baseClass()->prerequisites());
665 docstring const msg =
666 bformat(_("The selected document class\n"
668 "requires external files that are not available.\n"
669 "The document class can still be used, but the\n"
670 "document cannot be compiled until the following\n"
671 "prerequisites are installed:\n"
673 "See section 3.1.2.2 (Class Availability) of the\n"
674 "User's Guide for more information."), desc, prereqs);
675 frontend::Alert::warning(_("Document class not available"),
678 } else if (token == "\\save_transient_properties") {
679 lex >> save_transient_properties;
680 } else if (token == "\\origin") {
682 origin = lex.getString();
683 string const sysdirprefix = "/systemlyxdir/";
684 if (prefixIs(origin, sysdirprefix)) {
685 origin.replace(0, sysdirprefix.length() - 1,
686 package().system_support().absFileName());
688 } else if (token == "\\begin_preamble") {
690 } else if (token == "\\begin_local_layout") {
691 readLocalLayout(lex, false);
692 } else if (token == "\\begin_forced_local_layout") {
693 readLocalLayout(lex, true);
694 } else if (token == "\\begin_modules") {
696 } else if (token == "\\begin_removed_modules") {
697 readRemovedModules(lex);
698 } else if (token == "\\begin_includeonly") {
699 readIncludeonly(lex);
700 } else if (token == "\\maintain_unincluded_children") {
701 lex >> maintain_unincluded_children;
702 } else if (token == "\\options") {
704 options = lex.getString();
705 } else if (token == "\\use_default_options") {
706 lex >> use_default_options;
707 } else if (token == "\\master") {
709 master = lex.getString();
710 if (!filepath.empty() && FileName::isAbsolute(origin)) {
711 bool const isabs = FileName::isAbsolute(master);
712 FileName const abspath(isabs ? master : origin + master);
713 bool const moved = filepath != FileName(origin);
714 if (moved && abspath.exists()) {
715 docstring const path = isabs
717 : from_utf8(abspath.realPath());
718 docstring const refpath =
719 from_utf8(filepath.absFileName());
720 master = to_utf8(makeRelPath(path, refpath));
723 } else if (token == "\\suppress_date") {
724 lex >> suppress_date;
725 } else if (token == "\\justification") {
726 lex >> justification;
727 } else if (token == "\\language") {
729 } else if (token == "\\language_package") {
731 lang_package = lex.getString();
732 } else if (token == "\\inputencoding") {
734 } else if (token == "\\graphics") {
735 readGraphicsDriver(lex);
736 } else if (token == "\\default_output_format") {
737 lex >> default_output_format;
738 } else if (token == "\\bibtex_command") {
740 bibtex_command = lex.getString();
741 } else if (token == "\\index_command") {
743 index_command = lex.getString();
744 } else if (token == "\\fontencoding") {
746 fontenc = lex.getString();
747 } else if (token == "\\font_roman") {
748 lex >> fonts_roman[0];
749 lex >> fonts_roman[1];
750 } else if (token == "\\font_sans") {
751 lex >> fonts_sans[0];
752 lex >> fonts_sans[1];
753 } else if (token == "\\font_typewriter") {
754 lex >> fonts_typewriter[0];
755 lex >> fonts_typewriter[1];
756 } else if (token == "\\font_math") {
757 lex >> fonts_math[0];
758 lex >> fonts_math[1];
759 } else if (token == "\\font_default_family") {
760 lex >> fonts_default_family;
761 } else if (token == "\\use_non_tex_fonts") {
762 lex >> useNonTeXFonts;
763 } else if (token == "\\font_sc") {
764 lex >> fonts_expert_sc;
765 } else if (token == "\\font_osf") {
766 lex >> fonts_old_figures;
767 } else if (token == "\\font_sf_scale") {
768 lex >> fonts_sans_scale[0];
769 lex >> fonts_sans_scale[1];
770 } else if (token == "\\font_tt_scale") {
771 lex >> fonts_typewriter_scale[0];
772 lex >> fonts_typewriter_scale[1];
773 } else if (token == "\\font_cjk") {
775 } else if (token == "\\use_microtype") {
776 lex >> use_microtype;
777 } else if (token == "\\paragraph_separation") {
780 paragraph_separation = parseptranslator().find(parsep);
781 } else if (token == "\\paragraph_indentation") {
783 string indentation = lex.getString();
784 pimpl_->indentation = HSpace(indentation);
785 } else if (token == "\\defskip") {
787 string const defskip = lex.getString();
788 pimpl_->defskip = VSpace(defskip);
789 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
791 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
792 } else if (token == "\\quotes_language") {
795 quotes_language = quoteslangtranslator().find(quotes_lang);
796 } else if (token == "\\papersize") {
799 papersize = papersizetranslator().find(ppsize);
800 } else if (token == "\\use_geometry") {
802 } else if (token == "\\use_package") {
807 use_package(package, packagetranslator().find(use));
808 } else if (token == "\\cite_engine") {
810 vector<string> engine = getVectorFromString(lex.getString());
811 setCiteEngine(engine);
812 } else if (token == "\\cite_engine_type") {
815 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
816 } else if (token == "\\biblio_style") {
818 biblio_style = lex.getString();
819 } else if (token == "\\use_bibtopic") {
821 } else if (token == "\\use_indices") {
823 } else if (token == "\\tracking_changes") {
824 lex >> track_changes;
825 } else if (token == "\\output_changes") {
826 lex >> output_changes;
827 } else if (token == "\\branch") {
829 docstring branch = lex.getDocString();
830 branchlist().add(branch);
833 string const tok = lex.getString();
834 if (tok == "\\end_branch")
836 Branch * branch_ptr = branchlist().find(branch);
837 if (tok == "\\selected") {
840 branch_ptr->setSelected(lex.getInteger());
842 if (tok == "\\filename_suffix") {
845 branch_ptr->setFileNameSuffix(lex.getInteger());
847 if (tok == "\\color") {
849 string color = lex.getString();
851 branch_ptr->setColor(color);
852 // Update also the Color table:
854 color = lcolor.getX11Name(Color_background);
856 lcolor.setColor(to_utf8(branch), color);
859 } else if (token == "\\index") {
861 docstring index = lex.getDocString();
863 indiceslist().add(index);
866 string const tok = lex.getString();
867 if (tok == "\\end_index")
869 Index * index_ptr = indiceslist().find(index);
870 if (tok == "\\shortcut") {
872 shortcut = lex.getDocString();
874 index_ptr->setShortcut(shortcut);
876 if (tok == "\\color") {
878 string color = lex.getString();
880 index_ptr->setColor(color);
881 // Update also the Color table:
883 color = lcolor.getX11Name(Color_background);
885 if (!shortcut.empty())
886 lcolor.setColor(to_utf8(shortcut), color);
889 } else if (token == "\\author") {
891 istringstream ss(lex.getString());
895 } else if (token == "\\paperorientation") {
898 orientation = paperorientationtranslator().find(orient);
899 } else if (token == "\\backgroundcolor") {
901 backgroundcolor = lyx::rgbFromHexName(lex.getString());
902 isbackgroundcolor = true;
903 } else if (token == "\\fontcolor") {
905 fontcolor = lyx::rgbFromHexName(lex.getString());
907 } else if (token == "\\notefontcolor") {
909 string color = lex.getString();
910 notefontcolor = lyx::rgbFromHexName(color);
911 lcolor.setColor("notefontcolor", color);
912 } else if (token == "\\boxbgcolor") {
914 string color = lex.getString();
915 boxbgcolor = lyx::rgbFromHexName(color);
916 lcolor.setColor("boxbgcolor", color);
917 } else if (token == "\\paperwidth") {
919 } else if (token == "\\paperheight") {
921 } else if (token == "\\leftmargin") {
923 } else if (token == "\\topmargin") {
925 } else if (token == "\\rightmargin") {
927 } else if (token == "\\bottommargin") {
929 } else if (token == "\\headheight") {
931 } else if (token == "\\headsep") {
933 } else if (token == "\\footskip") {
935 } else if (token == "\\columnsep") {
937 } else if (token == "\\paperfontsize") {
939 } else if (token == "\\papercolumns") {
941 } else if (token == "\\listings_params") {
944 listings_params = InsetListingsParams(par).params();
945 } else if (token == "\\papersides") {
948 sides = sidestranslator().find(psides);
949 } else if (token == "\\paperpagestyle") {
951 } else if (token == "\\bullet") {
953 } else if (token == "\\bulletLaTeX") {
954 readBulletsLaTeX(lex);
955 } else if (token == "\\secnumdepth") {
957 } else if (token == "\\tocdepth") {
959 } else if (token == "\\spacing") {
963 if (nspacing == "other") {
966 spacing().set(spacetranslator().find(nspacing), tmp_val);
967 } else if (token == "\\float_placement") {
968 lex >> float_placement;
970 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
971 string toktmp = pdfoptions().readToken(lex, token);
972 if (!toktmp.empty()) {
973 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
977 } else if (token == "\\html_math_output") {
980 html_math_output = static_cast<MathOutput>(temp);
981 } else if (token == "\\html_be_strict") {
982 lex >> html_be_strict;
983 } else if (token == "\\html_css_as_file") {
984 lex >> html_css_as_file;
985 } else if (token == "\\html_math_img_scale") {
986 lex >> html_math_img_scale;
987 } else if (token == "\\html_latex_start") {
989 html_latex_start = lex.getString();
990 } else if (token == "\\html_latex_end") {
992 html_latex_end = lex.getString();
993 } else if (token == "\\output_sync") {
995 } else if (token == "\\output_sync_macro") {
996 lex >> output_sync_macro;
997 } else if (token == "\\use_refstyle") {
1000 lyxerr << "BufferParams::readToken(): Unknown token: " <<
1010 // Quote argument if it contains spaces
1011 string quoteIfNeeded(string const & str) {
1012 if (contains(str, ' '))
1013 return "\"" + str + "\"";
1019 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
1021 // The top of the file is written by the buffer.
1022 // Prints out the buffer info into the .lyx file given by file
1024 os << "\\save_transient_properties "
1025 << convert<string>(save_transient_properties) << '\n';
1027 // the document directory (must end with a path separator)
1028 // realPath() is used to resolve symlinks, while addPath(..., "")
1029 // ensures a trailing path separator.
1030 string filepath = addPath(buf->fileName().onlyPath().realPath(), "");
1031 string const sysdir = addPath(package().system_support().realPath(), "");
1032 string const relpath =
1033 to_utf8(makeRelPath(from_utf8(filepath), from_utf8(sysdir)));
1034 if (!prefixIs(relpath, "../") && !FileName::isAbsolute(relpath))
1035 filepath = addPath("/systemlyxdir", relpath);
1036 else if (!save_transient_properties || !lyxrc.save_origin)
1037 filepath = "unavailable";
1038 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1041 os << "\\textclass "
1042 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1043 baseClass()->name()), "layout"))
1046 // then the preamble
1047 if (!preamble.empty()) {
1048 // remove '\n' from the end of preamble
1049 string const tmppreamble = rtrim(preamble, "\n");
1050 os << "\\begin_preamble\n"
1052 << "\n\\end_preamble\n";
1056 if (!options.empty()) {
1057 os << "\\options " << options << '\n';
1060 // use the class options defined in the layout?
1061 os << "\\use_default_options "
1062 << convert<string>(use_default_options) << "\n";
1064 // the master document
1065 if (!master.empty()) {
1066 os << "\\master " << master << '\n';
1070 if (!removed_modules_.empty()) {
1071 os << "\\begin_removed_modules" << '\n';
1072 list<string>::const_iterator it = removed_modules_.begin();
1073 list<string>::const_iterator en = removed_modules_.end();
1074 for (; it != en; ++it)
1076 os << "\\end_removed_modules" << '\n';
1080 if (!layout_modules_.empty()) {
1081 os << "\\begin_modules" << '\n';
1082 LayoutModuleList::const_iterator it = layout_modules_.begin();
1083 LayoutModuleList::const_iterator en = layout_modules_.end();
1084 for (; it != en; ++it)
1086 os << "\\end_modules" << '\n';
1090 if (!included_children_.empty()) {
1091 os << "\\begin_includeonly" << '\n';
1092 list<string>::const_iterator it = included_children_.begin();
1093 list<string>::const_iterator en = included_children_.end();
1094 for (; it != en; ++it)
1096 os << "\\end_includeonly" << '\n';
1098 os << "\\maintain_unincluded_children "
1099 << convert<string>(maintain_unincluded_children) << '\n';
1101 // local layout information
1102 string const local_layout = getLocalLayout(false);
1103 if (!local_layout.empty()) {
1104 // remove '\n' from the end
1105 string const tmplocal = rtrim(local_layout, "\n");
1106 os << "\\begin_local_layout\n"
1108 << "\n\\end_local_layout\n";
1110 string const forced_local_layout = getLocalLayout(true);
1111 if (!forced_local_layout.empty()) {
1112 // remove '\n' from the end
1113 string const tmplocal = rtrim(forced_local_layout, "\n");
1114 os << "\\begin_forced_local_layout\n"
1116 << "\n\\end_forced_local_layout\n";
1119 // then the text parameters
1120 if (language != ignore_language)
1121 os << "\\language " << language->lang() << '\n';
1122 os << "\\language_package " << lang_package
1123 << "\n\\inputencoding " << inputenc
1124 << "\n\\fontencoding " << fontenc
1125 << "\n\\font_roman \"" << fonts_roman[0]
1126 << "\" \"" << fonts_roman[1] << '"'
1127 << "\n\\font_sans \"" << fonts_sans[0]
1128 << "\" \"" << fonts_sans[1] << '"'
1129 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1130 << "\" \"" << fonts_typewriter[1] << '"'
1131 << "\n\\font_math \"" << fonts_math[0]
1132 << "\" \"" << fonts_math[1] << '"'
1133 << "\n\\font_default_family " << fonts_default_family
1134 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1135 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1136 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1137 << "\n\\font_sf_scale " << fonts_sans_scale[0]
1138 << ' ' << fonts_sans_scale[1]
1139 << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1140 << ' ' << fonts_typewriter_scale[1]
1142 if (!fonts_cjk.empty()) {
1143 os << "\\font_cjk " << fonts_cjk << '\n';
1145 os << "\\use_microtype " << convert<string>(use_microtype) << '\n';
1146 os << "\\graphics " << graphics_driver << '\n';
1147 os << "\\default_output_format " << default_output_format << '\n';
1148 os << "\\output_sync " << output_sync << '\n';
1149 if (!output_sync_macro.empty())
1150 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1151 os << "\\bibtex_command " << bibtex_command << '\n';
1152 os << "\\index_command " << index_command << '\n';
1154 if (!float_placement.empty()) {
1155 os << "\\float_placement " << float_placement << '\n';
1157 os << "\\paperfontsize " << fontsize << '\n';
1159 spacing().writeFile(os);
1160 pdfoptions().writeFile(os);
1162 os << "\\papersize " << string_papersize[papersize]
1163 << "\n\\use_geometry " << convert<string>(use_geometry);
1164 map<string, string> const & packages = auto_packages();
1165 for (map<string, string>::const_iterator it = packages.begin();
1166 it != packages.end(); ++it)
1167 os << "\n\\use_package " << it->first << ' '
1168 << use_package(it->first);
1170 os << "\n\\cite_engine ";
1172 if (!cite_engine_.empty()) {
1173 LayoutModuleList::const_iterator be = cite_engine_.begin();
1174 LayoutModuleList::const_iterator en = cite_engine_.end();
1175 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1184 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1185 << "\n\\biblio_style " << biblio_style
1186 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1187 << "\n\\use_indices " << convert<string>(use_indices)
1188 << "\n\\paperorientation " << string_orientation[orientation]
1189 << "\n\\suppress_date " << convert<string>(suppress_date)
1190 << "\n\\justification " << convert<string>(justification)
1191 << "\n\\use_refstyle " << use_refstyle
1193 if (isbackgroundcolor == true)
1194 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1195 if (isfontcolor == true)
1196 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1197 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1198 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1199 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1200 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1202 BranchList::const_iterator it = branchlist().begin();
1203 BranchList::const_iterator end = branchlist().end();
1204 for (; it != end; ++it) {
1205 os << "\\branch " << to_utf8(it->branch())
1206 << "\n\\selected " << it->isSelected()
1207 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1208 << "\n\\color " << lyx::X11hexname(it->color())
1213 IndicesList::const_iterator iit = indiceslist().begin();
1214 IndicesList::const_iterator iend = indiceslist().end();
1215 for (; iit != iend; ++iit) {
1216 os << "\\index " << to_utf8(iit->index())
1217 << "\n\\shortcut " << to_utf8(iit->shortcut())
1218 << "\n\\color " << lyx::X11hexname(iit->color())
1223 if (!paperwidth.empty())
1224 os << "\\paperwidth "
1225 << VSpace(paperwidth).asLyXCommand() << '\n';
1226 if (!paperheight.empty())
1227 os << "\\paperheight "
1228 << VSpace(paperheight).asLyXCommand() << '\n';
1229 if (!leftmargin.empty())
1230 os << "\\leftmargin "
1231 << VSpace(leftmargin).asLyXCommand() << '\n';
1232 if (!topmargin.empty())
1233 os << "\\topmargin "
1234 << VSpace(topmargin).asLyXCommand() << '\n';
1235 if (!rightmargin.empty())
1236 os << "\\rightmargin "
1237 << VSpace(rightmargin).asLyXCommand() << '\n';
1238 if (!bottommargin.empty())
1239 os << "\\bottommargin "
1240 << VSpace(bottommargin).asLyXCommand() << '\n';
1241 if (!headheight.empty())
1242 os << "\\headheight "
1243 << VSpace(headheight).asLyXCommand() << '\n';
1244 if (!headsep.empty())
1246 << VSpace(headsep).asLyXCommand() << '\n';
1247 if (!footskip.empty())
1249 << VSpace(footskip).asLyXCommand() << '\n';
1250 if (!columnsep.empty())
1251 os << "\\columnsep "
1252 << VSpace(columnsep).asLyXCommand() << '\n';
1253 os << "\\secnumdepth " << secnumdepth
1254 << "\n\\tocdepth " << tocdepth
1255 << "\n\\paragraph_separation "
1256 << string_paragraph_separation[paragraph_separation];
1257 if (!paragraph_separation)
1258 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1260 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1261 os << "\n\\quotes_language "
1262 << string_quotes_language[quotes_language]
1263 << "\n\\papercolumns " << columns
1264 << "\n\\papersides " << sides
1265 << "\n\\paperpagestyle " << pagestyle << '\n';
1266 if (!listings_params.empty())
1267 os << "\\listings_params \"" <<
1268 InsetListingsParams(listings_params).encodedString() << "\"\n";
1269 for (int i = 0; i < 4; ++i) {
1270 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1271 if (user_defined_bullet(i).getFont() != -1) {
1272 os << "\\bullet " << i << " "
1273 << user_defined_bullet(i).getFont() << " "
1274 << user_defined_bullet(i).getCharacter() << " "
1275 << user_defined_bullet(i).getSize() << "\n";
1279 os << "\\bulletLaTeX " << i << " \""
1280 << lyx::to_ascii(user_defined_bullet(i).getText())
1286 os << "\\tracking_changes "
1287 << (save_transient_properties ? convert<string>(track_changes) : "false")
1290 os << "\\output_changes "
1291 << (save_transient_properties ? convert<string>(output_changes) : "false")
1294 os << "\\html_math_output " << html_math_output << '\n'
1295 << "\\html_css_as_file " << html_css_as_file << '\n'
1296 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1298 if (html_math_img_scale != 1.0)
1299 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1300 if (!html_latex_start.empty())
1301 os << "\\html_latex_start " << html_latex_start << '\n';
1302 if (!html_latex_end.empty())
1303 os << "\\html_latex_end " << html_latex_end << '\n';
1305 os << pimpl_->authorlist;
1309 void BufferParams::validate(LaTeXFeatures & features) const
1311 features.require(documentClass().requires());
1313 if (columns > 1 && language->rightToLeft())
1314 features.require("rtloutputdblcol");
1316 if (output_changes) {
1317 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1318 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1319 LaTeXFeatures::isAvailable("xcolor");
1321 switch (features.runparams().flavor) {
1322 case OutputParams::LATEX:
1323 case OutputParams::DVILUATEX:
1325 features.require("ct-dvipost");
1326 features.require("dvipost");
1327 } else if (xcolorulem) {
1328 features.require("ct-xcolor-ulem");
1329 features.require("ulem");
1330 features.require("xcolor");
1332 features.require("ct-none");
1335 case OutputParams::LUATEX:
1336 case OutputParams::PDFLATEX:
1337 case OutputParams::XETEX:
1339 features.require("ct-xcolor-ulem");
1340 features.require("ulem");
1341 features.require("xcolor");
1342 // improves color handling in PDF output
1343 features.require("pdfcolmk");
1345 features.require("ct-none");
1353 // Floats with 'Here definitely' as default setting.
1354 if (float_placement.find('H') != string::npos)
1355 features.require("float");
1357 for (PackageMap::const_iterator it = use_packages.begin();
1358 it != use_packages.end(); ++it) {
1359 if (it->first == "amsmath") {
1360 // AMS Style is at document level
1361 if (it->second == package_on ||
1362 features.isProvided("amsmath"))
1363 features.require(it->first);
1364 } else if (it->second == package_on)
1365 features.require(it->first);
1368 // Document-level line spacing
1369 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1370 features.require("setspace");
1372 // the bullet shapes are buffer level not paragraph level
1373 // so they are tested here
1374 for (int i = 0; i < 4; ++i) {
1375 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1377 int const font = user_defined_bullet(i).getFont();
1379 int const c = user_defined_bullet(i).getCharacter();
1385 features.require("latexsym");
1387 } else if (font == 1) {
1388 features.require("amssymb");
1389 } else if (font >= 2 && font <= 5) {
1390 features.require("pifont");
1394 if (pdfoptions().use_hyperref) {
1395 features.require("hyperref");
1396 // due to interferences with babel and hyperref, the color package has to
1397 // be loaded after hyperref when hyperref is used with the colorlinks
1398 // option, see http://www.lyx.org/trac/ticket/5291
1399 if (pdfoptions().colorlinks)
1400 features.require("color");
1402 if (!listings_params.empty()) {
1403 // do not test validity because listings_params is
1404 // supposed to be valid
1406 InsetListingsParams(listings_params).separatedParams(true);
1407 // we can't support all packages, but we should load the color package
1408 if (par.find("\\color", 0) != string::npos)
1409 features.require("color");
1412 // some languages are only available via polyglossia
1413 if (features.hasPolyglossiaExclusiveLanguages())
1414 features.require("polyglossia");
1416 if (useNonTeXFonts && fontsMath() != "auto")
1417 features.require("unicode-math");
1420 features.require("microtype");
1422 if (!language->requires().empty())
1423 features.require(language->requires());
1427 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1428 FileName const & filepath) const
1430 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1431 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1432 // \RequirePackage to do so, rather than the normal \usepackage
1433 // Do not try to load any other package before the document class, unless you
1434 // have a thorough understanding of the LATEX internals and know exactly what you
1436 if (features.mustProvide("fix-cm"))
1437 os << "\\RequirePackage{fix-cm}\n";
1438 // Likewise for fixltx2e. If other packages conflict with this policy,
1439 // treat it as a package bug (and report it!)
1440 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1441 if (features.mustProvide("fixltx2e"))
1442 os << "\\RequirePackage{fixltx2e}\n";
1444 os << "\\documentclass";
1446 DocumentClass const & tclass = documentClass();
1448 ostringstream clsoptions; // the document class options.
1450 if (tokenPos(tclass.opt_fontsize(),
1451 '|', fontsize) >= 0) {
1452 // only write if existing in list (and not default)
1453 clsoptions << fontsize << "pt,";
1456 // all paper sizes except of A4, A5, B5 and the US sizes need the
1458 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1459 && papersize != PAPER_USLETTER
1460 && papersize != PAPER_USLEGAL
1461 && papersize != PAPER_USEXECUTIVE
1462 && papersize != PAPER_A4
1463 && papersize != PAPER_A5
1464 && papersize != PAPER_B5;
1466 if (!use_geometry) {
1467 switch (papersize) {
1469 clsoptions << "a4paper,";
1471 case PAPER_USLETTER:
1472 clsoptions << "letterpaper,";
1475 clsoptions << "a5paper,";
1478 clsoptions << "b5paper,";
1480 case PAPER_USEXECUTIVE:
1481 clsoptions << "executivepaper,";
1484 clsoptions << "legalpaper,";
1518 if (sides != tclass.sides()) {
1521 clsoptions << "oneside,";
1524 clsoptions << "twoside,";
1530 if (columns != tclass.columns()) {
1532 clsoptions << "twocolumn,";
1534 clsoptions << "onecolumn,";
1538 && orientation == ORIENTATION_LANDSCAPE)
1539 clsoptions << "landscape,";
1541 // language should be a parameter to \documentclass
1542 if (language->babel() == "hebrew"
1543 && default_language->babel() != "hebrew")
1544 // This seems necessary
1545 features.useLanguage(default_language);
1547 ostringstream language_options;
1548 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1549 bool const use_polyglossia = features.usePolyglossia();
1550 bool const global = lyxrc.language_global_options;
1551 if (use_babel || (use_polyglossia && global)) {
1552 language_options << features.getBabelLanguages();
1553 if (!language->babel().empty()) {
1554 if (!language_options.str().empty())
1555 language_options << ',';
1556 language_options << language->babel();
1558 if (global && !features.needBabelLangOptions()
1559 && !language_options.str().empty())
1560 clsoptions << language_options.str() << ',';
1563 // the predefined options from the layout
1564 if (use_default_options && !tclass.options().empty())
1565 clsoptions << tclass.options() << ',';
1567 // the user-defined options
1568 if (!options.empty()) {
1569 clsoptions << options << ',';
1572 string strOptions(clsoptions.str());
1573 if (!strOptions.empty()) {
1574 strOptions = rtrim(strOptions, ",");
1576 os << '[' << from_utf8(strOptions) << ']';
1579 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1580 // end of \documentclass defs
1582 // if we use fontspec or newtxmath, we have to load the AMS packages here
1583 string const ams = features.loadAMSPackages();
1584 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1585 bool const use_newtxmath =
1586 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1587 ot1, false, false) == "newtxmath";
1588 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1589 os << from_ascii(ams);
1591 if (useNonTeXFonts) {
1592 if (!features.isProvided("fontspec"))
1593 os << "\\usepackage{fontspec}\n";
1594 if (features.mustProvide("unicode-math")
1595 && features.isAvailable("unicode-math"))
1596 os << "\\usepackage{unicode-math}\n";
1599 // font selection must be done before loading fontenc.sty
1600 string const fonts = loadFonts(features);
1602 os << from_utf8(fonts);
1604 if (fonts_default_family != "default")
1605 os << "\\renewcommand{\\familydefault}{\\"
1606 << from_ascii(fonts_default_family) << "}\n";
1608 // set font encoding
1609 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1610 if (!useNonTeXFonts && !features.isProvided("fontenc")
1611 && font_encoding() != "default") {
1612 // get main font encodings
1613 vector<string> fontencs = font_encodings();
1614 // get font encodings of secondary languages
1615 features.getFontEncodings(fontencs);
1616 if (!fontencs.empty()) {
1617 os << "\\usepackage["
1618 << from_ascii(getStringFromVector(fontencs))
1623 // handle inputenc etc.
1624 writeEncodingPreamble(os, features);
1627 if (!features.runparams().includeall && !included_children_.empty()) {
1628 os << "\\includeonly{";
1629 list<string>::const_iterator it = included_children_.begin();
1630 list<string>::const_iterator en = included_children_.end();
1632 for (; it != en; ++it) {
1633 string incfile = *it;
1634 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1635 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1637 if (!features.runparams().nice)
1639 // \includeonly doesn't want an extension
1640 incfile = changeExtension(incfile, string());
1641 incfile = support::latex_path(incfile);
1642 if (!incfile.empty()) {
1645 os << from_utf8(incfile);
1652 if (!features.isProvided("geometry")
1653 && (use_geometry || nonstandard_papersize)) {
1654 odocstringstream ods;
1655 if (!getGraphicsDriver("geometry").empty())
1656 ods << getGraphicsDriver("geometry");
1657 if (orientation == ORIENTATION_LANDSCAPE)
1658 ods << ",landscape";
1659 switch (papersize) {
1661 if (!paperwidth.empty())
1662 ods << ",paperwidth="
1663 << from_ascii(paperwidth);
1664 if (!paperheight.empty())
1665 ods << ",paperheight="
1666 << from_ascii(paperheight);
1668 case PAPER_USLETTER:
1669 ods << ",letterpaper";
1672 ods << ",legalpaper";
1674 case PAPER_USEXECUTIVE:
1675 ods << ",executivepaper";
1764 docstring const g_options = trim(ods.str(), ",");
1765 os << "\\usepackage";
1766 if (!g_options.empty())
1767 os << '[' << g_options << ']';
1768 os << "{geometry}\n";
1769 // output this only if use_geometry is true
1771 os << "\\geometry{verbose";
1772 if (!topmargin.empty())
1773 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1774 if (!bottommargin.empty())
1775 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1776 if (!leftmargin.empty())
1777 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1778 if (!rightmargin.empty())
1779 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1780 if (!headheight.empty())
1781 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1782 if (!headsep.empty())
1783 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1784 if (!footskip.empty())
1785 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1786 if (!columnsep.empty())
1787 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1790 } else if (orientation == ORIENTATION_LANDSCAPE
1791 || papersize != PAPER_DEFAULT) {
1792 features.require("papersize");
1795 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1796 if (pagestyle == "fancy")
1797 os << "\\usepackage{fancyhdr}\n";
1798 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1801 // only output when the background color is not default
1802 if (isbackgroundcolor == true) {
1803 // only require color here, the background color will be defined
1804 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1806 features.require("color");
1807 features.require("pagecolor");
1810 // only output when the font color is not default
1811 if (isfontcolor == true) {
1812 // only require color here, the font color will be defined
1813 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1815 features.require("color");
1816 features.require("fontcolor");
1819 // Only if class has a ToC hierarchy
1820 if (tclass.hasTocLevels()) {
1821 if (secnumdepth != tclass.secnumdepth()) {
1822 os << "\\setcounter{secnumdepth}{"
1826 if (tocdepth != tclass.tocdepth()) {
1827 os << "\\setcounter{tocdepth}{"
1833 if (paragraph_separation) {
1834 // when skip separation
1835 switch (getDefSkip().kind()) {
1836 case VSpace::SMALLSKIP:
1837 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1839 case VSpace::MEDSKIP:
1840 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1842 case VSpace::BIGSKIP:
1843 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1845 case VSpace::LENGTH:
1846 os << "\\setlength{\\parskip}{"
1847 << from_utf8(getDefSkip().length().asLatexString())
1850 default: // should never happen // Then delete it.
1851 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1854 os << "\\setlength{\\parindent}{0pt}\n";
1856 // when separation by indentation
1857 // only output something when a width is given
1858 if (getIndentation().asLyXCommand() != "default") {
1859 os << "\\setlength{\\parindent}{"
1860 << from_utf8(getIndentation().asLatexCommand())
1865 // Now insert the LyX specific LaTeX commands...
1866 docstring lyxpreamble;
1867 features.resolveAlternatives();
1870 if (!output_sync_macro.empty())
1871 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1872 else if (features.runparams().flavor == OutputParams::LATEX)
1873 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1874 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1875 lyxpreamble += "\\synctex=-1\n";
1878 // The package options (via \PassOptionsToPackage)
1879 lyxpreamble += from_ascii(features.getPackageOptions());
1881 // due to interferences with babel and hyperref, the color package has to
1882 // be loaded (when it is not already loaded) before babel when hyperref
1883 // is used with the colorlinks option, see
1884 // http://www.lyx.org/trac/ticket/5291
1885 // we decided therefore to load color always before babel, see
1886 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1887 lyxpreamble += from_ascii(features.getColorOptions());
1889 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1890 // we have to call babel before
1892 && (features.isRequired("jurabib")
1893 || features.isRequired("hyperref")
1894 || features.isRequired("varioref")
1895 || features.isRequired("vietnamese")
1896 || features.isRequired("japanese"))) {
1898 lyxpreamble += from_utf8(features.getBabelPresettings());
1899 lyxpreamble += from_utf8(babelCall(language_options.str(),
1900 features.needBabelLangOptions())) + '\n';
1901 lyxpreamble += from_utf8(features.getBabelPostsettings());
1904 // The optional packages;
1905 lyxpreamble += from_ascii(features.getPackages());
1907 // Additional Indices
1908 if (features.isRequired("splitidx")) {
1909 IndicesList::const_iterator iit = indiceslist().begin();
1910 IndicesList::const_iterator iend = indiceslist().end();
1911 for (; iit != iend; ++iit) {
1912 pair<docstring, docstring> indexname_latex =
1913 features.runparams().encoding->latexString(iit->index(),
1914 features.runparams().dryrun);
1915 if (!indexname_latex.second.empty()) {
1916 // issue a warning about omitted characters
1917 // FIXME: should be passed to the error dialog
1918 frontend::Alert::warning(_("Uncodable characters"),
1919 bformat(_("The following characters that are used in an index name are not\n"
1920 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1921 indexname_latex.second));
1923 lyxpreamble += "\\newindex[";
1924 lyxpreamble += indexname_latex.first;
1925 lyxpreamble += "]{";
1926 lyxpreamble += escape(iit->shortcut());
1927 lyxpreamble += "}\n";
1932 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1935 // * Hyperref manual: "Make sure it comes last of your loaded
1936 // packages, to give it a fighting chance of not being over-written,
1937 // since its job is to redefine many LaTeX commands."
1938 // * Email from Heiko Oberdiek: "It is usually better to load babel
1939 // before hyperref. Then hyperref has a chance to detect babel.
1940 // * Has to be loaded before the "LyX specific LaTeX commands" to
1941 // avoid errors with algorithm floats.
1942 // use hyperref explicitly if it is required
1943 if (features.isRequired("hyperref")) {
1944 // pass what we have to stream here, since we need
1945 // to access the stream itself in PDFOptions.
1948 OutputParams tmp_params = features.runparams();
1949 pdfoptions().writeLaTeX(tmp_params, os,
1950 features.isProvided("hyperref"));
1951 // set back for the rest
1952 lyxpreamble.clear();
1953 // correctly break URLs with hyperref and dvi output
1954 if (features.runparams().flavor == OutputParams::LATEX
1955 && features.isAvailable("breakurl"))
1956 lyxpreamble += "\\usepackage{breakurl}\n";
1957 } else if (features.isRequired("nameref"))
1958 // hyperref loads this automatically
1959 lyxpreamble += "\\usepackage{nameref}\n";
1961 // bibtopic needs to be loaded after hyperref.
1962 // the dot provides the aux file naming which LyX can detect.
1963 if (features.mustProvide("bibtopic"))
1964 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1966 // Will be surrounded by \makeatletter and \makeatother when not empty
1967 docstring atlyxpreamble;
1969 // Some macros LyX will need
1970 docstring tmppreamble(features.getMacros());
1972 if (!tmppreamble.empty())
1973 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1974 "LyX specific LaTeX commands.\n"
1975 + tmppreamble + '\n';
1977 // the text class specific preamble
1978 tmppreamble = features.getTClassPreamble();
1979 if (!tmppreamble.empty())
1980 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1981 "Textclass specific LaTeX commands.\n"
1982 + tmppreamble + '\n';
1984 // suppress date if selected
1985 // use \@ifundefined because we cannot be sure that every document class
1986 // has a \date command
1988 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1990 /* the user-defined preamble */
1991 if (!containsOnly(preamble, " \n\t")) {
1993 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1994 "User specified LaTeX commands.\n";
1996 // Check if the user preamble contains uncodable glyphs
1997 docstring const u_preamble = from_utf8(preamble);
1998 odocstringstream user_preamble;
1999 docstring uncodable_glyphs;
2000 Encoding const * const enc = features.runparams().encoding;
2002 for (size_t n = 0; n < u_preamble.size(); ++n) {
2003 char_type c = u_preamble[n];
2004 if (!enc->encodable(c)) {
2005 docstring const glyph(1, c);
2006 LYXERR0("Uncodable character '"
2008 << "' in user preamble!");
2009 uncodable_glyphs += glyph;
2010 if (features.runparams().dryrun) {
2011 user_preamble << "<" << _("LyX Warning: ")
2012 << _("uncodable character") << " '";
2013 user_preamble.put(c);
2014 user_preamble << "'>";
2017 user_preamble.put(c);
2020 user_preamble << u_preamble;
2022 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2023 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2024 frontend::Alert::warning(
2025 _("Uncodable character in user preamble"),
2027 _("The user preamble of your document contains glyphs "
2028 "that are unknown in the current document encoding "
2029 "(namely %1$s).\nThese glyphs are omitted "
2030 " from the output, which may result in "
2031 "incomplete output."
2032 "\n\nPlease select an appropriate "
2033 "document encoding\n"
2034 "(such as utf8) or change the "
2035 "preamble code accordingly."),
2038 atlyxpreamble += user_preamble.str() + '\n';
2041 // footmisc must be loaded after setspace
2042 // Load it here to avoid clashes with footmisc loaded in the user
2043 // preamble. For that reason we also pass the options via
2044 // \PassOptionsToPackage in getPreamble() and not here.
2045 if (features.mustProvide("footmisc"))
2046 atlyxpreamble += "\\usepackage{footmisc}\n";
2048 // subfig loads internally the LaTeX package "caption". As
2049 // caption is a very popular package, users will load it in
2050 // the preamble. Therefore we must load subfig behind the
2051 // user-defined preamble and check if the caption package was
2052 // loaded or not. For the case that caption is loaded before
2053 // subfig, there is the subfig option "caption=false". This
2054 // option also works when a koma-script class is used and
2055 // koma's own caption commands are used instead of caption. We
2056 // use \PassOptionsToPackage here because the user could have
2057 // already loaded subfig in the preamble.
2058 if (features.mustProvide("subfig")) {
2059 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
2060 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2061 "\\usepackage{subfig}\n";
2064 // Itemize bullet settings need to be last in case the user
2065 // defines their own bullets that use a package included
2066 // in the user-defined preamble -- ARRae
2067 // Actually it has to be done much later than that
2068 // since some packages like frenchb make modifications
2069 // at \begin{document} time -- JMarc
2070 docstring bullets_def;
2071 for (int i = 0; i < 4; ++i) {
2072 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2073 if (bullets_def.empty())
2074 bullets_def += "\\AtBeginDocument{\n";
2075 bullets_def += " \\def\\labelitemi";
2077 // `i' is one less than the item to modify
2084 bullets_def += "ii";
2090 bullets_def += '{' +
2091 user_defined_bullet(i).getText()
2096 if (!bullets_def.empty())
2097 atlyxpreamble += bullets_def + "}\n\n";
2099 if (!atlyxpreamble.empty())
2100 lyxpreamble += "\n\\makeatletter\n"
2101 + atlyxpreamble + "\\makeatother\n\n";
2103 // We try to load babel late, in case it interferes with other packages.
2104 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
2105 // called after babel, though.
2106 if (use_babel && !features.isRequired("jurabib")
2107 && !features.isRequired("hyperref")
2108 && !features.isRequired("varioref")
2109 && !features.isRequired("vietnamese")
2110 && !features.isRequired("japanese")) {
2112 lyxpreamble += from_utf8(features.getBabelPresettings());
2113 lyxpreamble += from_utf8(babelCall(language_options.str(),
2114 features.needBabelLangOptions())) + '\n';
2115 lyxpreamble += from_utf8(features.getBabelPostsettings());
2117 if (features.isRequired("bicaption"))
2118 lyxpreamble += "\\usepackage{bicaption}\n";
2119 if (!listings_params.empty() || features.mustProvide("listings"))
2120 lyxpreamble += "\\usepackage{listings}\n";
2121 if (!listings_params.empty()) {
2122 lyxpreamble += "\\lstset{";
2123 // do not test validity because listings_params is
2124 // supposed to be valid
2126 InsetListingsParams(listings_params).separatedParams(true);
2127 lyxpreamble += from_utf8(par);
2128 lyxpreamble += "}\n";
2131 // xunicode needs to be loaded at least after amsmath, amssymb,
2132 // esint and the other packages that provide special glyphs
2133 if (features.runparams().flavor == OutputParams::XETEX
2135 lyxpreamble += "\\usepackage{xunicode}\n";
2137 // Polyglossia must be loaded last
2138 if (use_polyglossia) {
2140 lyxpreamble += "\\usepackage{polyglossia}\n";
2141 // set the main language
2142 lyxpreamble += "\\setdefaultlanguage";
2143 if (!language->polyglossiaOpts().empty())
2144 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
2145 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
2146 // now setup the other languages
2147 std::map<std::string, std::string> const polylangs =
2148 features.getPolyglossiaLanguages();
2149 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
2150 mit != polylangs.end() ; ++mit) {
2151 lyxpreamble += "\\setotherlanguage";
2152 if (!mit->second.empty())
2153 lyxpreamble += "[" + from_ascii(mit->second) + "]";
2154 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
2158 // Load custom language package here
2159 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2160 if (lang_package == "default")
2161 lyxpreamble += from_utf8(lyxrc.language_custom_package);
2163 lyxpreamble += from_utf8(lang_package);
2164 lyxpreamble += '\n';
2167 docstring const i18npreamble =
2168 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2169 if (!i18npreamble.empty())
2170 lyxpreamble += i18npreamble + '\n';
2178 void BufferParams::useClassDefaults()
2180 DocumentClass const & tclass = documentClass();
2182 sides = tclass.sides();
2183 columns = tclass.columns();
2184 pagestyle = tclass.pagestyle();
2185 use_default_options = true;
2186 // Only if class has a ToC hierarchy
2187 if (tclass.hasTocLevels()) {
2188 secnumdepth = tclass.secnumdepth();
2189 tocdepth = tclass.tocdepth();
2194 bool BufferParams::hasClassDefaults() const
2196 DocumentClass const & tclass = documentClass();
2198 return sides == tclass.sides()
2199 && columns == tclass.columns()
2200 && pagestyle == tclass.pagestyle()
2201 && use_default_options
2202 && secnumdepth == tclass.secnumdepth()
2203 && tocdepth == tclass.tocdepth();
2207 DocumentClass const & BufferParams::documentClass() const
2213 DocumentClassConstPtr BufferParams::documentClassPtr() const
2219 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2221 // evil, but this function is evil
2222 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2226 bool BufferParams::setBaseClass(string const & classname)
2228 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2229 LayoutFileList & bcl = LayoutFileList::get();
2230 if (!bcl.haveClass(classname)) {
2232 bformat(_("The layout file:\n"
2234 "could not be found. A default textclass with default\n"
2235 "layouts will be used. LyX will not be able to produce\n"
2237 from_utf8(classname));
2238 frontend::Alert::error(_("Document class not found"), s);
2239 bcl.addEmptyClass(classname);
2242 bool const success = bcl[classname].load();
2245 bformat(_("Due to some error in it, the layout file:\n"
2247 "could not be loaded. A default textclass with default\n"
2248 "layouts will be used. LyX will not be able to produce\n"
2250 from_utf8(classname));
2251 frontend::Alert::error(_("Could not load class"), s);
2252 bcl.addEmptyClass(classname);
2255 pimpl_->baseClass_ = classname;
2256 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2261 LayoutFile const * BufferParams::baseClass() const
2263 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2264 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2270 LayoutFileIndex const & BufferParams::baseClassID() const
2272 return pimpl_->baseClass_;
2276 void BufferParams::makeDocumentClass(bool const clone)
2281 LayoutModuleList mods;
2282 LayoutModuleList::iterator it = layout_modules_.begin();
2283 LayoutModuleList::iterator en = layout_modules_.end();
2284 for (; it != en; ++it)
2285 mods.push_back(*it);
2287 it = cite_engine_.begin();
2288 en = cite_engine_.end();
2289 for (; it != en; ++it)
2290 mods.push_back(*it);
2292 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2294 TextClass::ReturnValues success = TextClass::OK;
2295 if (!forced_local_layout_.empty())
2296 success = doc_class_->read(forced_local_layout_, TextClass::MODULE);
2297 if (!local_layout_.empty() &&
2298 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2299 success = doc_class_->read(local_layout_, TextClass::MODULE);
2300 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2301 docstring const msg = _("Error reading internal layout information");
2302 frontend::Alert::warning(_("Read Error"), msg);
2307 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2309 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2313 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2315 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2319 std::string BufferParams::getLocalLayout(bool forced) const
2322 return doc_class_->forcedLayouts();
2324 return local_layout_;
2328 void BufferParams::setLocalLayout(string const & layout, bool forced)
2331 forced_local_layout_ = layout;
2333 local_layout_ = layout;
2337 bool BufferParams::addLayoutModule(string const & modName)
2339 LayoutModuleList::const_iterator it = layout_modules_.begin();
2340 LayoutModuleList::const_iterator end = layout_modules_.end();
2341 for (; it != end; ++it)
2344 layout_modules_.push_back(modName);
2349 string BufferParams::bufferFormat() const
2351 string format = documentClass().outputFormat();
2352 if (format == "latex") {
2354 return "xetex"; // actually "xetex or luatex"
2355 if (encoding().package() == Encoding::japanese)
2362 bool BufferParams::isExportable(string const & format) const
2364 vector<string> backs = backends();
2365 for (vector<string>::const_iterator it = backs.begin();
2366 it != backs.end(); ++it)
2367 if (theConverters().isReachable(*it, format))
2373 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2375 vector<string> const backs = backends();
2376 set<string> excludes;
2377 if (useNonTeXFonts) {
2378 excludes.insert("latex");
2379 excludes.insert("pdflatex");
2381 vector<Format const *> result =
2382 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2383 for (vector<string>::const_iterator it = backs.begin() + 1;
2384 it != backs.end(); ++it) {
2385 vector<Format const *> r =
2386 theConverters().getReachable(*it, only_viewable, false, excludes);
2387 result.insert(result.end(), r.begin(), r.end());
2393 bool BufferParams::isExportableFormat(string const & format) const
2395 typedef vector<Format const *> Formats;
2397 formats = exportableFormats(true);
2398 Formats::const_iterator fit = formats.begin();
2399 Formats::const_iterator end = formats.end();
2400 for (; fit != end ; ++fit) {
2401 if ((*fit)->name() == format)
2408 vector<string> BufferParams::backends() const
2411 string const buffmt = bufferFormat();
2413 // FIXME: Don't hardcode format names here, but use a flag
2414 if (buffmt == "latex") {
2415 if (!useNonTeXFonts) {
2416 v.push_back("pdflatex");
2417 v.push_back("latex");
2419 v.push_back("luatex");
2420 v.push_back("dviluatex");
2421 v.push_back("xetex");
2422 } else if (buffmt == "xetex") {
2423 v.push_back("xetex");
2424 // FIXME: need to test all languages (bug 8205)
2425 if (!language || !language->isPolyglossiaExclusive()) {
2426 v.push_back("luatex");
2427 v.push_back("dviluatex");
2430 v.push_back(buffmt);
2432 v.push_back("xhtml");
2433 v.push_back("text");
2439 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2441 string const dformat = (format.empty() || format == "default") ?
2442 getDefaultOutputFormat() : format;
2443 DefaultFlavorCache::const_iterator it =
2444 default_flavors_.find(dformat);
2446 if (it != default_flavors_.end())
2449 OutputParams::FLAVOR result = OutputParams::LATEX;
2451 // FIXME It'd be better not to hardcode this, but to do
2452 // something with formats.
2453 if (dformat == "xhtml")
2454 result = OutputParams::HTML;
2455 else if (dformat == "text")
2456 result = OutputParams::TEXT;
2457 else if (dformat == "lyx")
2458 result = OutputParams::LYX;
2459 else if (dformat == "pdflatex")
2460 result = OutputParams::PDFLATEX;
2461 else if (dformat == "xetex")
2462 result = OutputParams::XETEX;
2463 else if (dformat == "luatex")
2464 result = OutputParams::LUATEX;
2465 else if (dformat == "dviluatex")
2466 result = OutputParams::DVILUATEX;
2468 // Try to determine flavor of default output format
2469 vector<string> backs = backends();
2470 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2471 // Get shortest path to format
2472 Graph::EdgePath path;
2473 for (vector<string>::const_iterator it = backs.begin();
2474 it != backs.end(); ++it) {
2475 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2476 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2481 result = theConverters().getFlavor(path);
2484 // cache this flavor
2485 default_flavors_[dformat] = result;
2490 string BufferParams::getDefaultOutputFormat() const
2492 if (!default_output_format.empty()
2493 && default_output_format != "default")
2494 return default_output_format;
2496 || encoding().package() == Encoding::japanese) {
2497 vector<Format const *> const formats = exportableFormats(true);
2498 if (formats.empty())
2500 // return the first we find
2501 return formats.front()->name();
2504 return lyxrc.default_otf_view_format;
2505 return lyxrc.default_view_format;
2508 Font const BufferParams::getFont() const
2510 FontInfo f = documentClass().defaultfont();
2511 if (fonts_default_family == "rmdefault")
2512 f.setFamily(ROMAN_FAMILY);
2513 else if (fonts_default_family == "sfdefault")
2514 f.setFamily(SANS_FAMILY);
2515 else if (fonts_default_family == "ttdefault")
2516 f.setFamily(TYPEWRITER_FAMILY);
2517 return Font(f, language);
2521 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const & qs) const
2523 return quoteslangtranslator().find(qs);
2527 bool BufferParams::isLatex() const
2529 return documentClass().outputType() == LATEX;
2533 bool BufferParams::isLiterate() const
2535 return documentClass().outputType() == LITERATE;
2539 bool BufferParams::isDocBook() const
2541 return documentClass().outputType() == DOCBOOK;
2545 void BufferParams::readPreamble(Lexer & lex)
2547 if (lex.getString() != "\\begin_preamble")
2548 lyxerr << "Error (BufferParams::readPreamble):"
2549 "consistency check failed." << endl;
2551 preamble = lex.getLongString("\\end_preamble");
2555 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2557 string const expected = forced ? "\\begin_forced_local_layout" :
2558 "\\begin_local_layout";
2559 if (lex.getString() != expected)
2560 lyxerr << "Error (BufferParams::readLocalLayout):"
2561 "consistency check failed." << endl;
2564 forced_local_layout_ =
2565 lex.getLongString("\\end_forced_local_layout");
2567 local_layout_ = lex.getLongString("\\end_local_layout");
2571 bool BufferParams::setLanguage(string const & lang)
2573 Language const *new_language = languages.getLanguage(lang);
2574 if (!new_language) {
2575 // Language lang was not found
2578 language = new_language;
2583 void BufferParams::readLanguage(Lexer & lex)
2585 if (!lex.next()) return;
2587 string const tmptok = lex.getString();
2589 // check if tmptok is part of tex_babel in tex-defs.h
2590 if (!setLanguage(tmptok)) {
2591 // Language tmptok was not found
2592 language = default_language;
2593 lyxerr << "Warning: Setting language `"
2594 << tmptok << "' to `" << language->lang()
2600 void BufferParams::readGraphicsDriver(Lexer & lex)
2605 string const tmptok = lex.getString();
2606 // check if tmptok is part of tex_graphics in tex_defs.h
2609 string const test = tex_graphics[n++];
2611 if (test == tmptok) {
2612 graphics_driver = tmptok;
2617 "Warning: graphics driver `$$Token' not recognized!\n"
2618 " Setting graphics driver to `default'.\n");
2619 graphics_driver = "default";
2626 void BufferParams::readBullets(Lexer & lex)
2631 int const index = lex.getInteger();
2633 int temp_int = lex.getInteger();
2634 user_defined_bullet(index).setFont(temp_int);
2635 temp_bullet(index).setFont(temp_int);
2637 user_defined_bullet(index).setCharacter(temp_int);
2638 temp_bullet(index).setCharacter(temp_int);
2640 user_defined_bullet(index).setSize(temp_int);
2641 temp_bullet(index).setSize(temp_int);
2645 void BufferParams::readBulletsLaTeX(Lexer & lex)
2647 // The bullet class should be able to read this.
2650 int const index = lex.getInteger();
2652 docstring const temp_str = lex.getDocString();
2654 user_defined_bullet(index).setText(temp_str);
2655 temp_bullet(index).setText(temp_str);
2659 void BufferParams::readModules(Lexer & lex)
2661 if (!lex.eatLine()) {
2662 lyxerr << "Error (BufferParams::readModules):"
2663 "Unexpected end of input." << endl;
2667 string mod = lex.getString();
2668 if (mod == "\\end_modules")
2670 addLayoutModule(mod);
2676 void BufferParams::readRemovedModules(Lexer & lex)
2678 if (!lex.eatLine()) {
2679 lyxerr << "Error (BufferParams::readRemovedModules):"
2680 "Unexpected end of input." << endl;
2684 string mod = lex.getString();
2685 if (mod == "\\end_removed_modules")
2687 removed_modules_.push_back(mod);
2690 // now we want to remove any removed modules that were previously
2691 // added. normally, that will be because default modules were added in
2692 // setBaseClass(), which gets called when \textclass is read at the
2693 // start of the read.
2694 list<string>::const_iterator rit = removed_modules_.begin();
2695 list<string>::const_iterator const ren = removed_modules_.end();
2696 for (; rit != ren; ++rit) {
2697 LayoutModuleList::iterator const mit = layout_modules_.begin();
2698 LayoutModuleList::iterator const men = layout_modules_.end();
2699 LayoutModuleList::iterator found = find(mit, men, *rit);
2702 layout_modules_.erase(found);
2707 void BufferParams::readIncludeonly(Lexer & lex)
2709 if (!lex.eatLine()) {
2710 lyxerr << "Error (BufferParams::readIncludeonly):"
2711 "Unexpected end of input." << endl;
2715 string child = lex.getString();
2716 if (child == "\\end_includeonly")
2718 included_children_.push_back(child);
2724 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2726 switch (papersize) {
2728 // could be anything, so don't guess
2730 case PAPER_CUSTOM: {
2731 if (purpose == XDVI && !paperwidth.empty() &&
2732 !paperheight.empty()) {
2733 // heightxwidth<unit>
2734 string first = paperwidth;
2735 string second = paperheight;
2736 if (orientation == ORIENTATION_LANDSCAPE)
2739 return first.erase(first.length() - 2)
2745 // dvips and dvipdfm do not know this
2746 if (purpose == DVIPS || purpose == DVIPDFM)
2750 if (purpose == DVIPS || purpose == DVIPDFM)
2754 if (purpose == DVIPS || purpose == DVIPDFM)
2764 if (purpose == DVIPS || purpose == DVIPDFM)
2768 if (purpose == DVIPS || purpose == DVIPDFM)
2772 if (purpose == DVIPS || purpose == DVIPDFM)
2776 if (purpose == DVIPS || purpose == DVIPDFM)
2780 if (purpose == DVIPS || purpose == DVIPDFM)
2784 // dvipdfm does not know this
2785 if (purpose == DVIPDFM)
2789 if (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)
2837 if (purpose == DVIPS || purpose == DVIPDFM)
2841 if (purpose == DVIPS || purpose == DVIPDFM)
2845 if (purpose == DVIPS || purpose == DVIPDFM)
2849 if (purpose == DVIPS || purpose == DVIPDFM)
2852 case PAPER_USEXECUTIVE:
2853 // dvipdfm does not know this
2854 if (purpose == DVIPDFM)
2859 case PAPER_USLETTER:
2861 if (purpose == XDVI)
2868 string const BufferParams::dvips_options() const
2872 // If the class loads the geometry package, we do not know which
2873 // paper size is used, since we do not set it (bug 7013).
2874 // Therefore we must not specify any argument here.
2875 // dvips gets the correct paper size via DVI specials in this case
2876 // (if the class uses the geometry package correctly).
2877 if (documentClass().provides("geometry"))
2881 && papersize == PAPER_CUSTOM
2882 && !lyxrc.print_paper_dimension_flag.empty()
2883 && !paperwidth.empty()
2884 && !paperheight.empty()) {
2885 // using a custom papersize
2886 result = lyxrc.print_paper_dimension_flag;
2887 result += ' ' + paperwidth;
2888 result += ',' + paperheight;
2890 string const paper_option = paperSizeName(DVIPS);
2891 if (!paper_option.empty() && (paper_option != "letter" ||
2892 orientation != ORIENTATION_LANDSCAPE)) {
2893 // dvips won't accept -t letter -t landscape.
2894 // In all other cases, include the paper size
2896 result = lyxrc.print_paper_flag;
2897 result += ' ' + paper_option;
2900 if (orientation == ORIENTATION_LANDSCAPE &&
2901 papersize != PAPER_CUSTOM)
2902 result += ' ' + lyxrc.print_landscape_flag;
2907 string const BufferParams::font_encoding() const
2909 return font_encodings().empty() ? "default" : font_encodings().back();
2913 vector<string> const BufferParams::font_encodings() const
2915 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2917 vector<string> fontencs;
2919 // "default" means "no explicit font encoding"
2920 if (doc_fontenc != "default") {
2921 fontencs = getVectorFromString(doc_fontenc);
2922 if (!language->fontenc().empty()
2923 && ascii_lowercase(language->fontenc()) != "none") {
2924 vector<string> fencs = getVectorFromString(language->fontenc());
2925 vector<string>::const_iterator fit = fencs.begin();
2926 for (; fit != fencs.end(); ++fit) {
2927 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
2928 fontencs.push_back(*fit);
2937 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2939 // suppress the babel call if there is no BabelName defined
2940 // for the document language in the lib/languages file and if no
2941 // other languages are used (lang_opts is then empty)
2942 if (lang_opts.empty())
2944 // either a specific language (AsBabelOptions setting in
2945 // lib/languages) or the prefs require the languages to
2946 // be submitted to babel itself (not the class).
2948 return "\\usepackage[" + lang_opts + "]{babel}";
2949 return "\\usepackage{babel}";
2953 docstring BufferParams::getGraphicsDriver(string const & package) const
2957 if (package == "geometry") {
2958 if (graphics_driver == "dvips"
2959 || graphics_driver == "dvipdfm"
2960 || graphics_driver == "pdftex"
2961 || graphics_driver == "vtex")
2962 result = from_ascii(graphics_driver);
2963 else if (graphics_driver == "dvipdfmx")
2964 result = from_ascii("dvipdfm");
2971 void BufferParams::writeEncodingPreamble(otexstream & os,
2972 LaTeXFeatures & features) const
2974 // XeTeX/LuaTeX: (see also #9740)
2975 // With Unicode fonts we use utf8-plain without encoding package.
2976 // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails.
2977 // XeTeX must use ASCII encoding (see Buffer.cpp),
2978 // for LuaTeX, we load "luainputenc" (see below).
2979 if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
2982 if (inputenc == "auto") {
2983 string const doc_encoding =
2984 language->encoding()->latexName();
2985 Encoding::Package const package =
2986 language->encoding()->package();
2988 // Create list of inputenc options:
2989 set<string> encodings;
2990 // luainputenc fails with more than one encoding
2991 if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts
2992 // list all input encodings used in the document
2993 encodings = features.getEncodingSet(doc_encoding);
2995 // If the "japanese" package (i.e. pLaTeX) is used,
2996 // inputenc must be omitted.
2997 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2998 if ((!encodings.empty() || package == Encoding::inputenc)
2999 && !features.isRequired("japanese")
3000 && !features.isProvided("inputenc")) {
3001 os << "\\usepackage[";
3002 set<string>::const_iterator it = encodings.begin();
3003 set<string>::const_iterator const end = encodings.end();
3005 os << from_ascii(*it);
3008 for (; it != end; ++it)
3009 os << ',' << from_ascii(*it);
3010 if (package == Encoding::inputenc) {
3011 if (!encodings.empty())
3013 os << from_ascii(doc_encoding);
3015 if (features.runparams().flavor == OutputParams::LUATEX
3016 || features.runparams().flavor == OutputParams::DVILUATEX)
3017 os << "]{luainputenc}\n";
3019 os << "]{inputenc}\n";
3021 if (package == Encoding::CJK || features.mustProvide("CJK")) {
3022 if (language->encoding()->name() == "utf8-cjk"
3023 && LaTeXFeatures::isAvailable("CJKutf8"))
3024 os << "\\usepackage{CJKutf8}\n";
3026 os << "\\usepackage{CJK}\n";
3028 } else if (inputenc != "default") {
3029 switch (encoding().package()) {
3030 case Encoding::none:
3031 case Encoding::japanese:
3033 case Encoding::inputenc:
3034 // do not load inputenc if japanese is used
3035 // or if the class provides inputenc
3036 if (features.isRequired("japanese")
3037 || features.isProvided("inputenc"))
3039 os << "\\usepackage[" << from_ascii(encoding().latexName());
3040 if (features.runparams().flavor == OutputParams::LUATEX
3041 || features.runparams().flavor == OutputParams::DVILUATEX)
3042 os << "]{luainputenc}\n";
3044 os << "]{inputenc}\n";
3047 if (encoding().name() == "utf8-cjk"
3048 && LaTeXFeatures::isAvailable("CJKutf8"))
3049 os << "\\usepackage{CJKutf8}\n";
3051 os << "\\usepackage{CJK}\n";
3054 // Load the CJK package if needed by a secondary language.
3055 // If the main encoding is some variant of UTF8, use CJKutf8.
3056 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
3057 if (encoding().iconvName() == "UTF-8"
3058 && LaTeXFeatures::isAvailable("CJKutf8"))
3059 os << "\\usepackage{CJKutf8}\n";
3061 os << "\\usepackage{CJK}\n";
3067 string const BufferParams::parseFontName(string const & name) const
3069 string mangled = name;
3070 size_t const idx = mangled.find('[');
3071 if (idx == string::npos || idx == 0)
3074 return mangled.substr(0, idx - 1);
3078 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3080 if (fontsRoman() == "default" && fontsSans() == "default"
3081 && fontsTypewriter() == "default"
3082 && (fontsMath() == "default" || fontsMath() == "auto"))
3088 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3089 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3090 * Mapping=tex-text option assures TeX ligatures (such as "--")
3091 * are resolved. Note that tt does not use these ligatures.
3093 * -- add more GUI options?
3094 * -- add more fonts (fonts for other scripts)
3095 * -- if there's a way to find out if a font really supports
3096 * OldStyle, enable/disable the widget accordingly.
3098 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3099 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3100 // However, until v.2 (2010/07/11) fontspec only knew
3101 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3102 // was introduced for both XeTeX and LuaTeX (LuaTeX
3103 // didn't understand "Mapping=tex-text", while XeTeX
3104 // understood both. With most recent versions, both
3105 // variants are understood by both engines. However,
3106 // we want to provide support for at least TeXLive 2009
3107 // (for XeTeX; LuaTeX is only supported as of v.2)
3108 string const texmapping =
3109 (features.runparams().flavor == OutputParams::XETEX) ?
3110 "Mapping=tex-text" : "Ligatures=TeX";
3111 if (fontsRoman() != "default") {
3112 os << "\\setmainfont[" << texmapping;
3113 if (fonts_old_figures)
3114 os << ",Numbers=OldStyle";
3115 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3117 if (fontsSans() != "default") {
3118 string const sans = parseFontName(fontsSans());
3119 if (fontsSansScale() != 100)
3120 os << "\\setsansfont[Scale="
3121 << float(fontsSansScale()) / 100
3122 << "," << texmapping << "]{"
3125 os << "\\setsansfont[" << texmapping << "]{"
3128 if (fontsTypewriter() != "default") {
3129 string const mono = parseFontName(fontsTypewriter());
3130 if (fontsTypewriterScale() != 100)
3131 os << "\\setmonofont[Scale="
3132 << float(fontsTypewriterScale()) / 100
3136 os << "\\setmonofont{"
3143 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
3144 bool const dryrun = features.runparams().dryrun;
3145 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3146 bool const nomath = (fontsMath() == "default");
3149 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3150 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3154 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3155 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3156 nomath, fontsSansScale());
3158 // MONOSPACED/TYPEWRITER
3159 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3160 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3161 nomath, fontsTypewriterScale());
3164 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3165 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3172 Encoding const & BufferParams::encoding() const
3174 // Main encoding for LaTeX output.
3176 // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740).
3177 // As the "flavor" is only known once export started, this
3178 // cannot be handled here. Instead, runparams.encoding is set
3179 // to ASCII in Buffer::makeLaTeXFile (for export)
3180 // and Buffer::writeLaTeXSource (for preview).
3182 return *(encodings.fromLyXName("utf8-plain"));
3183 if (inputenc == "auto" || inputenc == "default")
3184 return *language->encoding();
3185 Encoding const * const enc = encodings.fromLyXName(inputenc);
3188 LYXERR0("Unknown inputenc value `" << inputenc
3189 << "'. Using `auto' instead.");
3190 return *language->encoding();
3194 bool BufferParams::addCiteEngine(string const & engine)
3196 LayoutModuleList::const_iterator it = cite_engine_.begin();
3197 LayoutModuleList::const_iterator en = cite_engine_.end();
3198 for (; it != en; ++it)
3201 cite_engine_.push_back(engine);
3206 bool BufferParams::addCiteEngine(vector<string> const & engine)
3208 vector<string>::const_iterator it = engine.begin();
3209 vector<string>::const_iterator en = engine.end();
3211 for (; it != en; ++it)
3212 if (!addCiteEngine(*it))
3218 string const & BufferParams::defaultBiblioStyle() const
3220 return documentClass().defaultBiblioStyle();
3224 bool const & BufferParams::fullAuthorList() const
3226 return documentClass().fullAuthorList();
3230 void BufferParams::setCiteEngine(string const & engine)
3233 addCiteEngine(engine);
3237 void BufferParams::setCiteEngine(vector<string> const & engine)
3240 addCiteEngine(engine);
3244 vector<string> BufferParams::citeCommands() const
3246 static CitationStyle const default_style;
3247 vector<string> commands =
3248 documentClass().citeCommands(citeEngineType());
3249 if (commands.empty())
3250 commands.push_back(default_style.cmd);
3255 vector<CitationStyle> BufferParams::citeStyles() const
3257 static CitationStyle const default_style;
3258 vector<CitationStyle> styles =
3259 documentClass().citeStyles(citeEngineType());
3261 styles.push_back(default_style);