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 string const relpath =
1024 to_utf8(makeRelPath(from_utf8(filepath), from_utf8(sysdir)));
1025 if (!prefixIs(relpath, "../") && !FileName::isAbsolute(relpath))
1026 filepath = addPath("/systemlyxdir", relpath);
1027 else if (!lyxrc.save_origin)
1028 filepath = "unavailable";
1029 os << "\\origin " << quoteIfNeeded(filepath) << '\n';
1032 os << "\\textclass "
1033 << quoteIfNeeded(buf->includedFilePath(addName(buf->layoutPos(),
1034 baseClass()->name()), "layout"))
1037 // then the preamble
1038 if (!preamble.empty()) {
1039 // remove '\n' from the end of preamble
1040 string const tmppreamble = rtrim(preamble, "\n");
1041 os << "\\begin_preamble\n"
1043 << "\n\\end_preamble\n";
1047 if (!options.empty()) {
1048 os << "\\options " << options << '\n';
1051 // use the class options defined in the layout?
1052 os << "\\use_default_options "
1053 << convert<string>(use_default_options) << "\n";
1055 // the master document
1056 if (!master.empty()) {
1057 os << "\\master " << master << '\n';
1061 if (!removed_modules_.empty()) {
1062 os << "\\begin_removed_modules" << '\n';
1063 list<string>::const_iterator it = removed_modules_.begin();
1064 list<string>::const_iterator en = removed_modules_.end();
1065 for (; it != en; ++it)
1067 os << "\\end_removed_modules" << '\n';
1071 if (!layout_modules_.empty()) {
1072 os << "\\begin_modules" << '\n';
1073 LayoutModuleList::const_iterator it = layout_modules_.begin();
1074 LayoutModuleList::const_iterator en = layout_modules_.end();
1075 for (; it != en; ++it)
1077 os << "\\end_modules" << '\n';
1081 if (!included_children_.empty()) {
1082 os << "\\begin_includeonly" << '\n';
1083 list<string>::const_iterator it = included_children_.begin();
1084 list<string>::const_iterator en = included_children_.end();
1085 for (; it != en; ++it)
1087 os << "\\end_includeonly" << '\n';
1089 os << "\\maintain_unincluded_children "
1090 << convert<string>(maintain_unincluded_children) << '\n';
1092 // local layout information
1093 string const local_layout = getLocalLayout(false);
1094 if (!local_layout.empty()) {
1095 // remove '\n' from the end
1096 string const tmplocal = rtrim(local_layout, "\n");
1097 os << "\\begin_local_layout\n"
1099 << "\n\\end_local_layout\n";
1101 string const forced_local_layout = getLocalLayout(true);
1102 if (!forced_local_layout.empty()) {
1103 // remove '\n' from the end
1104 string const tmplocal = rtrim(forced_local_layout, "\n");
1105 os << "\\begin_forced_local_layout\n"
1107 << "\n\\end_forced_local_layout\n";
1110 // then the text parameters
1111 if (language != ignore_language)
1112 os << "\\language " << language->lang() << '\n';
1113 os << "\\language_package " << lang_package
1114 << "\n\\inputencoding " << inputenc
1115 << "\n\\fontencoding " << fontenc
1116 << "\n\\font_roman \"" << fonts_roman[0]
1117 << "\" \"" << fonts_roman[1] << '"'
1118 << "\n\\font_sans \"" << fonts_sans[0]
1119 << "\" \"" << fonts_sans[1] << '"'
1120 << "\n\\font_typewriter \"" << fonts_typewriter[0]
1121 << "\" \"" << fonts_typewriter[1] << '"'
1122 << "\n\\font_math \"" << fonts_math[0]
1123 << "\" \"" << fonts_math[1] << '"'
1124 << "\n\\font_default_family " << fonts_default_family
1125 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1126 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1127 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1128 << "\n\\font_sf_scale " << fonts_sans_scale[0]
1129 << ' ' << fonts_sans_scale[1]
1130 << "\n\\font_tt_scale " << fonts_typewriter_scale[0]
1131 << ' ' << fonts_typewriter_scale[1]
1133 if (!fonts_cjk.empty()) {
1134 os << "\\font_cjk " << fonts_cjk << '\n';
1136 os << "\\graphics " << graphics_driver << '\n';
1137 os << "\\default_output_format " << default_output_format << '\n';
1138 os << "\\output_sync " << output_sync << '\n';
1139 if (!output_sync_macro.empty())
1140 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1141 os << "\\bibtex_command " << bibtex_command << '\n';
1142 os << "\\index_command " << index_command << '\n';
1144 if (!float_placement.empty()) {
1145 os << "\\float_placement " << float_placement << '\n';
1147 os << "\\paperfontsize " << fontsize << '\n';
1149 spacing().writeFile(os);
1150 pdfoptions().writeFile(os);
1152 os << "\\papersize " << string_papersize[papersize]
1153 << "\n\\use_geometry " << convert<string>(use_geometry);
1154 map<string, string> const & packages = auto_packages();
1155 for (map<string, string>::const_iterator it = packages.begin();
1156 it != packages.end(); ++it)
1157 os << "\n\\use_package " << it->first << ' '
1158 << use_package(it->first);
1160 os << "\n\\cite_engine ";
1162 if (!cite_engine_.empty()) {
1163 LayoutModuleList::const_iterator be = cite_engine_.begin();
1164 LayoutModuleList::const_iterator en = cite_engine_.end();
1165 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1174 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1175 << "\n\\biblio_style " << biblio_style
1176 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1177 << "\n\\use_indices " << convert<string>(use_indices)
1178 << "\n\\paperorientation " << string_orientation[orientation]
1179 << "\n\\suppress_date " << convert<string>(suppress_date)
1180 << "\n\\justification " << convert<string>(justification)
1181 << "\n\\use_refstyle " << use_refstyle
1183 if (isbackgroundcolor == true)
1184 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1185 if (isfontcolor == true)
1186 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1187 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1188 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1189 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1190 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1192 BranchList::const_iterator it = branchlist().begin();
1193 BranchList::const_iterator end = branchlist().end();
1194 for (; it != end; ++it) {
1195 os << "\\branch " << to_utf8(it->branch())
1196 << "\n\\selected " << it->isSelected()
1197 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1198 << "\n\\color " << lyx::X11hexname(it->color())
1203 IndicesList::const_iterator iit = indiceslist().begin();
1204 IndicesList::const_iterator iend = indiceslist().end();
1205 for (; iit != iend; ++iit) {
1206 os << "\\index " << to_utf8(iit->index())
1207 << "\n\\shortcut " << to_utf8(iit->shortcut())
1208 << "\n\\color " << lyx::X11hexname(iit->color())
1213 if (!paperwidth.empty())
1214 os << "\\paperwidth "
1215 << VSpace(paperwidth).asLyXCommand() << '\n';
1216 if (!paperheight.empty())
1217 os << "\\paperheight "
1218 << VSpace(paperheight).asLyXCommand() << '\n';
1219 if (!leftmargin.empty())
1220 os << "\\leftmargin "
1221 << VSpace(leftmargin).asLyXCommand() << '\n';
1222 if (!topmargin.empty())
1223 os << "\\topmargin "
1224 << VSpace(topmargin).asLyXCommand() << '\n';
1225 if (!rightmargin.empty())
1226 os << "\\rightmargin "
1227 << VSpace(rightmargin).asLyXCommand() << '\n';
1228 if (!bottommargin.empty())
1229 os << "\\bottommargin "
1230 << VSpace(bottommargin).asLyXCommand() << '\n';
1231 if (!headheight.empty())
1232 os << "\\headheight "
1233 << VSpace(headheight).asLyXCommand() << '\n';
1234 if (!headsep.empty())
1236 << VSpace(headsep).asLyXCommand() << '\n';
1237 if (!footskip.empty())
1239 << VSpace(footskip).asLyXCommand() << '\n';
1240 if (!columnsep.empty())
1241 os << "\\columnsep "
1242 << VSpace(columnsep).asLyXCommand() << '\n';
1243 os << "\\secnumdepth " << secnumdepth
1244 << "\n\\tocdepth " << tocdepth
1245 << "\n\\paragraph_separation "
1246 << string_paragraph_separation[paragraph_separation];
1247 if (!paragraph_separation)
1248 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1250 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1251 os << "\n\\quotes_language "
1252 << string_quotes_language[quotes_language]
1253 << "\n\\papercolumns " << columns
1254 << "\n\\papersides " << sides
1255 << "\n\\paperpagestyle " << pagestyle << '\n';
1256 if (!listings_params.empty())
1257 os << "\\listings_params \"" <<
1258 InsetListingsParams(listings_params).encodedString() << "\"\n";
1259 for (int i = 0; i < 4; ++i) {
1260 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1261 if (user_defined_bullet(i).getFont() != -1) {
1262 os << "\\bullet " << i << " "
1263 << user_defined_bullet(i).getFont() << " "
1264 << user_defined_bullet(i).getCharacter() << " "
1265 << user_defined_bullet(i).getSize() << "\n";
1269 os << "\\bulletLaTeX " << i << " \""
1270 << lyx::to_ascii(user_defined_bullet(i).getText())
1276 os << "\\tracking_changes " << convert<string>(track_changes) << '\n'
1277 << "\\html_math_output " << html_math_output << '\n'
1278 << "\\html_css_as_file " << html_css_as_file << '\n'
1279 // \output_changes is output at a distance from \tracking changes as a
1280 // workaround to bug #9841: both parameters can be seen as per-user
1281 // preferences and therefore can cause undesirable merge conflicts, in a
1282 // multi-author setting, if it were treated as a single block by the
1283 // version control system.
1284 << "\\output_changes " << convert<string>(output_changes) << '\n'
1285 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1287 if (html_math_img_scale != 1.0)
1288 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1289 if (!html_latex_start.empty())
1290 os << "\\html_latex_start " << html_latex_start << '\n';
1291 if (!html_latex_end.empty())
1292 os << "\\html_latex_end " << html_latex_end << '\n';
1294 os << pimpl_->authorlist;
1298 void BufferParams::validate(LaTeXFeatures & features) const
1300 features.require(documentClass().requires());
1302 if (columns > 1 && language->rightToLeft())
1303 features.require("rtloutputdblcol");
1305 if (output_changes) {
1306 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1307 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1308 LaTeXFeatures::isAvailable("xcolor");
1310 switch (features.runparams().flavor) {
1311 case OutputParams::LATEX:
1312 case OutputParams::DVILUATEX:
1314 features.require("ct-dvipost");
1315 features.require("dvipost");
1316 } else if (xcolorulem) {
1317 features.require("ct-xcolor-ulem");
1318 features.require("ulem");
1319 features.require("xcolor");
1321 features.require("ct-none");
1324 case OutputParams::LUATEX:
1325 case OutputParams::PDFLATEX:
1326 case OutputParams::XETEX:
1328 features.require("ct-xcolor-ulem");
1329 features.require("ulem");
1330 features.require("xcolor");
1331 // improves color handling in PDF output
1332 features.require("pdfcolmk");
1334 features.require("ct-none");
1342 // Floats with 'Here definitely' as default setting.
1343 if (float_placement.find('H') != string::npos)
1344 features.require("float");
1346 for (PackageMap::const_iterator it = use_packages.begin();
1347 it != use_packages.end(); ++it) {
1348 if (it->first == "amsmath") {
1349 // AMS Style is at document level
1350 if (it->second == package_on ||
1351 features.isProvided("amsmath"))
1352 features.require(it->first);
1353 } else if (it->second == package_on)
1354 features.require(it->first);
1357 // Document-level line spacing
1358 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1359 features.require("setspace");
1361 // the bullet shapes are buffer level not paragraph level
1362 // so they are tested here
1363 for (int i = 0; i < 4; ++i) {
1364 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1366 int const font = user_defined_bullet(i).getFont();
1368 int const c = user_defined_bullet(i).getCharacter();
1374 features.require("latexsym");
1376 } else if (font == 1) {
1377 features.require("amssymb");
1378 } else if (font >= 2 && font <= 5) {
1379 features.require("pifont");
1383 if (pdfoptions().use_hyperref) {
1384 features.require("hyperref");
1385 // due to interferences with babel and hyperref, the color package has to
1386 // be loaded after hyperref when hyperref is used with the colorlinks
1387 // option, see http://www.lyx.org/trac/ticket/5291
1388 if (pdfoptions().colorlinks)
1389 features.require("color");
1391 if (!listings_params.empty()) {
1392 // do not test validity because listings_params is
1393 // supposed to be valid
1395 InsetListingsParams(listings_params).separatedParams(true);
1396 // we can't support all packages, but we should load the color package
1397 if (par.find("\\color", 0) != string::npos)
1398 features.require("color");
1401 // some languages are only available via polyglossia
1402 if ((features.runparams().flavor == OutputParams::XETEX
1403 || features.runparams().flavor == OutputParams::LUATEX)
1404 && (features.hasPolyglossiaExclusiveLanguages()
1406 features.require("polyglossia");
1408 if (useNonTeXFonts && fontsMath() != "auto")
1409 features.require("unicode-math");
1411 if (!language->requires().empty())
1412 features.require(language->requires());
1416 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1417 FileName const & filepath) const
1419 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1420 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1421 // \RequirePackage to do so, rather than the normal \usepackage
1422 // Do not try to load any other package before the document class, unless you
1423 // have a thorough understanding of the LATEX internals and know exactly what you
1425 if (features.mustProvide("fix-cm"))
1426 os << "\\RequirePackage{fix-cm}\n";
1427 // Likewise for fixltx2e. If other packages conflict with this policy,
1428 // treat it as a package bug (and report it!)
1429 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1430 if (features.mustProvide("fixltx2e"))
1431 os << "\\RequirePackage{fixltx2e}\n";
1433 os << "\\documentclass";
1435 DocumentClass const & tclass = documentClass();
1437 ostringstream clsoptions; // the document class options.
1439 if (tokenPos(tclass.opt_fontsize(),
1440 '|', fontsize) >= 0) {
1441 // only write if existing in list (and not default)
1442 clsoptions << fontsize << "pt,";
1445 // all paper sizes except of A4, A5, B5 and the US sizes need the
1447 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1448 && papersize != PAPER_USLETTER
1449 && papersize != PAPER_USLEGAL
1450 && papersize != PAPER_USEXECUTIVE
1451 && papersize != PAPER_A4
1452 && papersize != PAPER_A5
1453 && papersize != PAPER_B5;
1455 if (!use_geometry) {
1456 switch (papersize) {
1458 clsoptions << "a4paper,";
1460 case PAPER_USLETTER:
1461 clsoptions << "letterpaper,";
1464 clsoptions << "a5paper,";
1467 clsoptions << "b5paper,";
1469 case PAPER_USEXECUTIVE:
1470 clsoptions << "executivepaper,";
1473 clsoptions << "legalpaper,";
1507 if (sides != tclass.sides()) {
1510 clsoptions << "oneside,";
1513 clsoptions << "twoside,";
1519 if (columns != tclass.columns()) {
1521 clsoptions << "twocolumn,";
1523 clsoptions << "onecolumn,";
1527 && orientation == ORIENTATION_LANDSCAPE)
1528 clsoptions << "landscape,";
1530 // language should be a parameter to \documentclass
1531 if (language->babel() == "hebrew"
1532 && default_language->babel() != "hebrew")
1533 // This seems necessary
1534 features.useLanguage(default_language);
1536 ostringstream language_options;
1537 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1538 bool const use_polyglossia = features.usePolyglossia();
1539 bool const global = lyxrc.language_global_options;
1540 if (use_babel || (use_polyglossia && global)) {
1541 language_options << features.getBabelLanguages();
1542 if (!language->babel().empty()) {
1543 if (!language_options.str().empty())
1544 language_options << ',';
1545 language_options << language->babel();
1547 if (global && !features.needBabelLangOptions()
1548 && !language_options.str().empty())
1549 clsoptions << language_options.str() << ',';
1552 // the predefined options from the layout
1553 if (use_default_options && !tclass.options().empty())
1554 clsoptions << tclass.options() << ',';
1556 // the user-defined options
1557 if (!options.empty()) {
1558 clsoptions << options << ',';
1561 string strOptions(clsoptions.str());
1562 if (!strOptions.empty()) {
1563 strOptions = rtrim(strOptions, ",");
1565 os << '[' << from_utf8(strOptions) << ']';
1568 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1569 // end of \documentclass defs
1571 // if we use fontspec or newtxmath, we have to load the AMS packages here
1572 string const ams = features.loadAMSPackages();
1573 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1574 bool const use_newtxmath =
1575 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1576 ot1, false, false) == "newtxmath";
1577 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1578 os << from_ascii(ams);
1580 if (useNonTeXFonts) {
1581 os << "\\usepackage{fontspec}\n";
1582 if (features.mustProvide("unicode-math")
1583 && features.isAvailable("unicode-math"))
1584 os << "\\usepackage{unicode-math}\n";
1587 // font selection must be done before loading fontenc.sty
1588 string const fonts = loadFonts(features);
1590 os << from_utf8(fonts);
1592 if (fonts_default_family != "default")
1593 os << "\\renewcommand{\\familydefault}{\\"
1594 << from_ascii(fonts_default_family) << "}\n";
1596 // set font encoding
1597 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1598 if (!useNonTeXFonts && !features.isProvided("fontenc")
1599 && font_encoding() != "default") {
1600 // get main font encodings
1601 vector<string> fontencs = font_encodings();
1602 // get font encodings of secondary languages
1603 features.getFontEncodings(fontencs);
1604 if (!fontencs.empty()) {
1605 os << "\\usepackage["
1606 << from_ascii(getStringFromVector(fontencs))
1611 // handle inputenc etc.
1612 writeEncodingPreamble(os, features);
1615 if (!features.runparams().includeall && !included_children_.empty()) {
1616 os << "\\includeonly{";
1617 list<string>::const_iterator it = included_children_.begin();
1618 list<string>::const_iterator en = included_children_.end();
1620 for (; it != en; ++it) {
1621 string incfile = *it;
1622 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1623 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1625 if (!features.runparams().nice)
1627 // \includeonly doesn't want an extension
1628 incfile = changeExtension(incfile, string());
1629 incfile = support::latex_path(incfile);
1630 if (!incfile.empty()) {
1633 os << from_utf8(incfile);
1640 if (!features.isProvided("geometry")
1641 && (use_geometry || nonstandard_papersize)) {
1642 odocstringstream ods;
1643 if (!getGraphicsDriver("geometry").empty())
1644 ods << getGraphicsDriver("geometry");
1645 if (orientation == ORIENTATION_LANDSCAPE)
1646 ods << ",landscape";
1647 switch (papersize) {
1649 if (!paperwidth.empty())
1650 ods << ",paperwidth="
1651 << from_ascii(paperwidth);
1652 if (!paperheight.empty())
1653 ods << ",paperheight="
1654 << from_ascii(paperheight);
1656 case PAPER_USLETTER:
1657 ods << ",letterpaper";
1660 ods << ",legalpaper";
1662 case PAPER_USEXECUTIVE:
1663 ods << ",executivepaper";
1752 docstring const g_options = trim(ods.str(), ",");
1753 os << "\\usepackage";
1754 if (!g_options.empty())
1755 os << '[' << g_options << ']';
1756 os << "{geometry}\n";
1757 // output this only if use_geometry is true
1759 os << "\\geometry{verbose";
1760 if (!topmargin.empty())
1761 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1762 if (!bottommargin.empty())
1763 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1764 if (!leftmargin.empty())
1765 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1766 if (!rightmargin.empty())
1767 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1768 if (!headheight.empty())
1769 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1770 if (!headsep.empty())
1771 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1772 if (!footskip.empty())
1773 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1774 if (!columnsep.empty())
1775 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1778 } else if (orientation == ORIENTATION_LANDSCAPE
1779 || papersize != PAPER_DEFAULT) {
1780 features.require("papersize");
1783 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1784 if (pagestyle == "fancy")
1785 os << "\\usepackage{fancyhdr}\n";
1786 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1789 // only output when the background color is not default
1790 if (isbackgroundcolor == true) {
1791 // only require color here, the background color will be defined
1792 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1794 features.require("color");
1795 features.require("pagecolor");
1798 // only output when the font color is not default
1799 if (isfontcolor == true) {
1800 // only require color here, the font color will be defined
1801 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1803 features.require("color");
1804 features.require("fontcolor");
1807 // Only if class has a ToC hierarchy
1808 if (tclass.hasTocLevels()) {
1809 if (secnumdepth != tclass.secnumdepth()) {
1810 os << "\\setcounter{secnumdepth}{"
1814 if (tocdepth != tclass.tocdepth()) {
1815 os << "\\setcounter{tocdepth}{"
1821 if (paragraph_separation) {
1822 // when skip separation
1823 switch (getDefSkip().kind()) {
1824 case VSpace::SMALLSKIP:
1825 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1827 case VSpace::MEDSKIP:
1828 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1830 case VSpace::BIGSKIP:
1831 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1833 case VSpace::LENGTH:
1834 os << "\\setlength{\\parskip}{"
1835 << from_utf8(getDefSkip().length().asLatexString())
1838 default: // should never happen // Then delete it.
1839 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1842 os << "\\setlength{\\parindent}{0pt}\n";
1844 // when separation by indentation
1845 // only output something when a width is given
1846 if (getIndentation().asLyXCommand() != "default") {
1847 os << "\\setlength{\\parindent}{"
1848 << from_utf8(getIndentation().asLatexCommand())
1853 // Now insert the LyX specific LaTeX commands...
1854 docstring lyxpreamble;
1855 features.resolveAlternatives();
1858 if (!output_sync_macro.empty())
1859 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1860 else if (features.runparams().flavor == OutputParams::LATEX)
1861 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1862 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1863 lyxpreamble += "\\synctex=-1\n";
1866 // The package options (via \PassOptionsToPackage)
1867 lyxpreamble += from_ascii(features.getPackageOptions());
1869 // due to interferences with babel and hyperref, the color package has to
1870 // be loaded (when it is not already loaded) before babel when hyperref
1871 // is used with the colorlinks option, see
1872 // http://www.lyx.org/trac/ticket/5291
1873 // we decided therefore to load color always before babel, see
1874 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1875 lyxpreamble += from_ascii(features.getColorOptions());
1877 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1878 // we have to call babel before
1880 && (features.isRequired("jurabib")
1881 || features.isRequired("hyperref")
1882 || features.isRequired("varioref")
1883 || features.isRequired("vietnamese")
1884 || features.isRequired("japanese"))) {
1886 lyxpreamble += from_utf8(features.getBabelPresettings());
1887 lyxpreamble += from_utf8(babelCall(language_options.str(),
1888 features.needBabelLangOptions())) + '\n';
1889 lyxpreamble += from_utf8(features.getBabelPostsettings());
1892 // The optional packages;
1893 lyxpreamble += from_ascii(features.getPackages());
1895 // Additional Indices
1896 if (features.isRequired("splitidx")) {
1897 IndicesList::const_iterator iit = indiceslist().begin();
1898 IndicesList::const_iterator iend = indiceslist().end();
1899 for (; iit != iend; ++iit) {
1900 pair<docstring, docstring> indexname_latex =
1901 features.runparams().encoding->latexString(iit->index(),
1902 features.runparams().dryrun);
1903 if (!indexname_latex.second.empty()) {
1904 // issue a warning about omitted characters
1905 // FIXME: should be passed to the error dialog
1906 frontend::Alert::warning(_("Uncodable characters"),
1907 bformat(_("The following characters that are used in an index name are not\n"
1908 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1909 indexname_latex.second));
1911 lyxpreamble += "\\newindex[";
1912 lyxpreamble += indexname_latex.first;
1913 lyxpreamble += "]{";
1914 lyxpreamble += escape(iit->shortcut());
1915 lyxpreamble += "}\n";
1920 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1923 // * Hyperref manual: "Make sure it comes last of your loaded
1924 // packages, to give it a fighting chance of not being over-written,
1925 // since its job is to redefine many LaTeX commands."
1926 // * Email from Heiko Oberdiek: "It is usually better to load babel
1927 // before hyperref. Then hyperref has a chance to detect babel.
1928 // * Has to be loaded before the "LyX specific LaTeX commands" to
1929 // avoid errors with algorithm floats.
1930 // use hyperref explicitly if it is required
1931 if (features.isRequired("hyperref")) {
1932 // pass what we have to stream here, since we need
1933 // to access the stream itself in PDFOptions.
1936 OutputParams tmp_params = features.runparams();
1937 pdfoptions().writeLaTeX(tmp_params, os,
1938 features.isProvided("hyperref"));
1939 // set back for the rest
1940 lyxpreamble.clear();
1941 // correctly break URLs with hyperref and dvi output
1942 if (features.runparams().flavor == OutputParams::LATEX
1943 && features.isAvailable("breakurl"))
1944 lyxpreamble += "\\usepackage{breakurl}\n";
1945 } else if (features.isRequired("nameref"))
1946 // hyperref loads this automatically
1947 lyxpreamble += "\\usepackage{nameref}\n";
1949 // bibtopic needs to be loaded after hyperref.
1950 // the dot provides the aux file naming which LyX can detect.
1951 if (features.mustProvide("bibtopic"))
1952 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1954 // Will be surrounded by \makeatletter and \makeatother when not empty
1955 docstring atlyxpreamble;
1957 // Some macros LyX will need
1958 docstring tmppreamble(features.getMacros());
1960 if (!tmppreamble.empty())
1961 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1962 "LyX specific LaTeX commands.\n"
1963 + tmppreamble + '\n';
1965 // the text class specific preamble
1966 tmppreamble = features.getTClassPreamble();
1967 if (!tmppreamble.empty())
1968 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1969 "Textclass specific LaTeX commands.\n"
1970 + tmppreamble + '\n';
1972 // suppress date if selected
1973 // use \@ifundefined because we cannot be sure that every document class
1974 // has a \date command
1976 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1978 /* the user-defined preamble */
1979 if (!containsOnly(preamble, " \n\t")) {
1981 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1982 "User specified LaTeX commands.\n";
1984 // Check if the user preamble contains uncodable glyphs
1985 docstring const u_preamble = from_utf8(preamble);
1986 odocstringstream user_preamble;
1987 docstring uncodable_glyphs;
1988 Encoding const * const enc = features.runparams().encoding;
1990 for (size_t n = 0; n < u_preamble.size(); ++n) {
1991 char_type c = u_preamble[n];
1992 if (!enc->encodable(c)) {
1993 docstring const glyph(1, c);
1994 LYXERR0("Uncodable character '"
1996 << "' in user preamble!");
1997 uncodable_glyphs += glyph;
1998 if (features.runparams().dryrun) {
1999 user_preamble << "<" << _("LyX Warning: ")
2000 << _("uncodable character") << " '";
2001 user_preamble.put(c);
2002 user_preamble << "'>";
2005 user_preamble.put(c);
2008 user_preamble << u_preamble;
2010 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2011 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2012 frontend::Alert::warning(
2013 _("Uncodable character in user preamble"),
2015 _("The user preamble of your document contains glyphs "
2016 "that are unknown in the current document encoding "
2017 "(namely %1$s).\nThese glyphs are omitted "
2018 " from the output, which may result in "
2019 "incomplete output."
2020 "\n\nPlease select an appropriate "
2021 "document encoding\n"
2022 "(such as utf8) or change the "
2023 "preamble code accordingly."),
2026 atlyxpreamble += user_preamble.str() + '\n';
2029 // footmisc must be loaded after setspace
2030 // Load it here to avoid clashes with footmisc loaded in the user
2031 // preamble. For that reason we also pass the options via
2032 // \PassOptionsToPackage in getPreamble() and not here.
2033 if (features.mustProvide("footmisc"))
2034 atlyxpreamble += "\\usepackage{footmisc}\n";
2036 // subfig loads internally the LaTeX package "caption". As
2037 // caption is a very popular package, users will load it in
2038 // the preamble. Therefore we must load subfig behind the
2039 // user-defined preamble and check if the caption package was
2040 // loaded or not. For the case that caption is loaded before
2041 // subfig, there is the subfig option "caption=false". This
2042 // option also works when a koma-script class is used and
2043 // koma's own caption commands are used instead of caption. We
2044 // use \PassOptionsToPackage here because the user could have
2045 // already loaded subfig in the preamble.
2046 if (features.isRequired("subfig")) {
2047 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
2048 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2049 "\\usepackage{subfig}\n";
2052 // Itemize bullet settings need to be last in case the user
2053 // defines their own bullets that use a package included
2054 // in the user-defined preamble -- ARRae
2055 // Actually it has to be done much later than that
2056 // since some packages like frenchb make modifications
2057 // at \begin{document} time -- JMarc
2058 docstring bullets_def;
2059 for (int i = 0; i < 4; ++i) {
2060 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2061 if (bullets_def.empty())
2062 bullets_def += "\\AtBeginDocument{\n";
2063 bullets_def += " \\def\\labelitemi";
2065 // `i' is one less than the item to modify
2072 bullets_def += "ii";
2078 bullets_def += '{' +
2079 user_defined_bullet(i).getText()
2084 if (!bullets_def.empty())
2085 atlyxpreamble += bullets_def + "}\n\n";
2087 if (!atlyxpreamble.empty())
2088 lyxpreamble += "\n\\makeatletter\n"
2089 + atlyxpreamble + "\\makeatother\n\n";
2091 // We try to load babel late, in case it interferes with other packages.
2092 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
2093 // called after babel, though.
2094 if (use_babel && !features.isRequired("jurabib")
2095 && !features.isRequired("hyperref")
2096 && !features.isRequired("varioref")
2097 && !features.isRequired("vietnamese")
2098 && !features.isRequired("japanese")) {
2100 lyxpreamble += from_utf8(features.getBabelPresettings());
2101 lyxpreamble += from_utf8(babelCall(language_options.str(),
2102 features.needBabelLangOptions())) + '\n';
2103 lyxpreamble += from_utf8(features.getBabelPostsettings());
2105 if (features.isRequired("bicaption"))
2106 lyxpreamble += "\\usepackage{bicaption}\n";
2107 if (!listings_params.empty() || features.isRequired("listings"))
2108 lyxpreamble += "\\usepackage{listings}\n";
2109 if (!listings_params.empty()) {
2110 lyxpreamble += "\\lstset{";
2111 // do not test validity because listings_params is
2112 // supposed to be valid
2114 InsetListingsParams(listings_params).separatedParams(true);
2115 lyxpreamble += from_utf8(par);
2116 lyxpreamble += "}\n";
2119 // xunicode needs to be loaded at least after amsmath, amssymb,
2120 // esint and the other packages that provide special glyphs
2121 if (features.runparams().flavor == OutputParams::XETEX
2123 lyxpreamble += "\\usepackage{xunicode}\n";
2125 // Polyglossia must be loaded last
2126 if (use_polyglossia) {
2128 lyxpreamble += "\\usepackage{polyglossia}\n";
2129 // set the main language
2130 lyxpreamble += "\\setdefaultlanguage";
2131 if (!language->polyglossiaOpts().empty())
2132 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
2133 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
2134 // now setup the other languages
2135 std::map<std::string, std::string> const polylangs =
2136 features.getPolyglossiaLanguages();
2137 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
2138 mit != polylangs.end() ; ++mit) {
2139 lyxpreamble += "\\setotherlanguage";
2140 if (!mit->second.empty())
2141 lyxpreamble += "[" + from_ascii(mit->second) + "]";
2142 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
2146 // Load custom language package here
2147 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2148 if (lang_package == "default")
2149 lyxpreamble += from_utf8(lyxrc.language_custom_package);
2151 lyxpreamble += from_utf8(lang_package);
2152 lyxpreamble += '\n';
2155 docstring const i18npreamble =
2156 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2157 if (!i18npreamble.empty())
2158 lyxpreamble += i18npreamble + '\n';
2166 void BufferParams::useClassDefaults()
2168 DocumentClass const & tclass = documentClass();
2170 sides = tclass.sides();
2171 columns = tclass.columns();
2172 pagestyle = tclass.pagestyle();
2173 use_default_options = true;
2174 // Only if class has a ToC hierarchy
2175 if (tclass.hasTocLevels()) {
2176 secnumdepth = tclass.secnumdepth();
2177 tocdepth = tclass.tocdepth();
2182 bool BufferParams::hasClassDefaults() const
2184 DocumentClass const & tclass = documentClass();
2186 return sides == tclass.sides()
2187 && columns == tclass.columns()
2188 && pagestyle == tclass.pagestyle()
2189 && use_default_options
2190 && secnumdepth == tclass.secnumdepth()
2191 && tocdepth == tclass.tocdepth();
2195 DocumentClass const & BufferParams::documentClass() const
2197 return *doc_class_.get();
2201 DocumentClassConstPtr BufferParams::documentClassPtr() const
2207 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2209 // evil, but this function is evil
2210 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2214 bool BufferParams::setBaseClass(string const & classname)
2216 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2217 LayoutFileList & bcl = LayoutFileList::get();
2218 if (!bcl.haveClass(classname)) {
2220 bformat(_("The layout file:\n"
2222 "could not be found. A default textclass with default\n"
2223 "layouts will be used. LyX will not be able to produce\n"
2225 from_utf8(classname));
2226 frontend::Alert::error(_("Document class not found"), s);
2227 bcl.addEmptyClass(classname);
2230 bool const success = bcl[classname].load();
2233 bformat(_("Due to some error in it, the layout file:\n"
2235 "could not be loaded. A default textclass with default\n"
2236 "layouts will be used. LyX will not be able to produce\n"
2238 from_utf8(classname));
2239 frontend::Alert::error(_("Could not load class"), s);
2240 bcl.addEmptyClass(classname);
2243 pimpl_->baseClass_ = classname;
2244 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2249 LayoutFile const * BufferParams::baseClass() const
2251 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2252 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2258 LayoutFileIndex const & BufferParams::baseClassID() const
2260 return pimpl_->baseClass_;
2264 void BufferParams::makeDocumentClass(bool const clone)
2269 LayoutModuleList mods;
2270 LayoutModuleList::iterator it = layout_modules_.begin();
2271 LayoutModuleList::iterator en = layout_modules_.end();
2272 for (; it != en; ++it)
2273 mods.push_back(*it);
2275 it = cite_engine_.begin();
2276 en = cite_engine_.end();
2277 for (; it != en; ++it)
2278 mods.push_back(*it);
2280 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2282 TextClass::ReturnValues success = TextClass::OK;
2283 if (!forced_local_layout_.empty())
2284 success = doc_class_->read(forced_local_layout_, TextClass::MODULE);
2285 if (!local_layout_.empty() &&
2286 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2287 success = doc_class_->read(local_layout_, TextClass::MODULE);
2288 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2289 docstring const msg = _("Error reading internal layout information");
2290 frontend::Alert::warning(_("Read Error"), msg);
2295 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2297 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2301 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2303 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2307 std::string BufferParams::getLocalLayout(bool forced) const
2310 return doc_class_->forcedLayouts();
2312 return local_layout_;
2316 void BufferParams::setLocalLayout(string const & layout, bool forced)
2319 forced_local_layout_ = layout;
2321 local_layout_ = layout;
2325 bool BufferParams::addLayoutModule(string const & modName)
2327 LayoutModuleList::const_iterator it = layout_modules_.begin();
2328 LayoutModuleList::const_iterator end = layout_modules_.end();
2329 for (; it != end; ++it)
2332 layout_modules_.push_back(modName);
2337 string BufferParams::bufferFormat() const
2339 string format = documentClass().outputFormat();
2340 if (format == "latex") {
2342 return "xetex"; // actually "xetex or luatex"
2343 if (encoding().package() == Encoding::japanese)
2350 bool BufferParams::isExportable(string const & format) const
2352 vector<string> backs = backends();
2353 for (vector<string>::const_iterator it = backs.begin();
2354 it != backs.end(); ++it)
2355 if (theConverters().isReachable(*it, format))
2361 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2363 vector<string> const backs = backends();
2364 set<string> excludes;
2365 if (useNonTeXFonts) {
2366 excludes.insert("latex");
2367 excludes.insert("pdflatex");
2369 vector<Format const *> result =
2370 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2371 for (vector<string>::const_iterator it = backs.begin() + 1;
2372 it != backs.end(); ++it) {
2373 vector<Format const *> r =
2374 theConverters().getReachable(*it, only_viewable, false, excludes);
2375 result.insert(result.end(), r.begin(), r.end());
2381 bool BufferParams::isExportableFormat(string const & format) const
2383 typedef vector<Format const *> Formats;
2385 formats = exportableFormats(true);
2386 Formats::const_iterator fit = formats.begin();
2387 Formats::const_iterator end = formats.end();
2388 for (; fit != end ; ++fit) {
2389 if ((*fit)->name() == format)
2396 vector<string> BufferParams::backends() const
2399 string const buffmt = bufferFormat();
2401 // FIXME: Don't hardcode format names here, but use a flag
2402 if (buffmt == "latex") {
2403 if (!useNonTeXFonts) {
2404 v.push_back("pdflatex");
2405 v.push_back("latex");
2407 v.push_back("luatex");
2408 v.push_back("dviluatex");
2409 v.push_back("xetex");
2410 } else if (buffmt == "xetex") {
2411 v.push_back("xetex");
2412 // FIXME: need to test all languages (bug 8205)
2413 if (!language || !language->isPolyglossiaExclusive()) {
2414 v.push_back("luatex");
2415 v.push_back("dviluatex");
2418 v.push_back(buffmt);
2420 v.push_back("xhtml");
2421 v.push_back("text");
2427 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2429 string const dformat = (format.empty() || format == "default") ?
2430 getDefaultOutputFormat() : format;
2431 DefaultFlavorCache::const_iterator it =
2432 default_flavors_.find(dformat);
2434 if (it != default_flavors_.end())
2437 OutputParams::FLAVOR result = OutputParams::LATEX;
2439 // FIXME It'd be better not to hardcode this, but to do
2440 // something with formats.
2441 if (dformat == "xhtml")
2442 result = OutputParams::HTML;
2443 else if (dformat == "text")
2444 result = OutputParams::TEXT;
2445 else if (dformat == "lyx")
2446 result = OutputParams::LYX;
2447 else if (dformat == "pdflatex")
2448 result = OutputParams::PDFLATEX;
2449 else if (dformat == "xetex")
2450 result = OutputParams::XETEX;
2451 else if (dformat == "luatex")
2452 result = OutputParams::LUATEX;
2453 else if (dformat == "dviluatex")
2454 result = OutputParams::DVILUATEX;
2456 // Try to determine flavor of default output format
2457 vector<string> backs = backends();
2458 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2459 // Get shortest path to format
2460 Graph::EdgePath path;
2461 for (vector<string>::const_iterator it = backs.begin();
2462 it != backs.end(); ++it) {
2463 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2464 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2469 result = theConverters().getFlavor(path);
2472 // cache this flavor
2473 default_flavors_[dformat] = result;
2478 string BufferParams::getDefaultOutputFormat() const
2480 if (!default_output_format.empty()
2481 && default_output_format != "default")
2482 return default_output_format;
2484 || encoding().package() == Encoding::japanese) {
2485 vector<Format const *> const formats = exportableFormats(true);
2486 if (formats.empty())
2488 // return the first we find
2489 return formats.front()->name();
2492 return lyxrc.default_otf_view_format;
2493 return lyxrc.default_view_format;
2496 Font const BufferParams::getFont() const
2498 FontInfo f = documentClass().defaultfont();
2499 if (fonts_default_family == "rmdefault")
2500 f.setFamily(ROMAN_FAMILY);
2501 else if (fonts_default_family == "sfdefault")
2502 f.setFamily(SANS_FAMILY);
2503 else if (fonts_default_family == "ttdefault")
2504 f.setFamily(TYPEWRITER_FAMILY);
2505 return Font(f, language);
2509 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const & qs) const
2511 return quoteslangtranslator().find(qs);
2515 bool BufferParams::isLatex() const
2517 return documentClass().outputType() == LATEX;
2521 bool BufferParams::isLiterate() const
2523 return documentClass().outputType() == LITERATE;
2527 bool BufferParams::isDocBook() const
2529 return documentClass().outputType() == DOCBOOK;
2533 void BufferParams::readPreamble(Lexer & lex)
2535 if (lex.getString() != "\\begin_preamble")
2536 lyxerr << "Error (BufferParams::readPreamble):"
2537 "consistency check failed." << endl;
2539 preamble = lex.getLongString("\\end_preamble");
2543 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2545 string const expected = forced ? "\\begin_forced_local_layout" :
2546 "\\begin_local_layout";
2547 if (lex.getString() != expected)
2548 lyxerr << "Error (BufferParams::readLocalLayout):"
2549 "consistency check failed." << endl;
2552 forced_local_layout_ =
2553 lex.getLongString("\\end_forced_local_layout");
2555 local_layout_ = lex.getLongString("\\end_local_layout");
2559 bool BufferParams::setLanguage(string const & lang)
2561 Language const *new_language = languages.getLanguage(lang);
2562 if (!new_language) {
2563 // Language lang was not found
2566 language = new_language;
2571 void BufferParams::readLanguage(Lexer & lex)
2573 if (!lex.next()) return;
2575 string const tmptok = lex.getString();
2577 // check if tmptok is part of tex_babel in tex-defs.h
2578 if (!setLanguage(tmptok)) {
2579 // Language tmptok was not found
2580 language = default_language;
2581 lyxerr << "Warning: Setting language `"
2582 << tmptok << "' to `" << language->lang()
2588 void BufferParams::readGraphicsDriver(Lexer & lex)
2593 string const tmptok = lex.getString();
2594 // check if tmptok is part of tex_graphics in tex_defs.h
2597 string const test = tex_graphics[n++];
2599 if (test == tmptok) {
2600 graphics_driver = tmptok;
2605 "Warning: graphics driver `$$Token' not recognized!\n"
2606 " Setting graphics driver to `default'.\n");
2607 graphics_driver = "default";
2614 void BufferParams::readBullets(Lexer & lex)
2619 int const index = lex.getInteger();
2621 int temp_int = lex.getInteger();
2622 user_defined_bullet(index).setFont(temp_int);
2623 temp_bullet(index).setFont(temp_int);
2625 user_defined_bullet(index).setCharacter(temp_int);
2626 temp_bullet(index).setCharacter(temp_int);
2628 user_defined_bullet(index).setSize(temp_int);
2629 temp_bullet(index).setSize(temp_int);
2633 void BufferParams::readBulletsLaTeX(Lexer & lex)
2635 // The bullet class should be able to read this.
2638 int const index = lex.getInteger();
2640 docstring const temp_str = lex.getDocString();
2642 user_defined_bullet(index).setText(temp_str);
2643 temp_bullet(index).setText(temp_str);
2647 void BufferParams::readModules(Lexer & lex)
2649 if (!lex.eatLine()) {
2650 lyxerr << "Error (BufferParams::readModules):"
2651 "Unexpected end of input." << endl;
2655 string mod = lex.getString();
2656 if (mod == "\\end_modules")
2658 addLayoutModule(mod);
2664 void BufferParams::readRemovedModules(Lexer & lex)
2666 if (!lex.eatLine()) {
2667 lyxerr << "Error (BufferParams::readRemovedModules):"
2668 "Unexpected end of input." << endl;
2672 string mod = lex.getString();
2673 if (mod == "\\end_removed_modules")
2675 removed_modules_.push_back(mod);
2678 // now we want to remove any removed modules that were previously
2679 // added. normally, that will be because default modules were added in
2680 // setBaseClass(), which gets called when \textclass is read at the
2681 // start of the read.
2682 list<string>::const_iterator rit = removed_modules_.begin();
2683 list<string>::const_iterator const ren = removed_modules_.end();
2684 for (; rit != ren; ++rit) {
2685 LayoutModuleList::iterator const mit = layout_modules_.begin();
2686 LayoutModuleList::iterator const men = layout_modules_.end();
2687 LayoutModuleList::iterator found = find(mit, men, *rit);
2690 layout_modules_.erase(found);
2695 void BufferParams::readIncludeonly(Lexer & lex)
2697 if (!lex.eatLine()) {
2698 lyxerr << "Error (BufferParams::readIncludeonly):"
2699 "Unexpected end of input." << endl;
2703 string child = lex.getString();
2704 if (child == "\\end_includeonly")
2706 included_children_.push_back(child);
2712 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2714 switch (papersize) {
2716 // could be anything, so don't guess
2718 case PAPER_CUSTOM: {
2719 if (purpose == XDVI && !paperwidth.empty() &&
2720 !paperheight.empty()) {
2721 // heightxwidth<unit>
2722 string first = paperwidth;
2723 string second = paperheight;
2724 if (orientation == ORIENTATION_LANDSCAPE)
2727 return first.erase(first.length() - 2)
2733 // dvips and dvipdfm do not know this
2734 if (purpose == DVIPS || purpose == DVIPDFM)
2738 if (purpose == DVIPS || purpose == DVIPDFM)
2742 if (purpose == DVIPS || purpose == DVIPDFM)
2752 if (purpose == DVIPS || purpose == DVIPDFM)
2756 if (purpose == DVIPS || purpose == DVIPDFM)
2760 if (purpose == DVIPS || purpose == DVIPDFM)
2764 if (purpose == DVIPS || purpose == DVIPDFM)
2768 if (purpose == DVIPS || purpose == DVIPDFM)
2772 // dvipdfm does not know this
2773 if (purpose == DVIPDFM)
2777 if (purpose == DVIPDFM)
2781 if (purpose == DVIPS || purpose == DVIPDFM)
2785 if (purpose == DVIPS || purpose == DVIPDFM)
2789 if (purpose == DVIPS || purpose == DVIPDFM)
2793 if (purpose == DVIPS || purpose == DVIPDFM)
2797 if (purpose == DVIPS || purpose == DVIPDFM)
2801 if (purpose == DVIPS || purpose == DVIPDFM)
2805 if (purpose == DVIPS || purpose == DVIPDFM)
2809 if (purpose == DVIPS || purpose == DVIPDFM)
2813 if (purpose == DVIPS || purpose == DVIPDFM)
2817 if (purpose == DVIPS || purpose == DVIPDFM)
2821 if (purpose == DVIPS || purpose == DVIPDFM)
2825 if (purpose == DVIPS || purpose == DVIPDFM)
2829 if (purpose == DVIPS || purpose == DVIPDFM)
2833 if (purpose == DVIPS || purpose == DVIPDFM)
2837 if (purpose == DVIPS || purpose == DVIPDFM)
2840 case PAPER_USEXECUTIVE:
2841 // dvipdfm does not know this
2842 if (purpose == DVIPDFM)
2847 case PAPER_USLETTER:
2849 if (purpose == XDVI)
2856 string const BufferParams::dvips_options() const
2860 // If the class loads the geometry package, we do not know which
2861 // paper size is used, since we do not set it (bug 7013).
2862 // Therefore we must not specify any argument here.
2863 // dvips gets the correct paper size via DVI specials in this case
2864 // (if the class uses the geometry package correctly).
2865 if (documentClass().provides("geometry"))
2869 && papersize == PAPER_CUSTOM
2870 && !lyxrc.print_paper_dimension_flag.empty()
2871 && !paperwidth.empty()
2872 && !paperheight.empty()) {
2873 // using a custom papersize
2874 result = lyxrc.print_paper_dimension_flag;
2875 result += ' ' + paperwidth;
2876 result += ',' + paperheight;
2878 string const paper_option = paperSizeName(DVIPS);
2879 if (!paper_option.empty() && (paper_option != "letter" ||
2880 orientation != ORIENTATION_LANDSCAPE)) {
2881 // dvips won't accept -t letter -t landscape.
2882 // In all other cases, include the paper size
2884 result = lyxrc.print_paper_flag;
2885 result += ' ' + paper_option;
2888 if (orientation == ORIENTATION_LANDSCAPE &&
2889 papersize != PAPER_CUSTOM)
2890 result += ' ' + lyxrc.print_landscape_flag;
2895 string const BufferParams::font_encoding() const
2897 return font_encodings().empty() ? "default" : font_encodings().back();
2901 vector<string> const BufferParams::font_encodings() const
2903 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2905 vector<string> fontencs;
2907 // "default" means "no explicit font encoding"
2908 if (doc_fontenc != "default") {
2909 fontencs = getVectorFromString(doc_fontenc);
2910 if (!language->fontenc().empty()
2911 && ascii_lowercase(language->fontenc()) != "none") {
2912 vector<string> fencs = getVectorFromString(language->fontenc());
2913 vector<string>::const_iterator fit = fencs.begin();
2914 for (; fit != fencs.end(); ++fit) {
2915 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
2916 fontencs.push_back(*fit);
2925 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2927 // suppress the babel call if there is no BabelName defined
2928 // for the document language in the lib/languages file and if no
2929 // other languages are used (lang_opts is then empty)
2930 if (lang_opts.empty())
2932 // either a specific language (AsBabelOptions setting in
2933 // lib/languages) or the prefs require the languages to
2934 // be submitted to babel itself (not the class).
2936 return "\\usepackage[" + lang_opts + "]{babel}";
2937 return "\\usepackage{babel}";
2941 docstring BufferParams::getGraphicsDriver(string const & package) const
2945 if (package == "geometry") {
2946 if (graphics_driver == "dvips"
2947 || graphics_driver == "dvipdfm"
2948 || graphics_driver == "pdftex"
2949 || graphics_driver == "vtex")
2950 result = from_ascii(graphics_driver);
2951 else if (graphics_driver == "dvipdfmx")
2952 result = from_ascii("dvipdfm");
2959 void BufferParams::writeEncodingPreamble(otexstream & os,
2960 LaTeXFeatures & features) const
2962 // XeTeX/LuaTeX: (see also #9740)
2963 // With Unicode fonts we use utf8-plain without encoding package.
2964 // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails.
2965 // XeTeX must use ASCII encoding, for LuaTeX, we load
2966 // "luainputenc" (see below).
2967 if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
2970 if (inputenc == "auto") {
2971 string const doc_encoding =
2972 language->encoding()->latexName();
2973 Encoding::Package const package =
2974 language->encoding()->package();
2976 // Create list of inputenc options:
2977 set<string> encodings;
2978 // luainputenc fails with more than one encoding
2979 if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts
2980 // list all input encodings used in the document
2981 encodings = features.getEncodingSet(doc_encoding);
2983 // If the "japanese" package (i.e. pLaTeX) is used,
2984 // inputenc must be omitted.
2985 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2986 if ((!encodings.empty() || package == Encoding::inputenc)
2987 && !features.isRequired("japanese")
2988 && !features.isProvided("inputenc")) {
2989 os << "\\usepackage[";
2990 set<string>::const_iterator it = encodings.begin();
2991 set<string>::const_iterator const end = encodings.end();
2993 os << from_ascii(*it);
2996 for (; it != end; ++it)
2997 os << ',' << from_ascii(*it);
2998 if (package == Encoding::inputenc) {
2999 if (!encodings.empty())
3001 os << from_ascii(doc_encoding);
3003 if (features.runparams().flavor == OutputParams::LUATEX
3004 || features.runparams().flavor == OutputParams::DVILUATEX)
3005 os << "]{luainputenc}\n";
3007 os << "]{inputenc}\n";
3009 if (package == Encoding::CJK || features.mustProvide("CJK")) {
3010 if (language->encoding()->name() == "utf8-cjk"
3011 && LaTeXFeatures::isAvailable("CJKutf8"))
3012 os << "\\usepackage{CJKutf8}\n";
3014 os << "\\usepackage{CJK}\n";
3016 } else if (inputenc != "default") {
3017 switch (encoding().package()) {
3018 case Encoding::none:
3019 case Encoding::japanese:
3021 case Encoding::inputenc:
3022 // do not load inputenc if japanese is used
3023 // or if the class provides inputenc
3024 if (features.isRequired("japanese")
3025 || features.isProvided("inputenc"))
3027 os << "\\usepackage[" << from_ascii(encoding().latexName());
3028 if (features.runparams().flavor == OutputParams::LUATEX
3029 || features.runparams().flavor == OutputParams::DVILUATEX)
3030 os << "]{luainputenc}\n";
3032 os << "]{inputenc}\n";
3035 if (encoding().name() == "utf8-cjk"
3036 && LaTeXFeatures::isAvailable("CJKutf8"))
3037 os << "\\usepackage{CJKutf8}\n";
3039 os << "\\usepackage{CJK}\n";
3042 // Load the CJK package if needed by a secondary language.
3043 // If the main encoding is some variant of UTF8, use CJKutf8.
3044 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
3045 if (encoding().iconvName() == "UTF-8"
3046 && LaTeXFeatures::isAvailable("CJKutf8"))
3047 os << "\\usepackage{CJKutf8}\n";
3049 os << "\\usepackage{CJK}\n";
3055 string const BufferParams::parseFontName(string const & name) const
3057 string mangled = name;
3058 size_t const idx = mangled.find('[');
3059 if (idx == string::npos || idx == 0)
3062 return mangled.substr(0, idx - 1);
3066 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3068 if (fontsRoman() == "default" && fontsSans() == "default"
3069 && fontsTypewriter() == "default"
3070 && (fontsMath() == "default" || fontsMath() == "auto"))
3076 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3077 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3078 * Mapping=tex-text option assures TeX ligatures (such as "--")
3079 * are resolved. Note that tt does not use these ligatures.
3081 * -- add more GUI options?
3082 * -- add more fonts (fonts for other scripts)
3083 * -- if there's a way to find out if a font really supports
3084 * OldStyle, enable/disable the widget accordingly.
3086 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3087 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3088 // However, until v.2 (2010/07/11) fontspec only knew
3089 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3090 // was introduced for both XeTeX and LuaTeX (LuaTeX
3091 // didn't understand "Mapping=tex-text", while XeTeX
3092 // understood both. With most recent versions, both
3093 // variants are understood by both engines. However,
3094 // we want to provide support for at least TeXLive 2009
3095 // (for XeTeX; LuaTeX is only supported as of v.2)
3096 string const texmapping =
3097 (features.runparams().flavor == OutputParams::XETEX) ?
3098 "Mapping=tex-text" : "Ligatures=TeX";
3099 if (fontsRoman() != "default") {
3100 os << "\\setmainfont[" << texmapping;
3101 if (fonts_old_figures)
3102 os << ",Numbers=OldStyle";
3103 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3105 if (fontsSans() != "default") {
3106 string const sans = parseFontName(fontsSans());
3107 if (fontsSansScale() != 100)
3108 os << "\\setsansfont[Scale="
3109 << float(fontsSansScale()) / 100
3110 << "," << texmapping << "]{"
3113 os << "\\setsansfont[" << texmapping << "]{"
3116 if (fontsTypewriter() != "default") {
3117 string const mono = parseFontName(fontsTypewriter());
3118 if (fontsTypewriterScale() != 100)
3119 os << "\\setmonofont[Scale="
3120 << float(fontsTypewriterScale()) / 100
3124 os << "\\setmonofont{"
3131 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
3132 bool const dryrun = features.runparams().dryrun;
3133 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3134 bool const nomath = (fontsMath() == "default");
3137 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3138 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3142 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3143 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3144 nomath, fontsSansScale());
3146 // MONOSPACED/TYPEWRITER
3147 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3148 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3149 nomath, fontsTypewriterScale());
3152 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3153 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3160 Encoding const & BufferParams::encoding() const
3162 // Main encoding for LaTeX output.
3164 // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740).
3165 // As the "flavor" is only known once export started, this
3166 // cannot be handled here. Instead, runparams.encoding is set
3167 // to ASCII in Buffer::makeLaTeXFile (for export)
3168 // and Buffer::writeLaTeXSource (for preview).
3170 return *(encodings.fromLyXName("utf8-plain"));
3171 if (inputenc == "auto" || inputenc == "default")
3172 return *language->encoding();
3173 Encoding const * const enc = encodings.fromLyXName(inputenc);
3176 LYXERR0("Unknown inputenc value `" << inputenc
3177 << "'. Using `auto' instead.");
3178 return *language->encoding();
3182 bool BufferParams::addCiteEngine(string const & engine)
3184 LayoutModuleList::const_iterator it = cite_engine_.begin();
3185 LayoutModuleList::const_iterator en = cite_engine_.end();
3186 for (; it != en; ++it)
3189 cite_engine_.push_back(engine);
3194 bool BufferParams::addCiteEngine(vector<string> const & engine)
3196 vector<string>::const_iterator it = engine.begin();
3197 vector<string>::const_iterator en = engine.end();
3199 for (; it != en; ++it)
3200 if (!addCiteEngine(*it))
3206 string const & BufferParams::defaultBiblioStyle() const
3208 return documentClass().defaultBiblioStyle();
3212 bool const & BufferParams::fullAuthorList() const
3214 return documentClass().fullAuthorList();
3218 void BufferParams::setCiteEngine(string const & engine)
3221 addCiteEngine(engine);
3225 void BufferParams::setCiteEngine(vector<string> const & engine)
3228 addCiteEngine(engine);
3232 vector<string> BufferParams::citeCommands() const
3234 static CitationStyle const default_style;
3235 vector<string> commands =
3236 documentClass().citeCommands(citeEngineType());
3237 if (commands.empty())
3238 commands.push_back(default_style.cmd);
3243 vector<CitationStyle> BufferParams::citeStyles() const
3245 static CitationStyle const default_style;
3246 vector<CitationStyle> styles =
3247 documentClass().citeStyles(citeEngineType());
3249 styles.push_back(default_style);