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.hasPolyglossiaExclusiveLanguages())
1403 features.require("polyglossia");
1405 if (useNonTeXFonts && fontsMath() != "auto")
1406 features.require("unicode-math");
1408 if (!language->requires().empty())
1409 features.require(language->requires());
1413 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1414 FileName const & filepath) const
1416 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1417 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1418 // \RequirePackage to do so, rather than the normal \usepackage
1419 // Do not try to load any other package before the document class, unless you
1420 // have a thorough understanding of the LATEX internals and know exactly what you
1422 if (features.mustProvide("fix-cm"))
1423 os << "\\RequirePackage{fix-cm}\n";
1424 // Likewise for fixltx2e. If other packages conflict with this policy,
1425 // treat it as a package bug (and report it!)
1426 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1427 if (features.mustProvide("fixltx2e"))
1428 os << "\\RequirePackage{fixltx2e}\n";
1430 os << "\\documentclass";
1432 DocumentClass const & tclass = documentClass();
1434 ostringstream clsoptions; // the document class options.
1436 if (tokenPos(tclass.opt_fontsize(),
1437 '|', fontsize) >= 0) {
1438 // only write if existing in list (and not default)
1439 clsoptions << fontsize << "pt,";
1442 // all paper sizes except of A4, A5, B5 and the US sizes need the
1444 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1445 && papersize != PAPER_USLETTER
1446 && papersize != PAPER_USLEGAL
1447 && papersize != PAPER_USEXECUTIVE
1448 && papersize != PAPER_A4
1449 && papersize != PAPER_A5
1450 && papersize != PAPER_B5;
1452 if (!use_geometry) {
1453 switch (papersize) {
1455 clsoptions << "a4paper,";
1457 case PAPER_USLETTER:
1458 clsoptions << "letterpaper,";
1461 clsoptions << "a5paper,";
1464 clsoptions << "b5paper,";
1466 case PAPER_USEXECUTIVE:
1467 clsoptions << "executivepaper,";
1470 clsoptions << "legalpaper,";
1504 if (sides != tclass.sides()) {
1507 clsoptions << "oneside,";
1510 clsoptions << "twoside,";
1516 if (columns != tclass.columns()) {
1518 clsoptions << "twocolumn,";
1520 clsoptions << "onecolumn,";
1524 && orientation == ORIENTATION_LANDSCAPE)
1525 clsoptions << "landscape,";
1527 // language should be a parameter to \documentclass
1528 if (language->babel() == "hebrew"
1529 && default_language->babel() != "hebrew")
1530 // This seems necessary
1531 features.useLanguage(default_language);
1533 ostringstream language_options;
1534 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1535 bool const use_polyglossia = features.usePolyglossia();
1536 bool const global = lyxrc.language_global_options;
1537 if (use_babel || (use_polyglossia && global)) {
1538 language_options << features.getBabelLanguages();
1539 if (!language->babel().empty()) {
1540 if (!language_options.str().empty())
1541 language_options << ',';
1542 language_options << language->babel();
1544 if (global && !features.needBabelLangOptions()
1545 && !language_options.str().empty())
1546 clsoptions << language_options.str() << ',';
1549 // the predefined options from the layout
1550 if (use_default_options && !tclass.options().empty())
1551 clsoptions << tclass.options() << ',';
1553 // the user-defined options
1554 if (!options.empty()) {
1555 clsoptions << options << ',';
1558 string strOptions(clsoptions.str());
1559 if (!strOptions.empty()) {
1560 strOptions = rtrim(strOptions, ",");
1562 os << '[' << from_utf8(strOptions) << ']';
1565 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1566 // end of \documentclass defs
1568 // if we use fontspec or newtxmath, we have to load the AMS packages here
1569 string const ams = features.loadAMSPackages();
1570 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1571 bool const use_newtxmath =
1572 theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getUsedPackage(
1573 ot1, false, false) == "newtxmath";
1574 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1575 os << from_ascii(ams);
1577 if (useNonTeXFonts) {
1578 os << "\\usepackage{fontspec}\n";
1579 if (features.mustProvide("unicode-math")
1580 && features.isAvailable("unicode-math"))
1581 os << "\\usepackage{unicode-math}\n";
1584 // font selection must be done before loading fontenc.sty
1585 string const fonts = loadFonts(features);
1587 os << from_utf8(fonts);
1589 if (fonts_default_family != "default")
1590 os << "\\renewcommand{\\familydefault}{\\"
1591 << from_ascii(fonts_default_family) << "}\n";
1593 // set font encoding
1594 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1595 if (!useNonTeXFonts && !features.isProvided("fontenc")
1596 && font_encoding() != "default") {
1597 // get main font encodings
1598 vector<string> fontencs = font_encodings();
1599 // get font encodings of secondary languages
1600 features.getFontEncodings(fontencs);
1601 if (!fontencs.empty()) {
1602 os << "\\usepackage["
1603 << from_ascii(getStringFromVector(fontencs))
1608 // handle inputenc etc.
1609 writeEncodingPreamble(os, features);
1612 if (!features.runparams().includeall && !included_children_.empty()) {
1613 os << "\\includeonly{";
1614 list<string>::const_iterator it = included_children_.begin();
1615 list<string>::const_iterator en = included_children_.end();
1617 for (; it != en; ++it) {
1618 string incfile = *it;
1619 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1620 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1622 if (!features.runparams().nice)
1624 // \includeonly doesn't want an extension
1625 incfile = changeExtension(incfile, string());
1626 incfile = support::latex_path(incfile);
1627 if (!incfile.empty()) {
1630 os << from_utf8(incfile);
1637 if (!features.isProvided("geometry")
1638 && (use_geometry || nonstandard_papersize)) {
1639 odocstringstream ods;
1640 if (!getGraphicsDriver("geometry").empty())
1641 ods << getGraphicsDriver("geometry");
1642 if (orientation == ORIENTATION_LANDSCAPE)
1643 ods << ",landscape";
1644 switch (papersize) {
1646 if (!paperwidth.empty())
1647 ods << ",paperwidth="
1648 << from_ascii(paperwidth);
1649 if (!paperheight.empty())
1650 ods << ",paperheight="
1651 << from_ascii(paperheight);
1653 case PAPER_USLETTER:
1654 ods << ",letterpaper";
1657 ods << ",legalpaper";
1659 case PAPER_USEXECUTIVE:
1660 ods << ",executivepaper";
1749 docstring const g_options = trim(ods.str(), ",");
1750 os << "\\usepackage";
1751 if (!g_options.empty())
1752 os << '[' << g_options << ']';
1753 os << "{geometry}\n";
1754 // output this only if use_geometry is true
1756 os << "\\geometry{verbose";
1757 if (!topmargin.empty())
1758 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1759 if (!bottommargin.empty())
1760 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1761 if (!leftmargin.empty())
1762 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1763 if (!rightmargin.empty())
1764 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1765 if (!headheight.empty())
1766 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1767 if (!headsep.empty())
1768 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1769 if (!footskip.empty())
1770 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1771 if (!columnsep.empty())
1772 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1775 } else if (orientation == ORIENTATION_LANDSCAPE
1776 || papersize != PAPER_DEFAULT) {
1777 features.require("papersize");
1780 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1781 if (pagestyle == "fancy")
1782 os << "\\usepackage{fancyhdr}\n";
1783 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1786 // only output when the background color is not default
1787 if (isbackgroundcolor == true) {
1788 // only require color here, the background color will be defined
1789 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1791 features.require("color");
1792 features.require("pagecolor");
1795 // only output when the font color is not default
1796 if (isfontcolor == true) {
1797 // only require color here, the font color will be defined
1798 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1800 features.require("color");
1801 features.require("fontcolor");
1804 // Only if class has a ToC hierarchy
1805 if (tclass.hasTocLevels()) {
1806 if (secnumdepth != tclass.secnumdepth()) {
1807 os << "\\setcounter{secnumdepth}{"
1811 if (tocdepth != tclass.tocdepth()) {
1812 os << "\\setcounter{tocdepth}{"
1818 if (paragraph_separation) {
1819 // when skip separation
1820 switch (getDefSkip().kind()) {
1821 case VSpace::SMALLSKIP:
1822 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1824 case VSpace::MEDSKIP:
1825 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1827 case VSpace::BIGSKIP:
1828 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1830 case VSpace::LENGTH:
1831 os << "\\setlength{\\parskip}{"
1832 << from_utf8(getDefSkip().length().asLatexString())
1835 default: // should never happen // Then delete it.
1836 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1839 os << "\\setlength{\\parindent}{0pt}\n";
1841 // when separation by indentation
1842 // only output something when a width is given
1843 if (getIndentation().asLyXCommand() != "default") {
1844 os << "\\setlength{\\parindent}{"
1845 << from_utf8(getIndentation().asLatexCommand())
1850 // Now insert the LyX specific LaTeX commands...
1851 docstring lyxpreamble;
1852 features.resolveAlternatives();
1855 if (!output_sync_macro.empty())
1856 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1857 else if (features.runparams().flavor == OutputParams::LATEX)
1858 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1859 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1860 lyxpreamble += "\\synctex=-1\n";
1863 // The package options (via \PassOptionsToPackage)
1864 lyxpreamble += from_ascii(features.getPackageOptions());
1866 // due to interferences with babel and hyperref, the color package has to
1867 // be loaded (when it is not already loaded) before babel when hyperref
1868 // is used with the colorlinks option, see
1869 // http://www.lyx.org/trac/ticket/5291
1870 // we decided therefore to load color always before babel, see
1871 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1872 lyxpreamble += from_ascii(features.getColorOptions());
1874 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1875 // we have to call babel before
1877 && (features.isRequired("jurabib")
1878 || features.isRequired("hyperref")
1879 || features.isRequired("varioref")
1880 || features.isRequired("vietnamese")
1881 || features.isRequired("japanese"))) {
1883 lyxpreamble += from_utf8(features.getBabelPresettings());
1884 lyxpreamble += from_utf8(babelCall(language_options.str(),
1885 features.needBabelLangOptions())) + '\n';
1886 lyxpreamble += from_utf8(features.getBabelPostsettings());
1889 // The optional packages;
1890 lyxpreamble += from_ascii(features.getPackages());
1892 // Additional Indices
1893 if (features.isRequired("splitidx")) {
1894 IndicesList::const_iterator iit = indiceslist().begin();
1895 IndicesList::const_iterator iend = indiceslist().end();
1896 for (; iit != iend; ++iit) {
1897 pair<docstring, docstring> indexname_latex =
1898 features.runparams().encoding->latexString(iit->index(),
1899 features.runparams().dryrun);
1900 if (!indexname_latex.second.empty()) {
1901 // issue a warning about omitted characters
1902 // FIXME: should be passed to the error dialog
1903 frontend::Alert::warning(_("Uncodable characters"),
1904 bformat(_("The following characters that are used in an index name are not\n"
1905 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1906 indexname_latex.second));
1908 lyxpreamble += "\\newindex[";
1909 lyxpreamble += indexname_latex.first;
1910 lyxpreamble += "]{";
1911 lyxpreamble += escape(iit->shortcut());
1912 lyxpreamble += "}\n";
1917 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1920 // * Hyperref manual: "Make sure it comes last of your loaded
1921 // packages, to give it a fighting chance of not being over-written,
1922 // since its job is to redefine many LaTeX commands."
1923 // * Email from Heiko Oberdiek: "It is usually better to load babel
1924 // before hyperref. Then hyperref has a chance to detect babel.
1925 // * Has to be loaded before the "LyX specific LaTeX commands" to
1926 // avoid errors with algorithm floats.
1927 // use hyperref explicitly if it is required
1928 if (features.isRequired("hyperref")) {
1929 // pass what we have to stream here, since we need
1930 // to access the stream itself in PDFOptions.
1933 OutputParams tmp_params = features.runparams();
1934 pdfoptions().writeLaTeX(tmp_params, os,
1935 features.isProvided("hyperref"));
1936 // set back for the rest
1937 lyxpreamble.clear();
1938 // correctly break URLs with hyperref and dvi output
1939 if (features.runparams().flavor == OutputParams::LATEX
1940 && features.isAvailable("breakurl"))
1941 lyxpreamble += "\\usepackage{breakurl}\n";
1942 } else if (features.isRequired("nameref"))
1943 // hyperref loads this automatically
1944 lyxpreamble += "\\usepackage{nameref}\n";
1946 // bibtopic needs to be loaded after hyperref.
1947 // the dot provides the aux file naming which LyX can detect.
1948 if (features.mustProvide("bibtopic"))
1949 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1951 // Will be surrounded by \makeatletter and \makeatother when not empty
1952 docstring atlyxpreamble;
1954 // Some macros LyX will need
1955 docstring tmppreamble(features.getMacros());
1957 if (!tmppreamble.empty())
1958 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1959 "LyX specific LaTeX commands.\n"
1960 + tmppreamble + '\n';
1962 // the text class specific preamble
1963 tmppreamble = features.getTClassPreamble();
1964 if (!tmppreamble.empty())
1965 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1966 "Textclass specific LaTeX commands.\n"
1967 + tmppreamble + '\n';
1969 // suppress date if selected
1970 // use \@ifundefined because we cannot be sure that every document class
1971 // has a \date command
1973 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1975 /* the user-defined preamble */
1976 if (!containsOnly(preamble, " \n\t")) {
1978 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1979 "User specified LaTeX commands.\n";
1981 // Check if the user preamble contains uncodable glyphs
1982 docstring const u_preamble = from_utf8(preamble);
1983 odocstringstream user_preamble;
1984 docstring uncodable_glyphs;
1985 Encoding const * const enc = features.runparams().encoding;
1987 for (size_t n = 0; n < u_preamble.size(); ++n) {
1988 char_type c = u_preamble[n];
1989 if (!enc->encodable(c)) {
1990 docstring const glyph(1, c);
1991 LYXERR0("Uncodable character '"
1993 << "' in user preamble!");
1994 uncodable_glyphs += glyph;
1995 if (features.runparams().dryrun) {
1996 user_preamble << "<" << _("LyX Warning: ")
1997 << _("uncodable character") << " '";
1998 user_preamble.put(c);
1999 user_preamble << "'>";
2002 user_preamble.put(c);
2005 user_preamble << u_preamble;
2007 // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs
2008 if (!features.runparams().dryrun && !uncodable_glyphs.empty()) {
2009 frontend::Alert::warning(
2010 _("Uncodable character in user preamble"),
2012 _("The user preamble of your document contains glyphs "
2013 "that are unknown in the current document encoding "
2014 "(namely %1$s).\nThese glyphs are omitted "
2015 " from the output, which may result in "
2016 "incomplete output."
2017 "\n\nPlease select an appropriate "
2018 "document encoding\n"
2019 "(such as utf8) or change the "
2020 "preamble code accordingly."),
2023 atlyxpreamble += user_preamble.str() + '\n';
2026 // footmisc must be loaded after setspace
2027 // Load it here to avoid clashes with footmisc loaded in the user
2028 // preamble. For that reason we also pass the options via
2029 // \PassOptionsToPackage in getPreamble() and not here.
2030 if (features.mustProvide("footmisc"))
2031 atlyxpreamble += "\\usepackage{footmisc}\n";
2033 // subfig loads internally the LaTeX package "caption". As
2034 // caption is a very popular package, users will load it in
2035 // the preamble. Therefore we must load subfig behind the
2036 // user-defined preamble and check if the caption package was
2037 // loaded or not. For the case that caption is loaded before
2038 // subfig, there is the subfig option "caption=false". This
2039 // option also works when a koma-script class is used and
2040 // koma's own caption commands are used instead of caption. We
2041 // use \PassOptionsToPackage here because the user could have
2042 // already loaded subfig in the preamble.
2043 if (features.isRequired("subfig")) {
2044 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
2045 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
2046 "\\usepackage{subfig}\n";
2049 // Itemize bullet settings need to be last in case the user
2050 // defines their own bullets that use a package included
2051 // in the user-defined preamble -- ARRae
2052 // Actually it has to be done much later than that
2053 // since some packages like frenchb make modifications
2054 // at \begin{document} time -- JMarc
2055 docstring bullets_def;
2056 for (int i = 0; i < 4; ++i) {
2057 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
2058 if (bullets_def.empty())
2059 bullets_def += "\\AtBeginDocument{\n";
2060 bullets_def += " \\def\\labelitemi";
2062 // `i' is one less than the item to modify
2069 bullets_def += "ii";
2075 bullets_def += '{' +
2076 user_defined_bullet(i).getText()
2081 if (!bullets_def.empty())
2082 atlyxpreamble += bullets_def + "}\n\n";
2084 if (!atlyxpreamble.empty())
2085 lyxpreamble += "\n\\makeatletter\n"
2086 + atlyxpreamble + "\\makeatother\n\n";
2088 // We try to load babel late, in case it interferes with other packages.
2089 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
2090 // called after babel, though.
2091 if (use_babel && !features.isRequired("jurabib")
2092 && !features.isRequired("hyperref")
2093 && !features.isRequired("varioref")
2094 && !features.isRequired("vietnamese")
2095 && !features.isRequired("japanese")) {
2097 lyxpreamble += from_utf8(features.getBabelPresettings());
2098 lyxpreamble += from_utf8(babelCall(language_options.str(),
2099 features.needBabelLangOptions())) + '\n';
2100 lyxpreamble += from_utf8(features.getBabelPostsettings());
2102 if (features.isRequired("bicaption"))
2103 lyxpreamble += "\\usepackage{bicaption}\n";
2104 if (!listings_params.empty() || features.isRequired("listings"))
2105 lyxpreamble += "\\usepackage{listings}\n";
2106 if (!listings_params.empty()) {
2107 lyxpreamble += "\\lstset{";
2108 // do not test validity because listings_params is
2109 // supposed to be valid
2111 InsetListingsParams(listings_params).separatedParams(true);
2112 lyxpreamble += from_utf8(par);
2113 lyxpreamble += "}\n";
2116 // xunicode needs to be loaded at least after amsmath, amssymb,
2117 // esint and the other packages that provide special glyphs
2118 if (features.runparams().flavor == OutputParams::XETEX
2120 lyxpreamble += "\\usepackage{xunicode}\n";
2122 // Polyglossia must be loaded last
2123 if (use_polyglossia) {
2125 lyxpreamble += "\\usepackage{polyglossia}\n";
2126 // set the main language
2127 lyxpreamble += "\\setdefaultlanguage";
2128 if (!language->polyglossiaOpts().empty())
2129 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
2130 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
2131 // now setup the other languages
2132 std::map<std::string, std::string> const polylangs =
2133 features.getPolyglossiaLanguages();
2134 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
2135 mit != polylangs.end() ; ++mit) {
2136 lyxpreamble += "\\setotherlanguage";
2137 if (!mit->second.empty())
2138 lyxpreamble += "[" + from_ascii(mit->second) + "]";
2139 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
2143 // Load custom language package here
2144 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2145 if (lang_package == "default")
2146 lyxpreamble += from_utf8(lyxrc.language_custom_package);
2148 lyxpreamble += from_utf8(lang_package);
2149 lyxpreamble += '\n';
2152 docstring const i18npreamble =
2153 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2154 if (!i18npreamble.empty())
2155 lyxpreamble += i18npreamble + '\n';
2163 void BufferParams::useClassDefaults()
2165 DocumentClass const & tclass = documentClass();
2167 sides = tclass.sides();
2168 columns = tclass.columns();
2169 pagestyle = tclass.pagestyle();
2170 use_default_options = true;
2171 // Only if class has a ToC hierarchy
2172 if (tclass.hasTocLevels()) {
2173 secnumdepth = tclass.secnumdepth();
2174 tocdepth = tclass.tocdepth();
2179 bool BufferParams::hasClassDefaults() const
2181 DocumentClass const & tclass = documentClass();
2183 return sides == tclass.sides()
2184 && columns == tclass.columns()
2185 && pagestyle == tclass.pagestyle()
2186 && use_default_options
2187 && secnumdepth == tclass.secnumdepth()
2188 && tocdepth == tclass.tocdepth();
2192 DocumentClass const & BufferParams::documentClass() const
2194 return *doc_class_.get();
2198 DocumentClassConstPtr BufferParams::documentClassPtr() const
2204 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2206 // evil, but this function is evil
2207 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2211 bool BufferParams::setBaseClass(string const & classname)
2213 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2214 LayoutFileList & bcl = LayoutFileList::get();
2215 if (!bcl.haveClass(classname)) {
2217 bformat(_("The layout file:\n"
2219 "could not be found. A default textclass with default\n"
2220 "layouts will be used. LyX will not be able to produce\n"
2222 from_utf8(classname));
2223 frontend::Alert::error(_("Document class not found"), s);
2224 bcl.addEmptyClass(classname);
2227 bool const success = bcl[classname].load();
2230 bformat(_("Due to some error in it, the layout file:\n"
2232 "could not be loaded. A default textclass with default\n"
2233 "layouts will be used. LyX will not be able to produce\n"
2235 from_utf8(classname));
2236 frontend::Alert::error(_("Could not load class"), s);
2237 bcl.addEmptyClass(classname);
2240 pimpl_->baseClass_ = classname;
2241 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2246 LayoutFile const * BufferParams::baseClass() const
2248 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2249 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2255 LayoutFileIndex const & BufferParams::baseClassID() const
2257 return pimpl_->baseClass_;
2261 void BufferParams::makeDocumentClass(bool const clone)
2266 LayoutModuleList mods;
2267 LayoutModuleList::iterator it = layout_modules_.begin();
2268 LayoutModuleList::iterator en = layout_modules_.end();
2269 for (; it != en; ++it)
2270 mods.push_back(*it);
2272 it = cite_engine_.begin();
2273 en = cite_engine_.end();
2274 for (; it != en; ++it)
2275 mods.push_back(*it);
2277 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2279 TextClass::ReturnValues success = TextClass::OK;
2280 if (!forced_local_layout_.empty())
2281 success = doc_class_->read(forced_local_layout_, TextClass::MODULE);
2282 if (!local_layout_.empty() &&
2283 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2284 success = doc_class_->read(local_layout_, TextClass::MODULE);
2285 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2286 docstring const msg = _("Error reading internal layout information");
2287 frontend::Alert::warning(_("Read Error"), msg);
2292 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2294 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2298 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2300 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2304 std::string BufferParams::getLocalLayout(bool forced) const
2307 return doc_class_->forcedLayouts();
2309 return local_layout_;
2313 void BufferParams::setLocalLayout(string const & layout, bool forced)
2316 forced_local_layout_ = layout;
2318 local_layout_ = layout;
2322 bool BufferParams::addLayoutModule(string const & modName)
2324 LayoutModuleList::const_iterator it = layout_modules_.begin();
2325 LayoutModuleList::const_iterator end = layout_modules_.end();
2326 for (; it != end; ++it)
2329 layout_modules_.push_back(modName);
2334 string BufferParams::bufferFormat() const
2336 string format = documentClass().outputFormat();
2337 if (format == "latex") {
2339 return "xetex"; // actually "xetex or luatex"
2340 if (encoding().package() == Encoding::japanese)
2347 bool BufferParams::isExportable(string const & format) const
2349 vector<string> backs = backends();
2350 for (vector<string>::const_iterator it = backs.begin();
2351 it != backs.end(); ++it)
2352 if (theConverters().isReachable(*it, format))
2358 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2360 vector<string> const backs = backends();
2361 set<string> excludes;
2362 if (useNonTeXFonts) {
2363 excludes.insert("latex");
2364 excludes.insert("pdflatex");
2366 vector<Format const *> result =
2367 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2368 for (vector<string>::const_iterator it = backs.begin() + 1;
2369 it != backs.end(); ++it) {
2370 vector<Format const *> r =
2371 theConverters().getReachable(*it, only_viewable, false, excludes);
2372 result.insert(result.end(), r.begin(), r.end());
2378 bool BufferParams::isExportableFormat(string const & format) const
2380 typedef vector<Format const *> Formats;
2382 formats = exportableFormats(true);
2383 Formats::const_iterator fit = formats.begin();
2384 Formats::const_iterator end = formats.end();
2385 for (; fit != end ; ++fit) {
2386 if ((*fit)->name() == format)
2393 vector<string> BufferParams::backends() const
2396 string const buffmt = bufferFormat();
2398 // FIXME: Don't hardcode format names here, but use a flag
2399 if (buffmt == "latex") {
2400 if (!useNonTeXFonts) {
2401 v.push_back("pdflatex");
2402 v.push_back("latex");
2404 v.push_back("luatex");
2405 v.push_back("dviluatex");
2406 v.push_back("xetex");
2407 } else if (buffmt == "xetex") {
2408 v.push_back("xetex");
2409 // FIXME: need to test all languages (bug 8205)
2410 if (!language || !language->isPolyglossiaExclusive()) {
2411 v.push_back("luatex");
2412 v.push_back("dviluatex");
2415 v.push_back(buffmt);
2417 v.push_back("xhtml");
2418 v.push_back("text");
2424 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2426 string const dformat = (format.empty() || format == "default") ?
2427 getDefaultOutputFormat() : format;
2428 DefaultFlavorCache::const_iterator it =
2429 default_flavors_.find(dformat);
2431 if (it != default_flavors_.end())
2434 OutputParams::FLAVOR result = OutputParams::LATEX;
2436 // FIXME It'd be better not to hardcode this, but to do
2437 // something with formats.
2438 if (dformat == "xhtml")
2439 result = OutputParams::HTML;
2440 else if (dformat == "text")
2441 result = OutputParams::TEXT;
2442 else if (dformat == "lyx")
2443 result = OutputParams::LYX;
2444 else if (dformat == "pdflatex")
2445 result = OutputParams::PDFLATEX;
2446 else if (dformat == "xetex")
2447 result = OutputParams::XETEX;
2448 else if (dformat == "luatex")
2449 result = OutputParams::LUATEX;
2450 else if (dformat == "dviluatex")
2451 result = OutputParams::DVILUATEX;
2453 // Try to determine flavor of default output format
2454 vector<string> backs = backends();
2455 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2456 // Get shortest path to format
2457 Graph::EdgePath path;
2458 for (vector<string>::const_iterator it = backs.begin();
2459 it != backs.end(); ++it) {
2460 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2461 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2466 result = theConverters().getFlavor(path);
2469 // cache this flavor
2470 default_flavors_[dformat] = result;
2475 string BufferParams::getDefaultOutputFormat() const
2477 if (!default_output_format.empty()
2478 && default_output_format != "default")
2479 return default_output_format;
2481 || encoding().package() == Encoding::japanese) {
2482 vector<Format const *> const formats = exportableFormats(true);
2483 if (formats.empty())
2485 // return the first we find
2486 return formats.front()->name();
2489 return lyxrc.default_otf_view_format;
2490 return lyxrc.default_view_format;
2493 Font const BufferParams::getFont() const
2495 FontInfo f = documentClass().defaultfont();
2496 if (fonts_default_family == "rmdefault")
2497 f.setFamily(ROMAN_FAMILY);
2498 else if (fonts_default_family == "sfdefault")
2499 f.setFamily(SANS_FAMILY);
2500 else if (fonts_default_family == "ttdefault")
2501 f.setFamily(TYPEWRITER_FAMILY);
2502 return Font(f, language);
2506 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const & qs) const
2508 return quoteslangtranslator().find(qs);
2512 bool BufferParams::isLatex() const
2514 return documentClass().outputType() == LATEX;
2518 bool BufferParams::isLiterate() const
2520 return documentClass().outputType() == LITERATE;
2524 bool BufferParams::isDocBook() const
2526 return documentClass().outputType() == DOCBOOK;
2530 void BufferParams::readPreamble(Lexer & lex)
2532 if (lex.getString() != "\\begin_preamble")
2533 lyxerr << "Error (BufferParams::readPreamble):"
2534 "consistency check failed." << endl;
2536 preamble = lex.getLongString("\\end_preamble");
2540 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2542 string const expected = forced ? "\\begin_forced_local_layout" :
2543 "\\begin_local_layout";
2544 if (lex.getString() != expected)
2545 lyxerr << "Error (BufferParams::readLocalLayout):"
2546 "consistency check failed." << endl;
2549 forced_local_layout_ =
2550 lex.getLongString("\\end_forced_local_layout");
2552 local_layout_ = lex.getLongString("\\end_local_layout");
2556 bool BufferParams::setLanguage(string const & lang)
2558 Language const *new_language = languages.getLanguage(lang);
2559 if (!new_language) {
2560 // Language lang was not found
2563 language = new_language;
2568 void BufferParams::readLanguage(Lexer & lex)
2570 if (!lex.next()) return;
2572 string const tmptok = lex.getString();
2574 // check if tmptok is part of tex_babel in tex-defs.h
2575 if (!setLanguage(tmptok)) {
2576 // Language tmptok was not found
2577 language = default_language;
2578 lyxerr << "Warning: Setting language `"
2579 << tmptok << "' to `" << language->lang()
2585 void BufferParams::readGraphicsDriver(Lexer & lex)
2590 string const tmptok = lex.getString();
2591 // check if tmptok is part of tex_graphics in tex_defs.h
2594 string const test = tex_graphics[n++];
2596 if (test == tmptok) {
2597 graphics_driver = tmptok;
2602 "Warning: graphics driver `$$Token' not recognized!\n"
2603 " Setting graphics driver to `default'.\n");
2604 graphics_driver = "default";
2611 void BufferParams::readBullets(Lexer & lex)
2616 int const index = lex.getInteger();
2618 int temp_int = lex.getInteger();
2619 user_defined_bullet(index).setFont(temp_int);
2620 temp_bullet(index).setFont(temp_int);
2622 user_defined_bullet(index).setCharacter(temp_int);
2623 temp_bullet(index).setCharacter(temp_int);
2625 user_defined_bullet(index).setSize(temp_int);
2626 temp_bullet(index).setSize(temp_int);
2630 void BufferParams::readBulletsLaTeX(Lexer & lex)
2632 // The bullet class should be able to read this.
2635 int const index = lex.getInteger();
2637 docstring const temp_str = lex.getDocString();
2639 user_defined_bullet(index).setText(temp_str);
2640 temp_bullet(index).setText(temp_str);
2644 void BufferParams::readModules(Lexer & lex)
2646 if (!lex.eatLine()) {
2647 lyxerr << "Error (BufferParams::readModules):"
2648 "Unexpected end of input." << endl;
2652 string mod = lex.getString();
2653 if (mod == "\\end_modules")
2655 addLayoutModule(mod);
2661 void BufferParams::readRemovedModules(Lexer & lex)
2663 if (!lex.eatLine()) {
2664 lyxerr << "Error (BufferParams::readRemovedModules):"
2665 "Unexpected end of input." << endl;
2669 string mod = lex.getString();
2670 if (mod == "\\end_removed_modules")
2672 removed_modules_.push_back(mod);
2675 // now we want to remove any removed modules that were previously
2676 // added. normally, that will be because default modules were added in
2677 // setBaseClass(), which gets called when \textclass is read at the
2678 // start of the read.
2679 list<string>::const_iterator rit = removed_modules_.begin();
2680 list<string>::const_iterator const ren = removed_modules_.end();
2681 for (; rit != ren; ++rit) {
2682 LayoutModuleList::iterator const mit = layout_modules_.begin();
2683 LayoutModuleList::iterator const men = layout_modules_.end();
2684 LayoutModuleList::iterator found = find(mit, men, *rit);
2687 layout_modules_.erase(found);
2692 void BufferParams::readIncludeonly(Lexer & lex)
2694 if (!lex.eatLine()) {
2695 lyxerr << "Error (BufferParams::readIncludeonly):"
2696 "Unexpected end of input." << endl;
2700 string child = lex.getString();
2701 if (child == "\\end_includeonly")
2703 included_children_.push_back(child);
2709 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2711 switch (papersize) {
2713 // could be anything, so don't guess
2715 case PAPER_CUSTOM: {
2716 if (purpose == XDVI && !paperwidth.empty() &&
2717 !paperheight.empty()) {
2718 // heightxwidth<unit>
2719 string first = paperwidth;
2720 string second = paperheight;
2721 if (orientation == ORIENTATION_LANDSCAPE)
2724 return first.erase(first.length() - 2)
2730 // dvips and dvipdfm do not know this
2731 if (purpose == DVIPS || purpose == DVIPDFM)
2735 if (purpose == DVIPS || purpose == DVIPDFM)
2739 if (purpose == DVIPS || purpose == DVIPDFM)
2749 if (purpose == DVIPS || purpose == DVIPDFM)
2753 if (purpose == DVIPS || purpose == DVIPDFM)
2757 if (purpose == DVIPS || purpose == DVIPDFM)
2761 if (purpose == DVIPS || purpose == DVIPDFM)
2765 if (purpose == DVIPS || purpose == DVIPDFM)
2769 // dvipdfm does not know this
2770 if (purpose == DVIPDFM)
2774 if (purpose == DVIPDFM)
2778 if (purpose == DVIPS || purpose == DVIPDFM)
2782 if (purpose == DVIPS || purpose == DVIPDFM)
2786 if (purpose == DVIPS || purpose == DVIPDFM)
2790 if (purpose == DVIPS || purpose == DVIPDFM)
2794 if (purpose == DVIPS || purpose == DVIPDFM)
2798 if (purpose == DVIPS || purpose == DVIPDFM)
2802 if (purpose == DVIPS || purpose == DVIPDFM)
2806 if (purpose == DVIPS || purpose == DVIPDFM)
2810 if (purpose == DVIPS || purpose == DVIPDFM)
2814 if (purpose == DVIPS || purpose == DVIPDFM)
2818 if (purpose == DVIPS || purpose == DVIPDFM)
2822 if (purpose == DVIPS || purpose == DVIPDFM)
2826 if (purpose == DVIPS || purpose == DVIPDFM)
2830 if (purpose == DVIPS || purpose == DVIPDFM)
2834 if (purpose == DVIPS || purpose == DVIPDFM)
2837 case PAPER_USEXECUTIVE:
2838 // dvipdfm does not know this
2839 if (purpose == DVIPDFM)
2844 case PAPER_USLETTER:
2846 if (purpose == XDVI)
2853 string const BufferParams::dvips_options() const
2857 // If the class loads the geometry package, we do not know which
2858 // paper size is used, since we do not set it (bug 7013).
2859 // Therefore we must not specify any argument here.
2860 // dvips gets the correct paper size via DVI specials in this case
2861 // (if the class uses the geometry package correctly).
2862 if (documentClass().provides("geometry"))
2866 && papersize == PAPER_CUSTOM
2867 && !lyxrc.print_paper_dimension_flag.empty()
2868 && !paperwidth.empty()
2869 && !paperheight.empty()) {
2870 // using a custom papersize
2871 result = lyxrc.print_paper_dimension_flag;
2872 result += ' ' + paperwidth;
2873 result += ',' + paperheight;
2875 string const paper_option = paperSizeName(DVIPS);
2876 if (!paper_option.empty() && (paper_option != "letter" ||
2877 orientation != ORIENTATION_LANDSCAPE)) {
2878 // dvips won't accept -t letter -t landscape.
2879 // In all other cases, include the paper size
2881 result = lyxrc.print_paper_flag;
2882 result += ' ' + paper_option;
2885 if (orientation == ORIENTATION_LANDSCAPE &&
2886 papersize != PAPER_CUSTOM)
2887 result += ' ' + lyxrc.print_landscape_flag;
2892 string const BufferParams::font_encoding() const
2894 return font_encodings().empty() ? "default" : font_encodings().back();
2898 vector<string> const BufferParams::font_encodings() const
2900 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2902 vector<string> fontencs;
2904 // "default" means "no explicit font encoding"
2905 if (doc_fontenc != "default") {
2906 fontencs = getVectorFromString(doc_fontenc);
2907 if (!language->fontenc().empty()
2908 && ascii_lowercase(language->fontenc()) != "none") {
2909 vector<string> fencs = getVectorFromString(language->fontenc());
2910 vector<string>::const_iterator fit = fencs.begin();
2911 for (; fit != fencs.end(); ++fit) {
2912 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
2913 fontencs.push_back(*fit);
2922 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2924 // suppress the babel call if there is no BabelName defined
2925 // for the document language in the lib/languages file and if no
2926 // other languages are used (lang_opts is then empty)
2927 if (lang_opts.empty())
2929 // either a specific language (AsBabelOptions setting in
2930 // lib/languages) or the prefs require the languages to
2931 // be submitted to babel itself (not the class).
2933 return "\\usepackage[" + lang_opts + "]{babel}";
2934 return "\\usepackage{babel}";
2938 docstring BufferParams::getGraphicsDriver(string const & package) const
2942 if (package == "geometry") {
2943 if (graphics_driver == "dvips"
2944 || graphics_driver == "dvipdfm"
2945 || graphics_driver == "pdftex"
2946 || graphics_driver == "vtex")
2947 result = from_ascii(graphics_driver);
2948 else if (graphics_driver == "dvipdfmx")
2949 result = from_ascii("dvipdfm");
2956 void BufferParams::writeEncodingPreamble(otexstream & os,
2957 LaTeXFeatures & features) const
2959 // XeTeX/LuaTeX: (see also #9740)
2960 // With Unicode fonts we use utf8-plain without encoding package.
2961 // With TeX fonts, we cannot use utf8-plain, but "inputenc" fails.
2962 // XeTeX must use ASCII encoding, for LuaTeX, we load
2963 // "luainputenc" (see below).
2964 if (useNonTeXFonts || features.runparams().flavor == OutputParams::XETEX)
2967 if (inputenc == "auto") {
2968 string const doc_encoding =
2969 language->encoding()->latexName();
2970 Encoding::Package const package =
2971 language->encoding()->package();
2973 // Create list of inputenc options:
2974 set<string> encodings;
2975 // luainputenc fails with more than one encoding
2976 if (!features.runparams().isFullUnicode()) // if we reach this point, this means LuaTeX with TeX fonts
2977 // list all input encodings used in the document
2978 encodings = features.getEncodingSet(doc_encoding);
2980 // If the "japanese" package (i.e. pLaTeX) is used,
2981 // inputenc must be omitted.
2982 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2983 if ((!encodings.empty() || package == Encoding::inputenc)
2984 && !features.isRequired("japanese")
2985 && !features.isProvided("inputenc")) {
2986 os << "\\usepackage[";
2987 set<string>::const_iterator it = encodings.begin();
2988 set<string>::const_iterator const end = encodings.end();
2990 os << from_ascii(*it);
2993 for (; it != end; ++it)
2994 os << ',' << from_ascii(*it);
2995 if (package == Encoding::inputenc) {
2996 if (!encodings.empty())
2998 os << from_ascii(doc_encoding);
3000 if (features.runparams().flavor == OutputParams::LUATEX
3001 || features.runparams().flavor == OutputParams::DVILUATEX)
3002 os << "]{luainputenc}\n";
3004 os << "]{inputenc}\n";
3006 if (package == Encoding::CJK || features.mustProvide("CJK")) {
3007 if (language->encoding()->name() == "utf8-cjk"
3008 && LaTeXFeatures::isAvailable("CJKutf8"))
3009 os << "\\usepackage{CJKutf8}\n";
3011 os << "\\usepackage{CJK}\n";
3013 } else if (inputenc != "default") {
3014 switch (encoding().package()) {
3015 case Encoding::none:
3016 case Encoding::japanese:
3018 case Encoding::inputenc:
3019 // do not load inputenc if japanese is used
3020 // or if the class provides inputenc
3021 if (features.isRequired("japanese")
3022 || features.isProvided("inputenc"))
3024 os << "\\usepackage[" << from_ascii(encoding().latexName());
3025 if (features.runparams().flavor == OutputParams::LUATEX
3026 || features.runparams().flavor == OutputParams::DVILUATEX)
3027 os << "]{luainputenc}\n";
3029 os << "]{inputenc}\n";
3032 if (encoding().name() == "utf8-cjk"
3033 && LaTeXFeatures::isAvailable("CJKutf8"))
3034 os << "\\usepackage{CJKutf8}\n";
3036 os << "\\usepackage{CJK}\n";
3039 // Load the CJK package if needed by a secondary language.
3040 // If the main encoding is some variant of UTF8, use CJKutf8.
3041 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
3042 if (encoding().iconvName() == "UTF-8"
3043 && LaTeXFeatures::isAvailable("CJKutf8"))
3044 os << "\\usepackage{CJKutf8}\n";
3046 os << "\\usepackage{CJK}\n";
3052 string const BufferParams::parseFontName(string const & name) const
3054 string mangled = name;
3055 size_t const idx = mangled.find('[');
3056 if (idx == string::npos || idx == 0)
3059 return mangled.substr(0, idx - 1);
3063 string const BufferParams::loadFonts(LaTeXFeatures & features) const
3065 if (fontsRoman() == "default" && fontsSans() == "default"
3066 && fontsTypewriter() == "default"
3067 && (fontsMath() == "default" || fontsMath() == "auto"))
3073 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
3074 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
3075 * Mapping=tex-text option assures TeX ligatures (such as "--")
3076 * are resolved. Note that tt does not use these ligatures.
3078 * -- add more GUI options?
3079 * -- add more fonts (fonts for other scripts)
3080 * -- if there's a way to find out if a font really supports
3081 * OldStyle, enable/disable the widget accordingly.
3083 if (useNonTeXFonts && features.isAvailable("fontspec")) {
3084 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
3085 // However, until v.2 (2010/07/11) fontspec only knew
3086 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
3087 // was introduced for both XeTeX and LuaTeX (LuaTeX
3088 // didn't understand "Mapping=tex-text", while XeTeX
3089 // understood both. With most recent versions, both
3090 // variants are understood by both engines. However,
3091 // we want to provide support for at least TeXLive 2009
3092 // (for XeTeX; LuaTeX is only supported as of v.2)
3093 string const texmapping =
3094 (features.runparams().flavor == OutputParams::XETEX) ?
3095 "Mapping=tex-text" : "Ligatures=TeX";
3096 if (fontsRoman() != "default") {
3097 os << "\\setmainfont[" << texmapping;
3098 if (fonts_old_figures)
3099 os << ",Numbers=OldStyle";
3100 os << "]{" << parseFontName(fontsRoman()) << "}\n";
3102 if (fontsSans() != "default") {
3103 string const sans = parseFontName(fontsSans());
3104 if (fontsSansScale() != 100)
3105 os << "\\setsansfont[Scale="
3106 << float(fontsSansScale()) / 100
3107 << "," << texmapping << "]{"
3110 os << "\\setsansfont[" << texmapping << "]{"
3113 if (fontsTypewriter() != "default") {
3114 string const mono = parseFontName(fontsTypewriter());
3115 if (fontsTypewriterScale() != 100)
3116 os << "\\setmonofont[Scale="
3117 << float(fontsTypewriterScale()) / 100
3121 os << "\\setmonofont{"
3128 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
3129 bool const dryrun = features.runparams().dryrun;
3130 bool const complete = (fontsSans() == "default" && fontsTypewriter() == "default");
3131 bool const nomath = (fontsMath() == "default");
3134 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsRoman())).getLaTeXCode(
3135 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3139 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsSans())).getLaTeXCode(
3140 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3141 nomath, fontsSansScale());
3143 // MONOSPACED/TYPEWRITER
3144 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsTypewriter())).getLaTeXCode(
3145 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3146 nomath, fontsTypewriterScale());
3149 os << theLaTeXFonts().getLaTeXFont(from_ascii(fontsMath())).getLaTeXCode(
3150 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3157 Encoding const & BufferParams::encoding() const
3159 // Main encoding for LaTeX output.
3161 // Exception: XeTeX with 8-bit TeX fonts requires ASCII (see #9740).
3162 // As the "flavor" is only known once export started, this
3163 // cannot be handled here. Instead, runparams.encoding is set
3164 // to ASCII in Buffer::makeLaTeXFile (for export)
3165 // and Buffer::writeLaTeXSource (for preview).
3167 return *(encodings.fromLyXName("utf8-plain"));
3168 if (inputenc == "auto" || inputenc == "default")
3169 return *language->encoding();
3170 Encoding const * const enc = encodings.fromLyXName(inputenc);
3173 LYXERR0("Unknown inputenc value `" << inputenc
3174 << "'. Using `auto' instead.");
3175 return *language->encoding();
3179 bool BufferParams::addCiteEngine(string const & engine)
3181 LayoutModuleList::const_iterator it = cite_engine_.begin();
3182 LayoutModuleList::const_iterator en = cite_engine_.end();
3183 for (; it != en; ++it)
3186 cite_engine_.push_back(engine);
3191 bool BufferParams::addCiteEngine(vector<string> const & engine)
3193 vector<string>::const_iterator it = engine.begin();
3194 vector<string>::const_iterator en = engine.end();
3196 for (; it != en; ++it)
3197 if (!addCiteEngine(*it))
3203 string const & BufferParams::defaultBiblioStyle() const
3205 return documentClass().defaultBiblioStyle();
3209 bool const & BufferParams::fullAuthorList() const
3211 return documentClass().fullAuthorList();
3215 void BufferParams::setCiteEngine(string const & engine)
3218 addCiteEngine(engine);
3222 void BufferParams::setCiteEngine(vector<string> const & engine)
3225 addCiteEngine(engine);
3229 vector<string> BufferParams::citeCommands() const
3231 static CitationStyle const default_style;
3232 vector<string> commands =
3233 documentClass().citeCommands(citeEngineType());
3234 if (commands.empty())
3235 commands.push_back(default_style.cmd);
3240 vector<CitationStyle> BufferParams::citeStyles() const
3242 static CitationStyle const default_style;
3243 vector<CitationStyle> styles =
3244 documentClass().citeStyles(citeEngineType());
3246 styles.push_back(default_style);