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 fonts_expert_sc = false;
392 fonts_old_figures = false;
393 fonts_sans_scale[0] = 100;
394 fonts_sans_scale[1] = 100;
395 fonts_typewriter_scale[0] = 100;
396 fonts_typewriter_scale[1] = 100;
398 lang_package = "default";
399 graphics_driver = "default";
400 default_output_format = "default";
401 bibtex_command = "default";
402 index_command = "default";
405 listings_params = string();
406 pagestyle = "default";
407 suppress_date = false;
408 justification = true;
409 // no color is the default (white)
410 backgroundcolor = lyx::rgbFromHexName("#ffffff");
411 isbackgroundcolor = false;
412 // no color is the default (black)
413 fontcolor = lyx::rgbFromHexName("#000000");
415 // light gray is the default font color for greyed-out notes
416 notefontcolor = lyx::rgbFromHexName("#cccccc");
417 boxbgcolor = lyx::rgbFromHexName("#ff0000");
418 compressed = lyxrc.save_compressed;
419 for (int iter = 0; iter < 4; ++iter) {
420 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
421 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
424 indiceslist().addDefault(B_("Index"));
425 html_be_strict = false;
426 html_math_output = MathML;
427 html_math_img_scale = 1.0;
428 html_css_as_file = false;
429 display_pixel_ratio = 1.0;
434 // map current author
435 author_map_[pimpl_->authorlist.get(0).bufferId()] = 0;
439 docstring BufferParams::B_(string const & l10n) const
441 LASSERT(language, return from_utf8(l10n));
442 return getMessages(language->code()).get(l10n);
446 BufferParams::Package BufferParams::use_package(std::string const & p) const
448 PackageMap::const_iterator it = use_packages.find(p);
449 if (it == use_packages.end())
455 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
461 map<string, string> const & BufferParams::auto_packages()
463 static map<string, string> packages;
464 if (packages.empty()) {
465 // We could have a race condition here that two threads
466 // discover an empty map at the same time and want to fill
467 // it, but that is no problem, since the same contents is
468 // filled in twice then. Having the locker inside the
469 // packages.empty() condition has the advantage that we
470 // don't need the mutex overhead for simple reading.
472 Mutex::Locker locker(&mutex);
473 // adding a package here implies a file format change!
474 packages["amsmath"] =
475 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
476 packages["amssymb"] =
477 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
479 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
481 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
482 packages["mathdots"] =
483 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
484 packages["mathtools"] =
485 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
487 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
488 packages["stackrel"] =
489 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
490 packages["stmaryrd"] =
491 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");
492 packages["undertilde"] =
493 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
499 AuthorList & BufferParams::authors()
501 return pimpl_->authorlist;
505 AuthorList const & BufferParams::authors() const
507 return pimpl_->authorlist;
511 void BufferParams::addAuthor(Author a)
513 author_map_[a.bufferId()] = pimpl_->authorlist.record(a);
517 BranchList & BufferParams::branchlist()
519 return pimpl_->branchlist;
523 BranchList const & BufferParams::branchlist() const
525 return pimpl_->branchlist;
529 IndicesList & BufferParams::indiceslist()
531 return pimpl_->indiceslist;
535 IndicesList const & BufferParams::indiceslist() const
537 return pimpl_->indiceslist;
541 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
543 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
544 return pimpl_->temp_bullets[index];
548 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
550 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
551 return pimpl_->temp_bullets[index];
555 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
557 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
558 return pimpl_->user_defined_bullets[index];
562 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
564 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
565 return pimpl_->user_defined_bullets[index];
569 Spacing & BufferParams::spacing()
571 return pimpl_->spacing;
575 Spacing const & BufferParams::spacing() const
577 return pimpl_->spacing;
581 PDFOptions & BufferParams::pdfoptions()
583 return pimpl_->pdfoptions;
587 PDFOptions const & BufferParams::pdfoptions() const
589 return pimpl_->pdfoptions;
593 HSpace const & BufferParams::getIndentation() const
595 return pimpl_->indentation;
599 void BufferParams::setIndentation(HSpace const & indent)
601 pimpl_->indentation = indent;
605 VSpace const & BufferParams::getDefSkip() const
607 return pimpl_->defskip;
611 void BufferParams::setDefSkip(VSpace const & vs)
613 // DEFSKIP will cause an infinite loop
614 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
615 pimpl_->defskip = vs;
619 string BufferParams::readToken(Lexer & lex, string const & token,
620 FileName const & filepath)
624 if (token == "\\textclass") {
626 string const classname = lex.getString();
627 // if there exists a local layout file, ignore the system one
628 // NOTE: in this case, the textclass (.cls file) is assumed to
631 LayoutFileList & bcl = LayoutFileList::get();
632 if (!filepath.empty()) {
633 // If classname is an absolute path, the document is
634 // using a local layout file which could not be accessed
635 // by a relative path. In this case the path is correct
636 // even if the document was moved to a different
637 // location. However, we will have a problem if the
638 // document was generated on a different platform.
639 bool isabsolute = FileName::isAbsolute(classname);
640 string const classpath = onlyPath(classname);
641 string const path = isabsolute ? classpath
642 : FileName(addPath(filepath.absFileName(),
643 classpath)).realPath();
644 string const oldpath = isabsolute ? string()
645 : FileName(addPath(origin, classpath)).realPath();
646 tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
648 // that returns non-empty if a "local" layout file is found.
650 result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
651 from_utf8(filepath.absFileName())));
654 setBaseClass(onlyFileName(tcp));
656 setBaseClass(onlyFileName(classname));
657 // We assume that a tex class exists for local or unknown
658 // layouts so this warning, will only be given for system layouts.
659 if (!baseClass()->isTeXClassAvailable()) {
660 docstring const desc =
661 translateIfPossible(from_utf8(baseClass()->description()));
662 docstring const prereqs =
663 from_utf8(baseClass()->prerequisites());
664 docstring const msg =
665 bformat(_("The selected document class\n"
667 "requires external files that are not available.\n"
668 "The document class can still be used, but the\n"
669 "document cannot be compiled until the following\n"
670 "prerequisites are installed:\n"
672 "See section 3.1.2.2 (Class Availability) of the\n"
673 "User's Guide for more information."), desc, prereqs);
674 frontend::Alert::warning(_("Document class not available"),
677 } else if (token == "\\save_transient_properties") {
678 lex >> save_transient_properties;
679 } else if (token == "\\origin") {
681 origin = lex.getString();
682 string const sysdirprefix = "/systemlyxdir/";
683 if (prefixIs(origin, sysdirprefix)) {
684 origin.replace(0, sysdirprefix.length() - 1,
685 package().system_support().absFileName());
687 } else if (token == "\\begin_preamble") {
689 } else if (token == "\\begin_local_layout") {
690 readLocalLayout(lex, false);
691 } else if (token == "\\begin_forced_local_layout") {
692 readLocalLayout(lex, true);
693 } else if (token == "\\begin_modules") {
695 } else if (token == "\\begin_removed_modules") {
696 readRemovedModules(lex);
697 } else if (token == "\\begin_includeonly") {
698 readIncludeonly(lex);
699 } else if (token == "\\maintain_unincluded_children") {
700 lex >> maintain_unincluded_children;
701 } else if (token == "\\options") {
703 options = lex.getString();
704 } else if (token == "\\use_default_options") {
705 lex >> use_default_options;
706 } else if (token == "\\master") {
708 master = lex.getString();
709 if (!filepath.empty() && FileName::isAbsolute(origin)) {
710 bool const isabs = FileName::isAbsolute(master);
711 FileName const abspath(isabs ? master : origin + master);
712 bool const moved = filepath != FileName(origin);
713 if (moved && abspath.exists()) {
714 docstring const path = isabs
716 : from_utf8(abspath.realPath());
717 docstring const refpath =
718 from_utf8(filepath.absFileName());
719 master = to_utf8(makeRelPath(path, refpath));
722 } else if (token == "\\suppress_date") {
723 lex >> suppress_date;
724 } else if (token == "\\justification") {
725 lex >> justification;
726 } else if (token == "\\language") {
728 } else if (token == "\\language_package") {
730 lang_package = lex.getString();
731 } else if (token == "\\inputencoding") {
733 } else if (token == "\\graphics") {
734 readGraphicsDriver(lex);
735 } else if (token == "\\default_output_format") {
736 lex >> default_output_format;
737 } else if (token == "\\bibtex_command") {
739 bibtex_command = lex.getString();
740 } else if (token == "\\index_command") {
742 index_command = lex.getString();
743 } else if (token == "\\fontencoding") {
745 fontenc = lex.getString();
746 } else if (token == "\\font_roman") {
747 lex >> fonts_roman[0];
748 lex >> fonts_roman[1];
749 } else if (token == "\\font_sans") {
750 lex >> fonts_sans[0];
751 lex >> fonts_sans[1];
752 } else if (token == "\\font_typewriter") {
753 lex >> fonts_typewriter[0];
754 lex >> fonts_typewriter[1];
755 } else if (token == "\\font_math") {
756 lex >> fonts_math[0];
757 lex >> fonts_math[1];
758 } else if (token == "\\font_default_family") {
759 lex >> fonts_default_family;
760 } else if (token == "\\use_non_tex_fonts") {
761 lex >> useNonTeXFonts;
762 } else if (token == "\\font_sc") {
763 lex >> fonts_expert_sc;
764 } else if (token == "\\font_osf") {
765 lex >> fonts_old_figures;
766 } else if (token == "\\font_sf_scale") {
767 lex >> fonts_sans_scale[0];
768 lex >> fonts_sans_scale[1];
769 } else if (token == "\\font_tt_scale") {
770 lex >> fonts_typewriter_scale[0];
771 lex >> fonts_typewriter_scale[1];
772 } else if (token == "\\font_cjk") {
774 } else if (token == "\\paragraph_separation") {
777 paragraph_separation = parseptranslator().find(parsep);
778 } else if (token == "\\paragraph_indentation") {
780 string indentation = lex.getString();
781 pimpl_->indentation = HSpace(indentation);
782 } else if (token == "\\defskip") {
784 string const defskip = lex.getString();
785 pimpl_->defskip = VSpace(defskip);
786 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
788 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
789 } else if (token == "\\quotes_language") {
792 quotes_language = quoteslangtranslator().find(quotes_lang);
793 } else if (token == "\\papersize") {
796 papersize = papersizetranslator().find(ppsize);
797 } else if (token == "\\use_geometry") {
799 } else if (token == "\\use_package") {
804 use_package(package, packagetranslator().find(use));
805 } else if (token == "\\cite_engine") {
807 vector<string> engine = getVectorFromString(lex.getString());
808 setCiteEngine(engine);
809 } else if (token == "\\cite_engine_type") {
812 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
813 } else if (token == "\\biblio_style") {
815 biblio_style = lex.getString();
816 } else if (token == "\\use_bibtopic") {
818 } else if (token == "\\use_indices") {
820 } else if (token == "\\tracking_changes") {
821 lex >> track_changes;
822 } else if (token == "\\output_changes") {
823 lex >> output_changes;
824 } else if (token == "\\branch") {
826 docstring branch = lex.getDocString();
827 branchlist().add(branch);
830 string const tok = lex.getString();
831 if (tok == "\\end_branch")
833 Branch * branch_ptr = branchlist().find(branch);
834 if (tok == "\\selected") {
837 branch_ptr->setSelected(lex.getInteger());
839 if (tok == "\\filename_suffix") {
842 branch_ptr->setFileNameSuffix(lex.getInteger());
844 if (tok == "\\color") {
846 string color = lex.getString();
848 branch_ptr->setColor(color);
849 // Update also the Color table:
851 color = lcolor.getX11Name(Color_background);
853 lcolor.setColor(to_utf8(branch), color);
856 } else if (token == "\\index") {
858 docstring index = lex.getDocString();
860 indiceslist().add(index);
863 string const tok = lex.getString();
864 if (tok == "\\end_index")
866 Index * index_ptr = indiceslist().find(index);
867 if (tok == "\\shortcut") {
869 shortcut = lex.getDocString();
871 index_ptr->setShortcut(shortcut);
873 if (tok == "\\color") {
875 string color = lex.getString();
877 index_ptr->setColor(color);
878 // Update also the Color table:
880 color = lcolor.getX11Name(Color_background);
882 if (!shortcut.empty())
883 lcolor.setColor(to_utf8(shortcut), color);
886 } else if (token == "\\author") {
888 istringstream ss(lex.getString());
892 } else if (token == "\\paperorientation") {
895 orientation = paperorientationtranslator().find(orient);
896 } else if (token == "\\backgroundcolor") {
898 backgroundcolor = lyx::rgbFromHexName(lex.getString());
899 isbackgroundcolor = true;
900 } else if (token == "\\fontcolor") {
902 fontcolor = lyx::rgbFromHexName(lex.getString());
904 } else if (token == "\\notefontcolor") {
906 string color = lex.getString();
907 notefontcolor = lyx::rgbFromHexName(color);
908 lcolor.setColor("notefontcolor", color);
909 } else if (token == "\\boxbgcolor") {
911 string color = lex.getString();
912 boxbgcolor = lyx::rgbFromHexName(color);
913 lcolor.setColor("boxbgcolor", color);
914 } else if (token == "\\paperwidth") {
916 } else if (token == "\\paperheight") {
918 } else if (token == "\\leftmargin") {
920 } else if (token == "\\topmargin") {
922 } else if (token == "\\rightmargin") {
924 } else if (token == "\\bottommargin") {
926 } else if (token == "\\headheight") {
928 } else if (token == "\\headsep") {
930 } else if (token == "\\footskip") {
932 } else if (token == "\\columnsep") {
934 } else if (token == "\\paperfontsize") {
936 } else if (token == "\\papercolumns") {
938 } else if (token == "\\listings_params") {
941 listings_params = InsetListingsParams(par).params();
942 } else if (token == "\\papersides") {
945 sides = sidestranslator().find(psides);
946 } else if (token == "\\paperpagestyle") {
948 } else if (token == "\\bullet") {
950 } else if (token == "\\bulletLaTeX") {
951 readBulletsLaTeX(lex);
952 } else if (token == "\\secnumdepth") {
954 } else if (token == "\\tocdepth") {
956 } else if (token == "\\spacing") {
960 if (nspacing == "other") {
963 spacing().set(spacetranslator().find(nspacing), tmp_val);
964 } else if (token == "\\float_placement") {
965 lex >> float_placement;
967 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
968 string toktmp = pdfoptions().readToken(lex, token);
969 if (!toktmp.empty()) {
970 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
974 } else if (token == "\\html_math_output") {
977 html_math_output = static_cast<MathOutput>(temp);
978 } else if (token == "\\html_be_strict") {
979 lex >> html_be_strict;
980 } else if (token == "\\html_css_as_file") {
981 lex >> html_css_as_file;
982 } else if (token == "\\html_math_img_scale") {
983 lex >> html_math_img_scale;
984 } else if (token == "\\html_latex_start") {
986 html_latex_start = lex.getString();
987 } else if (token == "\\html_latex_end") {
989 html_latex_end = lex.getString();
990 } else if (token == "\\output_sync") {
992 } else if (token == "\\output_sync_macro") {
993 lex >> output_sync_macro;
994 } else if (token == "\\use_refstyle") {
997 lyxerr << "BufferParams::readToken(): Unknown token: " <<
1007 // Quote argument if it contains spaces
1008 string quoteIfNeeded(string const & str) {
1009 if (contains(str, ' '))
1010 return "\"" + str + "\"";
1016 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
1018 // The top of the file is written by the buffer.
1019 // Prints out the buffer info into the .lyx file given by file
1021 os << "\\save_transient_properties "
1022 << convert<string>(save_transient_properties) << '\n';
1024 // the document directory (must end with a path separator)
1025 // realPath() is used to resolve symlinks, while addPath(..., "")
1026 // ensures a trailing path separator.
1027 string filepath = addPath(buf->fileName().onlyPath().realPath(), "");
1028 string const sysdir = addPath(package().system_support().realPath(), "");
1029 string const relpath =
1030 to_utf8(makeRelPath(from_utf8(filepath), from_utf8(sysdir)));
1031 if (!prefixIs(relpath, "../") && !FileName::isAbsolute(relpath))
1032 filepath = addPath("/systemlyxdir", relpath);
1033 else if (!save_transient_properties || !lyxrc.save_origin)
1034 filepath = "unavailable";
1035 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1038 os << "\\textclass "
1039 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1040 baseClass()->name()), "layout"))
1043 // then the preamble
1044 if (!preamble.empty()) {
1045 // remove '\n' from the end of preamble
1046 string const tmppreamble = rtrim(preamble, "\n");
1047 os << "\\begin_preamble\n"
1049 << "\n\\end_preamble\n";
1053 if (!options.empty()) {
1054 os << "\\options " << options << '\n';
1057 // use the class options defined in the layout?
1058 os << "\\use_default_options "
1059 << convert<string>(use_default_options) << "\n";
1061 // the master document
1062 if (!master.empty()) {
1063 os << "\\master " << master << '\n';
1067 if (!removed_modules_.empty()) {
1068 os << "\\begin_removed_modules" << '\n';
1069 list<string>::const_iterator it = removed_modules_.begin();
1070 list<string>::const_iterator en = removed_modules_.end();
1071 for (; it != en; ++it)
1073 os << "\\end_removed_modules" << '\n';
1077 if (!layout_modules_.empty()) {
1078 os << "\\begin_modules" << '\n';
1079 LayoutModuleList::const_iterator it = layout_modules_.begin();
1080 LayoutModuleList::const_iterator en = layout_modules_.end();
1081 for (; it != en; ++it)
1083 os << "\\end_modules" << '\n';
1087 if (!included_children_.empty()) {
1088 os << "\\begin_includeonly" << '\n';
1089 list<string>::const_iterator it = included_children_.begin();
1090 list<string>::const_iterator en = included_children_.end();
1091 for (; it != en; ++it)
1093 os << "\\end_includeonly" << '\n';
1095 os << "\\maintain_unincluded_children "
1096 << convert<string>(maintain_unincluded_children) << '\n';
1098 // local layout information
1099 string const local_layout = getLocalLayout(false);
1100 if (!local_layout.empty()) {
1101 // remove '\n' from the end
1102 string const tmplocal = rtrim(local_layout, "\n");
1103 os << "\\begin_local_layout\n"
1105 << "\n\\end_local_layout\n";
1107 string const forced_local_layout = getLocalLayout(true);
1108 if (!forced_local_layout.empty()) {
1109 // remove '\n' from the end
1110 string const tmplocal = rtrim(forced_local_layout, "\n");
1111 os << "\\begin_forced_local_layout\n"
1113 << "\n\\end_forced_local_layout\n";
1116 // then the text parameters
1117 if (language != ignore_language)
1118 os << "\\language " << language->lang() << '\n';
1119 os << "\\language_package " << lang_package
1120 << "\n\\inputencoding " << inputenc
1121 << "\n\\fontencoding " << fontenc
1122 << "\n\\font_roman \"" << fonts_roman[0]
1123 << "\" \"" << fonts_roman[1] << '"'
1124 << "\n\\font_sans \"" << fonts_sans[0]
1125 << "\" \"" << fonts_sans[1] << '"'
1126 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1127 << "\" \"" << fonts_typewriter[1] << '"'
1128 << "\n\\font_math \"" << fonts_math[0]
1129 << "\" \"" << fonts_math[1] << '"'
1130 << "\n\\font_default_family " << fonts_default_family
1131 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1132 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1133 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1134 << "\n\\font_sf_scale " << fonts_sans_scale[0]
1135 << ' ' << fonts_sans_scale[1]
1136 << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1137 << ' ' << fonts_typewriter_scale[1]
1139 if (!fonts_cjk.empty()) {
1140 os << "\\font_cjk " << fonts_cjk << '\n';
1142 os << "\\graphics " << graphics_driver << '\n';
1143 os << "\\default_output_format " << default_output_format << '\n';
1144 os << "\\output_sync " << output_sync << '\n';
1145 if (!output_sync_macro.empty())
1146 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1147 os << "\\bibtex_command " << bibtex_command << '\n';
1148 os << "\\index_command " << index_command << '\n';
1150 if (!float_placement.empty()) {
1151 os << "\\float_placement " << float_placement << '\n';
1153 os << "\\paperfontsize " << fontsize << '\n';
1155 spacing().writeFile(os);
1156 pdfoptions().writeFile(os);
1158 os << "\\papersize " << string_papersize[papersize]
1159 << "\n\\use_geometry " << convert<string>(use_geometry);
1160 map<string, string> const & packages = auto_packages();
1161 for (map<string, string>::const_iterator it = packages.begin();
1162 it != packages.end(); ++it)
1163 os << "\n\\use_package " << it->first << ' '
1164 << use_package(it->first);
1166 os << "\n\\cite_engine ";
1168 if (!cite_engine_.empty()) {
1169 LayoutModuleList::const_iterator be = cite_engine_.begin();
1170 LayoutModuleList::const_iterator en = cite_engine_.end();
1171 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1180 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1181 << "\n\\biblio_style " << biblio_style
1182 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1183 << "\n\\use_indices " << convert<string>(use_indices)
1184 << "\n\\paperorientation " << string_orientation[orientation]
1185 << "\n\\suppress_date " << convert<string>(suppress_date)
1186 << "\n\\justification " << convert<string>(justification)
1187 << "\n\\use_refstyle " << use_refstyle
1189 if (isbackgroundcolor == true)
1190 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1191 if (isfontcolor == true)
1192 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1193 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1194 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1195 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1196 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1198 BranchList::const_iterator it = branchlist().begin();
1199 BranchList::const_iterator end = branchlist().end();
1200 for (; it != end; ++it) {
1201 os << "\\branch " << to_utf8(it->branch())
1202 << "\n\\selected " << it->isSelected()
1203 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1204 << "\n\\color " << lyx::X11hexname(it->color())
1209 IndicesList::const_iterator iit = indiceslist().begin();
1210 IndicesList::const_iterator iend = indiceslist().end();
1211 for (; iit != iend; ++iit) {
1212 os << "\\index " << to_utf8(iit->index())
1213 << "\n\\shortcut " << to_utf8(iit->shortcut())
1214 << "\n\\color " << lyx::X11hexname(iit->color())
1219 if (!paperwidth.empty())
1220 os << "\\paperwidth "
1221 << VSpace(paperwidth).asLyXCommand() << '\n';
1222 if (!paperheight.empty())
1223 os << "\\paperheight "
1224 << VSpace(paperheight).asLyXCommand() << '\n';
1225 if (!leftmargin.empty())
1226 os << "\\leftmargin "
1227 << VSpace(leftmargin).asLyXCommand() << '\n';
1228 if (!topmargin.empty())
1229 os << "\\topmargin "
1230 << VSpace(topmargin).asLyXCommand() << '\n';
1231 if (!rightmargin.empty())
1232 os << "\\rightmargin "
1233 << VSpace(rightmargin).asLyXCommand() << '\n';
1234 if (!bottommargin.empty())
1235 os << "\\bottommargin "
1236 << VSpace(bottommargin).asLyXCommand() << '\n';
1237 if (!headheight.empty())
1238 os << "\\headheight "
1239 << VSpace(headheight).asLyXCommand() << '\n';
1240 if (!headsep.empty())
1242 << VSpace(headsep).asLyXCommand() << '\n';
1243 if (!footskip.empty())
1245 << VSpace(footskip).asLyXCommand() << '\n';
1246 if (!columnsep.empty())
1247 os << "\\columnsep "
1248 << VSpace(columnsep).asLyXCommand() << '\n';
1249 os << "\\secnumdepth " << secnumdepth
1250 << "\n\\tocdepth " << tocdepth
1251 << "\n\\paragraph_separation "
1252 << string_paragraph_separation[paragraph_separation];
1253 if (!paragraph_separation)
1254 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1256 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1257 os << "\n\\quotes_language "
1258 << string_quotes_language[quotes_language]
1259 << "\n\\papercolumns " << columns
1260 << "\n\\papersides " << sides
1261 << "\n\\paperpagestyle " << pagestyle << '\n';
1262 if (!listings_params.empty())
1263 os << "\\listings_params \"" <<
1264 InsetListingsParams(listings_params).encodedString() << "\"\n";
1265 for (int i = 0; i < 4; ++i) {
1266 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1267 if (user_defined_bullet(i).getFont() != -1) {
1268 os << "\\bullet " << i << " "
1269 << user_defined_bullet(i).getFont() << " "
1270 << user_defined_bullet(i).getCharacter() << " "
1271 << user_defined_bullet(i).getSize() << "\n";
1275 os << "\\bulletLaTeX " << i << " \""
1276 << lyx::to_ascii(user_defined_bullet(i).getText())
1282 os << "\\tracking_changes "
1283 << (save_transient_properties ? convert<string>(track_changes) : "false")
1286 os << "\\output_changes "
1287 << (save_transient_properties ? convert<string>(output_changes) : "false")
1290 os << "\\html_math_output " << html_math_output << '\n'
1291 << "\\html_css_as_file " << html_css_as_file << '\n'
1292 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1294 if (html_math_img_scale != 1.0)
1295 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1296 if (!html_latex_start.empty())
1297 os << "\\html_latex_start " << html_latex_start << '\n';
1298 if (!html_latex_end.empty())
1299 os << "\\html_latex_end " << html_latex_end << '\n';
1301 os << pimpl_->authorlist;
1305 void BufferParams::validate(LaTeXFeatures & features) const
1307 features.require(documentClass().requires());
1309 if (columns > 1 && language->rightToLeft())
1310 features.require("rtloutputdblcol");
1312 if (output_changes) {
1313 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1314 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1315 LaTeXFeatures::isAvailable("xcolor");
1317 switch (features.runparams().flavor) {
1318 case OutputParams::LATEX:
1319 case OutputParams::DVILUATEX:
1321 features.require("ct-dvipost");
1322 features.require("dvipost");
1323 } else if (xcolorulem) {
1324 features.require("ct-xcolor-ulem");
1325 features.require("ulem");
1326 features.require("xcolor");
1328 features.require("ct-none");
1331 case OutputParams::LUATEX:
1332 case OutputParams::PDFLATEX:
1333 case OutputParams::XETEX:
1335 features.require("ct-xcolor-ulem");
1336 features.require("ulem");
1337 features.require("xcolor");
1338 // improves color handling in PDF output
1339 features.require("pdfcolmk");
1341 features.require("ct-none");
1349 // Floats with 'Here definitely' as default setting.
1350 if (float_placement.find('H') != string::npos)
1351 features.require("float");
1353 for (PackageMap::const_iterator it = use_packages.begin();
1354 it != use_packages.end(); ++it) {
1355 if (it->first == "amsmath") {
1356 // AMS Style is at document level
1357 if (it->second == package_on ||
1358 features.isProvided("amsmath"))
1359 features.require(it->first);
1360 } else if (it->second == package_on)
1361 features.require(it->first);
1364 // Document-level line spacing
1365 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1366 features.require("setspace");
1368 // the bullet shapes are buffer level not paragraph level
1369 // so they are tested here
1370 for (int i = 0; i < 4; ++i) {
1371 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1373 int const font = user_defined_bullet(i).getFont();
1375 int const c = user_defined_bullet(i).getCharacter();
1381 features.require("latexsym");
1383 } else if (font == 1) {
1384 features.require("amssymb");
1385 } else if (font >= 2 && font <= 5) {
1386 features.require("pifont");
1390 if (pdfoptions().use_hyperref) {
1391 features.require("hyperref");
1392 // due to interferences with babel and hyperref, the color package has to
1393 // be loaded after hyperref when hyperref is used with the colorlinks
1394 // option, see http://www.lyx.org/trac/ticket/5291
1395 if (pdfoptions().colorlinks)
1396 features.require("color");
1398 if (!listings_params.empty()) {
1399 // do not test validity because listings_params is
1400 // supposed to be valid
1402 InsetListingsParams(listings_params).separatedParams(true);
1403 // we can't support all packages, but we should load the color package
1404 if (par.find("\\color", 0) != string::npos)
1405 features.require("color");
1408 // some languages are only available via polyglossia
1409 if (features.hasPolyglossiaExclusiveLanguages())
1410 features.require("polyglossia");
1412 if (useNonTeXFonts && fontsMath() != "auto")
1413 features.require("unicode-math");
1415 if (!language->requires().empty())
1416 features.require(language->requires());
1420 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1421 FileName const & filepath) const
1423 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1424 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1425 // \RequirePackage to do so, rather than the normal \usepackage
1426 // Do not try to load any other package before the document class, unless you
1427 // have a thorough understanding of the LATEX internals and know exactly what you
1429 if (features.mustProvide("fix-cm"))
1430 os << "\\RequirePackage{fix-cm}\n";
1431 // Likewise for fixltx2e. If other packages conflict with this policy,
1432 // treat it as a package bug (and report it!)
1433 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1434 if (features.mustProvide("fixltx2e"))
1435 os << "\\RequirePackage{fixltx2e}\n";
1437 os << "\\documentclass";
1439 DocumentClass const & tclass = documentClass();
1441 ostringstream clsoptions; // the document class options.
1443 if (tokenPos(tclass.opt_fontsize(),
1444 '|', fontsize) >= 0) {
1445 // only write if existing in list (and not default)
1446 clsoptions << fontsize << "pt,";
1449 // all paper sizes except of A4, A5, B5 and the US sizes need the
1451 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1452 && papersize != PAPER_USLETTER
1453 && papersize != PAPER_USLEGAL
1454 && papersize != PAPER_USEXECUTIVE
1455 && papersize != PAPER_A4
1456 && papersize != PAPER_A5
1457 && papersize != PAPER_B5;
1459 if (!use_geometry) {
1460 switch (papersize) {
1462 clsoptions << "a4paper,";
1464 case PAPER_USLETTER:
1465 clsoptions << "letterpaper,";
1468 clsoptions << "a5paper,";
1471 clsoptions << "b5paper,";
1473 case PAPER_USEXECUTIVE:
1474 clsoptions << "executivepaper,";
1477 clsoptions << "legalpaper,";
1511 if (sides != tclass.sides()) {
1514 clsoptions << "oneside,";
1517 clsoptions << "twoside,";
1523 if (columns != tclass.columns()) {
1525 clsoptions << "twocolumn,";
1527 clsoptions << "onecolumn,";
1531 && orientation == ORIENTATION_LANDSCAPE)
1532 clsoptions << "landscape,";
1534 // language should be a parameter to \documentclass
1535 if (language->babel() == "hebrew"
1536 && default_language->babel() != "hebrew")
1537 // This seems necessary
1538 features.useLanguage(default_language);
1540 ostringstream language_options;
1541 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1542 bool const use_polyglossia = features.usePolyglossia();
1543 bool const global = lyxrc.language_global_options;
1544 if (use_babel || (use_polyglossia && global)) {
1545 language_options << features.getBabelLanguages();
1546 if (!language->babel().empty()) {
1547 if (!language_options.str().empty())
1548 language_options << ',';
1549 language_options << language->babel();
1551 if (global && !features.needBabelLangOptions()
1552 && !language_options.str().empty())
1553 clsoptions << language_options.str() << ',';
1556 // the predefined options from the layout
1557 if (use_default_options && !tclass.options().empty())
1558 clsoptions << tclass.options() << ',';
1560 // the user-defined options
1561 if (!options.empty()) {
1562 clsoptions << options << ',';
1565 string strOptions(clsoptions.str());
1566 if (!strOptions.empty()) {
1567 strOptions = rtrim(strOptions, ",");
1569 os << '[' << from_utf8(strOptions) << ']';
1572 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1573 // end of \documentclass defs
1575 // if we use fontspec or newtxmath, we have to load the AMS packages here
1576 string const ams = features.loadAMSPackages();
1577 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1578 bool const use_newtxmath =
1579 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1580 ot1, false, false) == "newtxmath";
1581 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1582 os << from_ascii(ams);
1584 if (useNonTeXFonts) {
1585 if (!features.isProvided("fontspec"))
1586 os << "\\usepackage{fontspec}\n";
1587 if (features.mustProvide("unicode-math")
1588 && features.isAvailable("unicode-math"))
1589 os << "\\usepackage{unicode-math}\n";
1592 // font selection must be done before loading fontenc.sty
1593 string const fonts = loadFonts(features);
1595 os << from_utf8(fonts);
1597 if (fonts_default_family != "default")
1598 os << "\\renewcommand{\\familydefault}{\\"
1599 << from_ascii(fonts_default_family) << "}\n";
1601 // set font encoding
1602 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1603 if (!useNonTeXFonts && !features.isProvided("fontenc")
1604 && font_encoding() != "default") {
1605 // get main font encodings
1606 vector<string> fontencs = font_encodings();
1607 // get font encodings of secondary languages
1608 features.getFontEncodings(fontencs);
1609 if (!fontencs.empty()) {
1610 os << "\\usepackage["
1611 << from_ascii(getStringFromVector(fontencs))
1616 // handle inputenc etc.
1617 writeEncodingPreamble(os, features);
1620 if (!features.runparams().includeall && !included_children_.empty()) {
1621 os << "\\includeonly{";
1622 list<string>::const_iterator it = included_children_.begin();
1623 list<string>::const_iterator en = included_children_.end();
1625 for (; it != en; ++it) {
1626 string incfile = *it;
1627 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1628 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1630 if (!features.runparams().nice)
1632 // \includeonly doesn't want an extension
1633 incfile = changeExtension(incfile, string());
1634 incfile = support::latex_path(incfile);
1635 if (!incfile.empty()) {
1638 os << from_utf8(incfile);
1645 if (!features.isProvided("geometry")
1646 && (use_geometry || nonstandard_papersize)) {
1647 odocstringstream ods;
1648 if (!getGraphicsDriver("geometry").empty())
1649 ods << getGraphicsDriver("geometry");
1650 if (orientation == ORIENTATION_LANDSCAPE)
1651 ods << ",landscape";
1652 switch (papersize) {
1654 if (!paperwidth.empty())
1655 ods << ",paperwidth="
1656 << from_ascii(paperwidth);
1657 if (!paperheight.empty())
1658 ods << ",paperheight="
1659 << from_ascii(paperheight);
1661 case PAPER_USLETTER:
1662 ods << ",letterpaper";
1665 ods << ",legalpaper";
1667 case PAPER_USEXECUTIVE:
1668 ods << ",executivepaper";
1757 docstring const g_options = trim(ods.str(), ",");
1758 os << "\\usepackage";
1759 if (!g_options.empty())
1760 os << '[' << g_options << ']';
1761 os << "{geometry}\n";
1762 // output this only if use_geometry is true
1764 os << "\\geometry{verbose";
1765 if (!topmargin.empty())
1766 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1767 if (!bottommargin.empty())
1768 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1769 if (!leftmargin.empty())
1770 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1771 if (!rightmargin.empty())
1772 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1773 if (!headheight.empty())
1774 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1775 if (!headsep.empty())
1776 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1777 if (!footskip.empty())
1778 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1779 if (!columnsep.empty())
1780 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1783 } else if (orientation == ORIENTATION_LANDSCAPE
1784 || papersize != PAPER_DEFAULT) {
1785 features.require("papersize");
1788 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1789 if (pagestyle == "fancy")
1790 os << "\\usepackage{fancyhdr}\n";
1791 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1794 // only output when the background color is not default
1795 if (isbackgroundcolor == true) {
1796 // only require color here, the background color will be defined
1797 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1799 features.require("color");
1800 features.require("pagecolor");
1803 // only output when the font color is not default
1804 if (isfontcolor == true) {
1805 // only require color here, the font color will be defined
1806 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1808 features.require("color");
1809 features.require("fontcolor");
1812 // Only if class has a ToC hierarchy
1813 if (tclass.hasTocLevels()) {
1814 if (secnumdepth != tclass.secnumdepth()) {
1815 os << "\\setcounter{secnumdepth}{"
1819 if (tocdepth != tclass.tocdepth()) {
1820 os << "\\setcounter{tocdepth}{"
1826 if (paragraph_separation) {
1827 // when skip separation
1828 switch (getDefSkip().kind()) {
1829 case VSpace::SMALLSKIP:
1830 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1832 case VSpace::MEDSKIP:
1833 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1835 case VSpace::BIGSKIP:
1836 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1838 case VSpace::LENGTH:
1839 os << "\\setlength{\\parskip}{"
1840 << from_utf8(getDefSkip().length().asLatexString())
1843 default: // should never happen // Then delete it.
1844 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1847 os << "\\setlength{\\parindent}{0pt}\n";
1849 // when separation by indentation
1850 // only output something when a width is given
1851 if (getIndentation().asLyXCommand() != "default") {
1852 os << "\\setlength{\\parindent}{"
1853 << from_utf8(getIndentation().asLatexCommand())
1858 // Now insert the LyX specific LaTeX commands...
1859 docstring lyxpreamble;
1860 features.resolveAlternatives();
1863 if (!output_sync_macro.empty())
1864 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1865 else if (features.runparams().flavor == OutputParams::LATEX)
1866 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1867 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1868 lyxpreamble += "\\synctex=-1\n";
1871 // The package options (via \PassOptionsToPackage)
1872 lyxpreamble += from_ascii(features.getPackageOptions());
1874 // due to interferences with babel and hyperref, the color package has to
1875 // be loaded (when it is not already loaded) before babel when hyperref
1876 // is used with the colorlinks option, see
1877 // http://www.lyx.org/trac/ticket/5291
1878 // we decided therefore to load color always before babel, see
1879 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1880 lyxpreamble += from_ascii(features.getColorOptions());
1882 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1883 // we have to call babel before
1885 && (features.isRequired("jurabib")
1886 || features.isRequired("hyperref")
1887 || features.isRequired("varioref")
1888 || features.isRequired("vietnamese")
1889 || features.isRequired("japanese"))) {
1891 lyxpreamble += from_utf8(features.getBabelPresettings());
1892 lyxpreamble += from_utf8(babelCall(language_options.str(),
1893 features.needBabelLangOptions())) + '\n';
1894 lyxpreamble += from_utf8(features.getBabelPostsettings());
1897 // The optional packages;
1898 lyxpreamble += from_ascii(features.getPackages());
1900 // Additional Indices
1901 if (features.isRequired("splitidx")) {
1902 IndicesList::const_iterator iit = indiceslist().begin();
1903 IndicesList::const_iterator iend = indiceslist().end();
1904 for (; iit != iend; ++iit) {
1905 pair<docstring, docstring> indexname_latex =
1906 features.runparams().encoding->latexString(iit->index(),
1907 features.runparams().dryrun);
1908 if (!indexname_latex.second.empty()) {
1909 // issue a warning about omitted characters
1910 // FIXME: should be passed to the error dialog
1911 frontend::Alert::warning(_("Uncodable characters"),
1912 bformat(_("The following characters that are used in an index name are not\n"
1913 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1914 indexname_latex.second));
1916 lyxpreamble += "\\newindex[";
1917 lyxpreamble += indexname_latex.first;
1918 lyxpreamble += "]{";
1919 lyxpreamble += escape(iit->shortcut());
1920 lyxpreamble += "}\n";
1925 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1928 // * Hyperref manual: "Make sure it comes last of your loaded
1929 // packages, to give it a fighting chance of not being over-written,
1930 // since its job is to redefine many LaTeX commands."
1931 // * Email from Heiko Oberdiek: "It is usually better to load babel
1932 // before hyperref. Then hyperref has a chance to detect babel.
1933 // * Has to be loaded before the "LyX specific LaTeX commands" to
1934 // avoid errors with algorithm floats.
1935 // use hyperref explicitly if it is required
1936 if (features.isRequired("hyperref")) {
1937 // pass what we have to stream here, since we need
1938 // to access the stream itself in PDFOptions.
1941 OutputParams tmp_params = features.runparams();
1942 pdfoptions().writeLaTeX(tmp_params, os,
1943 features.isProvided("hyperref"));
1944 // set back for the rest
1945 lyxpreamble.clear();
1946 // correctly break URLs with hyperref and dvi output
1947 if (features.runparams().flavor == OutputParams::LATEX
1948 && features.isAvailable("breakurl"))
1949 lyxpreamble += "\\usepackage{breakurl}\n";
1950 } else if (features.isRequired("nameref"))
1951 // hyperref loads this automatically
1952 lyxpreamble += "\\usepackage{nameref}\n";
1954 // bibtopic needs to be loaded after hyperref.
1955 // the dot provides the aux file naming which LyX can detect.
1956 if (features.mustProvide("bibtopic"))
1957 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1959 // Will be surrounded by \makeatletter and \makeatother when not empty
1960 docstring atlyxpreamble;
1962 // Some macros LyX will need
1963 docstring tmppreamble(features.getMacros());
1965 if (!tmppreamble.empty())
1966 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1967 "LyX specific LaTeX commands.\n"
1968 + tmppreamble + '\n';
1970 // the text class specific preamble
1971 tmppreamble = features.getTClassPreamble();
1972 if (!tmppreamble.empty())
1973 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1974 "Textclass specific LaTeX commands.\n"
1975 + tmppreamble + '\n';
1977 // suppress date if selected
1978 // use \@ifundefined because we cannot be sure that every document class
1979 // has a \date command
1981 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1983 /* the user-defined preamble */
1984 if (!containsOnly(preamble, " \n\t")) {
1986 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1987 "User specified LaTeX commands.\n";
1989 // Check if the user preamble contains uncodable glyphs
1990 docstring const u_preamble = from_utf8(preamble);
1991 odocstringstream user_preamble;
1992 docstring uncodable_glyphs;
1993 Encoding const * const enc = features.runparams().encoding;
1995 for (size_t n = 0; n < u_preamble.size(); ++n) {
1996 char_type c = u_preamble[n];
1997 if (!enc->encodable(c)) {
1998 docstring const glyph(1, c);
1999 LYXERR0("Uncodable character '"
2001 << "' in user preamble!");
2002 uncodable_glyphs += glyph;
2003 if (features.runparams().dryrun) {
2004 user_preamble << "<" << _("LyX Warning: ")
2005 << _("uncodable character") << " '";
2006 user_preamble.put(c);
2007 user_preamble << "'>";
2010 user_preamble.put(c);
2013 user_preamble << u_preamble;
2015 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2016 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2017 frontend::Alert::warning(
2018 _("Uncodable character in user preamble"),
2020 _("The user preamble of your document contains glyphs "
2021 "that are unknown in the current document encoding "
2022 "(namely %1$s).\nThese glyphs are omitted "
2023 " from the output, which may result in "
2024 "incomplete output."
2025 "\n\nPlease select an appropriate "
2026 "document encoding\n"
2027 "(such as utf8) or change the "
2028 "preamble code accordingly."),
2031 atlyxpreamble += user_preamble.str() + '\n';
2034 // footmisc must be loaded after setspace
2035 // Load it here to avoid clashes with footmisc loaded in the user
2036 // preamble. For that reason we also pass the options via
2037 // \PassOptionsToPackage in getPreamble() and not here.
2038 if (features.mustProvide("footmisc"))
2039 atlyxpreamble += "\\usepackage{footmisc}\n";
2041 // subfig loads internally the LaTeX package "caption". As
2042 // caption is a very popular package, users will load it in
2043 // the preamble. Therefore we must load subfig behind the
2044 // user-defined preamble and check if the caption package was
2045 // loaded or not. For the case that caption is loaded before
2046 // subfig, there is the subfig option "caption=false". This
2047 // option also works when a koma-script class is used and
2048 // koma's own caption commands are used instead of caption. We
2049 // use \PassOptionsToPackage here because the user could have
2050 // already loaded subfig in the preamble.
2051 if (features.mustProvide("subfig")) {
2052 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
2053 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2054 "\\usepackage{subfig}\n";
2057 // Itemize bullet settings need to be last in case the user
2058 // defines their own bullets that use a package included
2059 // in the user-defined preamble -- ARRae
2060 // Actually it has to be done much later than that
2061 // since some packages like frenchb make modifications
2062 // at \begin{document} time -- JMarc
2063 docstring bullets_def;
2064 for (int i = 0; i < 4; ++i) {
2065 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2066 if (bullets_def.empty())
2067 bullets_def += "\\AtBeginDocument{\n";
2068 bullets_def += " \\def\\labelitemi";
2070 // `i' is one less than the item to modify
2077 bullets_def += "ii";
2083 bullets_def += '{' +
2084 user_defined_bullet(i).getText()
2089 if (!bullets_def.empty())
2090 atlyxpreamble += bullets_def + "}\n\n";
2092 if (!atlyxpreamble.empty())
2093 lyxpreamble += "\n\\makeatletter\n"
2094 + atlyxpreamble + "\\makeatother\n\n";
2096 // We try to load babel late, in case it interferes with other packages.
2097 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
2098 // called after babel, though.
2099 if (use_babel && !features.isRequired("jurabib")
2100 && !features.isRequired("hyperref")
2101 && !features.isRequired("varioref")
2102 && !features.isRequired("vietnamese")
2103 && !features.isRequired("japanese")) {
2105 lyxpreamble += from_utf8(features.getBabelPresettings());
2106 lyxpreamble += from_utf8(babelCall(language_options.str(),
2107 features.needBabelLangOptions())) + '\n';
2108 lyxpreamble += from_utf8(features.getBabelPostsettings());
2110 if (features.isRequired("bicaption"))
2111 lyxpreamble += "\\usepackage{bicaption}\n";
2112 if (!listings_params.empty() || features.mustProvide("listings"))
2113 lyxpreamble += "\\usepackage{listings}\n";
2114 if (!listings_params.empty()) {
2115 lyxpreamble += "\\lstset{";
2116 // do not test validity because listings_params is
2117 // supposed to be valid
2119 InsetListingsParams(listings_params).separatedParams(true);
2120 lyxpreamble += from_utf8(par);
2121 lyxpreamble += "}\n";
2124 // xunicode needs to be loaded at least after amsmath, amssymb,
2125 // esint and the other packages that provide special glyphs
2126 // The package only supports XeTeX currently.
2127 if (features.runparams().flavor == OutputParams::XETEX
2129 lyxpreamble += "\\usepackage{xunicode}\n";
2131 // Polyglossia must be loaded last
2132 if (use_polyglossia) {
2134 lyxpreamble += "\\usepackage{polyglossia}\n";
2135 // set the main language
2136 lyxpreamble += "\\setdefaultlanguage";
2137 if (!language->polyglossiaOpts().empty())
2138 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
2139 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
2140 // now setup the other languages
2141 std::map<std::string, std::string> const polylangs =
2142 features.getPolyglossiaLanguages();
2143 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
2144 mit != polylangs.end() ; ++mit) {
2145 lyxpreamble += "\\setotherlanguage";
2146 if (!mit->second.empty())
2147 lyxpreamble += "[" + from_ascii(mit->second) + "]";
2148 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
2152 // Load custom language package here
2153 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2154 if (lang_package == "default")
2155 lyxpreamble += from_utf8(lyxrc.language_custom_package);
2157 lyxpreamble += from_utf8(lang_package);
2158 lyxpreamble += '\n';
2161 docstring const i18npreamble =
2162 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2163 if (!i18npreamble.empty())
2164 lyxpreamble += i18npreamble + '\n';
2172 void BufferParams::useClassDefaults()
2174 DocumentClass const & tclass = documentClass();
2176 sides = tclass.sides();
2177 columns = tclass.columns();
2178 pagestyle = tclass.pagestyle();
2179 use_default_options = true;
2180 // Only if class has a ToC hierarchy
2181 if (tclass.hasTocLevels()) {
2182 secnumdepth = tclass.secnumdepth();
2183 tocdepth = tclass.tocdepth();
2188 bool BufferParams::hasClassDefaults() const
2190 DocumentClass const & tclass = documentClass();
2192 return sides == tclass.sides()
2193 && columns == tclass.columns()
2194 && pagestyle == tclass.pagestyle()
2195 && use_default_options
2196 && secnumdepth == tclass.secnumdepth()
2197 && tocdepth == tclass.tocdepth();
2201 DocumentClass const & BufferParams::documentClass() const
2203 return *doc_class_.get();
2207 DocumentClassConstPtr BufferParams::documentClassPtr() const
2213 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2215 // evil, but this function is evil
2216 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2220 bool BufferParams::setBaseClass(string const & classname)
2222 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2223 LayoutFileList & bcl = LayoutFileList::get();
2224 if (!bcl.haveClass(classname)) {
2226 bformat(_("The layout file:\n"
2228 "could not be found. A default textclass with default\n"
2229 "layouts will be used. LyX will not be able to produce\n"
2231 from_utf8(classname));
2232 frontend::Alert::error(_("Document class not found"), s);
2233 bcl.addEmptyClass(classname);
2236 bool const success = bcl[classname].load();
2239 bformat(_("Due to some error in it, the layout file:\n"
2241 "could not be loaded. A default textclass with default\n"
2242 "layouts will be used. LyX will not be able to produce\n"
2244 from_utf8(classname));
2245 frontend::Alert::error(_("Could not load class"), s);
2246 bcl.addEmptyClass(classname);
2249 pimpl_->baseClass_ = classname;
2250 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2255 LayoutFile const * BufferParams::baseClass() const
2257 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2258 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2264 LayoutFileIndex const & BufferParams::baseClassID() const
2266 return pimpl_->baseClass_;
2270 void BufferParams::makeDocumentClass(bool const clone)
2275 LayoutModuleList mods;
2276 LayoutModuleList::iterator it = layout_modules_.begin();
2277 LayoutModuleList::iterator en = layout_modules_.end();
2278 for (; it != en; ++it)
2279 mods.push_back(*it);
2281 it = cite_engine_.begin();
2282 en = cite_engine_.end();
2283 for (; it != en; ++it)
2284 mods.push_back(*it);
2286 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2288 TextClass::ReturnValues success = TextClass::OK;
2289 if (!forced_local_layout_.empty())
2290 success = doc_class_->read(forced_local_layout_, TextClass::MODULE);
2291 if (!local_layout_.empty() &&
2292 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2293 success = doc_class_->read(local_layout_, TextClass::MODULE);
2294 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2295 docstring const msg = _("Error reading internal layout information");
2296 frontend::Alert::warning(_("Read Error"), msg);
2301 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2303 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2307 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2309 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2313 std::string BufferParams::getLocalLayout(bool forced) const
2316 return doc_class_->forcedLayouts();
2318 return local_layout_;
2322 void BufferParams::setLocalLayout(string const & layout, bool forced)
2325 forced_local_layout_ = layout;
2327 local_layout_ = layout;
2331 bool BufferParams::addLayoutModule(string const & modName)
2333 LayoutModuleList::const_iterator it = layout_modules_.begin();
2334 LayoutModuleList::const_iterator end = layout_modules_.end();
2335 for (; it != end; ++it)
2338 layout_modules_.push_back(modName);
2343 string BufferParams::bufferFormat() const
2345 string format = documentClass().outputFormat();
2346 if (format == "latex") {
2348 // FIXME: In this context, this means "xetex or luatex"
2349 // with fontspec. We cannot differentiate further here.
2350 // But maybe use a more appropriate string.
2352 if (encoding().package() == Encoding::japanese)
2359 bool BufferParams::isExportable(string const & format) const
2361 vector<string> backs = backends();
2362 for (vector<string>::const_iterator it = backs.begin();
2363 it != backs.end(); ++it)
2364 if (theConverters().isReachable(*it, format))
2370 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2372 vector<string> const backs = backends();
2373 set<string> excludes;
2374 if (useNonTeXFonts) {
2375 excludes.insert("latex");
2376 excludes.insert("pdflatex");
2378 vector<Format const *> result =
2379 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2380 for (vector<string>::const_iterator it = backs.begin() + 1;
2381 it != backs.end(); ++it) {
2382 vector<Format const *> r =
2383 theConverters().getReachable(*it, only_viewable, false, excludes);
2384 result.insert(result.end(), r.begin(), r.end());
2390 bool BufferParams::isExportableFormat(string const & format) const
2392 typedef vector<Format const *> Formats;
2394 formats = exportableFormats(true);
2395 Formats::const_iterator fit = formats.begin();
2396 Formats::const_iterator end = formats.end();
2397 for (; fit != end ; ++fit) {
2398 if ((*fit)->name() == format)
2405 vector<string> BufferParams::backends() const
2408 string const buffmt = bufferFormat();
2410 // FIXME: Don't hardcode format names here, but use a flag
2411 if (buffmt == "latex") {
2412 if (!useNonTeXFonts) {
2413 v.push_back("pdflatex");
2414 v.push_back("latex");
2416 v.push_back("luatex");
2417 v.push_back("dviluatex");
2418 v.push_back("xetex");
2419 } else if (buffmt == "xetex") {
2420 v.push_back("xetex");
2421 // FIXME: need to test all languages (bug 8205)
2422 if (!language || !language->isPolyglossiaExclusive()) {
2423 v.push_back("luatex");
2424 v.push_back("dviluatex");
2427 v.push_back(buffmt);
2429 v.push_back("xhtml");
2430 v.push_back("text");
2436 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2438 string const dformat = (format.empty() || format == "default") ?
2439 getDefaultOutputFormat() : format;
2440 DefaultFlavorCache::const_iterator it =
2441 default_flavors_.find(dformat);
2443 if (it != default_flavors_.end())
2446 OutputParams::FLAVOR result = OutputParams::LATEX;
2448 // FIXME It'd be better not to hardcode this, but to do
2449 // something with formats.
2450 if (dformat == "xhtml")
2451 result = OutputParams::HTML;
2452 else if (dformat == "text")
2453 result = OutputParams::TEXT;
2454 else if (dformat == "lyx")
2455 result = OutputParams::LYX;
2456 else if (dformat == "pdflatex")
2457 result = OutputParams::PDFLATEX;
2458 else if (dformat == "xetex")
2459 result = OutputParams::XETEX;
2460 else if (dformat == "luatex")
2461 result = OutputParams::LUATEX;
2462 else if (dformat == "dviluatex")
2463 result = OutputParams::DVILUATEX;
2465 // Try to determine flavor of default output format
2466 vector<string> backs = backends();
2467 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2468 // Get shortest path to format
2469 Graph::EdgePath path;
2470 for (vector<string>::const_iterator it = backs.begin();
2471 it != backs.end(); ++it) {
2472 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2473 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2478 result = theConverters().getFlavor(path);
2481 // cache this flavor
2482 default_flavors_[dformat] = result;
2487 string BufferParams::getDefaultOutputFormat() const
2489 if (!default_output_format.empty()
2490 && default_output_format != "default")
2491 return default_output_format;
2493 || encoding().package() == Encoding::japanese) {
2494 vector<Format const *> const formats = exportableFormats(true);
2495 if (formats.empty())
2497 // return the first we find
2498 return formats.front()->name();
2501 return lyxrc.default_otf_view_format;
2502 return lyxrc.default_view_format;
2505 Font const BufferParams::getFont() const
2507 FontInfo f = documentClass().defaultfont();
2508 if (fonts_default_family == "rmdefault")
2509 f.setFamily(ROMAN_FAMILY);
2510 else if (fonts_default_family == "sfdefault")
2511 f.setFamily(SANS_FAMILY);
2512 else if (fonts_default_family == "ttdefault")
2513 f.setFamily(TYPEWRITER_FAMILY);
2514 return Font(f, language);
2518 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const & qs) const
2520 return quoteslangtranslator().find(qs);
2524 bool BufferParams::isLatex() const
2526 return documentClass().outputType() == LATEX;
2530 bool BufferParams::isLiterate() const
2532 return documentClass().outputType() == LITERATE;
2536 bool BufferParams::isDocBook() const
2538 return documentClass().outputType() == DOCBOOK;
2542 void BufferParams::readPreamble(Lexer & lex)
2544 if (lex.getString() != "\\begin_preamble")
2545 lyxerr << "Error (BufferParams::readPreamble):"
2546 "consistency check failed." << endl;
2548 preamble = lex.getLongString("\\end_preamble");
2552 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2554 string const expected = forced ? "\\begin_forced_local_layout" :
2555 "\\begin_local_layout";
2556 if (lex.getString() != expected)
2557 lyxerr << "Error (BufferParams::readLocalLayout):"
2558 "consistency check failed." << endl;
2561 forced_local_layout_ =
2562 lex.getLongString("\\end_forced_local_layout");
2564 local_layout_ = lex.getLongString("\\end_local_layout");
2568 bool BufferParams::setLanguage(string const & lang)
2570 Language const *new_language = languages.getLanguage(lang);
2571 if (!new_language) {
2572 // Language lang was not found
2575 language = new_language;
2580 void BufferParams::readLanguage(Lexer & lex)
2582 if (!lex.next()) return;
2584 string const tmptok = lex.getString();
2586 // check if tmptok is part of tex_babel in tex-defs.h
2587 if (!setLanguage(tmptok)) {
2588 // Language tmptok was not found
2589 language = default_language;
2590 lyxerr << "Warning: Setting language `"
2591 << tmptok << "' to `" << language->lang()
2597 void BufferParams::readGraphicsDriver(Lexer & lex)
2602 string const tmptok = lex.getString();
2603 // check if tmptok is part of tex_graphics in tex_defs.h
2606 string const test = tex_graphics[n++];
2608 if (test == tmptok) {
2609 graphics_driver = tmptok;
2614 "Warning: graphics driver `$$Token' not recognized!\n"
2615 " Setting graphics driver to `default'.\n");
2616 graphics_driver = "default";
2623 void BufferParams::readBullets(Lexer & lex)
2628 int const index = lex.getInteger();
2630 int temp_int = lex.getInteger();
2631 user_defined_bullet(index).setFont(temp_int);
2632 temp_bullet(index).setFont(temp_int);
2634 user_defined_bullet(index).setCharacter(temp_int);
2635 temp_bullet(index).setCharacter(temp_int);
2637 user_defined_bullet(index).setSize(temp_int);
2638 temp_bullet(index).setSize(temp_int);
2642 void BufferParams::readBulletsLaTeX(Lexer & lex)
2644 // The bullet class should be able to read this.
2647 int const index = lex.getInteger();
2649 docstring const temp_str = lex.getDocString();
2651 user_defined_bullet(index).setText(temp_str);
2652 temp_bullet(index).setText(temp_str);
2656 void BufferParams::readModules(Lexer & lex)
2658 if (!lex.eatLine()) {
2659 lyxerr << "Error (BufferParams::readModules):"
2660 "Unexpected end of input." << endl;
2664 string mod = lex.getString();
2665 if (mod == "\\end_modules")
2667 addLayoutModule(mod);
2673 void BufferParams::readRemovedModules(Lexer & lex)
2675 if (!lex.eatLine()) {
2676 lyxerr << "Error (BufferParams::readRemovedModules):"
2677 "Unexpected end of input." << endl;
2681 string mod = lex.getString();
2682 if (mod == "\\end_removed_modules")
2684 removed_modules_.push_back(mod);
2687 // now we want to remove any removed modules that were previously
2688 // added. normally, that will be because default modules were added in
2689 // setBaseClass(), which gets called when \textclass is read at the
2690 // start of the read.
2691 list<string>::const_iterator rit = removed_modules_.begin();
2692 list<string>::const_iterator const ren = removed_modules_.end();
2693 for (; rit != ren; ++rit) {
2694 LayoutModuleList::iterator const mit = layout_modules_.begin();
2695 LayoutModuleList::iterator const men = layout_modules_.end();
2696 LayoutModuleList::iterator found = find(mit, men, *rit);
2699 layout_modules_.erase(found);
2704 void BufferParams::readIncludeonly(Lexer & lex)
2706 if (!lex.eatLine()) {
2707 lyxerr << "Error (BufferParams::readIncludeonly):"
2708 "Unexpected end of input." << endl;
2712 string child = lex.getString();
2713 if (child == "\\end_includeonly")
2715 included_children_.push_back(child);
2721 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2723 switch (papersize) {
2725 // could be anything, so don't guess
2727 case PAPER_CUSTOM: {
2728 if (purpose == XDVI && !paperwidth.empty() &&
2729 !paperheight.empty()) {
2730 // heightxwidth<unit>
2731 string first = paperwidth;
2732 string second = paperheight;
2733 if (orientation == ORIENTATION_LANDSCAPE)
2736 return first.erase(first.length() - 2)
2742 // dvips and dvipdfm do not know this
2743 if (purpose == DVIPS || purpose == DVIPDFM)
2747 if (purpose == DVIPS || purpose == DVIPDFM)
2751 if (purpose == DVIPS || purpose == DVIPDFM)
2761 if (purpose == DVIPS || purpose == DVIPDFM)
2765 if (purpose == DVIPS || purpose == DVIPDFM)
2769 if (purpose == DVIPS || purpose == DVIPDFM)
2773 if (purpose == DVIPS || purpose == DVIPDFM)
2777 if (purpose == DVIPS || purpose == DVIPDFM)
2781 // dvipdfm does not know this
2782 if (purpose == DVIPDFM)
2786 if (purpose == DVIPDFM)
2790 if (purpose == DVIPS || purpose == DVIPDFM)
2794 if (purpose == DVIPS || purpose == DVIPDFM)
2798 if (purpose == DVIPS || purpose == DVIPDFM)
2802 if (purpose == DVIPS || purpose == DVIPDFM)
2806 if (purpose == DVIPS || purpose == DVIPDFM)
2810 if (purpose == DVIPS || purpose == DVIPDFM)
2814 if (purpose == DVIPS || purpose == DVIPDFM)
2818 if (purpose == DVIPS || purpose == DVIPDFM)
2822 if (purpose == DVIPS || purpose == DVIPDFM)
2826 if (purpose == DVIPS || purpose == DVIPDFM)
2830 if (purpose == DVIPS || purpose == DVIPDFM)
2834 if (purpose == DVIPS || purpose == DVIPDFM)
2838 if (purpose == DVIPS || purpose == DVIPDFM)
2842 if (purpose == DVIPS || purpose == DVIPDFM)
2846 if (purpose == DVIPS || purpose == DVIPDFM)
2849 case PAPER_USEXECUTIVE:
2850 // dvipdfm does not know this
2851 if (purpose == DVIPDFM)
2856 case PAPER_USLETTER:
2858 if (purpose == XDVI)
2865 string const BufferParams::dvips_options() const
2869 // If the class loads the geometry package, we do not know which
2870 // paper size is used, since we do not set it (bug 7013).
2871 // Therefore we must not specify any argument here.
2872 // dvips gets the correct paper size via DVI specials in this case
2873 // (if the class uses the geometry package correctly).
2874 if (documentClass().provides("geometry"))
2878 && papersize == PAPER_CUSTOM
2879 && !lyxrc.print_paper_dimension_flag.empty()
2880 && !paperwidth.empty()
2881 && !paperheight.empty()) {
2882 // using a custom papersize
2883 result = lyxrc.print_paper_dimension_flag;
2884 result += ' ' + paperwidth;
2885 result += ',' + paperheight;
2887 string const paper_option = paperSizeName(DVIPS);
2888 if (!paper_option.empty() && (paper_option != "letter" ||
2889 orientation != ORIENTATION_LANDSCAPE)) {
2890 // dvips won't accept -t letter -t landscape.
2891 // In all other cases, include the paper size
2893 result = lyxrc.print_paper_flag;
2894 result += ' ' + paper_option;
2897 if (orientation == ORIENTATION_LANDSCAPE &&
2898 papersize != PAPER_CUSTOM)
2899 result += ' ' + lyxrc.print_landscape_flag;
2904 string const BufferParams::font_encoding() const
2906 return font_encodings().empty() ? "default" : font_encodings().back();
2910 vector<string> const BufferParams::font_encodings() const
2912 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2914 vector<string> fontencs;
2916 // "default" means "no explicit font encoding"
2917 if (doc_fontenc != "default") {
2918 fontencs = getVectorFromString(doc_fontenc);
2919 if (!language->fontenc().empty()
2920 && ascii_lowercase(language->fontenc()) != "none") {
2921 vector<string> fencs = getVectorFromString(language->fontenc());
2922 vector<string>::const_iterator fit = fencs.begin();
2923 for (; fit != fencs.end(); ++fit) {
2924 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
2925 fontencs.push_back(*fit);
2934 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2936 // suppress the babel call if there is no BabelName defined
2937 // for the document language in the lib/languages file and if no
2938 // other languages are used (lang_opts is then empty)
2939 if (lang_opts.empty())
2941 // either a specific language (AsBabelOptions setting in
2942 // lib/languages) or the prefs require the languages to
2943 // be submitted to babel itself (not the class).
2945 return "\\usepackage[" + lang_opts + "]{babel}";
2946 return "\\usepackage{babel}";
2950 docstring BufferParams::getGraphicsDriver(string const & package) const
2954 if (package == "geometry") {
2955 if (graphics_driver == "dvips"
2956 || graphics_driver == "dvipdfm"
2957 || graphics_driver == "pdftex"
2958 || graphics_driver == "vtex")
2959 result = from_ascii(graphics_driver);
2960 else if (graphics_driver == "dvipdfmx")
2961 result = from_ascii("dvipdfm");
2968 void BufferParams::writeEncodingPreamble(otexstream & os,
2969 LaTeXFeatures & features) const
2971 // XeTeX/LuaTeX: (see also #9740)
2972 // With Unicode fonts we use utf8-plain without encoding package.
2973 // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails.
2974 // XeTeX must use ASCII encoding (see Buffer.cpp),
2975 // for LuaTeX, we load "luainputenc" (see below).
2976 if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
2979 if (inputenc == "auto") {
2980 string const doc_encoding =
2981 language->encoding()->latexName();
2982 Encoding::Package const package =
2983 language->encoding()->package();
2985 // Create list of inputenc options:
2986 set<string> encodings;
2987 // luainputenc fails with more than one encoding
2988 if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts
2989 // list all input encodings used in the document
2990 encodings = features.getEncodingSet(doc_encoding);
2992 // If the "japanese" package (i.e. pLaTeX) is used,
2993 // inputenc must be omitted.
2994 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2995 if ((!encodings.empty() || package == Encoding::inputenc)
2996 && !features.isRequired("japanese")
2997 && !features.isProvided("inputenc")) {
2998 os << "\\usepackage[";
2999 set<string>::const_iterator it = encodings.begin();
3000 set<string>::const_iterator const end = encodings.end();
3002 os << from_ascii(*it);
3005 for (; it != end; ++it)
3006 os << ',' << from_ascii(*it);
3007 if (package == Encoding::inputenc) {
3008 if (!encodings.empty())
3010 os << from_ascii(doc_encoding);
3012 if (features.runparams().flavor == OutputParams::LUATEX
3013 || features.runparams().flavor == OutputParams::DVILUATEX)
3014 os << "]{luainputenc}\n";
3016 os << "]{inputenc}\n";
3018 if (package == Encoding::CJK || features.mustProvide("CJK")) {
3019 if (language->encoding()->name() == "utf8-cjk"
3020 && LaTeXFeatures::isAvailable("CJKutf8"))
3021 os << "\\usepackage{CJKutf8}\n";
3023 os << "\\usepackage{CJK}\n";
3025 } else if (inputenc != "default") {
3026 switch (encoding().package()) {
3027 case Encoding::none:
3028 case Encoding::japanese:
3030 case Encoding::inputenc:
3031 // do not load inputenc if japanese is used
3032 // or if the class provides inputenc
3033 if (features.isRequired("japanese")
3034 || features.isProvided("inputenc"))
3036 os << "\\usepackage[" << from_ascii(encoding().latexName());
3037 if (features.runparams().flavor == OutputParams::LUATEX
3038 || features.runparams().flavor == OutputParams::DVILUATEX)
3039 os << "]{luainputenc}\n";
3041 os << "]{inputenc}\n";
3044 if (encoding().name() == "utf8-cjk"
3045 && LaTeXFeatures::isAvailable("CJKutf8"))
3046 os << "\\usepackage{CJKutf8}\n";
3048 os << "\\usepackage{CJK}\n";
3051 // Load the CJK package if needed by a secondary language.
3052 // If the main encoding is some variant of UTF8, use CJKutf8.
3053 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
3054 if (encoding().iconvName() == "UTF-8"
3055 && LaTeXFeatures::isAvailable("CJKutf8"))
3056 os << "\\usepackage{CJKutf8}\n";
3058 os << "\\usepackage{CJK}\n";
3064 string const BufferParams::parseFontName(string const & name) const
3066 string mangled = name;
3067 size_t const idx = mangled.find('[');
3068 if (idx == string::npos || idx == 0)
3071 return mangled.substr(0, idx - 1);
3075 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3077 if (fontsRoman() == "default" && fontsSans() == "default"
3078 && fontsTypewriter() == "default"
3079 && (fontsMath() == "default" || fontsMath() == "auto"))
3085 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3086 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3087 * Mapping=tex-text option assures TeX ligatures (such as "--")
3088 * are resolved. Note that tt does not use these ligatures.
3090 * -- add more GUI options?
3091 * -- add more fonts (fonts for other scripts)
3092 * -- if there's a way to find out if a font really supports
3093 * OldStyle, enable/disable the widget accordingly.
3095 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3096 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3097 // However, until v.2 (2010/07/11) fontspec only knew
3098 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3099 // was introduced for both XeTeX and LuaTeX (LuaTeX
3100 // didn't understand "Mapping=tex-text", while XeTeX
3101 // understood both. With most recent versions, both
3102 // variants are understood by both engines. However,
3103 // we want to provide support for at least TeXLive 2009
3104 // (for XeTeX; LuaTeX is only supported as of v.2)
3105 string const texmapping =
3106 (features.runparams().flavor == OutputParams::XETEX) ?
3107 "Mapping=tex-text" : "Ligatures=TeX";
3108 if (fontsRoman() != "default") {
3109 os << "\\setmainfont[" << texmapping;
3110 if (fonts_old_figures)
3111 os << ",Numbers=OldStyle";
3112 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3114 if (fontsSans() != "default") {
3115 string const sans = parseFontName(fontsSans());
3116 if (fontsSansScale() != 100)
3117 os << "\\setsansfont[Scale="
3118 << float(fontsSansScale()) / 100
3119 << "," << texmapping << "]{"
3122 os << "\\setsansfont[" << texmapping << "]{"
3125 if (fontsTypewriter() != "default") {
3126 string const mono = parseFontName(fontsTypewriter());
3127 if (fontsTypewriterScale() != 100)
3128 os << "\\setmonofont[Scale="
3129 << float(fontsTypewriterScale()) / 100
3133 os << "\\setmonofont{"
3140 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
3141 bool const dryrun = features.runparams().dryrun;
3142 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3143 bool const nomath = (fontsMath() == "default");
3146 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3147 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3151 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3152 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3153 nomath, fontsSansScale());
3155 // MONOSPACED/TYPEWRITER
3156 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3157 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3158 nomath, fontsTypewriterScale());
3161 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3162 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3169 Encoding const & BufferParams::encoding() const
3171 // Main encoding for LaTeX output.
3173 // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740).
3174 // As the "flavor" is only known once export started, this
3175 // cannot be handled here. Instead, runparams.encoding is set
3176 // to ASCII in Buffer::makeLaTeXFile (for export)
3177 // and Buffer::writeLaTeXSource (for preview).
3179 return *(encodings.fromLyXName("utf8-plain"));
3180 if (inputenc == "auto" || inputenc == "default")
3181 return *language->encoding();
3182 Encoding const * const enc = encodings.fromLyXName(inputenc);
3185 LYXERR0("Unknown inputenc value `" << inputenc
3186 << "'. Using `auto' instead.");
3187 return *language->encoding();
3191 bool BufferParams::addCiteEngine(string const & engine)
3193 LayoutModuleList::const_iterator it = cite_engine_.begin();
3194 LayoutModuleList::const_iterator en = cite_engine_.end();
3195 for (; it != en; ++it)
3198 cite_engine_.push_back(engine);
3203 bool BufferParams::addCiteEngine(vector<string> const & engine)
3205 vector<string>::const_iterator it = engine.begin();
3206 vector<string>::const_iterator en = engine.end();
3208 for (; it != en; ++it)
3209 if (!addCiteEngine(*it))
3215 string const & BufferParams::defaultBiblioStyle() const
3217 return documentClass().defaultBiblioStyle();
3221 bool const & BufferParams::fullAuthorList() const
3223 return documentClass().fullAuthorList();
3227 void BufferParams::setCiteEngine(string const & engine)
3230 addCiteEngine(engine);
3234 void BufferParams::setCiteEngine(vector<string> const & engine)
3237 addCiteEngine(engine);
3241 vector<string> BufferParams::citeCommands() const
3243 static CitationStyle const default_style;
3244 vector<string> commands =
3245 documentClass().citeCommands(citeEngineType());
3246 if (commands.empty())
3247 commands.push_back(default_style.cmd);
3252 vector<CitationStyle> BufferParams::citeStyles() const
3254 static CitationStyle const default_style;
3255 vector<CitationStyle> styles =
3256 documentClass().citeStyles(citeEngineType());
3258 styles.push_back(default_style);