2 * \file BufferParams.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Alfredo Braunstein
7 * \author Lars Gullik Bjønnes
8 * \author Jean-Marc Lasgouttes
10 * \author André Pönitz
11 * \author Martin Vermeer
13 * Full author contact details are available in file CREDITS.
18 #include "BufferParams.h"
21 #include "LayoutFile.h"
22 #include "BranchList.h"
24 #include "buffer_funcs.h"
28 #include "Converter.h"
31 #include "IndicesList.h"
33 #include "LaTeXFeatures.h"
34 #include "LaTeXFonts.h"
35 #include "ModuleList.h"
39 #include "OutputParams.h"
43 #include "PDFOptions.h"
45 #include "frontends/alert.h"
47 #include "insets/InsetListingsParams.h"
49 #include "support/convert.h"
50 #include "support/debug.h"
51 #include "support/docstream.h"
52 #include "support/FileName.h"
53 #include "support/filetools.h"
54 #include "support/gettext.h"
55 #include "support/Messages.h"
56 #include "support/mutex.h"
57 #include "support/Package.h"
58 #include "support/Translator.h"
59 #include "support/lstrings.h"
65 using namespace lyx::support;
68 static char const * const string_paragraph_separation[] = {
73 static char const * const string_quotes_language[] = {
74 "english", "swedish", "german", "polish", "french", "danish", ""
78 static char const * const string_papersize[] = {
79 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
80 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
81 "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
82 "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
83 "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
88 static char const * const string_orientation[] = {
89 "portrait", "landscape", ""
93 static char const * const tex_graphics[] = {
94 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
95 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
96 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
97 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
108 // Paragraph separation
109 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
112 ParSepTranslator const init_parseptranslator()
114 ParSepTranslator translator
115 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
116 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
121 ParSepTranslator const & parseptranslator()
123 static ParSepTranslator const translator =
124 init_parseptranslator();
130 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
133 QuotesLangTranslator const init_quoteslangtranslator()
135 QuotesLangTranslator translator
136 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
137 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
138 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
139 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
140 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
141 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
146 QuotesLangTranslator const & quoteslangtranslator()
148 static QuotesLangTranslator const translator =
149 init_quoteslangtranslator();
155 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
158 static PaperSizeTranslator initPaperSizeTranslator()
160 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
161 translator.addPair(string_papersize[1], PAPER_CUSTOM);
162 translator.addPair(string_papersize[2], PAPER_USLETTER);
163 translator.addPair(string_papersize[3], PAPER_USLEGAL);
164 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
165 translator.addPair(string_papersize[5], PAPER_A0);
166 translator.addPair(string_papersize[6], PAPER_A1);
167 translator.addPair(string_papersize[7], PAPER_A2);
168 translator.addPair(string_papersize[8], PAPER_A3);
169 translator.addPair(string_papersize[9], PAPER_A4);
170 translator.addPair(string_papersize[10], PAPER_A5);
171 translator.addPair(string_papersize[11], PAPER_A6);
172 translator.addPair(string_papersize[12], PAPER_B0);
173 translator.addPair(string_papersize[13], PAPER_B1);
174 translator.addPair(string_papersize[14], PAPER_B2);
175 translator.addPair(string_papersize[15], PAPER_B3);
176 translator.addPair(string_papersize[16], PAPER_B4);
177 translator.addPair(string_papersize[17], PAPER_B5);
178 translator.addPair(string_papersize[18], PAPER_B6);
179 translator.addPair(string_papersize[19], PAPER_C0);
180 translator.addPair(string_papersize[20], PAPER_C1);
181 translator.addPair(string_papersize[21], PAPER_C2);
182 translator.addPair(string_papersize[22], PAPER_C3);
183 translator.addPair(string_papersize[23], PAPER_C4);
184 translator.addPair(string_papersize[24], PAPER_C5);
185 translator.addPair(string_papersize[25], PAPER_C6);
186 translator.addPair(string_papersize[26], PAPER_JISB0);
187 translator.addPair(string_papersize[27], PAPER_JISB1);
188 translator.addPair(string_papersize[28], PAPER_JISB2);
189 translator.addPair(string_papersize[29], PAPER_JISB3);
190 translator.addPair(string_papersize[30], PAPER_JISB4);
191 translator.addPair(string_papersize[31], PAPER_JISB5);
192 translator.addPair(string_papersize[32], PAPER_JISB6);
197 PaperSizeTranslator const & papersizetranslator()
199 static PaperSizeTranslator const translator =
200 initPaperSizeTranslator();
206 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
209 PaperOrientationTranslator const init_paperorientationtranslator()
211 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
212 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
217 PaperOrientationTranslator const & paperorientationtranslator()
219 static PaperOrientationTranslator const translator =
220 init_paperorientationtranslator();
226 typedef Translator<int, PageSides> SidesTranslator;
229 SidesTranslator const init_sidestranslator()
231 SidesTranslator translator(1, OneSide);
232 translator.addPair(2, TwoSides);
237 SidesTranslator const & sidestranslator()
239 static SidesTranslator const translator = init_sidestranslator();
245 typedef Translator<int, BufferParams::Package> PackageTranslator;
248 PackageTranslator const init_packagetranslator()
250 PackageTranslator translator(0, BufferParams::package_off);
251 translator.addPair(1, BufferParams::package_auto);
252 translator.addPair(2, BufferParams::package_on);
257 PackageTranslator const & packagetranslator()
259 static PackageTranslator const translator =
260 init_packagetranslator();
266 typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator;
269 CiteEngineTypeTranslator const init_citeenginetypetranslator()
271 CiteEngineTypeTranslator translator("authoryear", ENGINE_TYPE_AUTHORYEAR);
272 translator.addPair("numerical", ENGINE_TYPE_NUMERICAL);
273 translator.addPair("default", ENGINE_TYPE_DEFAULT);
278 CiteEngineTypeTranslator const & citeenginetypetranslator()
280 static CiteEngineTypeTranslator const translator =
281 init_citeenginetypetranslator();
287 typedef Translator<string, Spacing::Space> SpaceTranslator;
290 SpaceTranslator const init_spacetranslator()
292 SpaceTranslator translator("default", Spacing::Default);
293 translator.addPair("single", Spacing::Single);
294 translator.addPair("onehalf", Spacing::Onehalf);
295 translator.addPair("double", Spacing::Double);
296 translator.addPair("other", Spacing::Other);
301 SpaceTranslator const & spacetranslator()
303 static SpaceTranslator const translator = init_spacetranslator();
310 class BufferParams::Impl
315 AuthorList authorlist;
316 BranchList branchlist;
317 Bullet temp_bullets[4];
318 Bullet user_defined_bullets[4];
319 IndicesList indiceslist;
321 /** This is the amount of space used for paragraph_separation "skip",
322 * and for detached paragraphs in "indented" documents.
326 PDFOptions pdfoptions;
327 LayoutFileIndex baseClass_;
331 BufferParams::Impl::Impl()
332 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
334 // set initial author
336 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
341 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
344 return new BufferParams::Impl(*ptr);
348 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
354 BufferParams::BufferParams()
357 setBaseClass(defaultBaseclass());
358 cite_engine_.push_back("basic");
359 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
361 paragraph_separation = ParagraphIndentSeparation;
362 quotes_language = InsetQuotes::EnglishQuotes;
363 fontsize = "default";
366 papersize = PAPER_DEFAULT;
367 orientation = ORIENTATION_PORTRAIT;
368 use_geometry = false;
369 biblio_style = "plain";
370 use_bibtopic = false;
372 track_changes = false;
373 output_changes = false;
374 use_default_options = true;
375 maintain_unincluded_children = false;
378 language = default_language;
380 fonts_roman[0] = "default";
381 fonts_roman[1] = "default";
382 fonts_sans[0] = "default";
383 fonts_sans[1] = "default";
384 fonts_typewriter[0] = "default";
385 fonts_typewriter[1] = "default";
386 fonts_math[0] = "auto";
387 fonts_math[1] = "auto";
388 fonts_default_family = "default";
389 useNonTeXFonts = false;
390 fonts_expert_sc = false;
391 fonts_old_figures = false;
392 fonts_sans_scale[0] = 100;
393 fonts_sans_scale[1] = 100;
394 fonts_typewriter_scale[0] = 100;
395 fonts_typewriter_scale[1] = 100;
397 lang_package = "default";
398 graphics_driver = "default";
399 default_output_format = "default";
400 bibtex_command = "default";
401 index_command = "default";
404 listings_params = string();
405 pagestyle = "default";
406 suppress_date = false;
407 justification = true;
408 // no color is the default (white)
409 backgroundcolor = lyx::rgbFromHexName("#ffffff");
410 isbackgroundcolor = false;
411 // no color is the default (black)
412 fontcolor = lyx::rgbFromHexName("#000000");
414 // light gray is the default font color for greyed-out notes
415 notefontcolor = lyx::rgbFromHexName("#cccccc");
416 boxbgcolor = lyx::rgbFromHexName("#ff0000");
417 compressed = lyxrc.save_compressed;
418 for (int iter = 0; iter < 4; ++iter) {
419 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
420 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
423 indiceslist().addDefault(B_("Index"));
424 html_be_strict = false;
425 html_math_output = MathML;
426 html_math_img_scale = 1.0;
427 html_css_as_file = false;
428 display_pixel_ratio = 1.0;
433 // map current author
434 author_map_[pimpl_->authorlist.get(0).bufferId()] = 0;
438 docstring BufferParams::B_(string const & l10n) const
440 LASSERT(language, return from_utf8(l10n));
441 return getMessages(language->code()).get(l10n);
445 BufferParams::Package BufferParams::use_package(std::string const & p) const
447 PackageMap::const_iterator it = use_packages.find(p);
448 if (it == use_packages.end())
454 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
460 map<string, string> const & BufferParams::auto_packages()
462 static map<string, string> packages;
463 if (packages.empty()) {
464 // We could have a race condition here that two threads
465 // discover an empty map at the same time and want to fill
466 // it, but that is no problem, since the same contents is
467 // filled in twice then. Having the locker inside the
468 // packages.empty() condition has the advantage that we
469 // don't need the mutex overhead for simple reading.
471 Mutex::Locker locker(&mutex);
472 // adding a package here implies a file format change!
473 packages["amsmath"] =
474 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
475 packages["amssymb"] =
476 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
478 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
480 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
481 packages["mathdots"] =
482 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
483 packages["mathtools"] =
484 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
486 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
487 packages["stackrel"] =
488 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
489 packages["stmaryrd"] =
490 N_("The LaTeX package stmaryrd is only used if symbols from the St Mary's Road symbol font for theoretical computer science are inserted into formulas");
491 packages["undertilde"] =
492 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
498 AuthorList & BufferParams::authors()
500 return pimpl_->authorlist;
504 AuthorList const & BufferParams::authors() const
506 return pimpl_->authorlist;
510 void BufferParams::addAuthor(Author a)
512 author_map_[a.bufferId()] = pimpl_->authorlist.record(a);
516 BranchList & BufferParams::branchlist()
518 return pimpl_->branchlist;
522 BranchList const & BufferParams::branchlist() const
524 return pimpl_->branchlist;
528 IndicesList & BufferParams::indiceslist()
530 return pimpl_->indiceslist;
534 IndicesList const & BufferParams::indiceslist() const
536 return pimpl_->indiceslist;
540 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
542 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
543 return pimpl_->temp_bullets[index];
547 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
549 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
550 return pimpl_->temp_bullets[index];
554 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
556 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
557 return pimpl_->user_defined_bullets[index];
561 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
563 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
564 return pimpl_->user_defined_bullets[index];
568 Spacing & BufferParams::spacing()
570 return pimpl_->spacing;
574 Spacing const & BufferParams::spacing() const
576 return pimpl_->spacing;
580 PDFOptions & BufferParams::pdfoptions()
582 return pimpl_->pdfoptions;
586 PDFOptions const & BufferParams::pdfoptions() const
588 return pimpl_->pdfoptions;
592 HSpace const & BufferParams::getIndentation() const
594 return pimpl_->indentation;
598 void BufferParams::setIndentation(HSpace const & indent)
600 pimpl_->indentation = indent;
604 VSpace const & BufferParams::getDefSkip() const
606 return pimpl_->defskip;
610 void BufferParams::setDefSkip(VSpace const & vs)
612 // DEFSKIP will cause an infinite loop
613 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
614 pimpl_->defskip = vs;
618 string BufferParams::readToken(Lexer & lex, string const & token,
619 FileName const & filepath)
623 if (token == "\\textclass") {
625 string const classname = lex.getString();
626 // if there exists a local layout file, ignore the system one
627 // NOTE: in this case, the textclass (.cls file) is assumed to
630 LayoutFileList & bcl = LayoutFileList::get();
631 if (!filepath.empty()) {
632 // If classname is an absolute path, the document is
633 // using a local layout file which could not be accessed
634 // by a relative path. In this case the path is correct
635 // even if the document was moved to a different
636 // location. However, we will have a problem if the
637 // document was generated on a different platform.
638 bool isabsolute = FileName::isAbsolute(classname);
639 string const classpath = onlyPath(classname);
640 string const path = isabsolute ? classpath
641 : FileName(addPath(filepath.absFileName(),
642 classpath)).realPath();
643 string const oldpath = isabsolute ? string()
644 : FileName(addPath(origin, classpath)).realPath();
645 tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
647 // that returns non-empty if a "local" layout file is found.
649 result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
650 from_utf8(filepath.absFileName())));
653 setBaseClass(onlyFileName(tcp));
655 setBaseClass(onlyFileName(classname));
656 // We assume that a tex class exists for local or unknown
657 // layouts so this warning, will only be given for system layouts.
658 if (!baseClass()->isTeXClassAvailable()) {
659 docstring const desc =
660 translateIfPossible(from_utf8(baseClass()->description()));
661 docstring const prereqs =
662 from_utf8(baseClass()->prerequisites());
663 docstring const msg =
664 bformat(_("The selected document class\n"
666 "requires external files that are not available.\n"
667 "The document class can still be used, but the\n"
668 "document cannot be compiled until the following\n"
669 "prerequisites are installed:\n"
671 "See section 3.1.2.2 (Class Availability) of the\n"
672 "User's Guide for more information."), desc, prereqs);
673 frontend::Alert::warning(_("Document class not available"),
676 } else if (token == "\\origin") {
678 origin = lex.getString();
679 string const sysdirprefix = "/systemlyxdir/";
680 if (prefixIs(origin, sysdirprefix)) {
681 origin.replace(0, sysdirprefix.length() - 1,
682 package().system_support().absFileName());
684 } else if (token == "\\begin_preamble") {
686 } else if (token == "\\begin_local_layout") {
687 readLocalLayout(lex, false);
688 } else if (token == "\\begin_forced_local_layout") {
689 readLocalLayout(lex, true);
690 } else if (token == "\\begin_modules") {
692 } else if (token == "\\begin_removed_modules") {
693 readRemovedModules(lex);
694 } else if (token == "\\begin_includeonly") {
695 readIncludeonly(lex);
696 } else if (token == "\\maintain_unincluded_children") {
697 lex >> maintain_unincluded_children;
698 } else if (token == "\\options") {
700 options = lex.getString();
701 } else if (token == "\\use_default_options") {
702 lex >> use_default_options;
703 } else if (token == "\\master") {
705 master = lex.getString();
706 if (!filepath.empty() && FileName::isAbsolute(origin)) {
707 bool const isabs = FileName::isAbsolute(master);
708 FileName const abspath(isabs ? master : origin + master);
709 bool const moved = filepath != FileName(origin);
710 if (moved && abspath.exists()) {
711 docstring const path = isabs
713 : from_utf8(abspath.realPath());
714 docstring const refpath =
715 from_utf8(filepath.absFileName());
716 master = to_utf8(makeRelPath(path, refpath));
719 } else if (token == "\\suppress_date") {
720 lex >> suppress_date;
721 } else if (token == "\\justification") {
722 lex >> justification;
723 } else if (token == "\\language") {
725 } else if (token == "\\language_package") {
727 lang_package = lex.getString();
728 } else if (token == "\\inputencoding") {
730 } else if (token == "\\graphics") {
731 readGraphicsDriver(lex);
732 } else if (token == "\\default_output_format") {
733 lex >> default_output_format;
734 } else if (token == "\\bibtex_command") {
736 bibtex_command = lex.getString();
737 } else if (token == "\\index_command") {
739 index_command = lex.getString();
740 } else if (token == "\\fontencoding") {
742 fontenc = lex.getString();
743 } else if (token == "\\font_roman") {
744 lex >> fonts_roman[0];
745 lex >> fonts_roman[1];
746 } else if (token == "\\font_sans") {
747 lex >> fonts_sans[0];
748 lex >> fonts_sans[1];
749 } else if (token == "\\font_typewriter") {
750 lex >> fonts_typewriter[0];
751 lex >> fonts_typewriter[1];
752 } else if (token == "\\font_math") {
753 lex >> fonts_math[0];
754 lex >> fonts_math[1];
755 } else if (token == "\\font_default_family") {
756 lex >> fonts_default_family;
757 } else if (token == "\\use_non_tex_fonts") {
758 lex >> useNonTeXFonts;
759 } else if (token == "\\font_sc") {
760 lex >> fonts_expert_sc;
761 } else if (token == "\\font_osf") {
762 lex >> fonts_old_figures;
763 } else if (token == "\\font_sf_scale") {
764 lex >> fonts_sans_scale[0];
765 lex >> fonts_sans_scale[1];
766 } else if (token == "\\font_tt_scale") {
767 lex >> fonts_typewriter_scale[0];
768 lex >> fonts_typewriter_scale[1];
769 } else if (token == "\\font_cjk") {
771 } else if (token == "\\paragraph_separation") {
774 paragraph_separation = parseptranslator().find(parsep);
775 } else if (token == "\\paragraph_indentation") {
777 string indentation = lex.getString();
778 pimpl_->indentation = HSpace(indentation);
779 } else if (token == "\\defskip") {
781 string const defskip = lex.getString();
782 pimpl_->defskip = VSpace(defskip);
783 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
785 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
786 } else if (token == "\\quotes_language") {
789 quotes_language = quoteslangtranslator().find(quotes_lang);
790 } else if (token == "\\papersize") {
793 papersize = papersizetranslator().find(ppsize);
794 } else if (token == "\\use_geometry") {
796 } else if (token == "\\use_package") {
801 use_package(package, packagetranslator().find(use));
802 } else if (token == "\\cite_engine") {
804 vector<string> engine = getVectorFromString(lex.getString());
805 setCiteEngine(engine);
806 } else if (token == "\\cite_engine_type") {
809 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
810 } else if (token == "\\biblio_style") {
812 biblio_style = lex.getString();
813 } else if (token == "\\use_bibtopic") {
815 } else if (token == "\\use_indices") {
817 } else if (token == "\\tracking_changes") {
818 lex >> track_changes;
819 } else if (token == "\\output_changes") {
820 lex >> output_changes;
821 } else if (token == "\\branch") {
823 docstring branch = lex.getDocString();
824 branchlist().add(branch);
827 string const tok = lex.getString();
828 if (tok == "\\end_branch")
830 Branch * branch_ptr = branchlist().find(branch);
831 if (tok == "\\selected") {
834 branch_ptr->setSelected(lex.getInteger());
836 if (tok == "\\filename_suffix") {
839 branch_ptr->setFileNameSuffix(lex.getInteger());
841 if (tok == "\\color") {
843 string color = lex.getString();
845 branch_ptr->setColor(color);
846 // Update also the Color table:
848 color = lcolor.getX11Name(Color_background);
850 lcolor.setColor(to_utf8(branch), color);
853 } else if (token == "\\index") {
855 docstring index = lex.getDocString();
857 indiceslist().add(index);
860 string const tok = lex.getString();
861 if (tok == "\\end_index")
863 Index * index_ptr = indiceslist().find(index);
864 if (tok == "\\shortcut") {
866 shortcut = lex.getDocString();
868 index_ptr->setShortcut(shortcut);
870 if (tok == "\\color") {
872 string color = lex.getString();
874 index_ptr->setColor(color);
875 // Update also the Color table:
877 color = lcolor.getX11Name(Color_background);
879 if (!shortcut.empty())
880 lcolor.setColor(to_utf8(shortcut), color);
883 } else if (token == "\\author") {
885 istringstream ss(lex.getString());
889 } else if (token == "\\paperorientation") {
892 orientation = paperorientationtranslator().find(orient);
893 } else if (token == "\\backgroundcolor") {
895 backgroundcolor = lyx::rgbFromHexName(lex.getString());
896 isbackgroundcolor = true;
897 } else if (token == "\\fontcolor") {
899 fontcolor = lyx::rgbFromHexName(lex.getString());
901 } else if (token == "\\notefontcolor") {
903 string color = lex.getString();
904 notefontcolor = lyx::rgbFromHexName(color);
905 lcolor.setColor("notefontcolor", color);
906 } else if (token == "\\boxbgcolor") {
908 string color = lex.getString();
909 boxbgcolor = lyx::rgbFromHexName(color);
910 lcolor.setColor("boxbgcolor", color);
911 } else if (token == "\\paperwidth") {
913 } else if (token == "\\paperheight") {
915 } else if (token == "\\leftmargin") {
917 } else if (token == "\\topmargin") {
919 } else if (token == "\\rightmargin") {
921 } else if (token == "\\bottommargin") {
923 } else if (token == "\\headheight") {
925 } else if (token == "\\headsep") {
927 } else if (token == "\\footskip") {
929 } else if (token == "\\columnsep") {
931 } else if (token == "\\paperfontsize") {
933 } else if (token == "\\papercolumns") {
935 } else if (token == "\\listings_params") {
938 listings_params = InsetListingsParams(par).params();
939 } else if (token == "\\papersides") {
942 sides = sidestranslator().find(psides);
943 } else if (token == "\\paperpagestyle") {
945 } else if (token == "\\bullet") {
947 } else if (token == "\\bulletLaTeX") {
948 readBulletsLaTeX(lex);
949 } else if (token == "\\secnumdepth") {
951 } else if (token == "\\tocdepth") {
953 } else if (token == "\\spacing") {
957 if (nspacing == "other") {
960 spacing().set(spacetranslator().find(nspacing), tmp_val);
961 } else if (token == "\\float_placement") {
962 lex >> float_placement;
964 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
965 string toktmp = pdfoptions().readToken(lex, token);
966 if (!toktmp.empty()) {
967 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
971 } else if (token == "\\html_math_output") {
974 html_math_output = static_cast<MathOutput>(temp);
975 } else if (token == "\\html_be_strict") {
976 lex >> html_be_strict;
977 } else if (token == "\\html_css_as_file") {
978 lex >> html_css_as_file;
979 } else if (token == "\\html_math_img_scale") {
980 lex >> html_math_img_scale;
981 } else if (token == "\\html_latex_start") {
983 html_latex_start = lex.getString();
984 } else if (token == "\\html_latex_end") {
986 html_latex_end = lex.getString();
987 } else if (token == "\\output_sync") {
989 } else if (token == "\\output_sync_macro") {
990 lex >> output_sync_macro;
991 } else if (token == "\\use_refstyle") {
994 lyxerr << "BufferParams::readToken(): Unknown token: " <<
1004 // Quote argument if it contains spaces
1005 string quoteIfNeeded(string const & str) {
1006 if (contains(str, ' '))
1007 return "\"" + str + "\"";
1013 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
1015 // The top of the file is written by the buffer.
1016 // Prints out the buffer info into the .lyx file given by file
1018 // the document directory
1019 // use realPath() instead of absFileName() for comparing
1020 // so we can catch also eventually used symbolic parts of the path.
1021 string filepath = buf->fileName().onlyPath().realPath();
1022 string const sysdir = package().system_support().realPath();
1023 if (prefixIs(filepath, sysdir)) {
1024 filepath.replace(0, sysdir.length(), "/systemlyxdir/");
1025 // Remove eventually added superfluous "/"
1026 filepath = subst(filepath, "//", "/");
1028 else if (!lyxrc.save_origin)
1029 filepath = "unavailable";
1030 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1033 os << "\\textclass "
1034 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1035 baseClass()->name()), "layout"))
1038 // then the preamble
1039 if (!preamble.empty()) {
1040 // remove '\n' from the end of preamble
1041 string const tmppreamble = rtrim(preamble, "\n");
1042 os << "\\begin_preamble\n"
1044 << "\n\\end_preamble\n";
1048 if (!options.empty()) {
1049 os << "\\options " << options << '\n';
1052 // use the class options defined in the layout?
1053 os << "\\use_default_options "
1054 << convert<string>(use_default_options) << "\n";
1056 // the master document
1057 if (!master.empty()) {
1058 os << "\\master " << master << '\n';
1062 if (!removed_modules_.empty()) {
1063 os << "\\begin_removed_modules" << '\n';
1064 list<string>::const_iterator it = removed_modules_.begin();
1065 list<string>::const_iterator en = removed_modules_.end();
1066 for (; it != en; ++it)
1068 os << "\\end_removed_modules" << '\n';
1072 if (!layout_modules_.empty()) {
1073 os << "\\begin_modules" << '\n';
1074 LayoutModuleList::const_iterator it = layout_modules_.begin();
1075 LayoutModuleList::const_iterator en = layout_modules_.end();
1076 for (; it != en; ++it)
1078 os << "\\end_modules" << '\n';
1082 if (!included_children_.empty()) {
1083 os << "\\begin_includeonly" << '\n';
1084 list<string>::const_iterator it = included_children_.begin();
1085 list<string>::const_iterator en = included_children_.end();
1086 for (; it != en; ++it)
1088 os << "\\end_includeonly" << '\n';
1090 os << "\\maintain_unincluded_children "
1091 << convert<string>(maintain_unincluded_children) << '\n';
1093 // local layout information
1094 string const local_layout = getLocalLayout(false);
1095 if (!local_layout.empty()) {
1096 // remove '\n' from the end
1097 string const tmplocal = rtrim(local_layout, "\n");
1098 os << "\\begin_local_layout\n"
1100 << "\n\\end_local_layout\n";
1102 string const forced_local_layout = getLocalLayout(true);
1103 if (!forced_local_layout.empty()) {
1104 // remove '\n' from the end
1105 string const tmplocal = rtrim(forced_local_layout, "\n");
1106 os << "\\begin_forced_local_layout\n"
1108 << "\n\\end_forced_local_layout\n";
1111 // then the text parameters
1112 if (language != ignore_language)
1113 os << "\\language " << language->lang() << '\n';
1114 os << "\\language_package " << lang_package
1115 << "\n\\inputencoding " << inputenc
1116 << "\n\\fontencoding " << fontenc
1117 << "\n\\font_roman \"" << fonts_roman[0]
1118 << "\" \"" << fonts_roman[1] << '"'
1119 << "\n\\font_sans \"" << fonts_sans[0]
1120 << "\" \"" << fonts_sans[1] << '"'
1121 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1122 << "\" \"" << fonts_typewriter[1] << '"'
1123 << "\n\\font_math \"" << fonts_math[0]
1124 << "\" \"" << fonts_math[1] << '"'
1125 << "\n\\font_default_family " << fonts_default_family
1126 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1127 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1128 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1129 << "\n\\font_sf_scale " << fonts_sans_scale[0]
1130 << ' ' << fonts_sans_scale[1]
1131 << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1132 << ' ' << fonts_typewriter_scale[1]
1134 if (!fonts_cjk.empty()) {
1135 os << "\\font_cjk " << fonts_cjk << '\n';
1137 os << "\\graphics " << graphics_driver << '\n';
1138 os << "\\default_output_format " << default_output_format << '\n';
1139 os << "\\output_sync " << output_sync << '\n';
1140 if (!output_sync_macro.empty())
1141 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1142 os << "\\bibtex_command " << bibtex_command << '\n';
1143 os << "\\index_command " << index_command << '\n';
1145 if (!float_placement.empty()) {
1146 os << "\\float_placement " << float_placement << '\n';
1148 os << "\\paperfontsize " << fontsize << '\n';
1150 spacing().writeFile(os);
1151 pdfoptions().writeFile(os);
1153 os << "\\papersize " << string_papersize[papersize]
1154 << "\n\\use_geometry " << convert<string>(use_geometry);
1155 map<string, string> const & packages = auto_packages();
1156 for (map<string, string>::const_iterator it = packages.begin();
1157 it != packages.end(); ++it)
1158 os << "\n\\use_package " << it->first << ' '
1159 << use_package(it->first);
1161 os << "\n\\cite_engine ";
1163 if (!cite_engine_.empty()) {
1164 LayoutModuleList::const_iterator be = cite_engine_.begin();
1165 LayoutModuleList::const_iterator en = cite_engine_.end();
1166 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1175 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1176 << "\n\\biblio_style " << biblio_style
1177 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1178 << "\n\\use_indices " << convert<string>(use_indices)
1179 << "\n\\paperorientation " << string_orientation[orientation]
1180 << "\n\\suppress_date " << convert<string>(suppress_date)
1181 << "\n\\justification " << convert<string>(justification)
1182 << "\n\\use_refstyle " << use_refstyle
1184 if (isbackgroundcolor == true)
1185 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1186 if (isfontcolor == true)
1187 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1188 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1189 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1190 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1191 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1193 BranchList::const_iterator it = branchlist().begin();
1194 BranchList::const_iterator end = branchlist().end();
1195 for (; it != end; ++it) {
1196 os << "\\branch " << to_utf8(it->branch())
1197 << "\n\\selected " << it->isSelected()
1198 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1199 << "\n\\color " << lyx::X11hexname(it->color())
1204 IndicesList::const_iterator iit = indiceslist().begin();
1205 IndicesList::const_iterator iend = indiceslist().end();
1206 for (; iit != iend; ++iit) {
1207 os << "\\index " << to_utf8(iit->index())
1208 << "\n\\shortcut " << to_utf8(iit->shortcut())
1209 << "\n\\color " << lyx::X11hexname(iit->color())
1214 if (!paperwidth.empty())
1215 os << "\\paperwidth "
1216 << VSpace(paperwidth).asLyXCommand() << '\n';
1217 if (!paperheight.empty())
1218 os << "\\paperheight "
1219 << VSpace(paperheight).asLyXCommand() << '\n';
1220 if (!leftmargin.empty())
1221 os << "\\leftmargin "
1222 << VSpace(leftmargin).asLyXCommand() << '\n';
1223 if (!topmargin.empty())
1224 os << "\\topmargin "
1225 << VSpace(topmargin).asLyXCommand() << '\n';
1226 if (!rightmargin.empty())
1227 os << "\\rightmargin "
1228 << VSpace(rightmargin).asLyXCommand() << '\n';
1229 if (!bottommargin.empty())
1230 os << "\\bottommargin "
1231 << VSpace(bottommargin).asLyXCommand() << '\n';
1232 if (!headheight.empty())
1233 os << "\\headheight "
1234 << VSpace(headheight).asLyXCommand() << '\n';
1235 if (!headsep.empty())
1237 << VSpace(headsep).asLyXCommand() << '\n';
1238 if (!footskip.empty())
1240 << VSpace(footskip).asLyXCommand() << '\n';
1241 if (!columnsep.empty())
1242 os << "\\columnsep "
1243 << VSpace(columnsep).asLyXCommand() << '\n';
1244 os << "\\secnumdepth " << secnumdepth
1245 << "\n\\tocdepth " << tocdepth
1246 << "\n\\paragraph_separation "
1247 << string_paragraph_separation[paragraph_separation];
1248 if (!paragraph_separation)
1249 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1251 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1252 os << "\n\\quotes_language "
1253 << string_quotes_language[quotes_language]
1254 << "\n\\papercolumns " << columns
1255 << "\n\\papersides " << sides
1256 << "\n\\paperpagestyle " << pagestyle << '\n';
1257 if (!listings_params.empty())
1258 os << "\\listings_params \"" <<
1259 InsetListingsParams(listings_params).encodedString() << "\"\n";
1260 for (int i = 0; i < 4; ++i) {
1261 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1262 if (user_defined_bullet(i).getFont() != -1) {
1263 os << "\\bullet " << i << " "
1264 << user_defined_bullet(i).getFont() << " "
1265 << user_defined_bullet(i).getCharacter() << " "
1266 << user_defined_bullet(i).getSize() << "\n";
1270 os << "\\bulletLaTeX " << i << " \""
1271 << lyx::to_ascii(user_defined_bullet(i).getText())
1277 os << "\\tracking_changes " << convert<string>(track_changes) << '\n'
1278 << "\\html_math_output " << html_math_output << '\n'
1279 << "\\html_css_as_file " << html_css_as_file << '\n'
1280 // \output_changes is output at a distance from \tracking changes as a
1281 // workaround to bug #9841: both parameters can be seen as per-user
1282 // preferences and therefore can cause undesirable merge conflicts, in a
1283 // multi-author setting, if it were treated as a single block by the
1284 // version control system.
1285 << "\\output_changes " << convert<string>(output_changes) << '\n'
1286 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1288 if (html_math_img_scale != 1.0)
1289 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1290 if (!html_latex_start.empty())
1291 os << "\\html_latex_start " << html_latex_start << '\n';
1292 if (!html_latex_end.empty())
1293 os << "\\html_latex_end " << html_latex_end << '\n';
1295 os << pimpl_->authorlist;
1299 void BufferParams::validate(LaTeXFeatures & features) const
1301 features.require(documentClass().requires());
1303 if (columns > 1 && language->rightToLeft())
1304 features.require("rtloutputdblcol");
1306 if (output_changes) {
1307 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1308 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1309 LaTeXFeatures::isAvailable("xcolor");
1311 switch (features.runparams().flavor) {
1312 case OutputParams::LATEX:
1313 case OutputParams::DVILUATEX:
1315 features.require("ct-dvipost");
1316 features.require("dvipost");
1317 } else if (xcolorulem) {
1318 features.require("ct-xcolor-ulem");
1319 features.require("ulem");
1320 features.require("xcolor");
1322 features.require("ct-none");
1325 case OutputParams::LUATEX:
1326 case OutputParams::PDFLATEX:
1327 case OutputParams::XETEX:
1329 features.require("ct-xcolor-ulem");
1330 features.require("ulem");
1331 features.require("xcolor");
1332 // improves color handling in PDF output
1333 features.require("pdfcolmk");
1335 features.require("ct-none");
1343 // Floats with 'Here definitely' as default setting.
1344 if (float_placement.find('H') != string::npos)
1345 features.require("float");
1347 for (PackageMap::const_iterator it = use_packages.begin();
1348 it != use_packages.end(); ++it) {
1349 if (it->first == "amsmath") {
1350 // AMS Style is at document level
1351 if (it->second == package_on ||
1352 features.isProvided("amsmath"))
1353 features.require(it->first);
1354 } else if (it->second == package_on)
1355 features.require(it->first);
1358 // Document-level line spacing
1359 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1360 features.require("setspace");
1362 // the bullet shapes are buffer level not paragraph level
1363 // so they are tested here
1364 for (int i = 0; i < 4; ++i) {
1365 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1367 int const font = user_defined_bullet(i).getFont();
1369 int const c = user_defined_bullet(i).getCharacter();
1375 features.require("latexsym");
1377 } else if (font == 1) {
1378 features.require("amssymb");
1379 } else if (font >= 2 && font <= 5) {
1380 features.require("pifont");
1384 if (pdfoptions().use_hyperref) {
1385 features.require("hyperref");
1386 // due to interferences with babel and hyperref, the color package has to
1387 // be loaded after hyperref when hyperref is used with the colorlinks
1388 // option, see http://www.lyx.org/trac/ticket/5291
1389 if (pdfoptions().colorlinks)
1390 features.require("color");
1392 if (!listings_params.empty()) {
1393 // do not test validity because listings_params is
1394 // supposed to be valid
1396 InsetListingsParams(listings_params).separatedParams(true);
1397 // we can't support all packages, but we should load the color package
1398 if (par.find("\\color", 0) != string::npos)
1399 features.require("color");
1402 // some languages are only available via polyglossia
1403 if ((features.runparams().flavor == OutputParams::XETEX
1404 || features.runparams().flavor == OutputParams::LUATEX)
1405 && (features.hasPolyglossiaExclusiveLanguages()
1407 features.require("polyglossia");
1409 if (useNonTeXFonts && fontsMath() != "auto")
1410 features.require("unicode-math");
1412 if (!language->requires().empty())
1413 features.require(language->requires());
1417 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1418 FileName const & filepath) const
1420 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1421 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1422 // \RequirePackage to do so, rather than the normal \usepackage
1423 // Do not try to load any other package before the document class, unless you
1424 // have a thorough understanding of the LATEX internals and know exactly what you
1426 if (features.mustProvide("fix-cm"))
1427 os << "\\RequirePackage{fix-cm}\n";
1428 // Likewise for fixltx2e. If other packages conflict with this policy,
1429 // treat it as a package bug (and report it!)
1430 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1431 if (features.mustProvide("fixltx2e"))
1432 os << "\\RequirePackage{fixltx2e}\n";
1434 os << "\\documentclass";
1436 DocumentClass const & tclass = documentClass();
1438 ostringstream clsoptions; // the document class options.
1440 if (tokenPos(tclass.opt_fontsize(),
1441 '|', fontsize) >= 0) {
1442 // only write if existing in list (and not default)
1443 clsoptions << fontsize << "pt,";
1446 // all paper sizes except of A4, A5, B5 and the US sizes need the
1448 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1449 && papersize != PAPER_USLETTER
1450 && papersize != PAPER_USLEGAL
1451 && papersize != PAPER_USEXECUTIVE
1452 && papersize != PAPER_A4
1453 && papersize != PAPER_A5
1454 && papersize != PAPER_B5;
1456 if (!use_geometry) {
1457 switch (papersize) {
1459 clsoptions << "a4paper,";
1461 case PAPER_USLETTER:
1462 clsoptions << "letterpaper,";
1465 clsoptions << "a5paper,";
1468 clsoptions << "b5paper,";
1470 case PAPER_USEXECUTIVE:
1471 clsoptions << "executivepaper,";
1474 clsoptions << "legalpaper,";
1508 if (sides != tclass.sides()) {
1511 clsoptions << "oneside,";
1514 clsoptions << "twoside,";
1520 if (columns != tclass.columns()) {
1522 clsoptions << "twocolumn,";
1524 clsoptions << "onecolumn,";
1528 && orientation == ORIENTATION_LANDSCAPE)
1529 clsoptions << "landscape,";
1531 // language should be a parameter to \documentclass
1532 if (language->babel() == "hebrew"
1533 && default_language->babel() != "hebrew")
1534 // This seems necessary
1535 features.useLanguage(default_language);
1537 ostringstream language_options;
1538 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1539 bool const use_polyglossia = features.usePolyglossia();
1540 bool const global = lyxrc.language_global_options;
1541 if (use_babel || (use_polyglossia && global)) {
1542 language_options << features.getBabelLanguages();
1543 if (!language->babel().empty()) {
1544 if (!language_options.str().empty())
1545 language_options << ',';
1546 language_options << language->babel();
1548 if (global && !features.needBabelLangOptions()
1549 && !language_options.str().empty())
1550 clsoptions << language_options.str() << ',';
1553 // the predefined options from the layout
1554 if (use_default_options && !tclass.options().empty())
1555 clsoptions << tclass.options() << ',';
1557 // the user-defined options
1558 if (!options.empty()) {
1559 clsoptions << options << ',';
1562 string strOptions(clsoptions.str());
1563 if (!strOptions.empty()) {
1564 strOptions = rtrim(strOptions, ",");
1566 os << '[' << from_utf8(strOptions) << ']';
1569 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1570 // end of \documentclass defs
1572 // if we use fontspec or newtxmath, we have to load the AMS packages here
1573 string const ams = features.loadAMSPackages();
1574 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1575 bool const use_newtxmath =
1576 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1577 ot1, false, false) == "newtxmath";
1578 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1579 os << from_ascii(ams);
1581 if (useNonTeXFonts) {
1582 os << "\\usepackage{fontspec}\n";
1583 if (features.mustProvide("unicode-math")
1584 && features.isAvailable("unicode-math"))
1585 os << "\\usepackage{unicode-math}\n";
1588 // font selection must be done before loading fontenc.sty
1589 string const fonts = loadFonts(features);
1591 os << from_utf8(fonts);
1593 if (fonts_default_family != "default")
1594 os << "\\renewcommand{\\familydefault}{\\"
1595 << from_ascii(fonts_default_family) << "}\n";
1597 // set font encoding
1598 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1599 if (!useNonTeXFonts && !features.isProvided("fontenc")
1600 && font_encoding() != "default") {
1601 // get main font encodings
1602 vector<string> fontencs = font_encodings();
1603 // get font encodings of secondary languages
1604 features.getFontEncodings(fontencs);
1605 if (!fontencs.empty()) {
1606 os << "\\usepackage["
1607 << from_ascii(getStringFromVector(fontencs))
1612 // handle inputenc etc.
1613 writeEncodingPreamble(os, features);
1616 if (!features.runparams().includeall && !included_children_.empty()) {
1617 os << "\\includeonly{";
1618 list<string>::const_iterator it = included_children_.begin();
1619 list<string>::const_iterator en = included_children_.end();
1621 for (; it != en; ++it) {
1622 string incfile = *it;
1623 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1624 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1626 if (!features.runparams().nice)
1628 // \includeonly doesn't want an extension
1629 incfile = changeExtension(incfile, string());
1630 incfile = support::latex_path(incfile);
1631 if (!incfile.empty()) {
1634 os << from_utf8(incfile);
1641 if (!features.isProvided("geometry")
1642 && (use_geometry || nonstandard_papersize)) {
1643 odocstringstream ods;
1644 if (!getGraphicsDriver("geometry").empty())
1645 ods << getGraphicsDriver("geometry");
1646 if (orientation == ORIENTATION_LANDSCAPE)
1647 ods << ",landscape";
1648 switch (papersize) {
1650 if (!paperwidth.empty())
1651 ods << ",paperwidth="
1652 << from_ascii(paperwidth);
1653 if (!paperheight.empty())
1654 ods << ",paperheight="
1655 << from_ascii(paperheight);
1657 case PAPER_USLETTER:
1658 ods << ",letterpaper";
1661 ods << ",legalpaper";
1663 case PAPER_USEXECUTIVE:
1664 ods << ",executivepaper";
1753 docstring const g_options = trim(ods.str(), ",");
1754 os << "\\usepackage";
1755 if (!g_options.empty())
1756 os << '[' << g_options << ']';
1757 os << "{geometry}\n";
1758 // output this only if use_geometry is true
1760 os << "\\geometry{verbose";
1761 if (!topmargin.empty())
1762 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1763 if (!bottommargin.empty())
1764 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1765 if (!leftmargin.empty())
1766 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1767 if (!rightmargin.empty())
1768 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1769 if (!headheight.empty())
1770 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1771 if (!headsep.empty())
1772 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1773 if (!footskip.empty())
1774 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1775 if (!columnsep.empty())
1776 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1779 } else if (orientation == ORIENTATION_LANDSCAPE
1780 || papersize != PAPER_DEFAULT) {
1781 features.require("papersize");
1784 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1785 if (pagestyle == "fancy")
1786 os << "\\usepackage{fancyhdr}\n";
1787 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1790 // only output when the background color is not default
1791 if (isbackgroundcolor == true) {
1792 // only require color here, the background color will be defined
1793 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1795 features.require("color");
1796 features.require("pagecolor");
1799 // only output when the font color is not default
1800 if (isfontcolor == true) {
1801 // only require color here, the font color will be defined
1802 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1804 features.require("color");
1805 features.require("fontcolor");
1808 // Only if class has a ToC hierarchy
1809 if (tclass.hasTocLevels()) {
1810 if (secnumdepth != tclass.secnumdepth()) {
1811 os << "\\setcounter{secnumdepth}{"
1815 if (tocdepth != tclass.tocdepth()) {
1816 os << "\\setcounter{tocdepth}{"
1822 if (paragraph_separation) {
1823 // when skip separation
1824 switch (getDefSkip().kind()) {
1825 case VSpace::SMALLSKIP:
1826 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1828 case VSpace::MEDSKIP:
1829 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1831 case VSpace::BIGSKIP:
1832 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1834 case VSpace::LENGTH:
1835 os << "\\setlength{\\parskip}{"
1836 << from_utf8(getDefSkip().length().asLatexString())
1839 default: // should never happen // Then delete it.
1840 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1843 os << "\\setlength{\\parindent}{0pt}\n";
1845 // when separation by indentation
1846 // only output something when a width is given
1847 if (getIndentation().asLyXCommand() != "default") {
1848 os << "\\setlength{\\parindent}{"
1849 << from_utf8(getIndentation().asLatexCommand())
1854 // Now insert the LyX specific LaTeX commands...
1855 docstring lyxpreamble;
1856 features.resolveAlternatives();
1859 if (!output_sync_macro.empty())
1860 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1861 else if (features.runparams().flavor == OutputParams::LATEX)
1862 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1863 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1864 lyxpreamble += "\\synctex=-1\n";
1867 // The package options (via \PassOptionsToPackage)
1868 lyxpreamble += from_ascii(features.getPackageOptions());
1870 // due to interferences with babel and hyperref, the color package has to
1871 // be loaded (when it is not already loaded) before babel when hyperref
1872 // is used with the colorlinks option, see
1873 // http://www.lyx.org/trac/ticket/5291
1874 // we decided therefore to load color always before babel, see
1875 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1876 lyxpreamble += from_ascii(features.getColorOptions());
1878 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1879 // we have to call babel before
1881 && (features.isRequired("jurabib")
1882 || features.isRequired("hyperref")
1883 || features.isRequired("varioref")
1884 || features.isRequired("vietnamese")
1885 || features.isRequired("japanese"))) {
1887 lyxpreamble += from_utf8(features.getBabelPresettings());
1888 lyxpreamble += from_utf8(babelCall(language_options.str(),
1889 features.needBabelLangOptions())) + '\n';
1890 lyxpreamble += from_utf8(features.getBabelPostsettings());
1893 // The optional packages;
1894 lyxpreamble += from_ascii(features.getPackages());
1896 // Additional Indices
1897 if (features.isRequired("splitidx")) {
1898 IndicesList::const_iterator iit = indiceslist().begin();
1899 IndicesList::const_iterator iend = indiceslist().end();
1900 for (; iit != iend; ++iit) {
1901 pair<docstring, docstring> indexname_latex =
1902 features.runparams().encoding->latexString(iit->index(),
1903 features.runparams().dryrun);
1904 if (!indexname_latex.second.empty()) {
1905 // issue a warning about omitted characters
1906 // FIXME: should be passed to the error dialog
1907 frontend::Alert::warning(_("Uncodable characters"),
1908 bformat(_("The following characters that are used in an index name are not\n"
1909 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1910 indexname_latex.second));
1912 lyxpreamble += "\\newindex[";
1913 lyxpreamble += indexname_latex.first;
1914 lyxpreamble += "]{";
1915 lyxpreamble += escape(iit->shortcut());
1916 lyxpreamble += "}\n";
1921 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1924 // * Hyperref manual: "Make sure it comes last of your loaded
1925 // packages, to give it a fighting chance of not being over-written,
1926 // since its job is to redefine many LaTeX commands."
1927 // * Email from Heiko Oberdiek: "It is usually better to load babel
1928 // before hyperref. Then hyperref has a chance to detect babel.
1929 // * Has to be loaded before the "LyX specific LaTeX commands" to
1930 // avoid errors with algorithm floats.
1931 // use hyperref explicitly if it is required
1932 if (features.isRequired("hyperref")) {
1933 // pass what we have to stream here, since we need
1934 // to access the stream itself in PDFOptions.
1937 OutputParams tmp_params = features.runparams();
1938 pdfoptions().writeLaTeX(tmp_params, os,
1939 features.isProvided("hyperref"));
1940 // set back for the rest
1941 lyxpreamble.clear();
1942 // correctly break URLs with hyperref and dvi output
1943 if (features.runparams().flavor == OutputParams::LATEX
1944 && features.isAvailable("breakurl"))
1945 lyxpreamble += "\\usepackage{breakurl}\n";
1946 } else if (features.isRequired("nameref"))
1947 // hyperref loads this automatically
1948 lyxpreamble += "\\usepackage{nameref}\n";
1950 // bibtopic needs to be loaded after hyperref.
1951 // the dot provides the aux file naming which LyX can detect.
1952 if (features.mustProvide("bibtopic"))
1953 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1955 // Will be surrounded by \makeatletter and \makeatother when not empty
1956 docstring atlyxpreamble;
1958 // Some macros LyX will need
1959 docstring tmppreamble(features.getMacros());
1961 if (!tmppreamble.empty())
1962 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1963 "LyX specific LaTeX commands.\n"
1964 + tmppreamble + '\n';
1966 // the text class specific preamble
1967 tmppreamble = features.getTClassPreamble();
1968 if (!tmppreamble.empty())
1969 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1970 "Textclass specific LaTeX commands.\n"
1971 + tmppreamble + '\n';
1973 // suppress date if selected
1974 // use \@ifundefined because we cannot be sure that every document class
1975 // has a \date command
1977 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1979 /* the user-defined preamble */
1980 if (!containsOnly(preamble, " \n\t")) {
1982 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1983 "User specified LaTeX commands.\n";
1985 // Check if the user preamble contains uncodable glyphs
1986 docstring const u_preamble = from_utf8(preamble);
1987 odocstringstream user_preamble;
1988 docstring uncodable_glyphs;
1989 Encoding const * const enc = features.runparams().encoding;
1991 for (size_t n = 0; n < u_preamble.size(); ++n) {
1992 char_type c = u_preamble[n];
1993 if (!enc->encodable(c)) {
1994 docstring const glyph(1, c);
1995 LYXERR0("Uncodable character '"
1997 << "' in user preamble!");
1998 uncodable_glyphs += glyph;
1999 if (features.runparams().dryrun) {
2000 user_preamble << "<" << _("LyX Warning: ")
2001 << _("uncodable character") << " '";
2002 user_preamble.put(c);
2003 user_preamble << "'>";
2006 user_preamble.put(c);
2009 user_preamble << u_preamble;
2011 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2012 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2013 frontend::Alert::warning(
2014 _("Uncodable character in user preamble"),
2016 _("The user preamble of your document contains glyphs "
2017 "that are unknown in the current document encoding "
2018 "(namely %1$s).\nThese glyphs are omitted "
2019 " from the output, which may result in "
2020 "incomplete output."
2021 "\n\nPlease select an appropriate "
2022 "document encoding\n"
2023 "(such as utf8) or change the "
2024 "preamble code accordingly."),
2027 atlyxpreamble += user_preamble.str() + '\n';
2030 // footmisc must be loaded after setspace
2031 // Load it here to avoid clashes with footmisc loaded in the user
2032 // preamble. For that reason we also pass the options via
2033 // \PassOptionsToPackage in getPreamble() and not here.
2034 if (features.mustProvide("footmisc"))
2035 atlyxpreamble += "\\usepackage{footmisc}\n";
2037 // subfig loads internally the LaTeX package "caption". As
2038 // caption is a very popular package, users will load it in
2039 // the preamble. Therefore we must load subfig behind the
2040 // user-defined preamble and check if the caption package was
2041 // loaded or not. For the case that caption is loaded before
2042 // subfig, there is the subfig option "caption=false". This
2043 // option also works when a koma-script class is used and
2044 // koma's own caption commands are used instead of caption. We
2045 // use \PassOptionsToPackage here because the user could have
2046 // already loaded subfig in the preamble.
2047 if (features.isRequired("subfig")) {
2048 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
2049 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2050 "\\usepackage{subfig}\n";
2053 // Itemize bullet settings need to be last in case the user
2054 // defines their own bullets that use a package included
2055 // in the user-defined preamble -- ARRae
2056 // Actually it has to be done much later than that
2057 // since some packages like frenchb make modifications
2058 // at \begin{document} time -- JMarc
2059 docstring bullets_def;
2060 for (int i = 0; i < 4; ++i) {
2061 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2062 if (bullets_def.empty())
2063 bullets_def += "\\AtBeginDocument{\n";
2064 bullets_def += " \\def\\labelitemi";
2066 // `i' is one less than the item to modify
2073 bullets_def += "ii";
2079 bullets_def += '{' +
2080 user_defined_bullet(i).getText()
2085 if (!bullets_def.empty())
2086 atlyxpreamble += bullets_def + "}\n\n";
2088 if (!atlyxpreamble.empty())
2089 lyxpreamble += "\n\\makeatletter\n"
2090 + atlyxpreamble + "\\makeatother\n\n";
2092 // We try to load babel late, in case it interferes with other packages.
2093 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
2094 // called after babel, though.
2095 if (use_babel && !features.isRequired("jurabib")
2096 && !features.isRequired("hyperref")
2097 && !features.isRequired("varioref")
2098 && !features.isRequired("vietnamese")
2099 && !features.isRequired("japanese")) {
2101 lyxpreamble += from_utf8(features.getBabelPresettings());
2102 lyxpreamble += from_utf8(babelCall(language_options.str(),
2103 features.needBabelLangOptions())) + '\n';
2104 lyxpreamble += from_utf8(features.getBabelPostsettings());
2106 if (features.isRequired("bicaption"))
2107 lyxpreamble += "\\usepackage{bicaption}\n";
2108 if (!listings_params.empty() || features.isRequired("listings"))
2109 lyxpreamble += "\\usepackage{listings}\n";
2110 if (!listings_params.empty()) {
2111 lyxpreamble += "\\lstset{";
2112 // do not test validity because listings_params is
2113 // supposed to be valid
2115 InsetListingsParams(listings_params).separatedParams(true);
2116 lyxpreamble += from_utf8(par);
2117 lyxpreamble += "}\n";
2120 // xunicode needs to be loaded at least after amsmath, amssymb,
2121 // esint and the other packages that provide special glyphs
2122 if (features.runparams().flavor == OutputParams::XETEX
2124 lyxpreamble += "\\usepackage{xunicode}\n";
2126 // Polyglossia must be loaded last
2127 if (use_polyglossia) {
2129 lyxpreamble += "\\usepackage{polyglossia}\n";
2130 // set the main language
2131 lyxpreamble += "\\setdefaultlanguage";
2132 if (!language->polyglossiaOpts().empty())
2133 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
2134 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
2135 // now setup the other languages
2136 std::map<std::string, std::string> const polylangs =
2137 features.getPolyglossiaLanguages();
2138 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
2139 mit != polylangs.end() ; ++mit) {
2140 lyxpreamble += "\\setotherlanguage";
2141 if (!mit->second.empty())
2142 lyxpreamble += "[" + from_ascii(mit->second) + "]";
2143 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
2147 // Load custom language package here
2148 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2149 if (lang_package == "default")
2150 lyxpreamble += from_utf8(lyxrc.language_custom_package);
2152 lyxpreamble += from_utf8(lang_package);
2153 lyxpreamble += '\n';
2156 docstring const i18npreamble =
2157 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2158 if (!i18npreamble.empty())
2159 lyxpreamble += i18npreamble + '\n';
2167 void BufferParams::useClassDefaults()
2169 DocumentClass const & tclass = documentClass();
2171 sides = tclass.sides();
2172 columns = tclass.columns();
2173 pagestyle = tclass.pagestyle();
2174 use_default_options = true;
2175 // Only if class has a ToC hierarchy
2176 if (tclass.hasTocLevels()) {
2177 secnumdepth = tclass.secnumdepth();
2178 tocdepth = tclass.tocdepth();
2183 bool BufferParams::hasClassDefaults() const
2185 DocumentClass const & tclass = documentClass();
2187 return sides == tclass.sides()
2188 && columns == tclass.columns()
2189 && pagestyle == tclass.pagestyle()
2190 && use_default_options
2191 && secnumdepth == tclass.secnumdepth()
2192 && tocdepth == tclass.tocdepth();
2196 DocumentClass const & BufferParams::documentClass() const
2198 return *doc_class_.get();
2202 DocumentClassConstPtr BufferParams::documentClassPtr() const
2208 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2210 // evil, but this function is evil
2211 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2215 bool BufferParams::setBaseClass(string const & classname)
2217 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2218 LayoutFileList & bcl = LayoutFileList::get();
2219 if (!bcl.haveClass(classname)) {
2221 bformat(_("The layout file:\n"
2223 "could not be found. A default textclass with default\n"
2224 "layouts will be used. LyX will not be able to produce\n"
2226 from_utf8(classname));
2227 frontend::Alert::error(_("Document class not found"), s);
2228 bcl.addEmptyClass(classname);
2231 bool const success = bcl[classname].load();
2234 bformat(_("Due to some error in it, the layout file:\n"
2236 "could not be loaded. A default textclass with default\n"
2237 "layouts will be used. LyX will not be able to produce\n"
2239 from_utf8(classname));
2240 frontend::Alert::error(_("Could not load class"), s);
2241 bcl.addEmptyClass(classname);
2244 pimpl_->baseClass_ = classname;
2245 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2250 LayoutFile const * BufferParams::baseClass() const
2252 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2253 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2259 LayoutFileIndex const & BufferParams::baseClassID() const
2261 return pimpl_->baseClass_;
2265 void BufferParams::makeDocumentClass(bool const clone)
2270 LayoutModuleList mods;
2271 LayoutModuleList::iterator it = layout_modules_.begin();
2272 LayoutModuleList::iterator en = layout_modules_.end();
2273 for (; it != en; ++it)
2274 mods.push_back(*it);
2276 it = cite_engine_.begin();
2277 en = cite_engine_.end();
2278 for (; it != en; ++it)
2279 mods.push_back(*it);
2281 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2283 TextClass::ReturnValues success = TextClass::OK;
2284 if (!forced_local_layout_.empty())
2285 success = doc_class_->read(forced_local_layout_, TextClass::MODULE);
2286 if (!local_layout_.empty() &&
2287 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2288 success = doc_class_->read(local_layout_, TextClass::MODULE);
2289 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2290 docstring const msg = _("Error reading internal layout information");
2291 frontend::Alert::warning(_("Read Error"), msg);
2296 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2298 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2302 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2304 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2308 std::string BufferParams::getLocalLayout(bool forced) const
2311 return doc_class_->forcedLayouts();
2313 return local_layout_;
2317 void BufferParams::setLocalLayout(string const & layout, bool forced)
2320 forced_local_layout_ = layout;
2322 local_layout_ = layout;
2326 bool BufferParams::addLayoutModule(string const & modName)
2328 LayoutModuleList::const_iterator it = layout_modules_.begin();
2329 LayoutModuleList::const_iterator end = layout_modules_.end();
2330 for (; it != end; ++it)
2333 layout_modules_.push_back(modName);
2338 string BufferParams::bufferFormat() const
2340 string format = documentClass().outputFormat();
2341 if (format == "latex") {
2343 return "xetex"; // actually "xetex or luatex"
2344 if (encoding().package() == Encoding::japanese)
2351 bool BufferParams::isExportable(string const & format) const
2353 vector<string> backs = backends();
2354 for (vector<string>::const_iterator it = backs.begin();
2355 it != backs.end(); ++it)
2356 if (theConverters().isReachable(*it, format))
2362 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2364 vector<string> const backs = backends();
2365 set<string> excludes;
2366 if (useNonTeXFonts) {
2367 excludes.insert("latex");
2368 excludes.insert("pdflatex");
2370 vector<Format const *> result =
2371 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2372 for (vector<string>::const_iterator it = backs.begin() + 1;
2373 it != backs.end(); ++it) {
2374 vector<Format const *> r =
2375 theConverters().getReachable(*it, only_viewable, false, excludes);
2376 result.insert(result.end(), r.begin(), r.end());
2382 bool BufferParams::isExportableFormat(string const & format) const
2384 typedef vector<Format const *> Formats;
2386 formats = exportableFormats(true);
2387 Formats::const_iterator fit = formats.begin();
2388 Formats::const_iterator end = formats.end();
2389 for (; fit != end ; ++fit) {
2390 if ((*fit)->name() == format)
2397 vector<string> BufferParams::backends() const
2400 string const buffmt = bufferFormat();
2402 // FIXME: Don't hardcode format names here, but use a flag
2403 if (buffmt == "latex") {
2404 if (!useNonTeXFonts) {
2405 v.push_back("pdflatex");
2406 v.push_back("latex");
2408 v.push_back("luatex");
2409 v.push_back("dviluatex");
2410 v.push_back("xetex");
2411 } else if (buffmt == "xetex") {
2412 v.push_back("xetex");
2413 // FIXME: need to test all languages (bug 8205)
2414 if (!language || !language->isPolyglossiaExclusive()) {
2415 v.push_back("luatex");
2416 v.push_back("dviluatex");
2419 v.push_back(buffmt);
2421 v.push_back("xhtml");
2422 v.push_back("text");
2428 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2430 string const dformat = (format.empty() || format == "default") ?
2431 getDefaultOutputFormat() : format;
2432 DefaultFlavorCache::const_iterator it =
2433 default_flavors_.find(dformat);
2435 if (it != default_flavors_.end())
2438 OutputParams::FLAVOR result = OutputParams::LATEX;
2440 // FIXME It'd be better not to hardcode this, but to do
2441 // something with formats.
2442 if (dformat == "xhtml")
2443 result = OutputParams::HTML;
2444 else if (dformat == "text")
2445 result = OutputParams::TEXT;
2446 else if (dformat == "lyx")
2447 result = OutputParams::LYX;
2448 else if (dformat == "pdflatex")
2449 result = OutputParams::PDFLATEX;
2450 else if (dformat == "xetex")
2451 result = OutputParams::XETEX;
2452 else if (dformat == "luatex")
2453 result = OutputParams::LUATEX;
2454 else if (dformat == "dviluatex")
2455 result = OutputParams::DVILUATEX;
2457 // Try to determine flavor of default output format
2458 vector<string> backs = backends();
2459 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2460 // Get shortest path to format
2461 Graph::EdgePath path;
2462 for (vector<string>::const_iterator it = backs.begin();
2463 it != backs.end(); ++it) {
2464 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2465 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2470 result = theConverters().getFlavor(path);
2473 // cache this flavor
2474 default_flavors_[dformat] = result;
2479 string BufferParams::getDefaultOutputFormat() const
2481 if (!default_output_format.empty()
2482 && default_output_format != "default")
2483 return default_output_format;
2485 || encoding().package() == Encoding::japanese) {
2486 vector<Format const *> const formats = exportableFormats(true);
2487 if (formats.empty())
2489 // return the first we find
2490 return formats.front()->name();
2493 return lyxrc.default_otf_view_format;
2494 return lyxrc.default_view_format;
2497 Font const BufferParams::getFont() const
2499 FontInfo f = documentClass().defaultfont();
2500 if (fonts_default_family == "rmdefault")
2501 f.setFamily(ROMAN_FAMILY);
2502 else if (fonts_default_family == "sfdefault")
2503 f.setFamily(SANS_FAMILY);
2504 else if (fonts_default_family == "ttdefault")
2505 f.setFamily(TYPEWRITER_FAMILY);
2506 return Font(f, language);
2510 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const & qs) const
2512 return quoteslangtranslator().find(qs);
2516 bool BufferParams::isLatex() const
2518 return documentClass().outputType() == LATEX;
2522 bool BufferParams::isLiterate() const
2524 return documentClass().outputType() == LITERATE;
2528 bool BufferParams::isDocBook() const
2530 return documentClass().outputType() == DOCBOOK;
2534 void BufferParams::readPreamble(Lexer & lex)
2536 if (lex.getString() != "\\begin_preamble")
2537 lyxerr << "Error (BufferParams::readPreamble):"
2538 "consistency check failed." << endl;
2540 preamble = lex.getLongString("\\end_preamble");
2544 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2546 string const expected = forced ? "\\begin_forced_local_layout" :
2547 "\\begin_local_layout";
2548 if (lex.getString() != expected)
2549 lyxerr << "Error (BufferParams::readLocalLayout):"
2550 "consistency check failed." << endl;
2553 forced_local_layout_ =
2554 lex.getLongString("\\end_forced_local_layout");
2556 local_layout_ = lex.getLongString("\\end_local_layout");
2560 bool BufferParams::setLanguage(string const & lang)
2562 Language const *new_language = languages.getLanguage(lang);
2563 if (!new_language) {
2564 // Language lang was not found
2567 language = new_language;
2572 void BufferParams::readLanguage(Lexer & lex)
2574 if (!lex.next()) return;
2576 string const tmptok = lex.getString();
2578 // check if tmptok is part of tex_babel in tex-defs.h
2579 if (!setLanguage(tmptok)) {
2580 // Language tmptok was not found
2581 language = default_language;
2582 lyxerr << "Warning: Setting language `"
2583 << tmptok << "' to `" << language->lang()
2589 void BufferParams::readGraphicsDriver(Lexer & lex)
2594 string const tmptok = lex.getString();
2595 // check if tmptok is part of tex_graphics in tex_defs.h
2598 string const test = tex_graphics[n++];
2600 if (test == tmptok) {
2601 graphics_driver = tmptok;
2606 "Warning: graphics driver `$$Token' not recognized!\n"
2607 " Setting graphics driver to `default'.\n");
2608 graphics_driver = "default";
2615 void BufferParams::readBullets(Lexer & lex)
2620 int const index = lex.getInteger();
2622 int temp_int = lex.getInteger();
2623 user_defined_bullet(index).setFont(temp_int);
2624 temp_bullet(index).setFont(temp_int);
2626 user_defined_bullet(index).setCharacter(temp_int);
2627 temp_bullet(index).setCharacter(temp_int);
2629 user_defined_bullet(index).setSize(temp_int);
2630 temp_bullet(index).setSize(temp_int);
2634 void BufferParams::readBulletsLaTeX(Lexer & lex)
2636 // The bullet class should be able to read this.
2639 int const index = lex.getInteger();
2641 docstring const temp_str = lex.getDocString();
2643 user_defined_bullet(index).setText(temp_str);
2644 temp_bullet(index).setText(temp_str);
2648 void BufferParams::readModules(Lexer & lex)
2650 if (!lex.eatLine()) {
2651 lyxerr << "Error (BufferParams::readModules):"
2652 "Unexpected end of input." << endl;
2656 string mod = lex.getString();
2657 if (mod == "\\end_modules")
2659 addLayoutModule(mod);
2665 void BufferParams::readRemovedModules(Lexer & lex)
2667 if (!lex.eatLine()) {
2668 lyxerr << "Error (BufferParams::readRemovedModules):"
2669 "Unexpected end of input." << endl;
2673 string mod = lex.getString();
2674 if (mod == "\\end_removed_modules")
2676 removed_modules_.push_back(mod);
2679 // now we want to remove any removed modules that were previously
2680 // added. normally, that will be because default modules were added in
2681 // setBaseClass(), which gets called when \textclass is read at the
2682 // start of the read.
2683 list<string>::const_iterator rit = removed_modules_.begin();
2684 list<string>::const_iterator const ren = removed_modules_.end();
2685 for (; rit != ren; ++rit) {
2686 LayoutModuleList::iterator const mit = layout_modules_.begin();
2687 LayoutModuleList::iterator const men = layout_modules_.end();
2688 LayoutModuleList::iterator found = find(mit, men, *rit);
2691 layout_modules_.erase(found);
2696 void BufferParams::readIncludeonly(Lexer & lex)
2698 if (!lex.eatLine()) {
2699 lyxerr << "Error (BufferParams::readIncludeonly):"
2700 "Unexpected end of input." << endl;
2704 string child = lex.getString();
2705 if (child == "\\end_includeonly")
2707 included_children_.push_back(child);
2713 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2715 switch (papersize) {
2717 // could be anything, so don't guess
2719 case PAPER_CUSTOM: {
2720 if (purpose == XDVI && !paperwidth.empty() &&
2721 !paperheight.empty()) {
2722 // heightxwidth<unit>
2723 string first = paperwidth;
2724 string second = paperheight;
2725 if (orientation == ORIENTATION_LANDSCAPE)
2728 return first.erase(first.length() - 2)
2734 // dvips and dvipdfm do not know this
2735 if (purpose == DVIPS || purpose == DVIPDFM)
2739 if (purpose == DVIPS || purpose == DVIPDFM)
2743 if (purpose == DVIPS || purpose == DVIPDFM)
2753 if (purpose == DVIPS || purpose == DVIPDFM)
2757 if (purpose == DVIPS || purpose == DVIPDFM)
2761 if (purpose == DVIPS || purpose == DVIPDFM)
2765 if (purpose == DVIPS || purpose == DVIPDFM)
2769 if (purpose == DVIPS || purpose == DVIPDFM)
2773 // dvipdfm does not know this
2774 if (purpose == DVIPDFM)
2778 if (purpose == DVIPDFM)
2782 if (purpose == DVIPS || purpose == DVIPDFM)
2786 if (purpose == DVIPS || 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)
2841 case PAPER_USEXECUTIVE:
2842 // dvipdfm does not know this
2843 if (purpose == DVIPDFM)
2848 case PAPER_USLETTER:
2850 if (purpose == XDVI)
2857 string const BufferParams::dvips_options() const
2861 // If the class loads the geometry package, we do not know which
2862 // paper size is used, since we do not set it (bug 7013).
2863 // Therefore we must not specify any argument here.
2864 // dvips gets the correct paper size via DVI specials in this case
2865 // (if the class uses the geometry package correctly).
2866 if (documentClass().provides("geometry"))
2870 && papersize == PAPER_CUSTOM
2871 && !lyxrc.print_paper_dimension_flag.empty()
2872 && !paperwidth.empty()
2873 && !paperheight.empty()) {
2874 // using a custom papersize
2875 result = lyxrc.print_paper_dimension_flag;
2876 result += ' ' + paperwidth;
2877 result += ',' + paperheight;
2879 string const paper_option = paperSizeName(DVIPS);
2880 if (!paper_option.empty() && (paper_option != "letter" ||
2881 orientation != ORIENTATION_LANDSCAPE)) {
2882 // dvips won't accept -t letter -t landscape.
2883 // In all other cases, include the paper size
2885 result = lyxrc.print_paper_flag;
2886 result += ' ' + paper_option;
2889 if (orientation == ORIENTATION_LANDSCAPE &&
2890 papersize != PAPER_CUSTOM)
2891 result += ' ' + lyxrc.print_landscape_flag;
2896 string const BufferParams::font_encoding() const
2898 return font_encodings().empty() ? "default" : font_encodings().back();
2902 vector<string> const BufferParams::font_encodings() const
2904 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2906 vector<string> fontencs;
2908 // "default" means "no explicit font encoding"
2909 if (doc_fontenc != "default") {
2910 fontencs = getVectorFromString(doc_fontenc);
2911 if (!language->fontenc().empty()
2912 && ascii_lowercase(language->fontenc()) != "none") {
2913 vector<string> fencs = getVectorFromString(language->fontenc());
2914 vector<string>::const_iterator fit = fencs.begin();
2915 for (; fit != fencs.end(); ++fit) {
2916 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
2917 fontencs.push_back(*fit);
2926 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2928 // suppress the babel call if there is no BabelName defined
2929 // for the document language in the lib/languages file and if no
2930 // other languages are used (lang_opts is then empty)
2931 if (lang_opts.empty())
2933 // either a specific language (AsBabelOptions setting in
2934 // lib/languages) or the prefs require the languages to
2935 // be submitted to babel itself (not the class).
2937 return "\\usepackage[" + lang_opts + "]{babel}";
2938 return "\\usepackage{babel}";
2942 docstring BufferParams::getGraphicsDriver(string const & package) const
2946 if (package == "geometry") {
2947 if (graphics_driver == "dvips"
2948 || graphics_driver == "dvipdfm"
2949 || graphics_driver == "pdftex"
2950 || graphics_driver == "vtex")
2951 result = from_ascii(graphics_driver);
2952 else if (graphics_driver == "dvipdfmx")
2953 result = from_ascii("dvipdfm");
2960 void BufferParams::writeEncodingPreamble(otexstream & os,
2961 LaTeXFeatures & features) const
2963 // XeTeX/LuaTeX: (see also #9740)
2964 // With Unicode fonts we use utf8-plain without encoding package.
2965 // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails.
2966 // XeTeX must use ASCII encoding, for LuaTeX, we load
2967 // "luainputenc" (see below).
2968 if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
2971 if (inputenc == "auto") {
2972 string const doc_encoding =
2973 language->encoding()->latexName();
2974 Encoding::Package const package =
2975 language->encoding()->package();
2977 // Create list of inputenc options:
2978 set<string> encodings;
2979 // luainputenc fails with more than one encoding
2980 if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts
2981 // list all input encodings used in the document
2982 encodings = features.getEncodingSet(doc_encoding);
2984 // If the "japanese" package (i.e. pLaTeX) is used,
2985 // inputenc must be omitted.
2986 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2987 if ((!encodings.empty() || package == Encoding::inputenc)
2988 && !features.isRequired("japanese")
2989 && !features.isProvided("inputenc")) {
2990 os << "\\usepackage[";
2991 set<string>::const_iterator it = encodings.begin();
2992 set<string>::const_iterator const end = encodings.end();
2994 os << from_ascii(*it);
2997 for (; it != end; ++it)
2998 os << ',' << from_ascii(*it);
2999 if (package == Encoding::inputenc) {
3000 if (!encodings.empty())
3002 os << from_ascii(doc_encoding);
3004 if (features.runparams().flavor == OutputParams::LUATEX
3005 || features.runparams().flavor == OutputParams::DVILUATEX)
3006 os << "]{luainputenc}\n";
3008 os << "]{inputenc}\n";
3010 if (package == Encoding::CJK || features.mustProvide("CJK")) {
3011 if (language->encoding()->name() == "utf8-cjk"
3012 && LaTeXFeatures::isAvailable("CJKutf8"))
3013 os << "\\usepackage{CJKutf8}\n";
3015 os << "\\usepackage{CJK}\n";
3017 } else if (inputenc != "default") {
3018 switch (encoding().package()) {
3019 case Encoding::none:
3020 case Encoding::japanese:
3022 case Encoding::inputenc:
3023 // do not load inputenc if japanese is used
3024 // or if the class provides inputenc
3025 if (features.isRequired("japanese")
3026 || features.isProvided("inputenc"))
3028 os << "\\usepackage[" << from_ascii(encoding().latexName());
3029 if (features.runparams().flavor == OutputParams::LUATEX
3030 || features.runparams().flavor == OutputParams::DVILUATEX)
3031 os << "]{luainputenc}\n";
3033 os << "]{inputenc}\n";
3036 if (encoding().name() == "utf8-cjk"
3037 && LaTeXFeatures::isAvailable("CJKutf8"))
3038 os << "\\usepackage{CJKutf8}\n";
3040 os << "\\usepackage{CJK}\n";
3043 // Load the CJK package if needed by a secondary language.
3044 // If the main encoding is some variant of UTF8, use CJKutf8.
3045 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
3046 if (encoding().iconvName() == "UTF-8"
3047 && LaTeXFeatures::isAvailable("CJKutf8"))
3048 os << "\\usepackage{CJKutf8}\n";
3050 os << "\\usepackage{CJK}\n";
3056 string const BufferParams::parseFontName(string const & name) const
3058 string mangled = name;
3059 size_t const idx = mangled.find('[');
3060 if (idx == string::npos || idx == 0)
3063 return mangled.substr(0, idx - 1);
3067 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3069 if (fontsRoman() == "default" && fontsSans() == "default"
3070 && fontsTypewriter() == "default"
3071 && (fontsMath() == "default" || fontsMath() == "auto"))
3077 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3078 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3079 * Mapping=tex-text option assures TeX ligatures (such as "--")
3080 * are resolved. Note that tt does not use these ligatures.
3082 * -- add more GUI options?
3083 * -- add more fonts (fonts for other scripts)
3084 * -- if there's a way to find out if a font really supports
3085 * OldStyle, enable/disable the widget accordingly.
3087 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3088 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3089 // However, until v.2 (2010/07/11) fontspec only knew
3090 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3091 // was introduced for both XeTeX and LuaTeX (LuaTeX
3092 // didn't understand "Mapping=tex-text", while XeTeX
3093 // understood both. With most recent versions, both
3094 // variants are understood by both engines. However,
3095 // we want to provide support for at least TeXLive 2009
3096 // (for XeTeX; LuaTeX is only supported as of v.2)
3097 string const texmapping =
3098 (features.runparams().flavor == OutputParams::XETEX) ?
3099 "Mapping=tex-text" : "Ligatures=TeX";
3100 if (fontsRoman() != "default") {
3101 os << "\\setmainfont[" << texmapping;
3102 if (fonts_old_figures)
3103 os << ",Numbers=OldStyle";
3104 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3106 if (fontsSans() != "default") {
3107 string const sans = parseFontName(fontsSans());
3108 if (fontsSansScale() != 100)
3109 os << "\\setsansfont[Scale="
3110 << float(fontsSansScale()) / 100
3111 << "," << texmapping << "]{"
3114 os << "\\setsansfont[" << texmapping << "]{"
3117 if (fontsTypewriter() != "default") {
3118 string const mono = parseFontName(fontsTypewriter());
3119 if (fontsTypewriterScale() != 100)
3120 os << "\\setmonofont[Scale="
3121 << float(fontsTypewriterScale()) / 100
3125 os << "\\setmonofont{"
3132 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
3133 bool const dryrun = features.runparams().dryrun;
3134 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3135 bool const nomath = (fontsMath() == "default");
3138 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3139 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3143 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3144 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3145 nomath, fontsSansScale());
3147 // MONOSPACED/TYPEWRITER
3148 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3149 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3150 nomath, fontsTypewriterScale());
3153 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3154 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3161 Encoding const & BufferParams::encoding() const
3163 // Main encoding for LaTeX output.
3165 // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740).
3166 // As the "flavor" is only known once export started, this
3167 // cannot be handled here. Instead, runparams.encoding is set
3168 // to ASCII in Buffer::makeLaTeXFile (for export)
3169 // and Buffer::writeLaTeXSource (for preview).
3171 return *(encodings.fromLyXName("utf8-plain"));
3172 if (inputenc == "auto" || inputenc == "default")
3173 return *language->encoding();
3174 Encoding const * const enc = encodings.fromLyXName(inputenc);
3177 LYXERR0("Unknown inputenc value `" << inputenc
3178 << "'. Using `auto' instead.");
3179 return *language->encoding();
3183 bool BufferParams::addCiteEngine(string const & engine)
3185 LayoutModuleList::const_iterator it = cite_engine_.begin();
3186 LayoutModuleList::const_iterator en = cite_engine_.end();
3187 for (; it != en; ++it)
3190 cite_engine_.push_back(engine);
3195 bool BufferParams::addCiteEngine(vector<string> const & engine)
3197 vector<string>::const_iterator it = engine.begin();
3198 vector<string>::const_iterator en = engine.end();
3200 for (; it != en; ++it)
3201 if (!addCiteEngine(*it))
3207 string const & BufferParams::defaultBiblioStyle() const
3209 return documentClass().defaultBiblioStyle();
3213 bool const & BufferParams::fullAuthorList() const
3215 return documentClass().fullAuthorList();
3219 void BufferParams::setCiteEngine(string const & engine)
3222 addCiteEngine(engine);
3226 void BufferParams::setCiteEngine(vector<string> const & engine)
3229 addCiteEngine(engine);
3233 vector<string> BufferParams::citeCommands() const
3235 static CitationStyle const default_style;
3236 vector<string> commands =
3237 documentClass().citeCommands(citeEngineType());
3238 if (commands.empty())
3239 commands.push_back(default_style.cmd);
3244 vector<CitationStyle> BufferParams::citeStyles() const
3246 static CitationStyle const default_style;
3247 vector<CitationStyle> styles =
3248 documentClass().citeStyles(citeEngineType());
3250 styles.push_back(default_style);