2 * \file BufferParams.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Alfredo Braunstein
7 * \author Lars Gullik Bjønnes
8 * \author Jean-Marc Lasgouttes
10 * \author André Pönitz
11 * \author Martin Vermeer
13 * Full author contact details are available in file CREDITS.
18 #include "BufferParams.h"
21 #include "LayoutFile.h"
22 #include "BranchList.h"
24 #include "buffer_funcs.h"
28 #include "Converter.h"
31 #include "IndicesList.h"
33 #include "LaTeXFeatures.h"
34 #include "LaTeXFonts.h"
35 #include "ModuleList.h"
39 #include "OutputParams.h"
43 #include "PDFOptions.h"
45 #include "frontends/alert.h"
47 #include "insets/InsetListingsParams.h"
49 #include "support/convert.h"
50 #include "support/debug.h"
51 #include "support/docstream.h"
52 #include "support/FileName.h"
53 #include "support/filetools.h"
54 #include "support/gettext.h"
55 #include "support/Messages.h"
56 #include "support/mutex.h"
57 #include "support/Package.h"
58 #include "support/Translator.h"
59 #include "support/lstrings.h"
65 using namespace lyx::support;
68 static char const * const string_paragraph_separation[] = {
73 static char const * const string_quotes_language[] = {
74 "english", "swedish", "german", "polish", "french", "danish", ""
78 static char const * const string_papersize[] = {
79 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
80 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
81 "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
82 "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
83 "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
88 static char const * const string_orientation[] = {
89 "portrait", "landscape", ""
93 static char const * const tex_graphics[] = {
94 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
95 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
96 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
97 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
108 // Paragraph separation
109 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
112 ParSepTranslator const init_parseptranslator()
114 ParSepTranslator translator
115 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
116 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
121 ParSepTranslator const & parseptranslator()
123 static ParSepTranslator const translator =
124 init_parseptranslator();
130 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
133 QuotesLangTranslator const init_quoteslangtranslator()
135 QuotesLangTranslator translator
136 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
137 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
138 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
139 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
140 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
141 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
146 QuotesLangTranslator const & quoteslangtranslator()
148 static QuotesLangTranslator const translator =
149 init_quoteslangtranslator();
155 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
158 static PaperSizeTranslator initPaperSizeTranslator()
160 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
161 translator.addPair(string_papersize[1], PAPER_CUSTOM);
162 translator.addPair(string_papersize[2], PAPER_USLETTER);
163 translator.addPair(string_papersize[3], PAPER_USLEGAL);
164 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
165 translator.addPair(string_papersize[5], PAPER_A0);
166 translator.addPair(string_papersize[6], PAPER_A1);
167 translator.addPair(string_papersize[7], PAPER_A2);
168 translator.addPair(string_papersize[8], PAPER_A3);
169 translator.addPair(string_papersize[9], PAPER_A4);
170 translator.addPair(string_papersize[10], PAPER_A5);
171 translator.addPair(string_papersize[11], PAPER_A6);
172 translator.addPair(string_papersize[12], PAPER_B0);
173 translator.addPair(string_papersize[13], PAPER_B1);
174 translator.addPair(string_papersize[14], PAPER_B2);
175 translator.addPair(string_papersize[15], PAPER_B3);
176 translator.addPair(string_papersize[16], PAPER_B4);
177 translator.addPair(string_papersize[17], PAPER_B5);
178 translator.addPair(string_papersize[18], PAPER_B6);
179 translator.addPair(string_papersize[19], PAPER_C0);
180 translator.addPair(string_papersize[20], PAPER_C1);
181 translator.addPair(string_papersize[21], PAPER_C2);
182 translator.addPair(string_papersize[22], PAPER_C3);
183 translator.addPair(string_papersize[23], PAPER_C4);
184 translator.addPair(string_papersize[24], PAPER_C5);
185 translator.addPair(string_papersize[25], PAPER_C6);
186 translator.addPair(string_papersize[26], PAPER_JISB0);
187 translator.addPair(string_papersize[27], PAPER_JISB1);
188 translator.addPair(string_papersize[28], PAPER_JISB2);
189 translator.addPair(string_papersize[29], PAPER_JISB3);
190 translator.addPair(string_papersize[30], PAPER_JISB4);
191 translator.addPair(string_papersize[31], PAPER_JISB5);
192 translator.addPair(string_papersize[32], PAPER_JISB6);
197 PaperSizeTranslator const & papersizetranslator()
199 static PaperSizeTranslator const translator =
200 initPaperSizeTranslator();
206 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
209 PaperOrientationTranslator const init_paperorientationtranslator()
211 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
212 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
217 PaperOrientationTranslator const & paperorientationtranslator()
219 static PaperOrientationTranslator const translator =
220 init_paperorientationtranslator();
226 typedef Translator<int, PageSides> SidesTranslator;
229 SidesTranslator const init_sidestranslator()
231 SidesTranslator translator(1, OneSide);
232 translator.addPair(2, TwoSides);
237 SidesTranslator const & sidestranslator()
239 static SidesTranslator const translator = init_sidestranslator();
245 typedef Translator<int, BufferParams::Package> PackageTranslator;
248 PackageTranslator const init_packagetranslator()
250 PackageTranslator translator(0, BufferParams::package_off);
251 translator.addPair(1, BufferParams::package_auto);
252 translator.addPair(2, BufferParams::package_on);
257 PackageTranslator const & packagetranslator()
259 static PackageTranslator const translator =
260 init_packagetranslator();
266 typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator;
269 CiteEngineTypeTranslator const init_citeenginetypetranslator()
271 CiteEngineTypeTranslator translator("authoryear", ENGINE_TYPE_AUTHORYEAR);
272 translator.addPair("numerical", ENGINE_TYPE_NUMERICAL);
273 translator.addPair("default", ENGINE_TYPE_DEFAULT);
278 CiteEngineTypeTranslator const & citeenginetypetranslator()
280 static CiteEngineTypeTranslator const translator =
281 init_citeenginetypetranslator();
287 typedef Translator<string, Spacing::Space> SpaceTranslator;
290 SpaceTranslator const init_spacetranslator()
292 SpaceTranslator translator("default", Spacing::Default);
293 translator.addPair("single", Spacing::Single);
294 translator.addPair("onehalf", Spacing::Onehalf);
295 translator.addPair("double", Spacing::Double);
296 translator.addPair("other", Spacing::Other);
301 SpaceTranslator const & spacetranslator()
303 static SpaceTranslator const translator = init_spacetranslator();
310 class BufferParams::Impl
315 AuthorList authorlist;
316 BranchList branchlist;
317 Bullet temp_bullets[4];
318 Bullet user_defined_bullets[4];
319 IndicesList indiceslist;
321 /** This is the amount of space used for paragraph_separation "skip",
322 * and for detached paragraphs in "indented" documents.
326 PDFOptions pdfoptions;
327 LayoutFileIndex baseClass_;
331 BufferParams::Impl::Impl()
332 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
334 // set initial author
336 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
341 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
344 return new BufferParams::Impl(*ptr);
348 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
354 BufferParams::BufferParams()
357 setBaseClass(defaultBaseclass());
358 cite_engine_.push_back("basic");
359 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
361 paragraph_separation = ParagraphIndentSeparation;
362 quotes_language = InsetQuotes::EnglishQuotes;
363 fontsize = "default";
366 papersize = PAPER_DEFAULT;
367 orientation = ORIENTATION_PORTRAIT;
368 use_geometry = false;
369 biblio_style = "plain";
370 use_bibtopic = false;
372 save_transient_properties = true;
373 track_changes = false;
374 output_changes = false;
375 use_default_options = true;
376 maintain_unincluded_children = false;
379 language = default_language;
381 fonts_roman[0] = "default";
382 fonts_roman[1] = "default";
383 fonts_sans[0] = "default";
384 fonts_sans[1] = "default";
385 fonts_typewriter[0] = "default";
386 fonts_typewriter[1] = "default";
387 fonts_math[0] = "auto";
388 fonts_math[1] = "auto";
389 fonts_default_family = "default";
390 useNonTeXFonts = false;
391 use_microtype = false;
392 fonts_expert_sc = false;
393 fonts_old_figures = false;
394 fonts_sans_scale[0] = 100;
395 fonts_sans_scale[1] = 100;
396 fonts_typewriter_scale[0] = 100;
397 fonts_typewriter_scale[1] = 100;
399 lang_package = "default";
400 graphics_driver = "default";
401 default_output_format = "default";
402 bibtex_command = "default";
403 index_command = "default";
406 listings_params = string();
407 pagestyle = "default";
408 suppress_date = false;
409 justification = true;
410 // no color is the default (white)
411 backgroundcolor = lyx::rgbFromHexName("#ffffff");
412 isbackgroundcolor = false;
413 // no color is the default (black)
414 fontcolor = lyx::rgbFromHexName("#000000");
416 // light gray is the default font color for greyed-out notes
417 notefontcolor = lyx::rgbFromHexName("#cccccc");
418 boxbgcolor = lyx::rgbFromHexName("#ff0000");
419 compressed = lyxrc.save_compressed;
420 for (int iter = 0; iter < 4; ++iter) {
421 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
422 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
425 indiceslist().addDefault(B_("Index"));
426 html_be_strict = false;
427 html_math_output = MathML;
428 html_math_img_scale = 1.0;
429 html_css_as_file = false;
430 display_pixel_ratio = 1.0;
435 // map current author
436 author_map_[pimpl_->authorlist.get(0).bufferId()] = 0;
440 docstring BufferParams::B_(string const & l10n) const
442 LASSERT(language, return from_utf8(l10n));
443 return getMessages(language->code()).get(l10n);
447 BufferParams::Package BufferParams::use_package(std::string const & p) const
449 PackageMap::const_iterator it = use_packages.find(p);
450 if (it == use_packages.end())
456 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
462 map<string, string> const & BufferParams::auto_packages()
464 static map<string, string> packages;
465 if (packages.empty()) {
466 // We could have a race condition here that two threads
467 // discover an empty map at the same time and want to fill
468 // it, but that is no problem, since the same contents is
469 // filled in twice then. Having the locker inside the
470 // packages.empty() condition has the advantage that we
471 // don't need the mutex overhead for simple reading.
473 Mutex::Locker locker(&mutex);
474 // adding a package here implies a file format change!
475 packages["amsmath"] =
476 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
477 packages["amssymb"] =
478 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
480 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
482 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
483 packages["mathdots"] =
484 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
485 packages["mathtools"] =
486 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
488 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
489 packages["stackrel"] =
490 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
491 packages["stmaryrd"] =
492 N_("The LaTeX package stmaryrd is only used if symbols from the St Mary's Road symbol font for theoretical computer science are inserted into formulas");
493 packages["undertilde"] =
494 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
500 AuthorList & BufferParams::authors()
502 return pimpl_->authorlist;
506 AuthorList const & BufferParams::authors() const
508 return pimpl_->authorlist;
512 void BufferParams::addAuthor(Author a)
514 author_map_[a.bufferId()] = pimpl_->authorlist.record(a);
518 BranchList & BufferParams::branchlist()
520 return pimpl_->branchlist;
524 BranchList const & BufferParams::branchlist() const
526 return pimpl_->branchlist;
530 IndicesList & BufferParams::indiceslist()
532 return pimpl_->indiceslist;
536 IndicesList const & BufferParams::indiceslist() const
538 return pimpl_->indiceslist;
542 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
544 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
545 return pimpl_->temp_bullets[index];
549 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
551 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
552 return pimpl_->temp_bullets[index];
556 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
558 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
559 return pimpl_->user_defined_bullets[index];
563 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
565 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
566 return pimpl_->user_defined_bullets[index];
570 Spacing & BufferParams::spacing()
572 return pimpl_->spacing;
576 Spacing const & BufferParams::spacing() const
578 return pimpl_->spacing;
582 PDFOptions & BufferParams::pdfoptions()
584 return pimpl_->pdfoptions;
588 PDFOptions const & BufferParams::pdfoptions() const
590 return pimpl_->pdfoptions;
594 HSpace const & BufferParams::getIndentation() const
596 return pimpl_->indentation;
600 void BufferParams::setIndentation(HSpace const & indent)
602 pimpl_->indentation = indent;
606 VSpace const & BufferParams::getDefSkip() const
608 return pimpl_->defskip;
612 void BufferParams::setDefSkip(VSpace const & vs)
614 // DEFSKIP will cause an infinite loop
615 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
616 pimpl_->defskip = vs;
620 string BufferParams::readToken(Lexer & lex, string const & token,
621 FileName const & filepath)
625 if (token == "\\textclass") {
627 string const classname = lex.getString();
628 // if there exists a local layout file, ignore the system one
629 // NOTE: in this case, the textclass (.cls file) is assumed to
632 LayoutFileList & bcl = LayoutFileList::get();
633 if (!filepath.empty()) {
634 // If classname is an absolute path, the document is
635 // using a local layout file which could not be accessed
636 // by a relative path. In this case the path is correct
637 // even if the document was moved to a different
638 // location. However, we will have a problem if the
639 // document was generated on a different platform.
640 bool isabsolute = FileName::isAbsolute(classname);
641 string const classpath = onlyPath(classname);
642 string const path = isabsolute ? classpath
643 : FileName(addPath(filepath.absFileName(),
644 classpath)).realPath();
645 string const oldpath = isabsolute ? string()
646 : FileName(addPath(origin, classpath)).realPath();
647 tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
649 // that returns non-empty if a "local" layout file is found.
651 result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
652 from_utf8(filepath.absFileName())));
655 setBaseClass(onlyFileName(tcp));
657 setBaseClass(onlyFileName(classname));
658 // We assume that a tex class exists for local or unknown
659 // layouts so this warning, will only be given for system layouts.
660 if (!baseClass()->isTeXClassAvailable()) {
661 docstring const desc =
662 translateIfPossible(from_utf8(baseClass()->description()));
663 docstring const prereqs =
664 from_utf8(baseClass()->prerequisites());
665 docstring const msg =
666 bformat(_("The selected document class\n"
668 "requires external files that are not available.\n"
669 "The document class can still be used, but the\n"
670 "document cannot be compiled until the following\n"
671 "prerequisites are installed:\n"
673 "See section 3.1.2.2 (Class Availability) of the\n"
674 "User's Guide for more information."), desc, prereqs);
675 frontend::Alert::warning(_("Document class not available"),
678 } else if (token == "\\save_transient_properties") {
679 lex >> save_transient_properties;
680 } else if (token == "\\origin") {
682 origin = lex.getString();
683 string const sysdirprefix = "/systemlyxdir/";
684 if (prefixIs(origin, sysdirprefix)) {
685 origin.replace(0, sysdirprefix.length() - 1,
686 package().system_support().absFileName());
688 } else if (token == "\\begin_preamble") {
690 } else if (token == "\\begin_local_layout") {
691 readLocalLayout(lex, false);
692 } else if (token == "\\begin_forced_local_layout") {
693 readLocalLayout(lex, true);
694 } else if (token == "\\begin_modules") {
696 } else if (token == "\\begin_removed_modules") {
697 readRemovedModules(lex);
698 } else if (token == "\\begin_includeonly") {
699 readIncludeonly(lex);
700 } else if (token == "\\maintain_unincluded_children") {
701 lex >> maintain_unincluded_children;
702 } else if (token == "\\options") {
704 options = lex.getString();
705 } else if (token == "\\use_default_options") {
706 lex >> use_default_options;
707 } else if (token == "\\master") {
709 master = lex.getString();
710 if (!filepath.empty() && FileName::isAbsolute(origin)) {
711 bool const isabs = FileName::isAbsolute(master);
712 FileName const abspath(isabs ? master : origin + master);
713 bool const moved = filepath != FileName(origin);
714 if (moved && abspath.exists()) {
715 docstring const path = isabs
717 : from_utf8(abspath.realPath());
718 docstring const refpath =
719 from_utf8(filepath.absFileName());
720 master = to_utf8(makeRelPath(path, refpath));
723 } else if (token == "\\suppress_date") {
724 lex >> suppress_date;
725 } else if (token == "\\justification") {
726 lex >> justification;
727 } else if (token == "\\language") {
729 } else if (token == "\\language_package") {
731 lang_package = lex.getString();
732 } else if (token == "\\inputencoding") {
734 } else if (token == "\\graphics") {
735 readGraphicsDriver(lex);
736 } else if (token == "\\default_output_format") {
737 lex >> default_output_format;
738 } else if (token == "\\bibtex_command") {
740 bibtex_command = lex.getString();
741 } else if (token == "\\index_command") {
743 index_command = lex.getString();
744 } else if (token == "\\fontencoding") {
746 fontenc = lex.getString();
747 } else if (token == "\\font_roman") {
748 lex >> fonts_roman[0];
749 lex >> fonts_roman[1];
750 } else if (token == "\\font_sans") {
751 lex >> fonts_sans[0];
752 lex >> fonts_sans[1];
753 } else if (token == "\\font_typewriter") {
754 lex >> fonts_typewriter[0];
755 lex >> fonts_typewriter[1];
756 } else if (token == "\\font_math") {
757 lex >> fonts_math[0];
758 lex >> fonts_math[1];
759 } else if (token == "\\font_default_family") {
760 lex >> fonts_default_family;
761 } else if (token == "\\use_non_tex_fonts") {
762 lex >> useNonTeXFonts;
763 } else if (token == "\\font_sc") {
764 lex >> fonts_expert_sc;
765 } else if (token == "\\font_osf") {
766 lex >> fonts_old_figures;
767 } else if (token == "\\font_sf_scale") {
768 lex >> fonts_sans_scale[0];
769 lex >> fonts_sans_scale[1];
770 } else if (token == "\\font_tt_scale") {
771 lex >> fonts_typewriter_scale[0];
772 lex >> fonts_typewriter_scale[1];
773 } else if (token == "\\font_cjk") {
775 } else if (token == "\\use_microtype") {
776 lex >> use_microtype;
777 } else if (token == "\\paragraph_separation") {
780 paragraph_separation = parseptranslator().find(parsep);
781 } else if (token == "\\paragraph_indentation") {
783 string indentation = lex.getString();
784 pimpl_->indentation = HSpace(indentation);
785 } else if (token == "\\defskip") {
787 string const defskip = lex.getString();
788 pimpl_->defskip = VSpace(defskip);
789 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
791 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
792 } else if (token == "\\quotes_language") {
795 quotes_language = quoteslangtranslator().find(quotes_lang);
796 } else if (token == "\\papersize") {
799 papersize = papersizetranslator().find(ppsize);
800 } else if (token == "\\use_geometry") {
802 } else if (token == "\\use_package") {
807 use_package(package, packagetranslator().find(use));
808 } else if (token == "\\cite_engine") {
810 vector<string> engine = getVectorFromString(lex.getString());
811 setCiteEngine(engine);
812 } else if (token == "\\cite_engine_type") {
815 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
816 } else if (token == "\\biblio_style") {
818 biblio_style = lex.getString();
819 } else if (token == "\\use_bibtopic") {
821 } else if (token == "\\use_indices") {
823 } else if (token == "\\tracking_changes") {
824 lex >> track_changes;
825 } else if (token == "\\output_changes") {
826 lex >> output_changes;
827 } else if (token == "\\branch") {
829 docstring branch = lex.getDocString();
830 branchlist().add(branch);
833 string const tok = lex.getString();
834 if (tok == "\\end_branch")
836 Branch * branch_ptr = branchlist().find(branch);
837 if (tok == "\\selected") {
840 branch_ptr->setSelected(lex.getInteger());
842 if (tok == "\\filename_suffix") {
845 branch_ptr->setFileNameSuffix(lex.getInteger());
847 if (tok == "\\color") {
849 string color = lex.getString();
851 branch_ptr->setColor(color);
852 // Update also the Color table:
854 color = lcolor.getX11Name(Color_background);
856 lcolor.setColor(to_utf8(branch), color);
859 } else if (token == "\\index") {
861 docstring index = lex.getDocString();
863 indiceslist().add(index);
866 string const tok = lex.getString();
867 if (tok == "\\end_index")
869 Index * index_ptr = indiceslist().find(index);
870 if (tok == "\\shortcut") {
872 shortcut = lex.getDocString();
874 index_ptr->setShortcut(shortcut);
876 if (tok == "\\color") {
878 string color = lex.getString();
880 index_ptr->setColor(color);
881 // Update also the Color table:
883 color = lcolor.getX11Name(Color_background);
885 if (!shortcut.empty())
886 lcolor.setColor(to_utf8(shortcut), color);
889 } else if (token == "\\author") {
891 istringstream ss(lex.getString());
895 } else if (token == "\\paperorientation") {
898 orientation = paperorientationtranslator().find(orient);
899 } else if (token == "\\backgroundcolor") {
901 backgroundcolor = lyx::rgbFromHexName(lex.getString());
902 isbackgroundcolor = true;
903 } else if (token == "\\fontcolor") {
905 fontcolor = lyx::rgbFromHexName(lex.getString());
907 } else if (token == "\\notefontcolor") {
909 string color = lex.getString();
910 notefontcolor = lyx::rgbFromHexName(color);
911 lcolor.setColor("notefontcolor", color);
912 } else if (token == "\\boxbgcolor") {
914 string color = lex.getString();
915 boxbgcolor = lyx::rgbFromHexName(color);
916 lcolor.setColor("boxbgcolor", color);
917 } else if (token == "\\paperwidth") {
919 } else if (token == "\\paperheight") {
921 } else if (token == "\\leftmargin") {
923 } else if (token == "\\topmargin") {
925 } else if (token == "\\rightmargin") {
927 } else if (token == "\\bottommargin") {
929 } else if (token == "\\headheight") {
931 } else if (token == "\\headsep") {
933 } else if (token == "\\footskip") {
935 } else if (token == "\\columnsep") {
937 } else if (token == "\\paperfontsize") {
939 } else if (token == "\\papercolumns") {
941 } else if (token == "\\listings_params") {
944 listings_params = InsetListingsParams(par).params();
945 } else if (token == "\\papersides") {
948 sides = sidestranslator().find(psides);
949 } else if (token == "\\paperpagestyle") {
951 } else if (token == "\\bullet") {
953 } else if (token == "\\bulletLaTeX") {
954 readBulletsLaTeX(lex);
955 } else if (token == "\\secnumdepth") {
957 } else if (token == "\\tocdepth") {
959 } else if (token == "\\spacing") {
963 if (nspacing == "other") {
966 spacing().set(spacetranslator().find(nspacing), tmp_val);
967 } else if (token == "\\float_placement") {
968 lex >> float_placement;
970 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
971 string toktmp = pdfoptions().readToken(lex, token);
972 if (!toktmp.empty()) {
973 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
977 } else if (token == "\\html_math_output") {
980 html_math_output = static_cast<MathOutput>(temp);
981 } else if (token == "\\html_be_strict") {
982 lex >> html_be_strict;
983 } else if (token == "\\html_css_as_file") {
984 lex >> html_css_as_file;
985 } else if (token == "\\html_math_img_scale") {
986 lex >> html_math_img_scale;
987 } else if (token == "\\html_latex_start") {
989 html_latex_start = lex.getString();
990 } else if (token == "\\html_latex_end") {
992 html_latex_end = lex.getString();
993 } else if (token == "\\output_sync") {
995 } else if (token == "\\output_sync_macro") {
996 lex >> output_sync_macro;
997 } else if (token == "\\use_refstyle") {
1000 lyxerr << "BufferParams::readToken(): Unknown token: " <<
1010 // Quote argument if it contains spaces
1011 string quoteIfNeeded(string const & str) {
1012 if (contains(str, ' '))
1013 return "\"" + str + "\"";
1019 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
1021 // The top of the file is written by the buffer.
1022 // Prints out the buffer info into the .lyx file given by file
1024 os << "\\save_transient_properties "
1025 << convert<string>(save_transient_properties) << '\n';
1027 // the document directory (must end with a path separator)
1028 // realPath() is used to resolve symlinks, while addPath(..., "")
1029 // ensures a trailing path separator.
1030 string filepath = addPath(buf->fileName().onlyPath().realPath(), "");
1031 string const sysdir = addPath(package().system_support().realPath(), "");
1032 string const relpath =
1033 to_utf8(makeRelPath(from_utf8(filepath), from_utf8(sysdir)));
1034 if (!prefixIs(relpath, "../") && !FileName::isAbsolute(relpath))
1035 filepath = addPath("/systemlyxdir", relpath);
1036 else if (!save_transient_properties || !lyxrc.save_origin)
1037 filepath = "unavailable";
1038 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1041 os << "\\textclass "
1042 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1043 baseClass()->name()), "layout"))
1046 // then the preamble
1047 if (!preamble.empty()) {
1048 // remove '\n' from the end of preamble
1049 string const tmppreamble = rtrim(preamble, "\n");
1050 os << "\\begin_preamble\n"
1052 << "\n\\end_preamble\n";
1056 if (!options.empty()) {
1057 os << "\\options " << options << '\n';
1060 // use the class options defined in the layout?
1061 os << "\\use_default_options "
1062 << convert<string>(use_default_options) << "\n";
1064 // the master document
1065 if (!master.empty()) {
1066 os << "\\master " << master << '\n';
1070 if (!removed_modules_.empty()) {
1071 os << "\\begin_removed_modules" << '\n';
1072 list<string>::const_iterator it = removed_modules_.begin();
1073 list<string>::const_iterator en = removed_modules_.end();
1074 for (; it != en; ++it)
1076 os << "\\end_removed_modules" << '\n';
1080 if (!layout_modules_.empty()) {
1081 os << "\\begin_modules" << '\n';
1082 LayoutModuleList::const_iterator it = layout_modules_.begin();
1083 LayoutModuleList::const_iterator en = layout_modules_.end();
1084 for (; it != en; ++it)
1086 os << "\\end_modules" << '\n';
1090 if (!included_children_.empty()) {
1091 os << "\\begin_includeonly" << '\n';
1092 list<string>::const_iterator it = included_children_.begin();
1093 list<string>::const_iterator en = included_children_.end();
1094 for (; it != en; ++it)
1096 os << "\\end_includeonly" << '\n';
1098 os << "\\maintain_unincluded_children "
1099 << convert<string>(maintain_unincluded_children) << '\n';
1101 // local layout information
1102 string const local_layout = getLocalLayout(false);
1103 if (!local_layout.empty()) {
1104 // remove '\n' from the end
1105 string const tmplocal = rtrim(local_layout, "\n");
1106 os << "\\begin_local_layout\n"
1108 << "\n\\end_local_layout\n";
1110 string const forced_local_layout = getLocalLayout(true);
1111 if (!forced_local_layout.empty()) {
1112 // remove '\n' from the end
1113 string const tmplocal = rtrim(forced_local_layout, "\n");
1114 os << "\\begin_forced_local_layout\n"
1116 << "\n\\end_forced_local_layout\n";
1119 // then the text parameters
1120 if (language != ignore_language)
1121 os << "\\language " << language->lang() << '\n';
1122 os << "\\language_package " << lang_package
1123 << "\n\\inputencoding " << inputenc
1124 << "\n\\fontencoding " << fontenc
1125 << "\n\\font_roman \"" << fonts_roman[0]
1126 << "\" \"" << fonts_roman[1] << '"'
1127 << "\n\\font_sans \"" << fonts_sans[0]
1128 << "\" \"" << fonts_sans[1] << '"'
1129 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1130 << "\" \"" << fonts_typewriter[1] << '"'
1131 << "\n\\font_math \"" << fonts_math[0]
1132 << "\" \"" << fonts_math[1] << '"'
1133 << "\n\\font_default_family " << fonts_default_family
1134 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1135 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1136 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1137 << "\n\\font_sf_scale " << fonts_sans_scale[0]
1138 << ' ' << fonts_sans_scale[1]
1139 << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1140 << ' ' << fonts_typewriter_scale[1]
1142 if (!fonts_cjk.empty()) {
1143 os << "\\font_cjk " << fonts_cjk << '\n';
1145 os << "\\use_microtype " << convert<string>(use_microtype) << '\n';
1146 os << "\\graphics " << graphics_driver << '\n';
1147 os << "\\default_output_format " << default_output_format << '\n';
1148 os << "\\output_sync " << output_sync << '\n';
1149 if (!output_sync_macro.empty())
1150 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1151 os << "\\bibtex_command " << bibtex_command << '\n';
1152 os << "\\index_command " << index_command << '\n';
1154 if (!float_placement.empty()) {
1155 os << "\\float_placement " << float_placement << '\n';
1157 os << "\\paperfontsize " << fontsize << '\n';
1159 spacing().writeFile(os);
1160 pdfoptions().writeFile(os);
1162 os << "\\papersize " << string_papersize[papersize]
1163 << "\n\\use_geometry " << convert<string>(use_geometry);
1164 map<string, string> const & packages = auto_packages();
1165 for (map<string, string>::const_iterator it = packages.begin();
1166 it != packages.end(); ++it)
1167 os << "\n\\use_package " << it->first << ' '
1168 << use_package(it->first);
1170 os << "\n\\cite_engine ";
1172 if (!cite_engine_.empty()) {
1173 LayoutModuleList::const_iterator be = cite_engine_.begin();
1174 LayoutModuleList::const_iterator en = cite_engine_.end();
1175 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1184 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1185 << "\n\\biblio_style " << biblio_style
1186 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1187 << "\n\\use_indices " << convert<string>(use_indices)
1188 << "\n\\paperorientation " << string_orientation[orientation]
1189 << "\n\\suppress_date " << convert<string>(suppress_date)
1190 << "\n\\justification " << convert<string>(justification)
1191 << "\n\\use_refstyle " << use_refstyle
1193 if (isbackgroundcolor == true)
1194 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1195 if (isfontcolor == true)
1196 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1197 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1198 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1199 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1200 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1202 BranchList::const_iterator it = branchlist().begin();
1203 BranchList::const_iterator end = branchlist().end();
1204 for (; it != end; ++it) {
1205 os << "\\branch " << to_utf8(it->branch())
1206 << "\n\\selected " << it->isSelected()
1207 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1208 << "\n\\color " << lyx::X11hexname(it->color())
1213 IndicesList::const_iterator iit = indiceslist().begin();
1214 IndicesList::const_iterator iend = indiceslist().end();
1215 for (; iit != iend; ++iit) {
1216 os << "\\index " << to_utf8(iit->index())
1217 << "\n\\shortcut " << to_utf8(iit->shortcut())
1218 << "\n\\color " << lyx::X11hexname(iit->color())
1223 if (!paperwidth.empty())
1224 os << "\\paperwidth "
1225 << VSpace(paperwidth).asLyXCommand() << '\n';
1226 if (!paperheight.empty())
1227 os << "\\paperheight "
1228 << VSpace(paperheight).asLyXCommand() << '\n';
1229 if (!leftmargin.empty())
1230 os << "\\leftmargin "
1231 << VSpace(leftmargin).asLyXCommand() << '\n';
1232 if (!topmargin.empty())
1233 os << "\\topmargin "
1234 << VSpace(topmargin).asLyXCommand() << '\n';
1235 if (!rightmargin.empty())
1236 os << "\\rightmargin "
1237 << VSpace(rightmargin).asLyXCommand() << '\n';
1238 if (!bottommargin.empty())
1239 os << "\\bottommargin "
1240 << VSpace(bottommargin).asLyXCommand() << '\n';
1241 if (!headheight.empty())
1242 os << "\\headheight "
1243 << VSpace(headheight).asLyXCommand() << '\n';
1244 if (!headsep.empty())
1246 << VSpace(headsep).asLyXCommand() << '\n';
1247 if (!footskip.empty())
1249 << VSpace(footskip).asLyXCommand() << '\n';
1250 if (!columnsep.empty())
1251 os << "\\columnsep "
1252 << VSpace(columnsep).asLyXCommand() << '\n';
1253 os << "\\secnumdepth " << secnumdepth
1254 << "\n\\tocdepth " << tocdepth
1255 << "\n\\paragraph_separation "
1256 << string_paragraph_separation[paragraph_separation];
1257 if (!paragraph_separation)
1258 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1260 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1261 os << "\n\\quotes_language "
1262 << string_quotes_language[quotes_language]
1263 << "\n\\papercolumns " << columns
1264 << "\n\\papersides " << sides
1265 << "\n\\paperpagestyle " << pagestyle << '\n';
1266 if (!listings_params.empty())
1267 os << "\\listings_params \"" <<
1268 InsetListingsParams(listings_params).encodedString() << "\"\n";
1269 for (int i = 0; i < 4; ++i) {
1270 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1271 if (user_defined_bullet(i).getFont() != -1) {
1272 os << "\\bullet " << i << " "
1273 << user_defined_bullet(i).getFont() << " "
1274 << user_defined_bullet(i).getCharacter() << " "
1275 << user_defined_bullet(i).getSize() << "\n";
1279 os << "\\bulletLaTeX " << i << " \""
1280 << lyx::to_ascii(user_defined_bullet(i).getText())
1286 os << "\\tracking_changes "
1287 << (save_transient_properties ? convert<string>(track_changes) : "false")
1290 os << "\\output_changes "
1291 << (save_transient_properties ? convert<string>(output_changes) : "false")
1294 os << "\\html_math_output " << html_math_output << '\n'
1295 << "\\html_css_as_file " << html_css_as_file << '\n'
1296 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1298 if (html_math_img_scale != 1.0)
1299 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1300 if (!html_latex_start.empty())
1301 os << "\\html_latex_start " << html_latex_start << '\n';
1302 if (!html_latex_end.empty())
1303 os << "\\html_latex_end " << html_latex_end << '\n';
1305 os << pimpl_->authorlist;
1309 void BufferParams::validate(LaTeXFeatures & features) const
1311 features.require(documentClass().requires());
1313 if (columns > 1 && language->rightToLeft())
1314 features.require("rtloutputdblcol");
1316 if (output_changes) {
1317 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1318 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1319 LaTeXFeatures::isAvailable("xcolor");
1321 switch (features.runparams().flavor) {
1322 case OutputParams::LATEX:
1323 case OutputParams::DVILUATEX:
1325 features.require("ct-dvipost");
1326 features.require("dvipost");
1327 } else if (xcolorulem) {
1328 features.require("ct-xcolor-ulem");
1329 features.require("ulem");
1330 features.require("xcolor");
1332 features.require("ct-none");
1335 case OutputParams::LUATEX:
1336 case OutputParams::PDFLATEX:
1337 case OutputParams::XETEX:
1339 features.require("ct-xcolor-ulem");
1340 features.require("ulem");
1341 features.require("xcolor");
1342 // improves color handling in PDF output
1343 features.require("pdfcolmk");
1345 features.require("ct-none");
1353 // Floats with 'Here definitely' as default setting.
1354 if (float_placement.find('H') != string::npos)
1355 features.require("float");
1357 for (PackageMap::const_iterator it = use_packages.begin();
1358 it != use_packages.end(); ++it) {
1359 if (it->first == "amsmath") {
1360 // AMS Style is at document level
1361 if (it->second == package_on ||
1362 features.isProvided("amsmath"))
1363 features.require(it->first);
1364 } else if (it->second == package_on)
1365 features.require(it->first);
1368 // Document-level line spacing
1369 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1370 features.require("setspace");
1372 // the bullet shapes are buffer level not paragraph level
1373 // so they are tested here
1374 for (int i = 0; i < 4; ++i) {
1375 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1377 int const font = user_defined_bullet(i).getFont();
1379 int const c = user_defined_bullet(i).getCharacter();
1385 features.require("latexsym");
1387 } else if (font == 1) {
1388 features.require("amssymb");
1389 } else if (font >= 2 && font <= 5) {
1390 features.require("pifont");
1394 if (pdfoptions().use_hyperref) {
1395 features.require("hyperref");
1396 // due to interferences with babel and hyperref, the color package has to
1397 // be loaded after hyperref when hyperref is used with the colorlinks
1398 // option, see http://www.lyx.org/trac/ticket/5291
1399 if (pdfoptions().colorlinks)
1400 features.require("color");
1402 if (!listings_params.empty()) {
1403 // do not test validity because listings_params is
1404 // supposed to be valid
1406 InsetListingsParams(listings_params).separatedParams(true);
1407 // we can't support all packages, but we should load the color package
1408 if (par.find("\\color", 0) != string::npos)
1409 features.require("color");
1412 // some languages are only available via polyglossia
1413 if (features.hasPolyglossiaExclusiveLanguages())
1414 features.require("polyglossia");
1416 if (useNonTeXFonts && fontsMath() != "auto")
1417 features.require("unicode-math");
1420 features.require("microtype");
1422 if (!language->requires().empty())
1423 features.require(language->requires());
1427 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1428 FileName const & filepath) const
1430 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1431 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1432 // \RequirePackage to do so, rather than the normal \usepackage
1433 // Do not try to load any other package before the document class, unless you
1434 // have a thorough understanding of the LATEX internals and know exactly what you
1436 if (features.mustProvide("fix-cm"))
1437 os << "\\RequirePackage{fix-cm}\n";
1438 // Likewise for fixltx2e. If other packages conflict with this policy,
1439 // treat it as a package bug (and report it!)
1440 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1441 if (features.mustProvide("fixltx2e"))
1442 os << "\\RequirePackage{fixltx2e}\n";
1444 os << "\\documentclass";
1446 DocumentClass const & tclass = documentClass();
1448 ostringstream clsoptions; // the document class options.
1450 if (tokenPos(tclass.opt_fontsize(),
1451 '|', fontsize) >= 0) {
1452 // only write if existing in list (and not default)
1453 clsoptions << fontsize << "pt,";
1456 // all paper sizes except of A4, A5, B5 and the US sizes need the
1458 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1459 && papersize != PAPER_USLETTER
1460 && papersize != PAPER_USLEGAL
1461 && papersize != PAPER_USEXECUTIVE
1462 && papersize != PAPER_A4
1463 && papersize != PAPER_A5
1464 && papersize != PAPER_B5;
1466 if (!use_geometry) {
1467 switch (papersize) {
1469 clsoptions << "a4paper,";
1471 case PAPER_USLETTER:
1472 clsoptions << "letterpaper,";
1475 clsoptions << "a5paper,";
1478 clsoptions << "b5paper,";
1480 case PAPER_USEXECUTIVE:
1481 clsoptions << "executivepaper,";
1484 clsoptions << "legalpaper,";
1518 if (sides != tclass.sides()) {
1521 clsoptions << "oneside,";
1524 clsoptions << "twoside,";
1530 if (columns != tclass.columns()) {
1532 clsoptions << "twocolumn,";
1534 clsoptions << "onecolumn,";
1538 && orientation == ORIENTATION_LANDSCAPE)
1539 clsoptions << "landscape,";
1541 // language should be a parameter to \documentclass
1542 if (language->babel() == "hebrew"
1543 && default_language->babel() != "hebrew")
1544 // This seems necessary
1545 features.useLanguage(default_language);
1547 ostringstream language_options;
1548 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1549 bool const use_polyglossia = features.usePolyglossia();
1550 bool const global = lyxrc.language_global_options;
1551 if (use_babel || (use_polyglossia && global)) {
1552 language_options << features.getBabelLanguages();
1553 if (!language->babel().empty()) {
1554 if (!language_options.str().empty())
1555 language_options << ',';
1556 language_options << language->babel();
1558 if (global && !features.needBabelLangOptions()
1559 && !language_options.str().empty())
1560 clsoptions << language_options.str() << ',';
1563 // the predefined options from the layout
1564 if (use_default_options && !tclass.options().empty())
1565 clsoptions << tclass.options() << ',';
1567 // the user-defined options
1568 if (!options.empty()) {
1569 clsoptions << options << ',';
1572 string strOptions(clsoptions.str());
1573 if (!strOptions.empty()) {
1574 strOptions = rtrim(strOptions, ",");
1576 os << '[' << from_utf8(strOptions) << ']';
1579 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1580 // end of \documentclass defs
1582 // if we use fontspec or newtxmath, we have to load the AMS packages here
1583 string const ams = features.loadAMSPackages();
1584 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1585 bool const use_newtxmath =
1586 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1587 ot1, false, false) == "newtxmath";
1588 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1589 os << from_ascii(ams);
1591 if (useNonTeXFonts) {
1592 os << "\\usepackage{fontspec}\n";
1593 if (features.mustProvide("unicode-math")
1594 && features.isAvailable("unicode-math"))
1595 os << "\\usepackage{unicode-math}\n";
1598 // font selection must be done before loading fontenc.sty
1599 string const fonts = loadFonts(features);
1601 os << from_utf8(fonts);
1603 if (fonts_default_family != "default")
1604 os << "\\renewcommand{\\familydefault}{\\"
1605 << from_ascii(fonts_default_family) << "}\n";
1607 // set font encoding
1608 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1609 if (!useNonTeXFonts && !features.isProvided("fontenc")
1610 && font_encoding() != "default") {
1611 // get main font encodings
1612 vector<string> fontencs = font_encodings();
1613 // get font encodings of secondary languages
1614 features.getFontEncodings(fontencs);
1615 if (!fontencs.empty()) {
1616 os << "\\usepackage["
1617 << from_ascii(getStringFromVector(fontencs))
1622 // handle inputenc etc.
1623 writeEncodingPreamble(os, features);
1626 if (!features.runparams().includeall && !included_children_.empty()) {
1627 os << "\\includeonly{";
1628 list<string>::const_iterator it = included_children_.begin();
1629 list<string>::const_iterator en = included_children_.end();
1631 for (; it != en; ++it) {
1632 string incfile = *it;
1633 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1634 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1636 if (!features.runparams().nice)
1638 // \includeonly doesn't want an extension
1639 incfile = changeExtension(incfile, string());
1640 incfile = support::latex_path(incfile);
1641 if (!incfile.empty()) {
1644 os << from_utf8(incfile);
1651 if (!features.isProvided("geometry")
1652 && (use_geometry || nonstandard_papersize)) {
1653 odocstringstream ods;
1654 if (!getGraphicsDriver("geometry").empty())
1655 ods << getGraphicsDriver("geometry");
1656 if (orientation == ORIENTATION_LANDSCAPE)
1657 ods << ",landscape";
1658 switch (papersize) {
1660 if (!paperwidth.empty())
1661 ods << ",paperwidth="
1662 << from_ascii(paperwidth);
1663 if (!paperheight.empty())
1664 ods << ",paperheight="
1665 << from_ascii(paperheight);
1667 case PAPER_USLETTER:
1668 ods << ",letterpaper";
1671 ods << ",legalpaper";
1673 case PAPER_USEXECUTIVE:
1674 ods << ",executivepaper";
1763 docstring const g_options = trim(ods.str(), ",");
1764 os << "\\usepackage";
1765 if (!g_options.empty())
1766 os << '[' << g_options << ']';
1767 os << "{geometry}\n";
1768 // output this only if use_geometry is true
1770 os << "\\geometry{verbose";
1771 if (!topmargin.empty())
1772 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1773 if (!bottommargin.empty())
1774 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1775 if (!leftmargin.empty())
1776 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1777 if (!rightmargin.empty())
1778 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1779 if (!headheight.empty())
1780 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1781 if (!headsep.empty())
1782 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1783 if (!footskip.empty())
1784 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1785 if (!columnsep.empty())
1786 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1789 } else if (orientation == ORIENTATION_LANDSCAPE
1790 || papersize != PAPER_DEFAULT) {
1791 features.require("papersize");
1794 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1795 if (pagestyle == "fancy")
1796 os << "\\usepackage{fancyhdr}\n";
1797 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1800 // only output when the background color is not default
1801 if (isbackgroundcolor == true) {
1802 // only require color here, the background color will be defined
1803 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1805 features.require("color");
1806 features.require("pagecolor");
1809 // only output when the font color is not default
1810 if (isfontcolor == true) {
1811 // only require color here, the font color will be defined
1812 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1814 features.require("color");
1815 features.require("fontcolor");
1818 // Only if class has a ToC hierarchy
1819 if (tclass.hasTocLevels()) {
1820 if (secnumdepth != tclass.secnumdepth()) {
1821 os << "\\setcounter{secnumdepth}{"
1825 if (tocdepth != tclass.tocdepth()) {
1826 os << "\\setcounter{tocdepth}{"
1832 if (paragraph_separation) {
1833 // when skip separation
1834 switch (getDefSkip().kind()) {
1835 case VSpace::SMALLSKIP:
1836 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1838 case VSpace::MEDSKIP:
1839 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1841 case VSpace::BIGSKIP:
1842 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1844 case VSpace::LENGTH:
1845 os << "\\setlength{\\parskip}{"
1846 << from_utf8(getDefSkip().length().asLatexString())
1849 default: // should never happen // Then delete it.
1850 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1853 os << "\\setlength{\\parindent}{0pt}\n";
1855 // when separation by indentation
1856 // only output something when a width is given
1857 if (getIndentation().asLyXCommand() != "default") {
1858 os << "\\setlength{\\parindent}{"
1859 << from_utf8(getIndentation().asLatexCommand())
1864 // Now insert the LyX specific LaTeX commands...
1865 docstring lyxpreamble;
1866 features.resolveAlternatives();
1869 if (!output_sync_macro.empty())
1870 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1871 else if (features.runparams().flavor == OutputParams::LATEX)
1872 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1873 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1874 lyxpreamble += "\\synctex=-1\n";
1877 // The package options (via \PassOptionsToPackage)
1878 lyxpreamble += from_ascii(features.getPackageOptions());
1880 // due to interferences with babel and hyperref, the color package has to
1881 // be loaded (when it is not already loaded) before babel when hyperref
1882 // is used with the colorlinks option, see
1883 // http://www.lyx.org/trac/ticket/5291
1884 // we decided therefore to load color always before babel, see
1885 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1886 lyxpreamble += from_ascii(features.getColorOptions());
1888 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1889 // we have to call babel before
1891 && (features.isRequired("jurabib")
1892 || features.isRequired("hyperref")
1893 || features.isRequired("varioref")
1894 || features.isRequired("vietnamese")
1895 || features.isRequired("japanese"))) {
1897 lyxpreamble += from_utf8(features.getBabelPresettings());
1898 lyxpreamble += from_utf8(babelCall(language_options.str(),
1899 features.needBabelLangOptions())) + '\n';
1900 lyxpreamble += from_utf8(features.getBabelPostsettings());
1903 // The optional packages;
1904 lyxpreamble += from_ascii(features.getPackages());
1906 // Additional Indices
1907 if (features.isRequired("splitidx")) {
1908 IndicesList::const_iterator iit = indiceslist().begin();
1909 IndicesList::const_iterator iend = indiceslist().end();
1910 for (; iit != iend; ++iit) {
1911 pair<docstring, docstring> indexname_latex =
1912 features.runparams().encoding->latexString(iit->index(),
1913 features.runparams().dryrun);
1914 if (!indexname_latex.second.empty()) {
1915 // issue a warning about omitted characters
1916 // FIXME: should be passed to the error dialog
1917 frontend::Alert::warning(_("Uncodable characters"),
1918 bformat(_("The following characters that are used in an index name are not\n"
1919 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1920 indexname_latex.second));
1922 lyxpreamble += "\\newindex[";
1923 lyxpreamble += indexname_latex.first;
1924 lyxpreamble += "]{";
1925 lyxpreamble += escape(iit->shortcut());
1926 lyxpreamble += "}\n";
1931 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1934 // * Hyperref manual: "Make sure it comes last of your loaded
1935 // packages, to give it a fighting chance of not being over-written,
1936 // since its job is to redefine many LaTeX commands."
1937 // * Email from Heiko Oberdiek: "It is usually better to load babel
1938 // before hyperref. Then hyperref has a chance to detect babel.
1939 // * Has to be loaded before the "LyX specific LaTeX commands" to
1940 // avoid errors with algorithm floats.
1941 // use hyperref explicitly if it is required
1942 if (features.isRequired("hyperref")) {
1943 // pass what we have to stream here, since we need
1944 // to access the stream itself in PDFOptions.
1947 OutputParams tmp_params = features.runparams();
1948 pdfoptions().writeLaTeX(tmp_params, os,
1949 features.isProvided("hyperref"));
1950 // set back for the rest
1951 lyxpreamble.clear();
1952 // correctly break URLs with hyperref and dvi output
1953 if (features.runparams().flavor == OutputParams::LATEX
1954 && features.isAvailable("breakurl"))
1955 lyxpreamble += "\\usepackage{breakurl}\n";
1956 } else if (features.isRequired("nameref"))
1957 // hyperref loads this automatically
1958 lyxpreamble += "\\usepackage{nameref}\n";
1960 // bibtopic needs to be loaded after hyperref.
1961 // the dot provides the aux file naming which LyX can detect.
1962 if (features.mustProvide("bibtopic"))
1963 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1965 // Will be surrounded by \makeatletter and \makeatother when not empty
1966 docstring atlyxpreamble;
1968 // Some macros LyX will need
1969 docstring tmppreamble(features.getMacros());
1971 if (!tmppreamble.empty())
1972 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1973 "LyX specific LaTeX commands.\n"
1974 + tmppreamble + '\n';
1976 // the text class specific preamble
1977 tmppreamble = features.getTClassPreamble();
1978 if (!tmppreamble.empty())
1979 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1980 "Textclass specific LaTeX commands.\n"
1981 + tmppreamble + '\n';
1983 // suppress date if selected
1984 // use \@ifundefined because we cannot be sure that every document class
1985 // has a \date command
1987 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1989 /* the user-defined preamble */
1990 if (!containsOnly(preamble, " \n\t")) {
1992 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1993 "User specified LaTeX commands.\n";
1995 // Check if the user preamble contains uncodable glyphs
1996 docstring const u_preamble = from_utf8(preamble);
1997 odocstringstream user_preamble;
1998 docstring uncodable_glyphs;
1999 Encoding const * const enc = features.runparams().encoding;
2001 for (size_t n = 0; n < u_preamble.size(); ++n) {
2002 char_type c = u_preamble[n];
2003 if (!enc->encodable(c)) {
2004 docstring const glyph(1, c);
2005 LYXERR0("Uncodable character '"
2007 << "' in user preamble!");
2008 uncodable_glyphs += glyph;
2009 if (features.runparams().dryrun) {
2010 user_preamble << "<" << _("LyX Warning: ")
2011 << _("uncodable character") << " '";
2012 user_preamble.put(c);
2013 user_preamble << "'>";
2016 user_preamble.put(c);
2019 user_preamble << u_preamble;
2021 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2022 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2023 frontend::Alert::warning(
2024 _("Uncodable character in user preamble"),
2026 _("The user preamble of your document contains glyphs "
2027 "that are unknown in the current document encoding "
2028 "(namely %1$s).\nThese glyphs are omitted "
2029 " from the output, which may result in "
2030 "incomplete output."
2031 "\n\nPlease select an appropriate "
2032 "document encoding\n"
2033 "(such as utf8) or change the "
2034 "preamble code accordingly."),
2037 atlyxpreamble += user_preamble.str() + '\n';
2040 // footmisc must be loaded after setspace
2041 // Load it here to avoid clashes with footmisc loaded in the user
2042 // preamble. For that reason we also pass the options via
2043 // \PassOptionsToPackage in getPreamble() and not here.
2044 if (features.mustProvide("footmisc"))
2045 atlyxpreamble += "\\usepackage{footmisc}\n";
2047 // subfig loads internally the LaTeX package "caption". As
2048 // caption is a very popular package, users will load it in
2049 // the preamble. Therefore we must load subfig behind the
2050 // user-defined preamble and check if the caption package was
2051 // loaded or not. For the case that caption is loaded before
2052 // subfig, there is the subfig option "caption=false". This
2053 // option also works when a koma-script class is used and
2054 // koma's own caption commands are used instead of caption. We
2055 // use \PassOptionsToPackage here because the user could have
2056 // already loaded subfig in the preamble.
2057 if (features.isRequired("subfig")) {
2058 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
2059 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2060 "\\usepackage{subfig}\n";
2063 // Itemize bullet settings need to be last in case the user
2064 // defines their own bullets that use a package included
2065 // in the user-defined preamble -- ARRae
2066 // Actually it has to be done much later than that
2067 // since some packages like frenchb make modifications
2068 // at \begin{document} time -- JMarc
2069 docstring bullets_def;
2070 for (int i = 0; i < 4; ++i) {
2071 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2072 if (bullets_def.empty())
2073 bullets_def += "\\AtBeginDocument{\n";
2074 bullets_def += " \\def\\labelitemi";
2076 // `i' is one less than the item to modify
2083 bullets_def += "ii";
2089 bullets_def += '{' +
2090 user_defined_bullet(i).getText()
2095 if (!bullets_def.empty())
2096 atlyxpreamble += bullets_def + "}\n\n";
2098 if (!atlyxpreamble.empty())
2099 lyxpreamble += "\n\\makeatletter\n"
2100 + atlyxpreamble + "\\makeatother\n\n";
2102 // We try to load babel late, in case it interferes with other packages.
2103 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
2104 // called after babel, though.
2105 if (use_babel && !features.isRequired("jurabib")
2106 && !features.isRequired("hyperref")
2107 && !features.isRequired("varioref")
2108 && !features.isRequired("vietnamese")
2109 && !features.isRequired("japanese")) {
2111 lyxpreamble += from_utf8(features.getBabelPresettings());
2112 lyxpreamble += from_utf8(babelCall(language_options.str(),
2113 features.needBabelLangOptions())) + '\n';
2114 lyxpreamble += from_utf8(features.getBabelPostsettings());
2116 if (features.isRequired("bicaption"))
2117 lyxpreamble += "\\usepackage{bicaption}\n";
2118 if (!listings_params.empty() || features.isRequired("listings"))
2119 lyxpreamble += "\\usepackage{listings}\n";
2120 if (!listings_params.empty()) {
2121 lyxpreamble += "\\lstset{";
2122 // do not test validity because listings_params is
2123 // supposed to be valid
2125 InsetListingsParams(listings_params).separatedParams(true);
2126 lyxpreamble += from_utf8(par);
2127 lyxpreamble += "}\n";
2130 // xunicode needs to be loaded at least after amsmath, amssymb,
2131 // esint and the other packages that provide special glyphs
2132 if (features.runparams().flavor == OutputParams::XETEX
2134 lyxpreamble += "\\usepackage{xunicode}\n";
2136 // Polyglossia must be loaded last
2137 if (use_polyglossia) {
2139 lyxpreamble += "\\usepackage{polyglossia}\n";
2140 // set the main language
2141 lyxpreamble += "\\setdefaultlanguage";
2142 if (!language->polyglossiaOpts().empty())
2143 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
2144 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
2145 // now setup the other languages
2146 std::map<std::string, std::string> const polylangs =
2147 features.getPolyglossiaLanguages();
2148 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
2149 mit != polylangs.end() ; ++mit) {
2150 lyxpreamble += "\\setotherlanguage";
2151 if (!mit->second.empty())
2152 lyxpreamble += "[" + from_ascii(mit->second) + "]";
2153 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
2157 // Load custom language package here
2158 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2159 if (lang_package == "default")
2160 lyxpreamble += from_utf8(lyxrc.language_custom_package);
2162 lyxpreamble += from_utf8(lang_package);
2163 lyxpreamble += '\n';
2166 docstring const i18npreamble =
2167 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2168 if (!i18npreamble.empty())
2169 lyxpreamble += i18npreamble + '\n';
2177 void BufferParams::useClassDefaults()
2179 DocumentClass const & tclass = documentClass();
2181 sides = tclass.sides();
2182 columns = tclass.columns();
2183 pagestyle = tclass.pagestyle();
2184 use_default_options = true;
2185 // Only if class has a ToC hierarchy
2186 if (tclass.hasTocLevels()) {
2187 secnumdepth = tclass.secnumdepth();
2188 tocdepth = tclass.tocdepth();
2193 bool BufferParams::hasClassDefaults() const
2195 DocumentClass const & tclass = documentClass();
2197 return sides == tclass.sides()
2198 && columns == tclass.columns()
2199 && pagestyle == tclass.pagestyle()
2200 && use_default_options
2201 && secnumdepth == tclass.secnumdepth()
2202 && tocdepth == tclass.tocdepth();
2206 DocumentClass const & BufferParams::documentClass() const
2212 DocumentClassConstPtr BufferParams::documentClassPtr() const
2218 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2220 // evil, but this function is evil
2221 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2225 bool BufferParams::setBaseClass(string const & classname)
2227 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2228 LayoutFileList & bcl = LayoutFileList::get();
2229 if (!bcl.haveClass(classname)) {
2231 bformat(_("The layout file:\n"
2233 "could not be found. A default textclass with default\n"
2234 "layouts will be used. LyX will not be able to produce\n"
2236 from_utf8(classname));
2237 frontend::Alert::error(_("Document class not found"), s);
2238 bcl.addEmptyClass(classname);
2241 bool const success = bcl[classname].load();
2244 bformat(_("Due to some error in it, the layout file:\n"
2246 "could not be loaded. A default textclass with default\n"
2247 "layouts will be used. LyX will not be able to produce\n"
2249 from_utf8(classname));
2250 frontend::Alert::error(_("Could not load class"), s);
2251 bcl.addEmptyClass(classname);
2254 pimpl_->baseClass_ = classname;
2255 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2260 LayoutFile const * BufferParams::baseClass() const
2262 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2263 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2269 LayoutFileIndex const & BufferParams::baseClassID() const
2271 return pimpl_->baseClass_;
2275 void BufferParams::makeDocumentClass(bool const clone)
2280 LayoutModuleList mods;
2281 LayoutModuleList::iterator it = layout_modules_.begin();
2282 LayoutModuleList::iterator en = layout_modules_.end();
2283 for (; it != en; ++it)
2284 mods.push_back(*it);
2286 it = cite_engine_.begin();
2287 en = cite_engine_.end();
2288 for (; it != en; ++it)
2289 mods.push_back(*it);
2291 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2293 TextClass::ReturnValues success = TextClass::OK;
2294 if (!forced_local_layout_.empty())
2295 success = doc_class_->read(forced_local_layout_, TextClass::MODULE);
2296 if (!local_layout_.empty() &&
2297 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2298 success = doc_class_->read(local_layout_, TextClass::MODULE);
2299 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2300 docstring const msg = _("Error reading internal layout information");
2301 frontend::Alert::warning(_("Read Error"), msg);
2306 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2308 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2312 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2314 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2318 std::string BufferParams::getLocalLayout(bool forced) const
2321 return doc_class_->forcedLayouts();
2323 return local_layout_;
2327 void BufferParams::setLocalLayout(string const & layout, bool forced)
2330 forced_local_layout_ = layout;
2332 local_layout_ = layout;
2336 bool BufferParams::addLayoutModule(string const & modName)
2338 LayoutModuleList::const_iterator it = layout_modules_.begin();
2339 LayoutModuleList::const_iterator end = layout_modules_.end();
2340 for (; it != end; ++it)
2343 layout_modules_.push_back(modName);
2348 string BufferParams::bufferFormat() const
2350 string format = documentClass().outputFormat();
2351 if (format == "latex") {
2353 return "xetex"; // actually "xetex or luatex"
2354 if (encoding().package() == Encoding::japanese)
2361 bool BufferParams::isExportable(string const & format) const
2363 vector<string> backs = backends();
2364 for (vector<string>::const_iterator it = backs.begin();
2365 it != backs.end(); ++it)
2366 if (theConverters().isReachable(*it, format))
2372 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2374 vector<string> const backs = backends();
2375 set<string> excludes;
2376 if (useNonTeXFonts) {
2377 excludes.insert("latex");
2378 excludes.insert("pdflatex");
2380 vector<Format const *> result =
2381 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2382 for (vector<string>::const_iterator it = backs.begin() + 1;
2383 it != backs.end(); ++it) {
2384 vector<Format const *> r =
2385 theConverters().getReachable(*it, only_viewable, false, excludes);
2386 result.insert(result.end(), r.begin(), r.end());
2392 bool BufferParams::isExportableFormat(string const & format) const
2394 typedef vector<Format const *> Formats;
2396 formats = exportableFormats(true);
2397 Formats::const_iterator fit = formats.begin();
2398 Formats::const_iterator end = formats.end();
2399 for (; fit != end ; ++fit) {
2400 if ((*fit)->name() == format)
2407 vector<string> BufferParams::backends() const
2410 string const buffmt = bufferFormat();
2412 // FIXME: Don't hardcode format names here, but use a flag
2413 if (buffmt == "latex") {
2414 if (!useNonTeXFonts) {
2415 v.push_back("pdflatex");
2416 v.push_back("latex");
2418 v.push_back("luatex");
2419 v.push_back("dviluatex");
2420 v.push_back("xetex");
2421 } else if (buffmt == "xetex") {
2422 v.push_back("xetex");
2423 // FIXME: need to test all languages (bug 8205)
2424 if (!language || !language->isPolyglossiaExclusive()) {
2425 v.push_back("luatex");
2426 v.push_back("dviluatex");
2429 v.push_back(buffmt);
2431 v.push_back("xhtml");
2432 v.push_back("text");
2438 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2440 string const dformat = (format.empty() || format == "default") ?
2441 getDefaultOutputFormat() : format;
2442 DefaultFlavorCache::const_iterator it =
2443 default_flavors_.find(dformat);
2445 if (it != default_flavors_.end())
2448 OutputParams::FLAVOR result = OutputParams::LATEX;
2450 // FIXME It'd be better not to hardcode this, but to do
2451 // something with formats.
2452 if (dformat == "xhtml")
2453 result = OutputParams::HTML;
2454 else if (dformat == "text")
2455 result = OutputParams::TEXT;
2456 else if (dformat == "lyx")
2457 result = OutputParams::LYX;
2458 else if (dformat == "pdflatex")
2459 result = OutputParams::PDFLATEX;
2460 else if (dformat == "xetex")
2461 result = OutputParams::XETEX;
2462 else if (dformat == "luatex")
2463 result = OutputParams::LUATEX;
2464 else if (dformat == "dviluatex")
2465 result = OutputParams::DVILUATEX;
2467 // Try to determine flavor of default output format
2468 vector<string> backs = backends();
2469 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2470 // Get shortest path to format
2471 Graph::EdgePath path;
2472 for (vector<string>::const_iterator it = backs.begin();
2473 it != backs.end(); ++it) {
2474 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2475 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2480 result = theConverters().getFlavor(path);
2483 // cache this flavor
2484 default_flavors_[dformat] = result;
2489 string BufferParams::getDefaultOutputFormat() const
2491 if (!default_output_format.empty()
2492 && default_output_format != "default")
2493 return default_output_format;
2495 || encoding().package() == Encoding::japanese) {
2496 vector<Format const *> const formats = exportableFormats(true);
2497 if (formats.empty())
2499 // return the first we find
2500 return formats.front()->name();
2503 return lyxrc.default_otf_view_format;
2504 return lyxrc.default_view_format;
2507 Font const BufferParams::getFont() const
2509 FontInfo f = documentClass().defaultfont();
2510 if (fonts_default_family == "rmdefault")
2511 f.setFamily(ROMAN_FAMILY);
2512 else if (fonts_default_family == "sfdefault")
2513 f.setFamily(SANS_FAMILY);
2514 else if (fonts_default_family == "ttdefault")
2515 f.setFamily(TYPEWRITER_FAMILY);
2516 return Font(f, language);
2520 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const & qs) const
2522 return quoteslangtranslator().find(qs);
2526 bool BufferParams::isLatex() const
2528 return documentClass().outputType() == LATEX;
2532 bool BufferParams::isLiterate() const
2534 return documentClass().outputType() == LITERATE;
2538 bool BufferParams::isDocBook() const
2540 return documentClass().outputType() == DOCBOOK;
2544 void BufferParams::readPreamble(Lexer & lex)
2546 if (lex.getString() != "\\begin_preamble")
2547 lyxerr << "Error (BufferParams::readPreamble):"
2548 "consistency check failed." << endl;
2550 preamble = lex.getLongString("\\end_preamble");
2554 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2556 string const expected = forced ? "\\begin_forced_local_layout" :
2557 "\\begin_local_layout";
2558 if (lex.getString() != expected)
2559 lyxerr << "Error (BufferParams::readLocalLayout):"
2560 "consistency check failed." << endl;
2563 forced_local_layout_ =
2564 lex.getLongString("\\end_forced_local_layout");
2566 local_layout_ = lex.getLongString("\\end_local_layout");
2570 bool BufferParams::setLanguage(string const & lang)
2572 Language const *new_language = languages.getLanguage(lang);
2573 if (!new_language) {
2574 // Language lang was not found
2577 language = new_language;
2582 void BufferParams::readLanguage(Lexer & lex)
2584 if (!lex.next()) return;
2586 string const tmptok = lex.getString();
2588 // check if tmptok is part of tex_babel in tex-defs.h
2589 if (!setLanguage(tmptok)) {
2590 // Language tmptok was not found
2591 language = default_language;
2592 lyxerr << "Warning: Setting language `"
2593 << tmptok << "' to `" << language->lang()
2599 void BufferParams::readGraphicsDriver(Lexer & lex)
2604 string const tmptok = lex.getString();
2605 // check if tmptok is part of tex_graphics in tex_defs.h
2608 string const test = tex_graphics[n++];
2610 if (test == tmptok) {
2611 graphics_driver = tmptok;
2616 "Warning: graphics driver `$$Token' not recognized!\n"
2617 " Setting graphics driver to `default'.\n");
2618 graphics_driver = "default";
2625 void BufferParams::readBullets(Lexer & lex)
2630 int const index = lex.getInteger();
2632 int temp_int = lex.getInteger();
2633 user_defined_bullet(index).setFont(temp_int);
2634 temp_bullet(index).setFont(temp_int);
2636 user_defined_bullet(index).setCharacter(temp_int);
2637 temp_bullet(index).setCharacter(temp_int);
2639 user_defined_bullet(index).setSize(temp_int);
2640 temp_bullet(index).setSize(temp_int);
2644 void BufferParams::readBulletsLaTeX(Lexer & lex)
2646 // The bullet class should be able to read this.
2649 int const index = lex.getInteger();
2651 docstring const temp_str = lex.getDocString();
2653 user_defined_bullet(index).setText(temp_str);
2654 temp_bullet(index).setText(temp_str);
2658 void BufferParams::readModules(Lexer & lex)
2660 if (!lex.eatLine()) {
2661 lyxerr << "Error (BufferParams::readModules):"
2662 "Unexpected end of input." << endl;
2666 string mod = lex.getString();
2667 if (mod == "\\end_modules")
2669 addLayoutModule(mod);
2675 void BufferParams::readRemovedModules(Lexer & lex)
2677 if (!lex.eatLine()) {
2678 lyxerr << "Error (BufferParams::readRemovedModules):"
2679 "Unexpected end of input." << endl;
2683 string mod = lex.getString();
2684 if (mod == "\\end_removed_modules")
2686 removed_modules_.push_back(mod);
2689 // now we want to remove any removed modules that were previously
2690 // added. normally, that will be because default modules were added in
2691 // setBaseClass(), which gets called when \textclass is read at the
2692 // start of the read.
2693 list<string>::const_iterator rit = removed_modules_.begin();
2694 list<string>::const_iterator const ren = removed_modules_.end();
2695 for (; rit != ren; ++rit) {
2696 LayoutModuleList::iterator const mit = layout_modules_.begin();
2697 LayoutModuleList::iterator const men = layout_modules_.end();
2698 LayoutModuleList::iterator found = find(mit, men, *rit);
2701 layout_modules_.erase(found);
2706 void BufferParams::readIncludeonly(Lexer & lex)
2708 if (!lex.eatLine()) {
2709 lyxerr << "Error (BufferParams::readIncludeonly):"
2710 "Unexpected end of input." << endl;
2714 string child = lex.getString();
2715 if (child == "\\end_includeonly")
2717 included_children_.push_back(child);
2723 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2725 switch (papersize) {
2727 // could be anything, so don't guess
2729 case PAPER_CUSTOM: {
2730 if (purpose == XDVI && !paperwidth.empty() &&
2731 !paperheight.empty()) {
2732 // heightxwidth<unit>
2733 string first = paperwidth;
2734 string second = paperheight;
2735 if (orientation == ORIENTATION_LANDSCAPE)
2738 return first.erase(first.length() - 2)
2744 // dvips and dvipdfm do not know this
2745 if (purpose == DVIPS || purpose == DVIPDFM)
2749 if (purpose == DVIPS || purpose == DVIPDFM)
2753 if (purpose == DVIPS || purpose == DVIPDFM)
2763 if (purpose == DVIPS || purpose == DVIPDFM)
2767 if (purpose == DVIPS || purpose == DVIPDFM)
2771 if (purpose == DVIPS || purpose == DVIPDFM)
2775 if (purpose == DVIPS || purpose == DVIPDFM)
2779 if (purpose == DVIPS || purpose == DVIPDFM)
2783 // dvipdfm does not know this
2784 if (purpose == DVIPDFM)
2788 if (purpose == DVIPDFM)
2792 if (purpose == DVIPS || purpose == DVIPDFM)
2796 if (purpose == DVIPS || purpose == DVIPDFM)
2800 if (purpose == DVIPS || purpose == DVIPDFM)
2804 if (purpose == DVIPS || purpose == DVIPDFM)
2808 if (purpose == DVIPS || purpose == DVIPDFM)
2812 if (purpose == DVIPS || purpose == DVIPDFM)
2816 if (purpose == DVIPS || purpose == DVIPDFM)
2820 if (purpose == DVIPS || purpose == DVIPDFM)
2824 if (purpose == DVIPS || purpose == DVIPDFM)
2828 if (purpose == DVIPS || purpose == DVIPDFM)
2832 if (purpose == DVIPS || purpose == DVIPDFM)
2836 if (purpose == DVIPS || purpose == DVIPDFM)
2840 if (purpose == DVIPS || purpose == DVIPDFM)
2844 if (purpose == DVIPS || purpose == DVIPDFM)
2848 if (purpose == DVIPS || purpose == DVIPDFM)
2851 case PAPER_USEXECUTIVE:
2852 // dvipdfm does not know this
2853 if (purpose == DVIPDFM)
2858 case PAPER_USLETTER:
2860 if (purpose == XDVI)
2867 string const BufferParams::dvips_options() const
2871 // If the class loads the geometry package, we do not know which
2872 // paper size is used, since we do not set it (bug 7013).
2873 // Therefore we must not specify any argument here.
2874 // dvips gets the correct paper size via DVI specials in this case
2875 // (if the class uses the geometry package correctly).
2876 if (documentClass().provides("geometry"))
2880 && papersize == PAPER_CUSTOM
2881 && !lyxrc.print_paper_dimension_flag.empty()
2882 && !paperwidth.empty()
2883 && !paperheight.empty()) {
2884 // using a custom papersize
2885 result = lyxrc.print_paper_dimension_flag;
2886 result += ' ' + paperwidth;
2887 result += ',' + paperheight;
2889 string const paper_option = paperSizeName(DVIPS);
2890 if (!paper_option.empty() && (paper_option != "letter" ||
2891 orientation != ORIENTATION_LANDSCAPE)) {
2892 // dvips won't accept -t letter -t landscape.
2893 // In all other cases, include the paper size
2895 result = lyxrc.print_paper_flag;
2896 result += ' ' + paper_option;
2899 if (orientation == ORIENTATION_LANDSCAPE &&
2900 papersize != PAPER_CUSTOM)
2901 result += ' ' + lyxrc.print_landscape_flag;
2906 string const BufferParams::font_encoding() const
2908 return font_encodings().empty() ? "default" : font_encodings().back();
2912 vector<string> const BufferParams::font_encodings() const
2914 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2916 vector<string> fontencs;
2918 // "default" means "no explicit font encoding"
2919 if (doc_fontenc != "default") {
2920 fontencs = getVectorFromString(doc_fontenc);
2921 if (!language->fontenc().empty()
2922 && ascii_lowercase(language->fontenc()) != "none") {
2923 vector<string> fencs = getVectorFromString(language->fontenc());
2924 vector<string>::const_iterator fit = fencs.begin();
2925 for (; fit != fencs.end(); ++fit) {
2926 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
2927 fontencs.push_back(*fit);
2936 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2938 // suppress the babel call if there is no BabelName defined
2939 // for the document language in the lib/languages file and if no
2940 // other languages are used (lang_opts is then empty)
2941 if (lang_opts.empty())
2943 // either a specific language (AsBabelOptions setting in
2944 // lib/languages) or the prefs require the languages to
2945 // be submitted to babel itself (not the class).
2947 return "\\usepackage[" + lang_opts + "]{babel}";
2948 return "\\usepackage{babel}";
2952 docstring BufferParams::getGraphicsDriver(string const & package) const
2956 if (package == "geometry") {
2957 if (graphics_driver == "dvips"
2958 || graphics_driver == "dvipdfm"
2959 || graphics_driver == "pdftex"
2960 || graphics_driver == "vtex")
2961 result = from_ascii(graphics_driver);
2962 else if (graphics_driver == "dvipdfmx")
2963 result = from_ascii("dvipdfm");
2970 void BufferParams::writeEncodingPreamble(otexstream & os,
2971 LaTeXFeatures & features) const
2973 // XeTeX/LuaTeX: (see also #9740)
2974 // With Unicode fonts we use utf8-plain without encoding package.
2975 // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails.
2976 // XeTeX must use ASCII encoding (see Buffer.cpp),
2977 // for LuaTeX, we load "luainputenc" (see below).
2978 if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
2981 if (inputenc == "auto") {
2982 string const doc_encoding =
2983 language->encoding()->latexName();
2984 Encoding::Package const package =
2985 language->encoding()->package();
2987 // Create list of inputenc options:
2988 set<string> encodings;
2989 // luainputenc fails with more than one encoding
2990 if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts
2991 // list all input encodings used in the document
2992 encodings = features.getEncodingSet(doc_encoding);
2994 // If the "japanese" package (i.e. pLaTeX) is used,
2995 // inputenc must be omitted.
2996 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2997 if ((!encodings.empty() || package == Encoding::inputenc)
2998 && !features.isRequired("japanese")
2999 && !features.isProvided("inputenc")) {
3000 os << "\\usepackage[";
3001 set<string>::const_iterator it = encodings.begin();
3002 set<string>::const_iterator const end = encodings.end();
3004 os << from_ascii(*it);
3007 for (; it != end; ++it)
3008 os << ',' << from_ascii(*it);
3009 if (package == Encoding::inputenc) {
3010 if (!encodings.empty())
3012 os << from_ascii(doc_encoding);
3014 if (features.runparams().flavor == OutputParams::LUATEX
3015 || features.runparams().flavor == OutputParams::DVILUATEX)
3016 os << "]{luainputenc}\n";
3018 os << "]{inputenc}\n";
3020 if (package == Encoding::CJK || features.mustProvide("CJK")) {
3021 if (language->encoding()->name() == "utf8-cjk"
3022 && LaTeXFeatures::isAvailable("CJKutf8"))
3023 os << "\\usepackage{CJKutf8}\n";
3025 os << "\\usepackage{CJK}\n";
3027 } else if (inputenc != "default") {
3028 switch (encoding().package()) {
3029 case Encoding::none:
3030 case Encoding::japanese:
3032 case Encoding::inputenc:
3033 // do not load inputenc if japanese is used
3034 // or if the class provides inputenc
3035 if (features.isRequired("japanese")
3036 || features.isProvided("inputenc"))
3038 os << "\\usepackage[" << from_ascii(encoding().latexName());
3039 if (features.runparams().flavor == OutputParams::LUATEX
3040 || features.runparams().flavor == OutputParams::DVILUATEX)
3041 os << "]{luainputenc}\n";
3043 os << "]{inputenc}\n";
3046 if (encoding().name() == "utf8-cjk"
3047 && LaTeXFeatures::isAvailable("CJKutf8"))
3048 os << "\\usepackage{CJKutf8}\n";
3050 os << "\\usepackage{CJK}\n";
3053 // Load the CJK package if needed by a secondary language.
3054 // If the main encoding is some variant of UTF8, use CJKutf8.
3055 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
3056 if (encoding().iconvName() == "UTF-8"
3057 && LaTeXFeatures::isAvailable("CJKutf8"))
3058 os << "\\usepackage{CJKutf8}\n";
3060 os << "\\usepackage{CJK}\n";
3066 string const BufferParams::parseFontName(string const & name) const
3068 string mangled = name;
3069 size_t const idx = mangled.find('[');
3070 if (idx == string::npos || idx == 0)
3073 return mangled.substr(0, idx - 1);
3077 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3079 if (fontsRoman() == "default" && fontsSans() == "default"
3080 && fontsTypewriter() == "default"
3081 && (fontsMath() == "default" || fontsMath() == "auto"))
3087 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3088 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3089 * Mapping=tex-text option assures TeX ligatures (such as "--")
3090 * are resolved. Note that tt does not use these ligatures.
3092 * -- add more GUI options?
3093 * -- add more fonts (fonts for other scripts)
3094 * -- if there's a way to find out if a font really supports
3095 * OldStyle, enable/disable the widget accordingly.
3097 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3098 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3099 // However, until v.2 (2010/07/11) fontspec only knew
3100 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3101 // was introduced for both XeTeX and LuaTeX (LuaTeX
3102 // didn't understand "Mapping=tex-text", while XeTeX
3103 // understood both. With most recent versions, both
3104 // variants are understood by both engines. However,
3105 // we want to provide support for at least TeXLive 2009
3106 // (for XeTeX; LuaTeX is only supported as of v.2)
3107 string const texmapping =
3108 (features.runparams().flavor == OutputParams::XETEX) ?
3109 "Mapping=tex-text" : "Ligatures=TeX";
3110 if (fontsRoman() != "default") {
3111 os << "\\setmainfont[" << texmapping;
3112 if (fonts_old_figures)
3113 os << ",Numbers=OldStyle";
3114 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3116 if (fontsSans() != "default") {
3117 string const sans = parseFontName(fontsSans());
3118 if (fontsSansScale() != 100)
3119 os << "\\setsansfont[Scale="
3120 << float(fontsSansScale()) / 100
3121 << "," << texmapping << "]{"
3124 os << "\\setsansfont[" << texmapping << "]{"
3127 if (fontsTypewriter() != "default") {
3128 string const mono = parseFontName(fontsTypewriter());
3129 if (fontsTypewriterScale() != 100)
3130 os << "\\setmonofont[Scale="
3131 << float(fontsTypewriterScale()) / 100
3135 os << "\\setmonofont{"
3142 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
3143 bool const dryrun = features.runparams().dryrun;
3144 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3145 bool const nomath = (fontsMath() == "default");
3148 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3149 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3153 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3154 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3155 nomath, fontsSansScale());
3157 // MONOSPACED/TYPEWRITER
3158 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3159 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3160 nomath, fontsTypewriterScale());
3163 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3164 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3171 Encoding const & BufferParams::encoding() const
3173 // Main encoding for LaTeX output.
3175 // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740).
3176 // As the "flavor" is only known once export started, this
3177 // cannot be handled here. Instead, runparams.encoding is set
3178 // to ASCII in Buffer::makeLaTeXFile (for export)
3179 // and Buffer::writeLaTeXSource (for preview).
3181 return *(encodings.fromLyXName("utf8-plain"));
3182 if (inputenc == "auto" || inputenc == "default")
3183 return *language->encoding();
3184 Encoding const * const enc = encodings.fromLyXName(inputenc);
3187 LYXERR0("Unknown inputenc value `" << inputenc
3188 << "'. Using `auto' instead.");
3189 return *language->encoding();
3193 bool BufferParams::addCiteEngine(string const & engine)
3195 LayoutModuleList::const_iterator it = cite_engine_.begin();
3196 LayoutModuleList::const_iterator en = cite_engine_.end();
3197 for (; it != en; ++it)
3200 cite_engine_.push_back(engine);
3205 bool BufferParams::addCiteEngine(vector<string> const & engine)
3207 vector<string>::const_iterator it = engine.begin();
3208 vector<string>::const_iterator en = engine.end();
3210 for (; it != en; ++it)
3211 if (!addCiteEngine(*it))
3217 string const & BufferParams::defaultBiblioStyle() const
3219 return documentClass().defaultBiblioStyle();
3223 bool const & BufferParams::fullAuthorList() const
3225 return documentClass().fullAuthorList();
3229 void BufferParams::setCiteEngine(string const & engine)
3232 addCiteEngine(engine);
3236 void BufferParams::setCiteEngine(vector<string> const & engine)
3239 addCiteEngine(engine);
3243 vector<string> BufferParams::citeCommands() const
3245 static CitationStyle const default_style;
3246 vector<string> commands =
3247 documentClass().citeCommands(citeEngineType());
3248 if (commands.empty())
3249 commands.push_back(default_style.cmd);
3254 vector<CitationStyle> BufferParams::citeStyles() const
3256 static CitationStyle const default_style;
3257 vector<CitationStyle> styles =
3258 documentClass().citeStyles(citeEngineType());
3260 styles.push_back(default_style);