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"
41 #include "texstream.h"
44 #include "PDFOptions.h"
46 #include "frontends/alert.h"
48 #include "insets/InsetListingsParams.h"
50 #include "support/convert.h"
51 #include "support/debug.h"
52 #include "support/docstream.h"
53 #include "support/FileName.h"
54 #include "support/filetools.h"
55 #include "support/gettext.h"
56 #include "support/Messages.h"
57 #include "support/mutex.h"
58 #include "support/Package.h"
59 #include "support/Translator.h"
60 #include "support/lstrings.h"
66 using namespace lyx::support;
69 static char const * const string_paragraph_separation[] = {
74 static char const * const string_quotes_language[] = {
75 "english", "swedish", "german", "polish", "french", "danish", ""
79 static char const * const string_papersize[] = {
80 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
81 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
82 "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
83 "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
84 "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
89 static char const * const string_orientation[] = {
90 "portrait", "landscape", ""
94 static char const * const tex_graphics[] = {
95 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
96 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
97 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
98 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
109 // Paragraph separation
110 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
113 ParSepTranslator const init_parseptranslator()
115 ParSepTranslator translator
116 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
117 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
122 ParSepTranslator const & parseptranslator()
124 static ParSepTranslator const translator =
125 init_parseptranslator();
131 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
134 QuotesLangTranslator const init_quoteslangtranslator()
136 QuotesLangTranslator translator
137 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
138 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
139 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
140 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
141 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
142 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
147 QuotesLangTranslator const & quoteslangtranslator()
149 static QuotesLangTranslator const translator =
150 init_quoteslangtranslator();
156 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
159 static PaperSizeTranslator initPaperSizeTranslator()
161 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
162 translator.addPair(string_papersize[1], PAPER_CUSTOM);
163 translator.addPair(string_papersize[2], PAPER_USLETTER);
164 translator.addPair(string_papersize[3], PAPER_USLEGAL);
165 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
166 translator.addPair(string_papersize[5], PAPER_A0);
167 translator.addPair(string_papersize[6], PAPER_A1);
168 translator.addPair(string_papersize[7], PAPER_A2);
169 translator.addPair(string_papersize[8], PAPER_A3);
170 translator.addPair(string_papersize[9], PAPER_A4);
171 translator.addPair(string_papersize[10], PAPER_A5);
172 translator.addPair(string_papersize[11], PAPER_A6);
173 translator.addPair(string_papersize[12], PAPER_B0);
174 translator.addPair(string_papersize[13], PAPER_B1);
175 translator.addPair(string_papersize[14], PAPER_B2);
176 translator.addPair(string_papersize[15], PAPER_B3);
177 translator.addPair(string_papersize[16], PAPER_B4);
178 translator.addPair(string_papersize[17], PAPER_B5);
179 translator.addPair(string_papersize[18], PAPER_B6);
180 translator.addPair(string_papersize[19], PAPER_C0);
181 translator.addPair(string_papersize[20], PAPER_C1);
182 translator.addPair(string_papersize[21], PAPER_C2);
183 translator.addPair(string_papersize[22], PAPER_C3);
184 translator.addPair(string_papersize[23], PAPER_C4);
185 translator.addPair(string_papersize[24], PAPER_C5);
186 translator.addPair(string_papersize[25], PAPER_C6);
187 translator.addPair(string_papersize[26], PAPER_JISB0);
188 translator.addPair(string_papersize[27], PAPER_JISB1);
189 translator.addPair(string_papersize[28], PAPER_JISB2);
190 translator.addPair(string_papersize[29], PAPER_JISB3);
191 translator.addPair(string_papersize[30], PAPER_JISB4);
192 translator.addPair(string_papersize[31], PAPER_JISB5);
193 translator.addPair(string_papersize[32], PAPER_JISB6);
198 PaperSizeTranslator const & papersizetranslator()
200 static PaperSizeTranslator const translator =
201 initPaperSizeTranslator();
207 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
210 PaperOrientationTranslator const init_paperorientationtranslator()
212 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
213 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
218 PaperOrientationTranslator const & paperorientationtranslator()
220 static PaperOrientationTranslator const translator =
221 init_paperorientationtranslator();
227 typedef Translator<int, PageSides> SidesTranslator;
230 SidesTranslator const init_sidestranslator()
232 SidesTranslator translator(1, OneSide);
233 translator.addPair(2, TwoSides);
238 SidesTranslator const & sidestranslator()
240 static SidesTranslator const translator = init_sidestranslator();
246 typedef Translator<int, BufferParams::Package> PackageTranslator;
249 PackageTranslator const init_packagetranslator()
251 PackageTranslator translator(0, BufferParams::package_off);
252 translator.addPair(1, BufferParams::package_auto);
253 translator.addPair(2, BufferParams::package_on);
258 PackageTranslator const & packagetranslator()
260 static PackageTranslator const translator =
261 init_packagetranslator();
267 typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator;
270 CiteEngineTypeTranslator const init_citeenginetypetranslator()
272 CiteEngineTypeTranslator translator("authoryear", ENGINE_TYPE_AUTHORYEAR);
273 translator.addPair("numerical", ENGINE_TYPE_NUMERICAL);
274 translator.addPair("default", ENGINE_TYPE_DEFAULT);
279 CiteEngineTypeTranslator const & citeenginetypetranslator()
281 static CiteEngineTypeTranslator const translator =
282 init_citeenginetypetranslator();
288 typedef Translator<string, Spacing::Space> SpaceTranslator;
291 SpaceTranslator const init_spacetranslator()
293 SpaceTranslator translator("default", Spacing::Default);
294 translator.addPair("single", Spacing::Single);
295 translator.addPair("onehalf", Spacing::Onehalf);
296 translator.addPair("double", Spacing::Double);
297 translator.addPair("other", Spacing::Other);
302 SpaceTranslator const & spacetranslator()
304 static SpaceTranslator const translator = init_spacetranslator();
311 class BufferParams::Impl
316 AuthorList authorlist;
317 BranchList branchlist;
318 Bullet temp_bullets[4];
319 Bullet user_defined_bullets[4];
320 IndicesList indiceslist;
322 /** This is the amount of space used for paragraph_separation "skip",
323 * and for detached paragraphs in "indented" documents.
327 PDFOptions pdfoptions;
328 LayoutFileIndex baseClass_;
332 BufferParams::Impl::Impl()
333 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
335 // set initial author
337 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
342 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
345 return new BufferParams::Impl(*ptr);
349 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
355 BufferParams::BufferParams()
358 setBaseClass(defaultBaseclass());
359 cite_engine_.push_back("basic");
360 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
362 paragraph_separation = ParagraphIndentSeparation;
363 quotes_language = InsetQuotes::EnglishQuotes;
364 fontsize = "default";
367 papersize = PAPER_DEFAULT;
368 orientation = ORIENTATION_PORTRAIT;
369 use_geometry = false;
370 biblio_style = "plain";
371 use_bibtopic = false;
373 save_transient_properties = true;
374 track_changes = false;
375 output_changes = false;
376 use_default_options = true;
377 maintain_unincluded_children = false;
380 language = default_language;
382 fonts_roman[0] = "default";
383 fonts_roman[1] = "default";
384 fonts_sans[0] = "default";
385 fonts_sans[1] = "default";
386 fonts_typewriter[0] = "default";
387 fonts_typewriter[1] = "default";
388 fonts_math[0] = "auto";
389 fonts_math[1] = "auto";
390 fonts_default_family = "default";
391 useNonTeXFonts = false;
392 use_microtype = false;
393 fonts_expert_sc = false;
394 fonts_old_figures = false;
395 fonts_sans_scale[0] = 100;
396 fonts_sans_scale[1] = 100;
397 fonts_typewriter_scale[0] = 100;
398 fonts_typewriter_scale[1] = 100;
400 lang_package = "default";
401 graphics_driver = "default";
402 default_output_format = "default";
403 bibtex_command = "default";
404 index_command = "default";
407 listings_params = string();
408 pagestyle = "default";
409 suppress_date = false;
410 justification = true;
411 // no color is the default (white)
412 backgroundcolor = lyx::rgbFromHexName("#ffffff");
413 isbackgroundcolor = false;
414 // no color is the default (black)
415 fontcolor = lyx::rgbFromHexName("#000000");
417 // light gray is the default font color for greyed-out notes
418 notefontcolor = lyx::rgbFromHexName("#cccccc");
419 boxbgcolor = lyx::rgbFromHexName("#ff0000");
420 compressed = lyxrc.save_compressed;
421 for (int iter = 0; iter < 4; ++iter) {
422 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
423 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
426 indiceslist().addDefault(B_("Index"));
427 html_be_strict = false;
428 html_math_output = MathML;
429 html_math_img_scale = 1.0;
430 html_css_as_file = false;
431 display_pixel_ratio = 1.0;
436 // map current author
437 author_map_[pimpl_->authorlist.get(0).bufferId()] = 0;
441 docstring BufferParams::B_(string const & l10n) const
443 LASSERT(language, return from_utf8(l10n));
444 return getMessages(language->code()).get(l10n);
448 BufferParams::Package BufferParams::use_package(std::string const & p) const
450 PackageMap::const_iterator it = use_packages.find(p);
451 if (it == use_packages.end())
457 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
463 map<string, string> const & BufferParams::auto_packages()
465 static map<string, string> packages;
466 if (packages.empty()) {
467 // We could have a race condition here that two threads
468 // discover an empty map at the same time and want to fill
469 // it, but that is no problem, since the same contents is
470 // filled in twice then. Having the locker inside the
471 // packages.empty() condition has the advantage that we
472 // don't need the mutex overhead for simple reading.
474 Mutex::Locker locker(&mutex);
475 // adding a package here implies a file format change!
476 packages["amsmath"] =
477 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
478 packages["amssymb"] =
479 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
481 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
483 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
484 packages["mathdots"] =
485 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
486 packages["mathtools"] =
487 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
489 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
490 packages["stackrel"] =
491 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
492 packages["stmaryrd"] =
493 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");
494 packages["undertilde"] =
495 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
501 AuthorList & BufferParams::authors()
503 return pimpl_->authorlist;
507 AuthorList const & BufferParams::authors() const
509 return pimpl_->authorlist;
513 void BufferParams::addAuthor(Author a)
515 author_map_[a.bufferId()] = pimpl_->authorlist.record(a);
519 BranchList & BufferParams::branchlist()
521 return pimpl_->branchlist;
525 BranchList const & BufferParams::branchlist() const
527 return pimpl_->branchlist;
531 IndicesList & BufferParams::indiceslist()
533 return pimpl_->indiceslist;
537 IndicesList const & BufferParams::indiceslist() const
539 return pimpl_->indiceslist;
543 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
545 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
546 return pimpl_->temp_bullets[index];
550 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
552 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
553 return pimpl_->temp_bullets[index];
557 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
559 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
560 return pimpl_->user_defined_bullets[index];
564 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
566 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
567 return pimpl_->user_defined_bullets[index];
571 Spacing & BufferParams::spacing()
573 return pimpl_->spacing;
577 Spacing const & BufferParams::spacing() const
579 return pimpl_->spacing;
583 PDFOptions & BufferParams::pdfoptions()
585 return pimpl_->pdfoptions;
589 PDFOptions const & BufferParams::pdfoptions() const
591 return pimpl_->pdfoptions;
595 HSpace const & BufferParams::getIndentation() const
597 return pimpl_->indentation;
601 void BufferParams::setIndentation(HSpace const & indent)
603 pimpl_->indentation = indent;
607 VSpace const & BufferParams::getDefSkip() const
609 return pimpl_->defskip;
613 void BufferParams::setDefSkip(VSpace const & vs)
615 // DEFSKIP will cause an infinite loop
616 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
617 pimpl_->defskip = vs;
621 string BufferParams::readToken(Lexer & lex, string const & token,
622 FileName const & filepath)
626 if (token == "\\textclass") {
628 string const classname = lex.getString();
629 // if there exists a local layout file, ignore the system one
630 // NOTE: in this case, the textclass (.cls file) is assumed to
633 LayoutFileList & bcl = LayoutFileList::get();
634 if (!filepath.empty()) {
635 // If classname is an absolute path, the document is
636 // using a local layout file which could not be accessed
637 // by a relative path. In this case the path is correct
638 // even if the document was moved to a different
639 // location. However, we will have a problem if the
640 // document was generated on a different platform.
641 bool isabsolute = FileName::isAbsolute(classname);
642 string const classpath = onlyPath(classname);
643 string const path = isabsolute ? classpath
644 : FileName(addPath(filepath.absFileName(),
645 classpath)).realPath();
646 string const oldpath = isabsolute ? string()
647 : FileName(addPath(origin, classpath)).realPath();
648 tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
650 // that returns non-empty if a "local" layout file is found.
652 result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
653 from_utf8(filepath.absFileName())));
656 setBaseClass(onlyFileName(tcp));
658 setBaseClass(onlyFileName(classname));
659 // We assume that a tex class exists for local or unknown
660 // layouts so this warning, will only be given for system layouts.
661 if (!baseClass()->isTeXClassAvailable()) {
662 docstring const desc =
663 translateIfPossible(from_utf8(baseClass()->description()));
664 docstring const prereqs =
665 from_utf8(baseClass()->prerequisites());
666 docstring const msg =
667 bformat(_("The selected document class\n"
669 "requires external files that are not available.\n"
670 "The document class can still be used, but the\n"
671 "document cannot be compiled until the following\n"
672 "prerequisites are installed:\n"
674 "See section 3.1.2.2 (Class Availability) of the\n"
675 "User's Guide for more information."), desc, prereqs);
676 frontend::Alert::warning(_("Document class not available"),
679 } else if (token == "\\save_transient_properties") {
680 lex >> save_transient_properties;
681 } else if (token == "\\origin") {
683 origin = lex.getString();
684 string const sysdirprefix = "/systemlyxdir/";
685 if (prefixIs(origin, sysdirprefix)) {
686 origin.replace(0, sysdirprefix.length() - 1,
687 package().system_support().absFileName());
689 } else if (token == "\\begin_preamble") {
691 } else if (token == "\\begin_local_layout") {
692 readLocalLayout(lex, false);
693 } else if (token == "\\begin_forced_local_layout") {
694 readLocalLayout(lex, true);
695 } else if (token == "\\begin_modules") {
697 } else if (token == "\\begin_removed_modules") {
698 readRemovedModules(lex);
699 } else if (token == "\\begin_includeonly") {
700 readIncludeonly(lex);
701 } else if (token == "\\maintain_unincluded_children") {
702 lex >> maintain_unincluded_children;
703 } else if (token == "\\options") {
705 options = lex.getString();
706 } else if (token == "\\use_default_options") {
707 lex >> use_default_options;
708 } else if (token == "\\master") {
710 master = lex.getString();
711 if (!filepath.empty() && FileName::isAbsolute(origin)) {
712 bool const isabs = FileName::isAbsolute(master);
713 FileName const abspath(isabs ? master : origin + master);
714 bool const moved = filepath != FileName(origin);
715 if (moved && abspath.exists()) {
716 docstring const path = isabs
718 : from_utf8(abspath.realPath());
719 docstring const refpath =
720 from_utf8(filepath.absFileName());
721 master = to_utf8(makeRelPath(path, refpath));
724 } else if (token == "\\suppress_date") {
725 lex >> suppress_date;
726 } else if (token == "\\justification") {
727 lex >> justification;
728 } else if (token == "\\language") {
730 } else if (token == "\\language_package") {
732 lang_package = lex.getString();
733 } else if (token == "\\inputencoding") {
735 } else if (token == "\\graphics") {
736 readGraphicsDriver(lex);
737 } else if (token == "\\default_output_format") {
738 lex >> default_output_format;
739 } else if (token == "\\bibtex_command") {
741 bibtex_command = lex.getString();
742 } else if (token == "\\index_command") {
744 index_command = lex.getString();
745 } else if (token == "\\fontencoding") {
747 fontenc = lex.getString();
748 } else if (token == "\\font_roman") {
749 lex >> fonts_roman[0];
750 lex >> fonts_roman[1];
751 } else if (token == "\\font_sans") {
752 lex >> fonts_sans[0];
753 lex >> fonts_sans[1];
754 } else if (token == "\\font_typewriter") {
755 lex >> fonts_typewriter[0];
756 lex >> fonts_typewriter[1];
757 } else if (token == "\\font_math") {
758 lex >> fonts_math[0];
759 lex >> fonts_math[1];
760 } else if (token == "\\font_default_family") {
761 lex >> fonts_default_family;
762 } else if (token == "\\use_non_tex_fonts") {
763 lex >> useNonTeXFonts;
764 } else if (token == "\\font_sc") {
765 lex >> fonts_expert_sc;
766 } else if (token == "\\font_osf") {
767 lex >> fonts_old_figures;
768 } else if (token == "\\font_sf_scale") {
769 lex >> fonts_sans_scale[0];
770 lex >> fonts_sans_scale[1];
771 } else if (token == "\\font_tt_scale") {
772 lex >> fonts_typewriter_scale[0];
773 lex >> fonts_typewriter_scale[1];
774 } else if (token == "\\font_cjk") {
776 } else if (token == "\\use_microtype") {
777 lex >> use_microtype;
778 } else if (token == "\\paragraph_separation") {
781 paragraph_separation = parseptranslator().find(parsep);
782 } else if (token == "\\paragraph_indentation") {
784 string indentation = lex.getString();
785 pimpl_->indentation = HSpace(indentation);
786 } else if (token == "\\defskip") {
788 string const defskip = lex.getString();
789 pimpl_->defskip = VSpace(defskip);
790 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
792 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
793 } else if (token == "\\quotes_language") {
796 quotes_language = quoteslangtranslator().find(quotes_lang);
797 } else if (token == "\\papersize") {
800 papersize = papersizetranslator().find(ppsize);
801 } else if (token == "\\use_geometry") {
803 } else if (token == "\\use_package") {
808 use_package(package, packagetranslator().find(use));
809 } else if (token == "\\cite_engine") {
811 vector<string> engine = getVectorFromString(lex.getString());
812 setCiteEngine(engine);
813 } else if (token == "\\cite_engine_type") {
816 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
817 } else if (token == "\\biblio_style") {
819 biblio_style = lex.getString();
820 } else if (token == "\\use_bibtopic") {
822 } else if (token == "\\use_indices") {
824 } else if (token == "\\tracking_changes") {
825 lex >> track_changes;
826 } else if (token == "\\output_changes") {
827 lex >> output_changes;
828 } else if (token == "\\branch") {
830 docstring branch = lex.getDocString();
831 branchlist().add(branch);
834 string const tok = lex.getString();
835 if (tok == "\\end_branch")
837 Branch * branch_ptr = branchlist().find(branch);
838 if (tok == "\\selected") {
841 branch_ptr->setSelected(lex.getInteger());
843 if (tok == "\\filename_suffix") {
846 branch_ptr->setFileNameSuffix(lex.getInteger());
848 if (tok == "\\color") {
850 string color = lex.getString();
852 branch_ptr->setColor(color);
853 // Update also the Color table:
855 color = lcolor.getX11Name(Color_background);
857 lcolor.setColor(to_utf8(branch), color);
860 } else if (token == "\\index") {
862 docstring index = lex.getDocString();
864 indiceslist().add(index);
867 string const tok = lex.getString();
868 if (tok == "\\end_index")
870 Index * index_ptr = indiceslist().find(index);
871 if (tok == "\\shortcut") {
873 shortcut = lex.getDocString();
875 index_ptr->setShortcut(shortcut);
877 if (tok == "\\color") {
879 string color = lex.getString();
881 index_ptr->setColor(color);
882 // Update also the Color table:
884 color = lcolor.getX11Name(Color_background);
886 if (!shortcut.empty())
887 lcolor.setColor(to_utf8(shortcut), color);
890 } else if (token == "\\author") {
892 istringstream ss(lex.getString());
896 } else if (token == "\\paperorientation") {
899 orientation = paperorientationtranslator().find(orient);
900 } else if (token == "\\backgroundcolor") {
902 backgroundcolor = lyx::rgbFromHexName(lex.getString());
903 isbackgroundcolor = true;
904 } else if (token == "\\fontcolor") {
906 fontcolor = lyx::rgbFromHexName(lex.getString());
908 } else if (token == "\\notefontcolor") {
910 string color = lex.getString();
911 notefontcolor = lyx::rgbFromHexName(color);
912 lcolor.setColor("notefontcolor", color);
913 } else if (token == "\\boxbgcolor") {
915 string color = lex.getString();
916 boxbgcolor = lyx::rgbFromHexName(color);
917 lcolor.setColor("boxbgcolor", color);
918 } else if (token == "\\paperwidth") {
920 } else if (token == "\\paperheight") {
922 } else if (token == "\\leftmargin") {
924 } else if (token == "\\topmargin") {
926 } else if (token == "\\rightmargin") {
928 } else if (token == "\\bottommargin") {
930 } else if (token == "\\headheight") {
932 } else if (token == "\\headsep") {
934 } else if (token == "\\footskip") {
936 } else if (token == "\\columnsep") {
938 } else if (token == "\\paperfontsize") {
940 } else if (token == "\\papercolumns") {
942 } else if (token == "\\listings_params") {
945 listings_params = InsetListingsParams(par).params();
946 } else if (token == "\\papersides") {
949 sides = sidestranslator().find(psides);
950 } else if (token == "\\paperpagestyle") {
952 } else if (token == "\\bullet") {
954 } else if (token == "\\bulletLaTeX") {
955 readBulletsLaTeX(lex);
956 } else if (token == "\\secnumdepth") {
958 } else if (token == "\\tocdepth") {
960 } else if (token == "\\spacing") {
964 if (nspacing == "other") {
967 spacing().set(spacetranslator().find(nspacing), tmp_val);
968 } else if (token == "\\float_placement") {
969 lex >> float_placement;
971 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
972 string toktmp = pdfoptions().readToken(lex, token);
973 if (!toktmp.empty()) {
974 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
978 } else if (token == "\\html_math_output") {
981 html_math_output = static_cast<MathOutput>(temp);
982 } else if (token == "\\html_be_strict") {
983 lex >> html_be_strict;
984 } else if (token == "\\html_css_as_file") {
985 lex >> html_css_as_file;
986 } else if (token == "\\html_math_img_scale") {
987 lex >> html_math_img_scale;
988 } else if (token == "\\html_latex_start") {
990 html_latex_start = lex.getString();
991 } else if (token == "\\html_latex_end") {
993 html_latex_end = lex.getString();
994 } else if (token == "\\output_sync") {
996 } else if (token == "\\output_sync_macro") {
997 lex >> output_sync_macro;
998 } else if (token == "\\use_refstyle") {
1001 lyxerr << "BufferParams::readToken(): Unknown token: " <<
1011 // Quote argument if it contains spaces
1012 string quoteIfNeeded(string const & str) {
1013 if (contains(str, ' '))
1014 return "\"" + str + "\"";
1020 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
1022 // The top of the file is written by the buffer.
1023 // Prints out the buffer info into the .lyx file given by file
1025 os << "\\save_transient_properties "
1026 << convert<string>(save_transient_properties) << '\n';
1028 // the document directory (must end with a path separator)
1029 // realPath() is used to resolve symlinks, while addPath(..., "")
1030 // ensures a trailing path separator.
1031 string filepath = addPath(buf->fileName().onlyPath().realPath(), "");
1032 string const sysdir = addPath(package().system_support().realPath(), "");
1033 string const relpath =
1034 to_utf8(makeRelPath(from_utf8(filepath), from_utf8(sysdir)));
1035 if (!prefixIs(relpath, "../") && !FileName::isAbsolute(relpath))
1036 filepath = addPath("/systemlyxdir", relpath);
1037 else if (!save_transient_properties || !lyxrc.save_origin)
1038 filepath = "unavailable";
1039 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1042 os << "\\textclass "
1043 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1044 baseClass()->name()), "layout"))
1047 // then the preamble
1048 if (!preamble.empty()) {
1049 // remove '\n' from the end of preamble
1050 string const tmppreamble = rtrim(preamble, "\n");
1051 os << "\\begin_preamble\n"
1053 << "\n\\end_preamble\n";
1057 if (!options.empty()) {
1058 os << "\\options " << options << '\n';
1061 // use the class options defined in the layout?
1062 os << "\\use_default_options "
1063 << convert<string>(use_default_options) << "\n";
1065 // the master document
1066 if (!master.empty()) {
1067 os << "\\master " << master << '\n';
1071 if (!removed_modules_.empty()) {
1072 os << "\\begin_removed_modules" << '\n';
1073 list<string>::const_iterator it = removed_modules_.begin();
1074 list<string>::const_iterator en = removed_modules_.end();
1075 for (; it != en; ++it)
1077 os << "\\end_removed_modules" << '\n';
1081 if (!layout_modules_.empty()) {
1082 os << "\\begin_modules" << '\n';
1083 LayoutModuleList::const_iterator it = layout_modules_.begin();
1084 LayoutModuleList::const_iterator en = layout_modules_.end();
1085 for (; it != en; ++it)
1087 os << "\\end_modules" << '\n';
1091 if (!included_children_.empty()) {
1092 os << "\\begin_includeonly" << '\n';
1093 list<string>::const_iterator it = included_children_.begin();
1094 list<string>::const_iterator en = included_children_.end();
1095 for (; it != en; ++it)
1097 os << "\\end_includeonly" << '\n';
1099 os << "\\maintain_unincluded_children "
1100 << convert<string>(maintain_unincluded_children) << '\n';
1102 // local layout information
1103 string const local_layout = getLocalLayout(false);
1104 if (!local_layout.empty()) {
1105 // remove '\n' from the end
1106 string const tmplocal = rtrim(local_layout, "\n");
1107 os << "\\begin_local_layout\n"
1109 << "\n\\end_local_layout\n";
1111 string const forced_local_layout = getLocalLayout(true);
1112 if (!forced_local_layout.empty()) {
1113 // remove '\n' from the end
1114 string const tmplocal = rtrim(forced_local_layout, "\n");
1115 os << "\\begin_forced_local_layout\n"
1117 << "\n\\end_forced_local_layout\n";
1120 // then the text parameters
1121 if (language != ignore_language)
1122 os << "\\language " << language->lang() << '\n';
1123 os << "\\language_package " << lang_package
1124 << "\n\\inputencoding " << inputenc
1125 << "\n\\fontencoding " << fontenc
1126 << "\n\\font_roman \"" << fonts_roman[0]
1127 << "\" \"" << fonts_roman[1] << '"'
1128 << "\n\\font_sans \"" << fonts_sans[0]
1129 << "\" \"" << fonts_sans[1] << '"'
1130 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1131 << "\" \"" << fonts_typewriter[1] << '"'
1132 << "\n\\font_math \"" << fonts_math[0]
1133 << "\" \"" << fonts_math[1] << '"'
1134 << "\n\\font_default_family " << fonts_default_family
1135 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1136 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1137 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1138 << "\n\\font_sf_scale " << fonts_sans_scale[0]
1139 << ' ' << fonts_sans_scale[1]
1140 << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1141 << ' ' << fonts_typewriter_scale[1]
1143 if (!fonts_cjk.empty()) {
1144 os << "\\font_cjk " << fonts_cjk << '\n';
1146 os << "\\use_microtype " << convert<string>(use_microtype) << '\n';
1147 os << "\\graphics " << graphics_driver << '\n';
1148 os << "\\default_output_format " << default_output_format << '\n';
1149 os << "\\output_sync " << output_sync << '\n';
1150 if (!output_sync_macro.empty())
1151 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1152 os << "\\bibtex_command " << bibtex_command << '\n';
1153 os << "\\index_command " << index_command << '\n';
1155 if (!float_placement.empty()) {
1156 os << "\\float_placement " << float_placement << '\n';
1158 os << "\\paperfontsize " << fontsize << '\n';
1160 spacing().writeFile(os);
1161 pdfoptions().writeFile(os);
1163 os << "\\papersize " << string_papersize[papersize]
1164 << "\n\\use_geometry " << convert<string>(use_geometry);
1165 map<string, string> const & packages = auto_packages();
1166 for (map<string, string>::const_iterator it = packages.begin();
1167 it != packages.end(); ++it)
1168 os << "\n\\use_package " << it->first << ' '
1169 << use_package(it->first);
1171 os << "\n\\cite_engine ";
1173 if (!cite_engine_.empty()) {
1174 LayoutModuleList::const_iterator be = cite_engine_.begin();
1175 LayoutModuleList::const_iterator en = cite_engine_.end();
1176 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1185 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1186 << "\n\\biblio_style " << biblio_style
1187 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1188 << "\n\\use_indices " << convert<string>(use_indices)
1189 << "\n\\paperorientation " << string_orientation[orientation]
1190 << "\n\\suppress_date " << convert<string>(suppress_date)
1191 << "\n\\justification " << convert<string>(justification)
1192 << "\n\\use_refstyle " << use_refstyle
1194 if (isbackgroundcolor == true)
1195 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1196 if (isfontcolor == true)
1197 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1198 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1199 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1200 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1201 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1203 BranchList::const_iterator it = branchlist().begin();
1204 BranchList::const_iterator end = branchlist().end();
1205 for (; it != end; ++it) {
1206 os << "\\branch " << to_utf8(it->branch())
1207 << "\n\\selected " << it->isSelected()
1208 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1209 << "\n\\color " << lyx::X11hexname(it->color())
1214 IndicesList::const_iterator iit = indiceslist().begin();
1215 IndicesList::const_iterator iend = indiceslist().end();
1216 for (; iit != iend; ++iit) {
1217 os << "\\index " << to_utf8(iit->index())
1218 << "\n\\shortcut " << to_utf8(iit->shortcut())
1219 << "\n\\color " << lyx::X11hexname(iit->color())
1224 if (!paperwidth.empty())
1225 os << "\\paperwidth "
1226 << VSpace(paperwidth).asLyXCommand() << '\n';
1227 if (!paperheight.empty())
1228 os << "\\paperheight "
1229 << VSpace(paperheight).asLyXCommand() << '\n';
1230 if (!leftmargin.empty())
1231 os << "\\leftmargin "
1232 << VSpace(leftmargin).asLyXCommand() << '\n';
1233 if (!topmargin.empty())
1234 os << "\\topmargin "
1235 << VSpace(topmargin).asLyXCommand() << '\n';
1236 if (!rightmargin.empty())
1237 os << "\\rightmargin "
1238 << VSpace(rightmargin).asLyXCommand() << '\n';
1239 if (!bottommargin.empty())
1240 os << "\\bottommargin "
1241 << VSpace(bottommargin).asLyXCommand() << '\n';
1242 if (!headheight.empty())
1243 os << "\\headheight "
1244 << VSpace(headheight).asLyXCommand() << '\n';
1245 if (!headsep.empty())
1247 << VSpace(headsep).asLyXCommand() << '\n';
1248 if (!footskip.empty())
1250 << VSpace(footskip).asLyXCommand() << '\n';
1251 if (!columnsep.empty())
1252 os << "\\columnsep "
1253 << VSpace(columnsep).asLyXCommand() << '\n';
1254 os << "\\secnumdepth " << secnumdepth
1255 << "\n\\tocdepth " << tocdepth
1256 << "\n\\paragraph_separation "
1257 << string_paragraph_separation[paragraph_separation];
1258 if (!paragraph_separation)
1259 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1261 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1262 os << "\n\\quotes_language "
1263 << string_quotes_language[quotes_language]
1264 << "\n\\papercolumns " << columns
1265 << "\n\\papersides " << sides
1266 << "\n\\paperpagestyle " << pagestyle << '\n';
1267 if (!listings_params.empty())
1268 os << "\\listings_params \"" <<
1269 InsetListingsParams(listings_params).encodedString() << "\"\n";
1270 for (int i = 0; i < 4; ++i) {
1271 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1272 if (user_defined_bullet(i).getFont() != -1) {
1273 os << "\\bullet " << i << " "
1274 << user_defined_bullet(i).getFont() << " "
1275 << user_defined_bullet(i).getCharacter() << " "
1276 << user_defined_bullet(i).getSize() << "\n";
1280 os << "\\bulletLaTeX " << i << " \""
1281 << lyx::to_ascii(user_defined_bullet(i).getText())
1287 os << "\\tracking_changes "
1288 << (save_transient_properties ? convert<string>(track_changes) : "false")
1291 os << "\\output_changes "
1292 << (save_transient_properties ? convert<string>(output_changes) : "false")
1295 os << "\\html_math_output " << html_math_output << '\n'
1296 << "\\html_css_as_file " << html_css_as_file << '\n'
1297 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1299 if (html_math_img_scale != 1.0)
1300 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1301 if (!html_latex_start.empty())
1302 os << "\\html_latex_start " << html_latex_start << '\n';
1303 if (!html_latex_end.empty())
1304 os << "\\html_latex_end " << html_latex_end << '\n';
1306 os << pimpl_->authorlist;
1310 void BufferParams::validate(LaTeXFeatures & features) const
1312 features.require(documentClass().requires());
1314 if (columns > 1 && language->rightToLeft())
1315 features.require("rtloutputdblcol");
1317 if (output_changes) {
1318 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1319 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1320 LaTeXFeatures::isAvailable("xcolor");
1322 switch (features.runparams().flavor) {
1323 case OutputParams::LATEX:
1324 case OutputParams::DVILUATEX:
1326 features.require("ct-dvipost");
1327 features.require("dvipost");
1328 } else if (xcolorulem) {
1329 features.require("ct-xcolor-ulem");
1330 features.require("ulem");
1331 features.require("xcolor");
1333 features.require("ct-none");
1336 case OutputParams::LUATEX:
1337 case OutputParams::PDFLATEX:
1338 case OutputParams::XETEX:
1340 features.require("ct-xcolor-ulem");
1341 features.require("ulem");
1342 features.require("xcolor");
1343 // improves color handling in PDF output
1344 features.require("pdfcolmk");
1346 features.require("ct-none");
1354 // Floats with 'Here definitely' as default setting.
1355 if (float_placement.find('H') != string::npos)
1356 features.require("float");
1358 for (PackageMap::const_iterator it = use_packages.begin();
1359 it != use_packages.end(); ++it) {
1360 if (it->first == "amsmath") {
1361 // AMS Style is at document level
1362 if (it->second == package_on ||
1363 features.isProvided("amsmath"))
1364 features.require(it->first);
1365 } else if (it->second == package_on)
1366 features.require(it->first);
1369 // Document-level line spacing
1370 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1371 features.require("setspace");
1373 // the bullet shapes are buffer level not paragraph level
1374 // so they are tested here
1375 for (int i = 0; i < 4; ++i) {
1376 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1378 int const font = user_defined_bullet(i).getFont();
1380 int const c = user_defined_bullet(i).getCharacter();
1386 features.require("latexsym");
1388 } else if (font == 1) {
1389 features.require("amssymb");
1390 } else if (font >= 2 && font <= 5) {
1391 features.require("pifont");
1395 if (pdfoptions().use_hyperref) {
1396 features.require("hyperref");
1397 // due to interferences with babel and hyperref, the color package has to
1398 // be loaded after hyperref when hyperref is used with the colorlinks
1399 // option, see http://www.lyx.org/trac/ticket/5291
1400 if (pdfoptions().colorlinks)
1401 features.require("color");
1403 if (!listings_params.empty()) {
1404 // do not test validity because listings_params is
1405 // supposed to be valid
1407 InsetListingsParams(listings_params).separatedParams(true);
1408 // we can't support all packages, but we should load the color package
1409 if (par.find("\\color", 0) != string::npos)
1410 features.require("color");
1413 // some languages are only available via polyglossia
1414 if (features.hasPolyglossiaExclusiveLanguages())
1415 features.require("polyglossia");
1417 if (useNonTeXFonts && fontsMath() != "auto")
1418 features.require("unicode-math");
1421 features.require("microtype");
1423 if (!language->requires().empty())
1424 features.require(language->requires());
1428 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1429 FileName const & filepath) const
1431 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1432 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1433 // \RequirePackage to do so, rather than the normal \usepackage
1434 // Do not try to load any other package before the document class, unless you
1435 // have a thorough understanding of the LATEX internals and know exactly what you
1437 if (features.mustProvide("fix-cm"))
1438 os << "\\RequirePackage{fix-cm}\n";
1439 // Likewise for fixltx2e. If other packages conflict with this policy,
1440 // treat it as a package bug (and report it!)
1441 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1442 if (features.mustProvide("fixltx2e"))
1443 os << "\\RequirePackage{fixltx2e}\n";
1445 os << "\\documentclass";
1447 DocumentClass const & tclass = documentClass();
1449 ostringstream clsoptions; // the document class options.
1451 if (tokenPos(tclass.opt_fontsize(),
1452 '|', fontsize) >= 0) {
1453 // only write if existing in list (and not default)
1454 clsoptions << fontsize << "pt,";
1457 // all paper sizes except of A4, A5, B5 and the US sizes need the
1459 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1460 && papersize != PAPER_USLETTER
1461 && papersize != PAPER_USLEGAL
1462 && papersize != PAPER_USEXECUTIVE
1463 && papersize != PAPER_A4
1464 && papersize != PAPER_A5
1465 && papersize != PAPER_B5;
1467 if (!use_geometry) {
1468 switch (papersize) {
1470 clsoptions << "a4paper,";
1472 case PAPER_USLETTER:
1473 clsoptions << "letterpaper,";
1476 clsoptions << "a5paper,";
1479 clsoptions << "b5paper,";
1481 case PAPER_USEXECUTIVE:
1482 clsoptions << "executivepaper,";
1485 clsoptions << "legalpaper,";
1519 if (sides != tclass.sides()) {
1522 clsoptions << "oneside,";
1525 clsoptions << "twoside,";
1531 if (columns != tclass.columns()) {
1533 clsoptions << "twocolumn,";
1535 clsoptions << "onecolumn,";
1539 && orientation == ORIENTATION_LANDSCAPE)
1540 clsoptions << "landscape,";
1542 // language should be a parameter to \documentclass
1543 if (language->babel() == "hebrew"
1544 && default_language->babel() != "hebrew")
1545 // This seems necessary
1546 features.useLanguage(default_language);
1548 ostringstream language_options;
1549 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1550 bool const use_polyglossia = features.usePolyglossia();
1551 bool const global = lyxrc.language_global_options;
1552 if (use_babel || (use_polyglossia && global)) {
1553 language_options << features.getBabelLanguages();
1554 if (!language->babel().empty()) {
1555 if (!language_options.str().empty())
1556 language_options << ',';
1557 language_options << language->babel();
1559 if (global && !features.needBabelLangOptions()
1560 && !language_options.str().empty())
1561 clsoptions << language_options.str() << ',';
1564 // the predefined options from the layout
1565 if (use_default_options && !tclass.options().empty())
1566 clsoptions << tclass.options() << ',';
1568 // the user-defined options
1569 if (!options.empty()) {
1570 clsoptions << options << ',';
1573 string strOptions(clsoptions.str());
1574 if (!strOptions.empty()) {
1575 strOptions = rtrim(strOptions, ",");
1577 os << '[' << from_utf8(strOptions) << ']';
1580 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1581 // end of \documentclass defs
1583 // if we use fontspec or newtxmath, we have to load the AMS packages here
1584 string const ams = features.loadAMSPackages();
1585 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1586 bool const use_newtxmath =
1587 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1588 ot1, false, false) == "newtxmath";
1589 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1590 os << from_ascii(ams);
1592 if (useNonTeXFonts) {
1593 if (!features.isProvided("fontspec"))
1594 os << "\\usepackage{fontspec}\n";
1595 if (features.mustProvide("unicode-math")
1596 && features.isAvailable("unicode-math"))
1597 os << "\\usepackage{unicode-math}\n";
1600 // font selection must be done before loading fontenc.sty
1601 string const fonts = loadFonts(features);
1603 os << from_utf8(fonts);
1605 if (fonts_default_family != "default")
1606 os << "\\renewcommand{\\familydefault}{\\"
1607 << from_ascii(fonts_default_family) << "}\n";
1609 // set font encoding
1610 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1611 if (!useNonTeXFonts && !features.isProvided("fontenc")
1612 && font_encoding() != "default") {
1613 // get main font encodings
1614 vector<string> fontencs = font_encodings();
1615 // get font encodings of secondary languages
1616 features.getFontEncodings(fontencs);
1617 if (!fontencs.empty()) {
1618 os << "\\usepackage["
1619 << from_ascii(getStringFromVector(fontencs))
1624 // handle inputenc etc.
1625 writeEncodingPreamble(os, features);
1628 if (!features.runparams().includeall && !included_children_.empty()) {
1629 os << "\\includeonly{";
1630 list<string>::const_iterator it = included_children_.begin();
1631 list<string>::const_iterator en = included_children_.end();
1633 for (; it != en; ++it) {
1634 string incfile = *it;
1635 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1636 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1638 if (!features.runparams().nice)
1640 // \includeonly doesn't want an extension
1641 incfile = changeExtension(incfile, string());
1642 incfile = support::latex_path(incfile);
1643 if (!incfile.empty()) {
1646 os << from_utf8(incfile);
1653 if (!features.isProvided("geometry")
1654 && (use_geometry || nonstandard_papersize)) {
1655 odocstringstream ods;
1656 if (!getGraphicsDriver("geometry").empty())
1657 ods << getGraphicsDriver("geometry");
1658 if (orientation == ORIENTATION_LANDSCAPE)
1659 ods << ",landscape";
1660 switch (papersize) {
1662 if (!paperwidth.empty())
1663 ods << ",paperwidth="
1664 << from_ascii(paperwidth);
1665 if (!paperheight.empty())
1666 ods << ",paperheight="
1667 << from_ascii(paperheight);
1669 case PAPER_USLETTER:
1670 ods << ",letterpaper";
1673 ods << ",legalpaper";
1675 case PAPER_USEXECUTIVE:
1676 ods << ",executivepaper";
1765 docstring const g_options = trim(ods.str(), ",");
1766 os << "\\usepackage";
1767 if (!g_options.empty())
1768 os << '[' << g_options << ']';
1769 os << "{geometry}\n";
1770 // output this only if use_geometry is true
1772 os << "\\geometry{verbose";
1773 if (!topmargin.empty())
1774 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1775 if (!bottommargin.empty())
1776 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1777 if (!leftmargin.empty())
1778 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1779 if (!rightmargin.empty())
1780 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1781 if (!headheight.empty())
1782 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1783 if (!headsep.empty())
1784 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1785 if (!footskip.empty())
1786 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1787 if (!columnsep.empty())
1788 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1791 } else if (orientation == ORIENTATION_LANDSCAPE
1792 || papersize != PAPER_DEFAULT) {
1793 features.require("papersize");
1796 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1797 if (pagestyle == "fancy")
1798 os << "\\usepackage{fancyhdr}\n";
1799 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1802 // only output when the background color is not default
1803 if (isbackgroundcolor == true) {
1804 // only require color here, the background color will be defined
1805 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1807 features.require("color");
1808 features.require("pagecolor");
1811 // only output when the font color is not default
1812 if (isfontcolor == true) {
1813 // only require color here, the font color will be defined
1814 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1816 features.require("color");
1817 features.require("fontcolor");
1820 // Only if class has a ToC hierarchy
1821 if (tclass.hasTocLevels()) {
1822 if (secnumdepth != tclass.secnumdepth()) {
1823 os << "\\setcounter{secnumdepth}{"
1827 if (tocdepth != tclass.tocdepth()) {
1828 os << "\\setcounter{tocdepth}{"
1834 if (paragraph_separation) {
1835 // when skip separation
1836 switch (getDefSkip().kind()) {
1837 case VSpace::SMALLSKIP:
1838 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1840 case VSpace::MEDSKIP:
1841 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1843 case VSpace::BIGSKIP:
1844 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1846 case VSpace::LENGTH:
1847 os << "\\setlength{\\parskip}{"
1848 << from_utf8(getDefSkip().length().asLatexString())
1851 default: // should never happen // Then delete it.
1852 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1855 os << "\\setlength{\\parindent}{0pt}\n";
1857 // when separation by indentation
1858 // only output something when a width is given
1859 if (getIndentation().asLyXCommand() != "default") {
1860 os << "\\setlength{\\parindent}{"
1861 << from_utf8(getIndentation().asLatexCommand())
1866 // Now insert the LyX specific LaTeX commands...
1867 docstring lyxpreamble;
1868 features.resolveAlternatives();
1871 if (!output_sync_macro.empty())
1872 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1873 else if (features.runparams().flavor == OutputParams::LATEX)
1874 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1875 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1876 lyxpreamble += "\\synctex=-1\n";
1879 // The package options (via \PassOptionsToPackage)
1880 lyxpreamble += from_ascii(features.getPackageOptions());
1882 // due to interferences with babel and hyperref, the color package has to
1883 // be loaded (when it is not already loaded) before babel when hyperref
1884 // is used with the colorlinks option, see
1885 // http://www.lyx.org/trac/ticket/5291
1886 // we decided therefore to load color always before babel, see
1887 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1888 lyxpreamble += from_ascii(features.getColorOptions());
1890 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1891 // we have to call babel before
1893 && (features.isRequired("jurabib")
1894 || features.isRequired("hyperref")
1895 || features.isRequired("varioref")
1896 || features.isRequired("vietnamese")
1897 || features.isRequired("japanese"))) {
1899 lyxpreamble += from_utf8(features.getBabelPresettings());
1900 lyxpreamble += from_utf8(babelCall(language_options.str(),
1901 features.needBabelLangOptions())) + '\n';
1902 lyxpreamble += from_utf8(features.getBabelPostsettings());
1905 // The optional packages;
1906 lyxpreamble += from_ascii(features.getPackages());
1908 // Additional Indices
1909 if (features.isRequired("splitidx")) {
1910 IndicesList::const_iterator iit = indiceslist().begin();
1911 IndicesList::const_iterator iend = indiceslist().end();
1912 for (; iit != iend; ++iit) {
1913 pair<docstring, docstring> indexname_latex =
1914 features.runparams().encoding->latexString(iit->index(),
1915 features.runparams().dryrun);
1916 if (!indexname_latex.second.empty()) {
1917 // issue a warning about omitted characters
1918 // FIXME: should be passed to the error dialog
1919 frontend::Alert::warning(_("Uncodable characters"),
1920 bformat(_("The following characters that are used in an index name are not\n"
1921 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1922 indexname_latex.second));
1924 lyxpreamble += "\\newindex[";
1925 lyxpreamble += indexname_latex.first;
1926 lyxpreamble += "]{";
1927 lyxpreamble += escape(iit->shortcut());
1928 lyxpreamble += "}\n";
1933 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1936 // * Hyperref manual: "Make sure it comes last of your loaded
1937 // packages, to give it a fighting chance of not being over-written,
1938 // since its job is to redefine many LaTeX commands."
1939 // * Email from Heiko Oberdiek: "It is usually better to load babel
1940 // before hyperref. Then hyperref has a chance to detect babel.
1941 // * Has to be loaded before the "LyX specific LaTeX commands" to
1942 // avoid errors with algorithm floats.
1943 // use hyperref explicitly if it is required
1944 if (features.isRequired("hyperref")) {
1945 // pass what we have to stream here, since we need
1946 // to access the stream itself in PDFOptions.
1949 OutputParams tmp_params = features.runparams();
1950 pdfoptions().writeLaTeX(tmp_params, os,
1951 features.isProvided("hyperref"));
1952 // set back for the rest
1953 lyxpreamble.clear();
1954 // correctly break URLs with hyperref and dvi output
1955 if (features.runparams().flavor == OutputParams::LATEX
1956 && features.isAvailable("breakurl"))
1957 lyxpreamble += "\\usepackage{breakurl}\n";
1958 } else if (features.isRequired("nameref"))
1959 // hyperref loads this automatically
1960 lyxpreamble += "\\usepackage{nameref}\n";
1962 // bibtopic needs to be loaded after hyperref.
1963 // the dot provides the aux file naming which LyX can detect.
1964 if (features.mustProvide("bibtopic"))
1965 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1967 // Will be surrounded by \makeatletter and \makeatother when not empty
1968 docstring atlyxpreamble;
1970 // Some macros LyX will need
1971 docstring tmppreamble(features.getMacros());
1973 if (!tmppreamble.empty())
1974 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1975 "LyX specific LaTeX commands.\n"
1976 + tmppreamble + '\n';
1978 // the text class specific preamble
1979 tmppreamble = features.getTClassPreamble();
1980 if (!tmppreamble.empty())
1981 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1982 "Textclass specific LaTeX commands.\n"
1983 + tmppreamble + '\n';
1985 // suppress date if selected
1986 // use \@ifundefined because we cannot be sure that every document class
1987 // has a \date command
1989 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1991 /* the user-defined preamble */
1992 if (!containsOnly(preamble, " \n\t")) {
1994 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1995 "User specified LaTeX commands.\n";
1997 // Check if the user preamble contains uncodable glyphs
1998 docstring const u_preamble = from_utf8(preamble);
1999 odocstringstream user_preamble;
2000 docstring uncodable_glyphs;
2001 Encoding const * const enc = features.runparams().encoding;
2003 for (size_t n = 0; n < u_preamble.size(); ++n) {
2004 char_type c = u_preamble[n];
2005 if (!enc->encodable(c)) {
2006 docstring const glyph(1, c);
2007 LYXERR0("Uncodable character '"
2009 << "' in user preamble!");
2010 uncodable_glyphs += glyph;
2011 if (features.runparams().dryrun) {
2012 user_preamble << "<" << _("LyX Warning: ")
2013 << _("uncodable character") << " '";
2014 user_preamble.put(c);
2015 user_preamble << "'>";
2018 user_preamble.put(c);
2021 user_preamble << u_preamble;
2023 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2024 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2025 frontend::Alert::warning(
2026 _("Uncodable character in user preamble"),
2028 _("The user preamble of your document contains glyphs "
2029 "that are unknown in the current document encoding "
2030 "(namely %1$s).\nThese glyphs are omitted "
2031 " from the output, which may result in "
2032 "incomplete output."
2033 "\n\nPlease select an appropriate "
2034 "document encoding\n"
2035 "(such as utf8) or change the "
2036 "preamble code accordingly."),
2039 atlyxpreamble += user_preamble.str() + '\n';
2042 // footmisc must be loaded after setspace
2043 // Load it here to avoid clashes with footmisc loaded in the user
2044 // preamble. For that reason we also pass the options via
2045 // \PassOptionsToPackage in getPreamble() and not here.
2046 if (features.mustProvide("footmisc"))
2047 atlyxpreamble += "\\usepackage{footmisc}\n";
2049 // subfig loads internally the LaTeX package "caption". As
2050 // caption is a very popular package, users will load it in
2051 // the preamble. Therefore we must load subfig behind the
2052 // user-defined preamble and check if the caption package was
2053 // loaded or not. For the case that caption is loaded before
2054 // subfig, there is the subfig option "caption=false". This
2055 // option also works when a koma-script class is used and
2056 // koma's own caption commands are used instead of caption. We
2057 // use \PassOptionsToPackage here because the user could have
2058 // already loaded subfig in the preamble.
2059 if (features.mustProvide("subfig")) {
2060 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
2061 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2062 "\\usepackage{subfig}\n";
2065 // Itemize bullet settings need to be last in case the user
2066 // defines their own bullets that use a package included
2067 // in the user-defined preamble -- ARRae
2068 // Actually it has to be done much later than that
2069 // since some packages like frenchb make modifications
2070 // at \begin{document} time -- JMarc
2071 docstring bullets_def;
2072 for (int i = 0; i < 4; ++i) {
2073 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2074 if (bullets_def.empty())
2075 bullets_def += "\\AtBeginDocument{\n";
2076 bullets_def += " \\def\\labelitemi";
2078 // `i' is one less than the item to modify
2085 bullets_def += "ii";
2091 bullets_def += '{' +
2092 user_defined_bullet(i).getText()
2097 if (!bullets_def.empty())
2098 atlyxpreamble += bullets_def + "}\n\n";
2100 if (!atlyxpreamble.empty())
2101 lyxpreamble += "\n\\makeatletter\n"
2102 + atlyxpreamble + "\\makeatother\n\n";
2104 // We try to load babel late, in case it interferes with other packages.
2105 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
2106 // called after babel, though.
2107 if (use_babel && !features.isRequired("jurabib")
2108 && !features.isRequired("hyperref")
2109 && !features.isRequired("varioref")
2110 && !features.isRequired("vietnamese")
2111 && !features.isRequired("japanese")) {
2113 lyxpreamble += from_utf8(features.getBabelPresettings());
2114 lyxpreamble += from_utf8(babelCall(language_options.str(),
2115 features.needBabelLangOptions())) + '\n';
2116 lyxpreamble += from_utf8(features.getBabelPostsettings());
2118 if (features.isRequired("bicaption"))
2119 lyxpreamble += "\\usepackage{bicaption}\n";
2120 if (!listings_params.empty() || features.mustProvide("listings"))
2121 lyxpreamble += "\\usepackage{listings}\n";
2122 if (!listings_params.empty()) {
2123 lyxpreamble += "\\lstset{";
2124 // do not test validity because listings_params is
2125 // supposed to be valid
2127 InsetListingsParams(listings_params).separatedParams(true);
2128 lyxpreamble += from_utf8(par);
2129 lyxpreamble += "}\n";
2132 // xunicode needs to be loaded at least after amsmath, amssymb,
2133 // esint and the other packages that provide special glyphs
2134 if (features.runparams().flavor == OutputParams::XETEX
2136 lyxpreamble += "\\usepackage{xunicode}\n";
2138 // Polyglossia must be loaded last
2139 if (use_polyglossia) {
2141 lyxpreamble += "\\usepackage{polyglossia}\n";
2142 // set the main language
2143 lyxpreamble += "\\setdefaultlanguage";
2144 if (!language->polyglossiaOpts().empty())
2145 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
2146 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
2147 // now setup the other languages
2148 std::map<std::string, std::string> const polylangs =
2149 features.getPolyglossiaLanguages();
2150 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
2151 mit != polylangs.end() ; ++mit) {
2152 lyxpreamble += "\\setotherlanguage";
2153 if (!mit->second.empty())
2154 lyxpreamble += "[" + from_ascii(mit->second) + "]";
2155 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
2159 // Load custom language package here
2160 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2161 if (lang_package == "default")
2162 lyxpreamble += from_utf8(lyxrc.language_custom_package);
2164 lyxpreamble += from_utf8(lang_package);
2165 lyxpreamble += '\n';
2168 docstring const i18npreamble =
2169 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2170 if (!i18npreamble.empty())
2171 lyxpreamble += i18npreamble + '\n';
2179 void BufferParams::useClassDefaults()
2181 DocumentClass const & tclass = documentClass();
2183 sides = tclass.sides();
2184 columns = tclass.columns();
2185 pagestyle = tclass.pagestyle();
2186 use_default_options = true;
2187 // Only if class has a ToC hierarchy
2188 if (tclass.hasTocLevels()) {
2189 secnumdepth = tclass.secnumdepth();
2190 tocdepth = tclass.tocdepth();
2195 bool BufferParams::hasClassDefaults() const
2197 DocumentClass const & tclass = documentClass();
2199 return sides == tclass.sides()
2200 && columns == tclass.columns()
2201 && pagestyle == tclass.pagestyle()
2202 && use_default_options
2203 && secnumdepth == tclass.secnumdepth()
2204 && tocdepth == tclass.tocdepth();
2208 DocumentClass const & BufferParams::documentClass() const
2214 DocumentClassConstPtr BufferParams::documentClassPtr() const
2220 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2222 // evil, but this function is evil
2223 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2227 bool BufferParams::setBaseClass(string const & classname)
2229 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2230 LayoutFileList & bcl = LayoutFileList::get();
2231 if (!bcl.haveClass(classname)) {
2233 bformat(_("The layout file:\n"
2235 "could not be found. A default textclass with default\n"
2236 "layouts will be used. LyX will not be able to produce\n"
2238 from_utf8(classname));
2239 frontend::Alert::error(_("Document class not found"), s);
2240 bcl.addEmptyClass(classname);
2243 bool const success = bcl[classname].load();
2246 bformat(_("Due to some error in it, the layout file:\n"
2248 "could not be loaded. A default textclass with default\n"
2249 "layouts will be used. LyX will not be able to produce\n"
2251 from_utf8(classname));
2252 frontend::Alert::error(_("Could not load class"), s);
2253 bcl.addEmptyClass(classname);
2256 pimpl_->baseClass_ = classname;
2257 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2262 LayoutFile const * BufferParams::baseClass() const
2264 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2265 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2271 LayoutFileIndex const & BufferParams::baseClassID() const
2273 return pimpl_->baseClass_;
2277 void BufferParams::makeDocumentClass(bool const clone)
2282 LayoutModuleList mods;
2283 LayoutModuleList::iterator it = layout_modules_.begin();
2284 LayoutModuleList::iterator en = layout_modules_.end();
2285 for (; it != en; ++it)
2286 mods.push_back(*it);
2288 it = cite_engine_.begin();
2289 en = cite_engine_.end();
2290 for (; it != en; ++it)
2291 mods.push_back(*it);
2293 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2295 TextClass::ReturnValues success = TextClass::OK;
2296 if (!forced_local_layout_.empty())
2297 success = doc_class_->read(forced_local_layout_, TextClass::MODULE);
2298 if (!local_layout_.empty() &&
2299 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2300 success = doc_class_->read(local_layout_, TextClass::MODULE);
2301 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2302 docstring const msg = _("Error reading internal layout information");
2303 frontend::Alert::warning(_("Read Error"), msg);
2308 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2310 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2314 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2316 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2320 std::string BufferParams::getLocalLayout(bool forced) const
2323 return doc_class_->forcedLayouts();
2325 return local_layout_;
2329 void BufferParams::setLocalLayout(string const & layout, bool forced)
2332 forced_local_layout_ = layout;
2334 local_layout_ = layout;
2338 bool BufferParams::addLayoutModule(string const & modName)
2340 LayoutModuleList::const_iterator it = layout_modules_.begin();
2341 LayoutModuleList::const_iterator end = layout_modules_.end();
2342 for (; it != end; ++it)
2345 layout_modules_.push_back(modName);
2350 string BufferParams::bufferFormat() const
2352 string format = documentClass().outputFormat();
2353 if (format == "latex") {
2355 return "xetex"; // actually "xetex or luatex"
2356 if (encoding().package() == Encoding::japanese)
2363 bool BufferParams::isExportable(string const & format) const
2365 vector<string> backs = backends();
2366 for (vector<string>::const_iterator it = backs.begin();
2367 it != backs.end(); ++it)
2368 if (theConverters().isReachable(*it, format))
2374 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2376 vector<string> const backs = backends();
2377 set<string> excludes;
2378 if (useNonTeXFonts) {
2379 excludes.insert("latex");
2380 excludes.insert("pdflatex");
2382 vector<Format const *> result =
2383 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2384 for (vector<string>::const_iterator it = backs.begin() + 1;
2385 it != backs.end(); ++it) {
2386 vector<Format const *> r =
2387 theConverters().getReachable(*it, only_viewable, false, excludes);
2388 result.insert(result.end(), r.begin(), r.end());
2394 bool BufferParams::isExportableFormat(string const & format) const
2396 typedef vector<Format const *> Formats;
2398 formats = exportableFormats(true);
2399 Formats::const_iterator fit = formats.begin();
2400 Formats::const_iterator end = formats.end();
2401 for (; fit != end ; ++fit) {
2402 if ((*fit)->name() == format)
2409 vector<string> BufferParams::backends() const
2412 string const buffmt = bufferFormat();
2414 // FIXME: Don't hardcode format names here, but use a flag
2415 if (buffmt == "latex") {
2416 if (!useNonTeXFonts) {
2417 v.push_back("pdflatex");
2418 v.push_back("latex");
2420 v.push_back("luatex");
2421 v.push_back("dviluatex");
2422 v.push_back("xetex");
2423 } else if (buffmt == "xetex") {
2424 v.push_back("xetex");
2425 // FIXME: need to test all languages (bug 8205)
2426 if (!language || !language->isPolyglossiaExclusive()) {
2427 v.push_back("luatex");
2428 v.push_back("dviluatex");
2431 v.push_back(buffmt);
2433 v.push_back("xhtml");
2434 v.push_back("text");
2440 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2442 string const dformat = (format.empty() || format == "default") ?
2443 getDefaultOutputFormat() : format;
2444 DefaultFlavorCache::const_iterator it =
2445 default_flavors_.find(dformat);
2447 if (it != default_flavors_.end())
2450 OutputParams::FLAVOR result = OutputParams::LATEX;
2452 // FIXME It'd be better not to hardcode this, but to do
2453 // something with formats.
2454 if (dformat == "xhtml")
2455 result = OutputParams::HTML;
2456 else if (dformat == "text")
2457 result = OutputParams::TEXT;
2458 else if (dformat == "lyx")
2459 result = OutputParams::LYX;
2460 else if (dformat == "pdflatex")
2461 result = OutputParams::PDFLATEX;
2462 else if (dformat == "xetex")
2463 result = OutputParams::XETEX;
2464 else if (dformat == "luatex")
2465 result = OutputParams::LUATEX;
2466 else if (dformat == "dviluatex")
2467 result = OutputParams::DVILUATEX;
2469 // Try to determine flavor of default output format
2470 vector<string> backs = backends();
2471 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2472 // Get shortest path to format
2473 Graph::EdgePath path;
2474 for (vector<string>::const_iterator it = backs.begin();
2475 it != backs.end(); ++it) {
2476 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2477 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2482 result = theConverters().getFlavor(path);
2485 // cache this flavor
2486 default_flavors_[dformat] = result;
2491 string BufferParams::getDefaultOutputFormat() const
2493 if (!default_output_format.empty()
2494 && default_output_format != "default")
2495 return default_output_format;
2497 || encoding().package() == Encoding::japanese) {
2498 vector<Format const *> const formats = exportableFormats(true);
2499 if (formats.empty())
2501 // return the first we find
2502 return formats.front()->name();
2505 return lyxrc.default_otf_view_format;
2506 return lyxrc.default_view_format;
2509 Font const BufferParams::getFont() const
2511 FontInfo f = documentClass().defaultfont();
2512 if (fonts_default_family == "rmdefault")
2513 f.setFamily(ROMAN_FAMILY);
2514 else if (fonts_default_family == "sfdefault")
2515 f.setFamily(SANS_FAMILY);
2516 else if (fonts_default_family == "ttdefault")
2517 f.setFamily(TYPEWRITER_FAMILY);
2518 return Font(f, language);
2522 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const & qs) const
2524 return quoteslangtranslator().find(qs);
2528 bool BufferParams::isLatex() const
2530 return documentClass().outputType() == LATEX;
2534 bool BufferParams::isLiterate() const
2536 return documentClass().outputType() == LITERATE;
2540 bool BufferParams::isDocBook() const
2542 return documentClass().outputType() == DOCBOOK;
2546 void BufferParams::readPreamble(Lexer & lex)
2548 if (lex.getString() != "\\begin_preamble")
2549 lyxerr << "Error (BufferParams::readPreamble):"
2550 "consistency check failed." << endl;
2552 preamble = lex.getLongString("\\end_preamble");
2556 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2558 string const expected = forced ? "\\begin_forced_local_layout" :
2559 "\\begin_local_layout";
2560 if (lex.getString() != expected)
2561 lyxerr << "Error (BufferParams::readLocalLayout):"
2562 "consistency check failed." << endl;
2565 forced_local_layout_ =
2566 lex.getLongString("\\end_forced_local_layout");
2568 local_layout_ = lex.getLongString("\\end_local_layout");
2572 bool BufferParams::setLanguage(string const & lang)
2574 Language const *new_language = languages.getLanguage(lang);
2575 if (!new_language) {
2576 // Language lang was not found
2579 language = new_language;
2584 void BufferParams::readLanguage(Lexer & lex)
2586 if (!lex.next()) return;
2588 string const tmptok = lex.getString();
2590 // check if tmptok is part of tex_babel in tex-defs.h
2591 if (!setLanguage(tmptok)) {
2592 // Language tmptok was not found
2593 language = default_language;
2594 lyxerr << "Warning: Setting language `"
2595 << tmptok << "' to `" << language->lang()
2601 void BufferParams::readGraphicsDriver(Lexer & lex)
2606 string const tmptok = lex.getString();
2607 // check if tmptok is part of tex_graphics in tex_defs.h
2610 string const test = tex_graphics[n++];
2612 if (test == tmptok) {
2613 graphics_driver = tmptok;
2618 "Warning: graphics driver `$$Token' not recognized!\n"
2619 " Setting graphics driver to `default'.\n");
2620 graphics_driver = "default";
2627 void BufferParams::readBullets(Lexer & lex)
2632 int const index = lex.getInteger();
2634 int temp_int = lex.getInteger();
2635 user_defined_bullet(index).setFont(temp_int);
2636 temp_bullet(index).setFont(temp_int);
2638 user_defined_bullet(index).setCharacter(temp_int);
2639 temp_bullet(index).setCharacter(temp_int);
2641 user_defined_bullet(index).setSize(temp_int);
2642 temp_bullet(index).setSize(temp_int);
2646 void BufferParams::readBulletsLaTeX(Lexer & lex)
2648 // The bullet class should be able to read this.
2651 int const index = lex.getInteger();
2653 docstring const temp_str = lex.getDocString();
2655 user_defined_bullet(index).setText(temp_str);
2656 temp_bullet(index).setText(temp_str);
2660 void BufferParams::readModules(Lexer & lex)
2662 if (!lex.eatLine()) {
2663 lyxerr << "Error (BufferParams::readModules):"
2664 "Unexpected end of input." << endl;
2668 string mod = lex.getString();
2669 if (mod == "\\end_modules")
2671 addLayoutModule(mod);
2677 void BufferParams::readRemovedModules(Lexer & lex)
2679 if (!lex.eatLine()) {
2680 lyxerr << "Error (BufferParams::readRemovedModules):"
2681 "Unexpected end of input." << endl;
2685 string mod = lex.getString();
2686 if (mod == "\\end_removed_modules")
2688 removed_modules_.push_back(mod);
2691 // now we want to remove any removed modules that were previously
2692 // added. normally, that will be because default modules were added in
2693 // setBaseClass(), which gets called when \textclass is read at the
2694 // start of the read.
2695 list<string>::const_iterator rit = removed_modules_.begin();
2696 list<string>::const_iterator const ren = removed_modules_.end();
2697 for (; rit != ren; ++rit) {
2698 LayoutModuleList::iterator const mit = layout_modules_.begin();
2699 LayoutModuleList::iterator const men = layout_modules_.end();
2700 LayoutModuleList::iterator found = find(mit, men, *rit);
2703 layout_modules_.erase(found);
2708 void BufferParams::readIncludeonly(Lexer & lex)
2710 if (!lex.eatLine()) {
2711 lyxerr << "Error (BufferParams::readIncludeonly):"
2712 "Unexpected end of input." << endl;
2716 string child = lex.getString();
2717 if (child == "\\end_includeonly")
2719 included_children_.push_back(child);
2725 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2727 switch (papersize) {
2729 // could be anything, so don't guess
2731 case PAPER_CUSTOM: {
2732 if (purpose == XDVI && !paperwidth.empty() &&
2733 !paperheight.empty()) {
2734 // heightxwidth<unit>
2735 string first = paperwidth;
2736 string second = paperheight;
2737 if (orientation == ORIENTATION_LANDSCAPE)
2740 return first.erase(first.length() - 2)
2746 // dvips and dvipdfm do not know this
2747 if (purpose == DVIPS || purpose == DVIPDFM)
2751 if (purpose == DVIPS || purpose == DVIPDFM)
2755 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 if (purpose == DVIPS || purpose == DVIPDFM)
2785 // dvipdfm does not know this
2786 if (purpose == DVIPDFM)
2790 if (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)
2850 if (purpose == DVIPS || purpose == DVIPDFM)
2853 case PAPER_USEXECUTIVE:
2854 // dvipdfm does not know this
2855 if (purpose == DVIPDFM)
2860 case PAPER_USLETTER:
2862 if (purpose == XDVI)
2869 string const BufferParams::dvips_options() const
2873 // If the class loads the geometry package, we do not know which
2874 // paper size is used, since we do not set it (bug 7013).
2875 // Therefore we must not specify any argument here.
2876 // dvips gets the correct paper size via DVI specials in this case
2877 // (if the class uses the geometry package correctly).
2878 if (documentClass().provides("geometry"))
2882 && papersize == PAPER_CUSTOM
2883 && !lyxrc.print_paper_dimension_flag.empty()
2884 && !paperwidth.empty()
2885 && !paperheight.empty()) {
2886 // using a custom papersize
2887 result = lyxrc.print_paper_dimension_flag;
2888 result += ' ' + paperwidth;
2889 result += ',' + paperheight;
2891 string const paper_option = paperSizeName(DVIPS);
2892 if (!paper_option.empty() && (paper_option != "letter" ||
2893 orientation != ORIENTATION_LANDSCAPE)) {
2894 // dvips won't accept -t letter -t landscape.
2895 // In all other cases, include the paper size
2897 result = lyxrc.print_paper_flag;
2898 result += ' ' + paper_option;
2901 if (orientation == ORIENTATION_LANDSCAPE &&
2902 papersize != PAPER_CUSTOM)
2903 result += ' ' + lyxrc.print_landscape_flag;
2908 string const BufferParams::font_encoding() const
2910 return font_encodings().empty() ? "default" : font_encodings().back();
2914 vector<string> const BufferParams::font_encodings() const
2916 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2918 vector<string> fontencs;
2920 // "default" means "no explicit font encoding"
2921 if (doc_fontenc != "default") {
2922 fontencs = getVectorFromString(doc_fontenc);
2923 if (!language->fontenc().empty()
2924 && ascii_lowercase(language->fontenc()) != "none") {
2925 vector<string> fencs = getVectorFromString(language->fontenc());
2926 vector<string>::const_iterator fit = fencs.begin();
2927 for (; fit != fencs.end(); ++fit) {
2928 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
2929 fontencs.push_back(*fit);
2938 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2940 // suppress the babel call if there is no BabelName defined
2941 // for the document language in the lib/languages file and if no
2942 // other languages are used (lang_opts is then empty)
2943 if (lang_opts.empty())
2945 // either a specific language (AsBabelOptions setting in
2946 // lib/languages) or the prefs require the languages to
2947 // be submitted to babel itself (not the class).
2949 return "\\usepackage[" + lang_opts + "]{babel}";
2950 return "\\usepackage{babel}";
2954 docstring BufferParams::getGraphicsDriver(string const & package) const
2958 if (package == "geometry") {
2959 if (graphics_driver == "dvips"
2960 || graphics_driver == "dvipdfm"
2961 || graphics_driver == "pdftex"
2962 || graphics_driver == "vtex")
2963 result = from_ascii(graphics_driver);
2964 else if (graphics_driver == "dvipdfmx")
2965 result = from_ascii("dvipdfm");
2972 void BufferParams::writeEncodingPreamble(otexstream & os,
2973 LaTeXFeatures & features) const
2975 // XeTeX/LuaTeX: (see also #9740)
2976 // With Unicode fonts we use utf8-plain without encoding package.
2977 // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails.
2978 // XeTeX must use ASCII encoding (see Buffer.cpp),
2979 // for LuaTeX, we load "luainputenc" (see below).
2980 if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
2983 if (inputenc == "auto") {
2984 string const doc_encoding =
2985 language->encoding()->latexName();
2986 Encoding::Package const package =
2987 language->encoding()->package();
2989 // Create list of inputenc options:
2990 set<string> encodings;
2991 // luainputenc fails with more than one encoding
2992 if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts
2993 // list all input encodings used in the document
2994 encodings = features.getEncodingSet(doc_encoding);
2996 // If the "japanese" package (i.e. pLaTeX) is used,
2997 // inputenc must be omitted.
2998 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2999 if ((!encodings.empty() || package == Encoding::inputenc)
3000 && !features.isRequired("japanese")
3001 && !features.isProvided("inputenc")) {
3002 os << "\\usepackage[";
3003 set<string>::const_iterator it = encodings.begin();
3004 set<string>::const_iterator const end = encodings.end();
3006 os << from_ascii(*it);
3009 for (; it != end; ++it)
3010 os << ',' << from_ascii(*it);
3011 if (package == Encoding::inputenc) {
3012 if (!encodings.empty())
3014 os << from_ascii(doc_encoding);
3016 if (features.runparams().flavor == OutputParams::LUATEX
3017 || features.runparams().flavor == OutputParams::DVILUATEX)
3018 os << "]{luainputenc}\n";
3020 os << "]{inputenc}\n";
3022 if (package == Encoding::CJK || features.mustProvide("CJK")) {
3023 if (language->encoding()->name() == "utf8-cjk"
3024 && LaTeXFeatures::isAvailable("CJKutf8"))
3025 os << "\\usepackage{CJKutf8}\n";
3027 os << "\\usepackage{CJK}\n";
3029 } else if (inputenc != "default") {
3030 switch (encoding().package()) {
3031 case Encoding::none:
3032 case Encoding::japanese:
3034 case Encoding::inputenc:
3035 // do not load inputenc if japanese is used
3036 // or if the class provides inputenc
3037 if (features.isRequired("japanese")
3038 || features.isProvided("inputenc"))
3040 os << "\\usepackage[" << from_ascii(encoding().latexName());
3041 if (features.runparams().flavor == OutputParams::LUATEX
3042 || features.runparams().flavor == OutputParams::DVILUATEX)
3043 os << "]{luainputenc}\n";
3045 os << "]{inputenc}\n";
3048 if (encoding().name() == "utf8-cjk"
3049 && LaTeXFeatures::isAvailable("CJKutf8"))
3050 os << "\\usepackage{CJKutf8}\n";
3052 os << "\\usepackage{CJK}\n";
3055 // Load the CJK package if needed by a secondary language.
3056 // If the main encoding is some variant of UTF8, use CJKutf8.
3057 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
3058 if (encoding().iconvName() == "UTF-8"
3059 && LaTeXFeatures::isAvailable("CJKutf8"))
3060 os << "\\usepackage{CJKutf8}\n";
3062 os << "\\usepackage{CJK}\n";
3068 string const BufferParams::parseFontName(string const & name) const
3070 string mangled = name;
3071 size_t const idx = mangled.find('[');
3072 if (idx == string::npos || idx == 0)
3075 return mangled.substr(0, idx - 1);
3079 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3081 if (fontsRoman() == "default" && fontsSans() == "default"
3082 && fontsTypewriter() == "default"
3083 && (fontsMath() == "default" || fontsMath() == "auto"))
3089 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3090 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3091 * Mapping=tex-text option assures TeX ligatures (such as "--")
3092 * are resolved. Note that tt does not use these ligatures.
3094 * -- add more GUI options?
3095 * -- add more fonts (fonts for other scripts)
3096 * -- if there's a way to find out if a font really supports
3097 * OldStyle, enable/disable the widget accordingly.
3099 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3100 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3101 // However, until v.2 (2010/07/11) fontspec only knew
3102 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3103 // was introduced for both XeTeX and LuaTeX (LuaTeX
3104 // didn't understand "Mapping=tex-text", while XeTeX
3105 // understood both. With most recent versions, both
3106 // variants are understood by both engines. However,
3107 // we want to provide support for at least TeXLive 2009
3108 // (for XeTeX; LuaTeX is only supported as of v.2)
3109 string const texmapping =
3110 (features.runparams().flavor == OutputParams::XETEX) ?
3111 "Mapping=tex-text" : "Ligatures=TeX";
3112 if (fontsRoman() != "default") {
3113 os << "\\setmainfont[" << texmapping;
3114 if (fonts_old_figures)
3115 os << ",Numbers=OldStyle";
3116 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3118 if (fontsSans() != "default") {
3119 string const sans = parseFontName(fontsSans());
3120 if (fontsSansScale() != 100)
3121 os << "\\setsansfont[Scale="
3122 << float(fontsSansScale()) / 100
3123 << "," << texmapping << "]{"
3126 os << "\\setsansfont[" << texmapping << "]{"
3129 if (fontsTypewriter() != "default") {
3130 string const mono = parseFontName(fontsTypewriter());
3131 if (fontsTypewriterScale() != 100)
3132 os << "\\setmonofont[Scale="
3133 << float(fontsTypewriterScale()) / 100
3137 os << "\\setmonofont{"
3144 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
3145 bool const dryrun = features.runparams().dryrun;
3146 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3147 bool const nomath = (fontsMath() == "default");
3150 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3151 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3155 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3156 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3157 nomath, fontsSansScale());
3159 // MONOSPACED/TYPEWRITER
3160 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3161 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3162 nomath, fontsTypewriterScale());
3165 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3166 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3173 Encoding const & BufferParams::encoding() const
3175 // Main encoding for LaTeX output.
3177 // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740).
3178 // As the "flavor" is only known once export started, this
3179 // cannot be handled here. Instead, runparams.encoding is set
3180 // to ASCII in Buffer::makeLaTeXFile (for export)
3181 // and Buffer::writeLaTeXSource (for preview).
3183 return *(encodings.fromLyXName("utf8-plain"));
3184 if (inputenc == "auto" || inputenc == "default")
3185 return *language->encoding();
3186 Encoding const * const enc = encodings.fromLyXName(inputenc);
3189 LYXERR0("Unknown inputenc value `" << inputenc
3190 << "'. Using `auto' instead.");
3191 return *language->encoding();
3195 bool BufferParams::addCiteEngine(string const & engine)
3197 LayoutModuleList::const_iterator it = cite_engine_.begin();
3198 LayoutModuleList::const_iterator en = cite_engine_.end();
3199 for (; it != en; ++it)
3202 cite_engine_.push_back(engine);
3207 bool BufferParams::addCiteEngine(vector<string> const & engine)
3209 vector<string>::const_iterator it = engine.begin();
3210 vector<string>::const_iterator en = engine.end();
3212 for (; it != en; ++it)
3213 if (!addCiteEngine(*it))
3219 string const & BufferParams::defaultBiblioStyle() const
3221 return documentClass().defaultBiblioStyle();
3225 bool const & BufferParams::fullAuthorList() const
3227 return documentClass().fullAuthorList();
3231 void BufferParams::setCiteEngine(string const & engine)
3234 addCiteEngine(engine);
3238 void BufferParams::setCiteEngine(vector<string> const & engine)
3241 addCiteEngine(engine);
3245 vector<string> BufferParams::citeCommands() const
3247 static CitationStyle const default_style;
3248 vector<string> commands =
3249 documentClass().citeCommands(citeEngineType());
3250 if (commands.empty())
3251 commands.push_back(default_style.cmd);
3256 vector<CitationStyle> BufferParams::citeStyles() const
3258 static CitationStyle const default_style;
3259 vector<CitationStyle> styles =
3260 documentClass().citeStyles(citeEngineType());
3262 styles.push_back(default_style);