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/Translator.h"
58 #include "support/lstrings.h"
64 using namespace lyx::support;
67 static char const * const string_paragraph_separation[] = {
72 static char const * const string_quotes_language[] = {
73 "english", "swedish", "german", "polish", "french", "danish", ""
77 static char const * const string_papersize[] = {
78 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
79 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
80 "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
81 "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
82 "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
87 static char const * const string_orientation[] = {
88 "portrait", "landscape", ""
92 static char const * const tex_graphics[] = {
93 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
94 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
95 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
96 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
107 // Paragraph separation
108 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
111 ParSepTranslator const init_parseptranslator()
113 ParSepTranslator translator
114 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
115 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
120 ParSepTranslator const & parseptranslator()
122 static ParSepTranslator const translator =
123 init_parseptranslator();
129 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
132 QuotesLangTranslator const init_quoteslangtranslator()
134 QuotesLangTranslator translator
135 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
136 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
137 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
138 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
139 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
140 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
145 QuotesLangTranslator const & quoteslangtranslator()
147 static QuotesLangTranslator const translator =
148 init_quoteslangtranslator();
154 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
157 static PaperSizeTranslator initPaperSizeTranslator()
159 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
160 translator.addPair(string_papersize[1], PAPER_CUSTOM);
161 translator.addPair(string_papersize[2], PAPER_USLETTER);
162 translator.addPair(string_papersize[3], PAPER_USLEGAL);
163 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
164 translator.addPair(string_papersize[5], PAPER_A0);
165 translator.addPair(string_papersize[6], PAPER_A1);
166 translator.addPair(string_papersize[7], PAPER_A2);
167 translator.addPair(string_papersize[8], PAPER_A3);
168 translator.addPair(string_papersize[9], PAPER_A4);
169 translator.addPair(string_papersize[10], PAPER_A5);
170 translator.addPair(string_papersize[11], PAPER_A6);
171 translator.addPair(string_papersize[12], PAPER_B0);
172 translator.addPair(string_papersize[13], PAPER_B1);
173 translator.addPair(string_papersize[14], PAPER_B2);
174 translator.addPair(string_papersize[15], PAPER_B3);
175 translator.addPair(string_papersize[16], PAPER_B4);
176 translator.addPair(string_papersize[17], PAPER_B5);
177 translator.addPair(string_papersize[18], PAPER_B6);
178 translator.addPair(string_papersize[19], PAPER_C0);
179 translator.addPair(string_papersize[20], PAPER_C1);
180 translator.addPair(string_papersize[21], PAPER_C2);
181 translator.addPair(string_papersize[22], PAPER_C3);
182 translator.addPair(string_papersize[23], PAPER_C4);
183 translator.addPair(string_papersize[24], PAPER_C5);
184 translator.addPair(string_papersize[25], PAPER_C6);
185 translator.addPair(string_papersize[26], PAPER_JISB0);
186 translator.addPair(string_papersize[27], PAPER_JISB1);
187 translator.addPair(string_papersize[28], PAPER_JISB2);
188 translator.addPair(string_papersize[29], PAPER_JISB3);
189 translator.addPair(string_papersize[30], PAPER_JISB4);
190 translator.addPair(string_papersize[31], PAPER_JISB5);
191 translator.addPair(string_papersize[32], PAPER_JISB6);
196 PaperSizeTranslator const & papersizetranslator()
198 static PaperSizeTranslator const translator =
199 initPaperSizeTranslator();
205 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
208 PaperOrientationTranslator const init_paperorientationtranslator()
210 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
211 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
216 PaperOrientationTranslator const & paperorientationtranslator()
218 static PaperOrientationTranslator const translator =
219 init_paperorientationtranslator();
225 typedef Translator<int, PageSides> SidesTranslator;
228 SidesTranslator const init_sidestranslator()
230 SidesTranslator translator(1, OneSide);
231 translator.addPair(2, TwoSides);
236 SidesTranslator const & sidestranslator()
238 static SidesTranslator const translator = init_sidestranslator();
244 typedef Translator<int, BufferParams::Package> PackageTranslator;
247 PackageTranslator const init_packagetranslator()
249 PackageTranslator translator(0, BufferParams::package_off);
250 translator.addPair(1, BufferParams::package_auto);
251 translator.addPair(2, BufferParams::package_on);
256 PackageTranslator const & packagetranslator()
258 static PackageTranslator const translator =
259 init_packagetranslator();
265 typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator;
268 CiteEngineTypeTranslator const init_citeenginetypetranslator()
270 CiteEngineTypeTranslator translator("authoryear", ENGINE_TYPE_AUTHORYEAR);
271 translator.addPair("numerical", ENGINE_TYPE_NUMERICAL);
272 translator.addPair("default", ENGINE_TYPE_DEFAULT);
277 CiteEngineTypeTranslator const & citeenginetypetranslator()
279 static CiteEngineTypeTranslator const translator =
280 init_citeenginetypetranslator();
286 typedef Translator<string, Spacing::Space> SpaceTranslator;
289 SpaceTranslator const init_spacetranslator()
291 SpaceTranslator translator("default", Spacing::Default);
292 translator.addPair("single", Spacing::Single);
293 translator.addPair("onehalf", Spacing::Onehalf);
294 translator.addPair("double", Spacing::Double);
295 translator.addPair("other", Spacing::Other);
300 SpaceTranslator const & spacetranslator()
302 static SpaceTranslator const translator = init_spacetranslator();
309 class BufferParams::Impl
314 AuthorList authorlist;
315 BranchList branchlist;
316 Bullet temp_bullets[4];
317 Bullet user_defined_bullets[4];
318 IndicesList indiceslist;
320 /** This is the amount of space used for paragraph_separation "skip",
321 * and for detached paragraphs in "indented" documents.
325 PDFOptions pdfoptions;
326 LayoutFileIndex baseClass_;
330 BufferParams::Impl::Impl()
331 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
333 // set initial author
335 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
340 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
343 return new BufferParams::Impl(*ptr);
347 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
353 BufferParams::BufferParams()
356 setBaseClass(defaultBaseclass());
358 paragraph_separation = ParagraphIndentSeparation;
359 quotes_language = InsetQuotes::EnglishQuotes;
360 fontsize = "default";
363 papersize = PAPER_DEFAULT;
364 orientation = ORIENTATION_PORTRAIT;
365 use_geometry = false;
366 cite_engine_.push_back("basic");
367 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
368 biblio_style = "plain";
369 use_bibtopic = false;
371 track_changes = false;
372 output_changes = false;
373 use_default_options = true;
374 maintain_unincluded_children = false;
377 language = default_language;
379 fonts_roman = "default";
380 fonts_sans = "default";
381 fonts_typewriter = "default";
383 fonts_default_family = "default";
384 useNonTeXFonts = false;
385 fonts_expert_sc = false;
386 fonts_old_figures = false;
387 fonts_sans_scale = 100;
388 fonts_typewriter_scale = 100;
390 lang_package = "default";
391 graphics_driver = "default";
392 default_output_format = "default";
393 bibtex_command = "default";
394 index_command = "default";
397 listings_params = string();
398 pagestyle = "default";
399 suppress_date = false;
400 justification = true;
401 // no color is the default (white)
402 backgroundcolor = lyx::rgbFromHexName("#ffffff");
403 isbackgroundcolor = false;
404 // no color is the default (black)
405 fontcolor = lyx::rgbFromHexName("#000000");
407 // light gray is the default font color for greyed-out notes
408 notefontcolor = lyx::rgbFromHexName("#cccccc");
409 boxbgcolor = lyx::rgbFromHexName("#ff0000");
410 compressed = lyxrc.save_compressed;
411 for (int iter = 0; iter < 4; ++iter) {
412 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
413 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
416 indiceslist().addDefault(B_("Index"));
417 html_be_strict = false;
418 html_math_output = MathML;
419 html_math_img_scale = 1.0;
420 html_css_as_file = false;
421 display_pixel_ratio = 1.0;
428 docstring BufferParams::B_(string const & l10n) const
430 LASSERT(language, return from_utf8(l10n));
431 return getMessages(language->code()).get(l10n);
435 BufferParams::Package BufferParams::use_package(std::string const & p) const
437 PackageMap::const_iterator it = use_packages.find(p);
438 if (it == use_packages.end())
444 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
450 map<string, string> const & BufferParams::auto_packages()
452 static map<string, string> packages;
453 if (packages.empty()) {
454 // We could have a race condition here that two threads
455 // discover an empty map at the same time and want to fill
456 // it, but that is no problem, since the same contents is
457 // filled in twice then. Having the locker inside the
458 // packages.empty() condition has the advantage that we
459 // don't need the mutex overhead for simple reading.
461 Mutex::Locker locker(&mutex);
462 // adding a package here implies a file format change!
463 packages["amsmath"] =
464 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
465 packages["amssymb"] =
466 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
468 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
470 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
471 packages["mathdots"] =
472 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
473 packages["mathtools"] =
474 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
476 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
477 packages["stackrel"] =
478 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
479 packages["stmaryrd"] =
480 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");
481 packages["undertilde"] =
482 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
488 AuthorList & BufferParams::authors()
490 return pimpl_->authorlist;
494 AuthorList const & BufferParams::authors() const
496 return pimpl_->authorlist;
500 BranchList & BufferParams::branchlist()
502 return pimpl_->branchlist;
506 BranchList const & BufferParams::branchlist() const
508 return pimpl_->branchlist;
512 IndicesList & BufferParams::indiceslist()
514 return pimpl_->indiceslist;
518 IndicesList const & BufferParams::indiceslist() const
520 return pimpl_->indiceslist;
524 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
526 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
527 return pimpl_->temp_bullets[index];
531 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
533 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
534 return pimpl_->temp_bullets[index];
538 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
540 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
541 return pimpl_->user_defined_bullets[index];
545 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
547 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
548 return pimpl_->user_defined_bullets[index];
552 Spacing & BufferParams::spacing()
554 return pimpl_->spacing;
558 Spacing const & BufferParams::spacing() const
560 return pimpl_->spacing;
564 PDFOptions & BufferParams::pdfoptions()
566 return pimpl_->pdfoptions;
570 PDFOptions const & BufferParams::pdfoptions() const
572 return pimpl_->pdfoptions;
576 HSpace const & BufferParams::getIndentation() const
578 return pimpl_->indentation;
582 void BufferParams::setIndentation(HSpace const & indent)
584 pimpl_->indentation = indent;
588 VSpace const & BufferParams::getDefSkip() const
590 return pimpl_->defskip;
594 void BufferParams::setDefSkip(VSpace const & vs)
596 // DEFSKIP will cause an infinite loop
597 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
598 pimpl_->defskip = vs;
602 string BufferParams::readToken(Lexer & lex, string const & token,
603 FileName const & filepath)
607 if (token == "\\textclass") {
609 string const classname = lex.getString();
610 // if there exists a local layout file, ignore the system one
611 // NOTE: in this case, the textclass (.cls file) is assumed to
614 LayoutFileList & bcl = LayoutFileList::get();
615 if (!filepath.empty()) {
616 // If classname is an absolute path, the document is
617 // using a local layout file which could not be accessed
618 // by a relative path. In this case the path is correct
619 // even if the document was moved to a different
620 // location. However, we will have a problem if the
621 // document was generated on a different platform.
622 bool isabsolute = FileName::isAbsolute(classname);
623 string const classpath = onlyPath(classname);
624 string const path = isabsolute ? classpath
625 : FileName(addPath(filepath.absFileName(),
626 classpath)).realPath();
627 string const oldpath = isabsolute ? string()
628 : FileName(addPath(origin, classpath)).realPath();
629 tcp = bcl.addLocalLayout(onlyFileName(classname), path, oldpath);
631 // that returns non-empty if a "local" layout file is found.
633 result = to_utf8(makeRelPath(from_utf8(onlyPath(tcp)),
634 from_utf8(filepath.absFileName())));
637 setBaseClass(onlyFileName(tcp));
639 setBaseClass(onlyFileName(classname));
640 // We assume that a tex class exists for local or unknown
641 // layouts so this warning, will only be given for system layouts.
642 if (!baseClass()->isTeXClassAvailable()) {
643 docstring const desc =
644 translateIfPossible(from_utf8(baseClass()->description()));
645 docstring const prereqs =
646 from_utf8(baseClass()->prerequisites());
647 docstring const msg =
648 bformat(_("The selected document class\n"
650 "requires external files that are not available.\n"
651 "The document class can still be used, but the\n"
652 "document cannot be compiled until the following\n"
653 "prerequisites are installed:\n"
655 "See section 3.1.2.2 (Class Availability) of the\n"
656 "User's Guide for more information."), desc, prereqs);
657 frontend::Alert::warning(_("Document class not available"),
660 } else if (token == "\\origin") {
662 origin = lex.getString();
663 } else if (token == "\\begin_preamble") {
665 } else if (token == "\\begin_local_layout") {
666 readLocalLayout(lex, false);
667 } else if (token == "\\begin_forced_local_layout") {
668 readLocalLayout(lex, true);
669 } else if (token == "\\begin_modules") {
671 } else if (token == "\\begin_removed_modules") {
672 readRemovedModules(lex);
673 } else if (token == "\\begin_includeonly") {
674 readIncludeonly(lex);
675 } else if (token == "\\maintain_unincluded_children") {
676 lex >> maintain_unincluded_children;
677 } else if (token == "\\options") {
679 options = lex.getString();
680 } else if (token == "\\use_default_options") {
681 lex >> use_default_options;
682 } else if (token == "\\master") {
684 master = lex.getString();
685 } else if (token == "\\suppress_date") {
686 lex >> suppress_date;
687 } else if (token == "\\justification") {
688 lex >> justification;
689 } else if (token == "\\language") {
691 } else if (token == "\\language_package") {
693 lang_package = lex.getString();
694 } else if (token == "\\inputencoding") {
696 } else if (token == "\\graphics") {
697 readGraphicsDriver(lex);
698 } else if (token == "\\default_output_format") {
699 lex >> default_output_format;
700 } else if (token == "\\bibtex_command") {
702 bibtex_command = lex.getString();
703 } else if (token == "\\index_command") {
705 index_command = lex.getString();
706 } else if (token == "\\fontencoding") {
708 fontenc = lex.getString();
709 } else if (token == "\\font_roman") {
711 fonts_roman = lex.getString();
712 } else if (token == "\\font_sans") {
714 fonts_sans = lex.getString();
715 } else if (token == "\\font_typewriter") {
717 fonts_typewriter = lex.getString();
718 } else if (token == "\\font_math") {
720 fonts_math = lex.getString();
721 } else if (token == "\\font_default_family") {
722 lex >> fonts_default_family;
723 } else if (token == "\\use_non_tex_fonts") {
724 lex >> useNonTeXFonts;
725 } else if (token == "\\font_sc") {
726 lex >> fonts_expert_sc;
727 } else if (token == "\\font_osf") {
728 lex >> fonts_old_figures;
729 } else if (token == "\\font_sf_scale") {
730 lex >> fonts_sans_scale;
731 } else if (token == "\\font_tt_scale") {
732 lex >> fonts_typewriter_scale;
733 } else if (token == "\\font_cjk") {
735 } else if (token == "\\paragraph_separation") {
738 paragraph_separation = parseptranslator().find(parsep);
739 } else if (token == "\\paragraph_indentation") {
741 string indentation = lex.getString();
742 pimpl_->indentation = HSpace(indentation);
743 } else if (token == "\\defskip") {
745 string const defskip = lex.getString();
746 pimpl_->defskip = VSpace(defskip);
747 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
749 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
750 } else if (token == "\\quotes_language") {
753 quotes_language = quoteslangtranslator().find(quotes_lang);
754 } else if (token == "\\papersize") {
757 papersize = papersizetranslator().find(ppsize);
758 } else if (token == "\\use_geometry") {
760 } else if (token == "\\use_package") {
765 use_package(package, packagetranslator().find(use));
766 } else if (token == "\\cite_engine") {
768 vector<string> engine = getVectorFromString(lex.getString());
769 setCiteEngine(engine);
770 } else if (token == "\\cite_engine_type") {
773 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
774 } else if (token == "\\biblio_style") {
776 biblio_style = lex.getString();
777 } else if (token == "\\use_bibtopic") {
779 } else if (token == "\\use_indices") {
781 } else if (token == "\\tracking_changes") {
782 lex >> track_changes;
783 } else if (token == "\\output_changes") {
784 lex >> output_changes;
785 } else if (token == "\\branch") {
787 docstring branch = lex.getDocString();
788 branchlist().add(branch);
791 string const tok = lex.getString();
792 if (tok == "\\end_branch")
794 Branch * branch_ptr = branchlist().find(branch);
795 if (tok == "\\selected") {
798 branch_ptr->setSelected(lex.getInteger());
800 if (tok == "\\filename_suffix") {
803 branch_ptr->setFileNameSuffix(lex.getInteger());
805 if (tok == "\\color") {
807 string color = lex.getString();
809 branch_ptr->setColor(color);
810 // Update also the Color table:
812 color = lcolor.getX11Name(Color_background);
814 lcolor.setColor(to_utf8(branch), color);
817 } else if (token == "\\index") {
819 docstring index = lex.getDocString();
821 indiceslist().add(index);
824 string const tok = lex.getString();
825 if (tok == "\\end_index")
827 Index * index_ptr = indiceslist().find(index);
828 if (tok == "\\shortcut") {
830 shortcut = lex.getDocString();
832 index_ptr->setShortcut(shortcut);
834 if (tok == "\\color") {
836 string color = lex.getString();
838 index_ptr->setColor(color);
839 // Update also the Color table:
841 color = lcolor.getX11Name(Color_background);
843 if (!shortcut.empty())
844 lcolor.setColor(to_utf8(shortcut), color);
847 } else if (token == "\\author") {
849 istringstream ss(lex.getString());
852 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
853 } else if (token == "\\paperorientation") {
856 orientation = paperorientationtranslator().find(orient);
857 } else if (token == "\\backgroundcolor") {
859 backgroundcolor = lyx::rgbFromHexName(lex.getString());
860 isbackgroundcolor = true;
861 } else if (token == "\\fontcolor") {
863 fontcolor = lyx::rgbFromHexName(lex.getString());
865 } else if (token == "\\notefontcolor") {
867 string color = lex.getString();
868 notefontcolor = lyx::rgbFromHexName(color);
869 lcolor.setColor("notefontcolor", color);
870 } else if (token == "\\boxbgcolor") {
872 string color = lex.getString();
873 boxbgcolor = lyx::rgbFromHexName(color);
874 lcolor.setColor("boxbgcolor", color);
875 } else if (token == "\\paperwidth") {
877 } else if (token == "\\paperheight") {
879 } else if (token == "\\leftmargin") {
881 } else if (token == "\\topmargin") {
883 } else if (token == "\\rightmargin") {
885 } else if (token == "\\bottommargin") {
887 } else if (token == "\\headheight") {
889 } else if (token == "\\headsep") {
891 } else if (token == "\\footskip") {
893 } else if (token == "\\columnsep") {
895 } else if (token == "\\paperfontsize") {
897 } else if (token == "\\papercolumns") {
899 } else if (token == "\\listings_params") {
902 listings_params = InsetListingsParams(par).params();
903 } else if (token == "\\papersides") {
906 sides = sidestranslator().find(psides);
907 } else if (token == "\\paperpagestyle") {
909 } else if (token == "\\bullet") {
911 } else if (token == "\\bulletLaTeX") {
912 readBulletsLaTeX(lex);
913 } else if (token == "\\secnumdepth") {
915 } else if (token == "\\tocdepth") {
917 } else if (token == "\\spacing") {
921 if (nspacing == "other") {
924 spacing().set(spacetranslator().find(nspacing), tmp_val);
925 } else if (token == "\\float_placement") {
926 lex >> float_placement;
928 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
929 string toktmp = pdfoptions().readToken(lex, token);
930 if (!toktmp.empty()) {
931 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
935 } else if (token == "\\html_math_output") {
938 html_math_output = static_cast<MathOutput>(temp);
939 } else if (token == "\\html_be_strict") {
940 lex >> html_be_strict;
941 } else if (token == "\\html_css_as_file") {
942 lex >> html_css_as_file;
943 } else if (token == "\\html_math_img_scale") {
944 lex >> html_math_img_scale;
945 } else if (token == "\\html_latex_start") {
947 html_latex_start = lex.getString();
948 } else if (token == "\\html_latex_end") {
950 html_latex_end = lex.getString();
951 } else if (token == "\\output_sync") {
953 } else if (token == "\\output_sync_macro") {
954 lex >> output_sync_macro;
955 } else if (token == "\\use_refstyle") {
958 lyxerr << "BufferParams::readToken(): Unknown token: " <<
967 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
969 // The top of the file is written by the buffer.
970 // Prints out the buffer info into the .lyx file given by file
972 // the document directory
973 os << "\\origin " << buf->filePath() << '\n';
976 os << "\\textclass " << buf->includedFilePath(addName(buf->layoutPos(),
977 baseClass()->name()), "layout")
981 if (!preamble.empty()) {
982 // remove '\n' from the end of preamble
983 string const tmppreamble = rtrim(preamble, "\n");
984 os << "\\begin_preamble\n"
986 << "\n\\end_preamble\n";
990 if (!options.empty()) {
991 os << "\\options " << options << '\n';
994 // use the class options defined in the layout?
995 os << "\\use_default_options "
996 << convert<string>(use_default_options) << "\n";
998 // the master document
999 if (!master.empty()) {
1000 os << "\\master " << master << '\n';
1004 if (!removed_modules_.empty()) {
1005 os << "\\begin_removed_modules" << '\n';
1006 list<string>::const_iterator it = removed_modules_.begin();
1007 list<string>::const_iterator en = removed_modules_.end();
1008 for (; it != en; ++it)
1010 os << "\\end_removed_modules" << '\n';
1014 if (!layout_modules_.empty()) {
1015 os << "\\begin_modules" << '\n';
1016 LayoutModuleList::const_iterator it = layout_modules_.begin();
1017 LayoutModuleList::const_iterator en = layout_modules_.end();
1018 for (; it != en; ++it)
1020 os << "\\end_modules" << '\n';
1024 if (!included_children_.empty()) {
1025 os << "\\begin_includeonly" << '\n';
1026 list<string>::const_iterator it = included_children_.begin();
1027 list<string>::const_iterator en = included_children_.end();
1028 for (; it != en; ++it)
1030 os << "\\end_includeonly" << '\n';
1032 os << "\\maintain_unincluded_children "
1033 << convert<string>(maintain_unincluded_children) << '\n';
1035 // local layout information
1036 string const local_layout = getLocalLayout(false);
1037 if (!local_layout.empty()) {
1038 // remove '\n' from the end
1039 string const tmplocal = rtrim(local_layout, "\n");
1040 os << "\\begin_local_layout\n"
1042 << "\n\\end_local_layout\n";
1044 string const forced_local_layout = getLocalLayout(true);
1045 if (!forced_local_layout.empty()) {
1046 // remove '\n' from the end
1047 string const tmplocal = rtrim(forced_local_layout, "\n");
1048 os << "\\begin_forced_local_layout\n"
1050 << "\n\\end_forced_local_layout\n";
1053 // then the text parameters
1054 if (language != ignore_language)
1055 os << "\\language " << language->lang() << '\n';
1056 os << "\\language_package " << lang_package
1057 << "\n\\inputencoding " << inputenc
1058 << "\n\\fontencoding " << fontenc
1059 << "\n\\font_roman " << fonts_roman
1060 << "\n\\font_sans " << fonts_sans
1061 << "\n\\font_typewriter " << fonts_typewriter
1062 << "\n\\font_math " << fonts_math
1063 << "\n\\font_default_family " << fonts_default_family
1064 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1065 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1066 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1067 << "\n\\font_sf_scale " << fonts_sans_scale
1068 << "\n\\font_tt_scale " << fonts_typewriter_scale
1070 if (!fonts_cjk.empty()) {
1071 os << "\\font_cjk " << fonts_cjk << '\n';
1073 os << "\\graphics " << graphics_driver << '\n';
1074 os << "\\default_output_format " << default_output_format << '\n';
1075 os << "\\output_sync " << output_sync << '\n';
1076 if (!output_sync_macro.empty())
1077 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1078 os << "\\bibtex_command " << bibtex_command << '\n';
1079 os << "\\index_command " << index_command << '\n';
1081 if (!float_placement.empty()) {
1082 os << "\\float_placement " << float_placement << '\n';
1084 os << "\\paperfontsize " << fontsize << '\n';
1086 spacing().writeFile(os);
1087 pdfoptions().writeFile(os);
1089 os << "\\papersize " << string_papersize[papersize]
1090 << "\n\\use_geometry " << convert<string>(use_geometry);
1091 map<string, string> const & packages = auto_packages();
1092 for (map<string, string>::const_iterator it = packages.begin();
1093 it != packages.end(); ++it)
1094 os << "\n\\use_package " << it->first << ' '
1095 << use_package(it->first);
1097 os << "\n\\cite_engine ";
1099 if (!cite_engine_.empty()) {
1100 LayoutModuleList::const_iterator be = cite_engine_.begin();
1101 LayoutModuleList::const_iterator en = cite_engine_.end();
1102 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1111 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1112 << "\n\\biblio_style " << biblio_style
1113 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1114 << "\n\\use_indices " << convert<string>(use_indices)
1115 << "\n\\paperorientation " << string_orientation[orientation]
1116 << "\n\\suppress_date " << convert<string>(suppress_date)
1117 << "\n\\justification " << convert<string>(justification)
1118 << "\n\\use_refstyle " << use_refstyle
1120 if (isbackgroundcolor == true)
1121 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1122 if (isfontcolor == true)
1123 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1124 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1125 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1126 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1127 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1129 BranchList::const_iterator it = branchlist().begin();
1130 BranchList::const_iterator end = branchlist().end();
1131 for (; it != end; ++it) {
1132 os << "\\branch " << to_utf8(it->branch())
1133 << "\n\\selected " << it->isSelected()
1134 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1135 << "\n\\color " << lyx::X11hexname(it->color())
1140 IndicesList::const_iterator iit = indiceslist().begin();
1141 IndicesList::const_iterator iend = indiceslist().end();
1142 for (; iit != iend; ++iit) {
1143 os << "\\index " << to_utf8(iit->index())
1144 << "\n\\shortcut " << to_utf8(iit->shortcut())
1145 << "\n\\color " << lyx::X11hexname(iit->color())
1150 if (!paperwidth.empty())
1151 os << "\\paperwidth "
1152 << VSpace(paperwidth).asLyXCommand() << '\n';
1153 if (!paperheight.empty())
1154 os << "\\paperheight "
1155 << VSpace(paperheight).asLyXCommand() << '\n';
1156 if (!leftmargin.empty())
1157 os << "\\leftmargin "
1158 << VSpace(leftmargin).asLyXCommand() << '\n';
1159 if (!topmargin.empty())
1160 os << "\\topmargin "
1161 << VSpace(topmargin).asLyXCommand() << '\n';
1162 if (!rightmargin.empty())
1163 os << "\\rightmargin "
1164 << VSpace(rightmargin).asLyXCommand() << '\n';
1165 if (!bottommargin.empty())
1166 os << "\\bottommargin "
1167 << VSpace(bottommargin).asLyXCommand() << '\n';
1168 if (!headheight.empty())
1169 os << "\\headheight "
1170 << VSpace(headheight).asLyXCommand() << '\n';
1171 if (!headsep.empty())
1173 << VSpace(headsep).asLyXCommand() << '\n';
1174 if (!footskip.empty())
1176 << VSpace(footskip).asLyXCommand() << '\n';
1177 if (!columnsep.empty())
1178 os << "\\columnsep "
1179 << VSpace(columnsep).asLyXCommand() << '\n';
1180 os << "\\secnumdepth " << secnumdepth
1181 << "\n\\tocdepth " << tocdepth
1182 << "\n\\paragraph_separation "
1183 << string_paragraph_separation[paragraph_separation];
1184 if (!paragraph_separation)
1185 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1187 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1188 os << "\n\\quotes_language "
1189 << string_quotes_language[quotes_language]
1190 << "\n\\papercolumns " << columns
1191 << "\n\\papersides " << sides
1192 << "\n\\paperpagestyle " << pagestyle << '\n';
1193 if (!listings_params.empty())
1194 os << "\\listings_params \"" <<
1195 InsetListingsParams(listings_params).encodedString() << "\"\n";
1196 for (int i = 0; i < 4; ++i) {
1197 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1198 if (user_defined_bullet(i).getFont() != -1) {
1199 os << "\\bullet " << i << " "
1200 << user_defined_bullet(i).getFont() << " "
1201 << user_defined_bullet(i).getCharacter() << " "
1202 << user_defined_bullet(i).getSize() << "\n";
1206 os << "\\bulletLaTeX " << i << " \""
1207 << lyx::to_ascii(user_defined_bullet(i).getText())
1213 os << "\\tracking_changes " << convert<string>(track_changes) << '\n'
1214 << "\\output_changes " << convert<string>(output_changes) << '\n'
1215 << "\\html_math_output " << html_math_output << '\n'
1216 << "\\html_css_as_file " << html_css_as_file << '\n'
1217 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1219 if (html_math_img_scale != 1.0)
1220 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1221 if (!html_latex_start.empty())
1222 os << "\\html_latex_start " << html_latex_start << '\n';
1223 if (!html_latex_end.empty())
1224 os << "\\html_latex_end " << html_latex_end << '\n';
1226 os << pimpl_->authorlist;
1230 void BufferParams::validate(LaTeXFeatures & features) const
1232 features.require(documentClass().requires());
1234 if (columns > 1 && language->rightToLeft())
1235 features.require("rtloutputdblcol");
1237 if (output_changes) {
1238 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1239 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1240 LaTeXFeatures::isAvailable("xcolor");
1242 switch (features.runparams().flavor) {
1243 case OutputParams::LATEX:
1244 case OutputParams::DVILUATEX:
1246 features.require("ct-dvipost");
1247 features.require("dvipost");
1248 } else if (xcolorulem) {
1249 features.require("ct-xcolor-ulem");
1250 features.require("ulem");
1251 features.require("xcolor");
1253 features.require("ct-none");
1256 case OutputParams::LUATEX:
1257 case OutputParams::PDFLATEX:
1258 case OutputParams::XETEX:
1260 features.require("ct-xcolor-ulem");
1261 features.require("ulem");
1262 features.require("xcolor");
1263 // improves color handling in PDF output
1264 features.require("pdfcolmk");
1266 features.require("ct-none");
1274 // Floats with 'Here definitely' as default setting.
1275 if (float_placement.find('H') != string::npos)
1276 features.require("float");
1278 for (PackageMap::const_iterator it = use_packages.begin();
1279 it != use_packages.end(); ++it) {
1280 if (it->first == "amsmath") {
1281 // AMS Style is at document level
1282 if (it->second == package_on ||
1283 features.isProvided("amsmath"))
1284 features.require(it->first);
1285 } else if (it->second == package_on)
1286 features.require(it->first);
1289 // Document-level line spacing
1290 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1291 features.require("setspace");
1293 // the bullet shapes are buffer level not paragraph level
1294 // so they are tested here
1295 for (int i = 0; i < 4; ++i) {
1296 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1298 int const font = user_defined_bullet(i).getFont();
1300 int const c = user_defined_bullet(i).getCharacter();
1306 features.require("latexsym");
1308 } else if (font == 1) {
1309 features.require("amssymb");
1310 } else if (font >= 2 && font <= 5) {
1311 features.require("pifont");
1315 if (pdfoptions().use_hyperref) {
1316 features.require("hyperref");
1317 // due to interferences with babel and hyperref, the color package has to
1318 // be loaded after hyperref when hyperref is used with the colorlinks
1319 // option, see http://www.lyx.org/trac/ticket/5291
1320 if (pdfoptions().colorlinks)
1321 features.require("color");
1323 if (!listings_params.empty()) {
1324 // do not test validity because listings_params is
1325 // supposed to be valid
1327 InsetListingsParams(listings_params).separatedParams(true);
1328 // we can't support all packages, but we should load the color package
1329 if (par.find("\\color", 0) != string::npos)
1330 features.require("color");
1333 // some languages are only available via polyglossia
1334 if (features.runparams().flavor == OutputParams::XETEX
1335 && (features.hasPolyglossiaExclusiveLanguages()
1337 features.require("polyglossia");
1339 if (useNonTeXFonts && fonts_math != "auto")
1340 features.require("unicode-math");
1342 if (!language->requires().empty())
1343 features.require(language->requires());
1347 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1348 FileName const & filepath) const
1350 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1351 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1352 // \RequirePackage to do so, rather than the normal \usepackage
1353 // Do not try to load any other package before the document class, unless you
1354 // have a thorough understanding of the LATEX internals and know exactly what you
1356 if (features.mustProvide("fix-cm"))
1357 os << "\\RequirePackage{fix-cm}\n";
1358 // Likewise for fixltx2e. If other packages conflict with this policy,
1359 // treat it as a package bug (and report it!)
1360 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1361 if (features.mustProvide("fixltx2e"))
1362 os << "\\RequirePackage{fixltx2e}\n";
1364 os << "\\documentclass";
1366 DocumentClass const & tclass = documentClass();
1368 ostringstream clsoptions; // the document class options.
1370 if (tokenPos(tclass.opt_fontsize(),
1371 '|', fontsize) >= 0) {
1372 // only write if existing in list (and not default)
1373 clsoptions << fontsize << "pt,";
1376 // all paper sizes except of A4, A5, B5 and the US sizes need the
1378 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1379 && papersize != PAPER_USLETTER
1380 && papersize != PAPER_USLEGAL
1381 && papersize != PAPER_USEXECUTIVE
1382 && papersize != PAPER_A4
1383 && papersize != PAPER_A5
1384 && papersize != PAPER_B5;
1386 if (!use_geometry) {
1387 switch (papersize) {
1389 clsoptions << "a4paper,";
1391 case PAPER_USLETTER:
1392 clsoptions << "letterpaper,";
1395 clsoptions << "a5paper,";
1398 clsoptions << "b5paper,";
1400 case PAPER_USEXECUTIVE:
1401 clsoptions << "executivepaper,";
1404 clsoptions << "legalpaper,";
1438 if (sides != tclass.sides()) {
1441 clsoptions << "oneside,";
1444 clsoptions << "twoside,";
1450 if (columns != tclass.columns()) {
1452 clsoptions << "twocolumn,";
1454 clsoptions << "onecolumn,";
1458 && orientation == ORIENTATION_LANDSCAPE)
1459 clsoptions << "landscape,";
1461 // language should be a parameter to \documentclass
1462 if (language->babel() == "hebrew"
1463 && default_language->babel() != "hebrew")
1464 // This seems necessary
1465 features.useLanguage(default_language);
1467 ostringstream language_options;
1468 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1469 bool const use_polyglossia = features.usePolyglossia();
1470 bool const global = lyxrc.language_global_options;
1471 if (use_babel || (use_polyglossia && global)) {
1472 language_options << features.getBabelLanguages();
1473 if (!language->babel().empty()) {
1474 if (!language_options.str().empty())
1475 language_options << ',';
1476 language_options << language->babel();
1478 if (global && !features.needBabelLangOptions()
1479 && !language_options.str().empty())
1480 clsoptions << language_options.str() << ',';
1483 // the predefined options from the layout
1484 if (use_default_options && !tclass.options().empty())
1485 clsoptions << tclass.options() << ',';
1487 // the user-defined options
1488 if (!options.empty()) {
1489 clsoptions << options << ',';
1492 string strOptions(clsoptions.str());
1493 if (!strOptions.empty()) {
1494 strOptions = rtrim(strOptions, ",");
1496 os << '[' << from_utf8(strOptions) << ']';
1499 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1500 // end of \documentclass defs
1502 // if we use fontspec or newtxmath, we have to load the AMS packages here
1503 string const ams = features.loadAMSPackages();
1504 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1505 bool const use_newtxmath =
1506 theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getUsedPackage(
1507 ot1, false, false) == "newtxmath";
1508 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1509 os << from_ascii(ams);
1511 if (useNonTeXFonts) {
1512 os << "\\usepackage{fontspec}\n";
1513 if (features.mustProvide("unicode-math")
1514 && features.isAvailable("unicode-math"))
1515 os << "\\usepackage{unicode-math}\n";
1518 // font selection must be done before loading fontenc.sty
1519 string const fonts = loadFonts(features);
1521 os << from_utf8(fonts);
1523 if (fonts_default_family != "default")
1524 os << "\\renewcommand{\\familydefault}{\\"
1525 << from_ascii(fonts_default_family) << "}\n";
1527 // set font encoding
1528 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1529 if (!useNonTeXFonts && !features.isProvided("fontenc")
1530 && font_encoding() != "default") {
1531 // get main font encodings
1532 vector<string> fontencs = font_encodings();
1533 // get font encodings of secondary languages
1534 features.getFontEncodings(fontencs);
1535 if (!fontencs.empty()) {
1536 os << "\\usepackage["
1537 << from_ascii(getStringFromVector(fontencs))
1542 // handle inputenc etc.
1543 writeEncodingPreamble(os, features);
1546 if (!features.runparams().includeall && !included_children_.empty()) {
1547 os << "\\includeonly{";
1548 list<string>::const_iterator it = included_children_.begin();
1549 list<string>::const_iterator en = included_children_.end();
1551 for (; it != en; ++it) {
1552 string incfile = *it;
1553 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1554 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1556 if (!features.runparams().nice)
1558 // \includeonly doesn't want an extension
1559 incfile = changeExtension(incfile, string());
1560 incfile = support::latex_path(incfile);
1561 if (!incfile.empty()) {
1564 os << from_utf8(incfile);
1571 if (!features.isProvided("geometry")
1572 && (use_geometry || nonstandard_papersize)) {
1573 odocstringstream ods;
1574 if (!getGraphicsDriver("geometry").empty())
1575 ods << getGraphicsDriver("geometry");
1576 if (orientation == ORIENTATION_LANDSCAPE)
1577 ods << ",landscape";
1578 switch (papersize) {
1580 if (!paperwidth.empty())
1581 ods << ",paperwidth="
1582 << from_ascii(paperwidth);
1583 if (!paperheight.empty())
1584 ods << ",paperheight="
1585 << from_ascii(paperheight);
1587 case PAPER_USLETTER:
1588 ods << ",letterpaper";
1591 ods << ",legalpaper";
1593 case PAPER_USEXECUTIVE:
1594 ods << ",executivepaper";
1683 docstring const g_options = trim(ods.str(), ",");
1684 os << "\\usepackage";
1685 if (!g_options.empty())
1686 os << '[' << g_options << ']';
1687 os << "{geometry}\n";
1688 // output this only if use_geometry is true
1690 os << "\\geometry{verbose";
1691 if (!topmargin.empty())
1692 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1693 if (!bottommargin.empty())
1694 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1695 if (!leftmargin.empty())
1696 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1697 if (!rightmargin.empty())
1698 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1699 if (!headheight.empty())
1700 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1701 if (!headsep.empty())
1702 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1703 if (!footskip.empty())
1704 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1705 if (!columnsep.empty())
1706 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1709 } else if (orientation == ORIENTATION_LANDSCAPE
1710 || papersize != PAPER_DEFAULT) {
1711 features.require("papersize");
1714 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1715 if (pagestyle == "fancy")
1716 os << "\\usepackage{fancyhdr}\n";
1717 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1720 // only output when the background color is not default
1721 if (isbackgroundcolor == true) {
1722 // only require color here, the background color will be defined
1723 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1725 features.require("color");
1726 features.require("pagecolor");
1729 // only output when the font color is not default
1730 if (isfontcolor == true) {
1731 // only require color here, the font color will be defined
1732 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1734 features.require("color");
1735 features.require("fontcolor");
1738 // Only if class has a ToC hierarchy
1739 if (tclass.hasTocLevels()) {
1740 if (secnumdepth != tclass.secnumdepth()) {
1741 os << "\\setcounter{secnumdepth}{"
1745 if (tocdepth != tclass.tocdepth()) {
1746 os << "\\setcounter{tocdepth}{"
1752 if (paragraph_separation) {
1753 // when skip separation
1754 switch (getDefSkip().kind()) {
1755 case VSpace::SMALLSKIP:
1756 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1758 case VSpace::MEDSKIP:
1759 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1761 case VSpace::BIGSKIP:
1762 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1764 case VSpace::LENGTH:
1765 os << "\\setlength{\\parskip}{"
1766 << from_utf8(getDefSkip().length().asLatexString())
1769 default: // should never happen // Then delete it.
1770 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1773 os << "\\setlength{\\parindent}{0pt}\n";
1775 // when separation by indentation
1776 // only output something when a width is given
1777 if (getIndentation().asLyXCommand() != "default") {
1778 os << "\\setlength{\\parindent}{"
1779 << from_utf8(getIndentation().asLatexCommand())
1784 // Now insert the LyX specific LaTeX commands...
1785 docstring lyxpreamble;
1786 features.resolveAlternatives();
1789 if (!output_sync_macro.empty())
1790 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1791 else if (features.runparams().flavor == OutputParams::LATEX)
1792 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1793 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1794 lyxpreamble += "\\synctex=-1\n";
1797 // The package options (via \PassOptionsToPackage)
1798 lyxpreamble += from_ascii(features.getPackageOptions());
1800 // due to interferences with babel and hyperref, the color package has to
1801 // be loaded (when it is not already loaded) before babel when hyperref
1802 // is used with the colorlinks option, see
1803 // http://www.lyx.org/trac/ticket/5291
1804 // we decided therefore to load color always before babel, see
1805 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1806 lyxpreamble += from_ascii(features.getColorOptions());
1808 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1809 // we have to call babel before
1811 && (features.isRequired("jurabib")
1812 || features.isRequired("hyperref")
1813 || features.isRequired("varioref")
1814 || features.isRequired("vietnamese")
1815 || features.isRequired("japanese"))) {
1817 lyxpreamble += from_utf8(features.getBabelPresettings());
1818 lyxpreamble += from_utf8(babelCall(language_options.str(),
1819 features.needBabelLangOptions())) + '\n';
1820 lyxpreamble += from_utf8(features.getBabelPostsettings());
1823 // The optional packages;
1824 lyxpreamble += from_ascii(features.getPackages());
1826 // Additional Indices
1827 if (features.isRequired("splitidx")) {
1828 IndicesList::const_iterator iit = indiceslist().begin();
1829 IndicesList::const_iterator iend = indiceslist().end();
1830 for (; iit != iend; ++iit) {
1831 pair<docstring, docstring> indexname_latex =
1832 features.runparams().encoding->latexString(iit->index(),
1833 features.runparams().dryrun);
1834 if (!indexname_latex.second.empty()) {
1835 // issue a warning about omitted characters
1836 // FIXME: should be passed to the error dialog
1837 frontend::Alert::warning(_("Uncodable characters"),
1838 bformat(_("The following characters that are used in an index name are not\n"
1839 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1840 indexname_latex.second));
1842 lyxpreamble += "\\newindex[";
1843 lyxpreamble += indexname_latex.first;
1844 lyxpreamble += "]{";
1845 lyxpreamble += escape(iit->shortcut());
1846 lyxpreamble += "}\n";
1851 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1854 // * Hyperref manual: "Make sure it comes last of your loaded
1855 // packages, to give it a fighting chance of not being over-written,
1856 // since its job is to redefine many LaTeX commands."
1857 // * Email from Heiko Oberdiek: "It is usually better to load babel
1858 // before hyperref. Then hyperref has a chance to detect babel.
1859 // * Has to be loaded before the "LyX specific LaTeX commands" to
1860 // avoid errors with algorithm floats.
1861 // use hyperref explicitly if it is required
1862 if (features.isRequired("hyperref")) {
1863 // pass what we have to stream here, since we need
1864 // to access the stream itself in PDFOptions.
1867 OutputParams tmp_params = features.runparams();
1868 pdfoptions().writeLaTeX(tmp_params, os,
1869 features.isProvided("hyperref"));
1870 // set back for the rest
1871 lyxpreamble.clear();
1872 // correctly break URLs with hyperref and dvi output
1873 if (features.runparams().flavor == OutputParams::LATEX
1874 && features.isAvailable("breakurl"))
1875 lyxpreamble += "\\usepackage{breakurl}\n";
1876 } else if (features.isRequired("nameref"))
1877 // hyperref loads this automatically
1878 lyxpreamble += "\\usepackage{nameref}\n";
1880 // bibtopic needs to be loaded after hyperref.
1881 // the dot provides the aux file naming which LyX can detect.
1882 if (features.mustProvide("bibtopic"))
1883 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1885 // Will be surrounded by \makeatletter and \makeatother when not empty
1886 docstring atlyxpreamble;
1888 // Some macros LyX will need
1889 docstring tmppreamble(features.getMacros());
1891 if (!tmppreamble.empty())
1892 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1893 "LyX specific LaTeX commands.\n"
1894 + tmppreamble + '\n';
1896 // the text class specific preamble
1897 tmppreamble = features.getTClassPreamble();
1898 if (!tmppreamble.empty())
1899 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1900 "Textclass specific LaTeX commands.\n"
1901 + tmppreamble + '\n';
1903 // suppress date if selected
1904 // use \@ifundefined because we cannot be sure that every document class
1905 // has a \date command
1907 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1909 /* the user-defined preamble */
1910 if (!containsOnly(preamble, " \n\t"))
1912 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1913 "User specified LaTeX commands.\n"
1914 + from_utf8(preamble) + '\n';
1916 // footmisc must be loaded after setspace
1917 // Load it here to avoid clashes with footmisc loaded in the user
1918 // preamble. For that reason we also pass the options via
1919 // \PassOptionsToPackage in getPreamble() and not here.
1920 if (features.mustProvide("footmisc"))
1921 atlyxpreamble += "\\usepackage{footmisc}\n";
1923 // subfig loads internally the LaTeX package "caption". As
1924 // caption is a very popular package, users will load it in
1925 // the preamble. Therefore we must load subfig behind the
1926 // user-defined preamble and check if the caption package was
1927 // loaded or not. For the case that caption is loaded before
1928 // subfig, there is the subfig option "caption=false". This
1929 // option also works when a koma-script class is used and
1930 // koma's own caption commands are used instead of caption. We
1931 // use \PassOptionsToPackage here because the user could have
1932 // already loaded subfig in the preamble.
1933 if (features.isRequired("subfig")) {
1934 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1935 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1936 "\\usepackage{subfig}\n";
1939 // Itemize bullet settings need to be last in case the user
1940 // defines their own bullets that use a package included
1941 // in the user-defined preamble -- ARRae
1942 // Actually it has to be done much later than that
1943 // since some packages like frenchb make modifications
1944 // at \begin{document} time -- JMarc
1945 docstring bullets_def;
1946 for (int i = 0; i < 4; ++i) {
1947 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1948 if (bullets_def.empty())
1949 bullets_def += "\\AtBeginDocument{\n";
1950 bullets_def += " \\def\\labelitemi";
1952 // `i' is one less than the item to modify
1959 bullets_def += "ii";
1965 bullets_def += '{' +
1966 user_defined_bullet(i).getText()
1971 if (!bullets_def.empty())
1972 atlyxpreamble += bullets_def + "}\n\n";
1974 if (!atlyxpreamble.empty())
1975 lyxpreamble += "\n\\makeatletter\n"
1976 + atlyxpreamble + "\\makeatother\n\n";
1978 // We try to load babel late, in case it interferes with other packages.
1979 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
1980 // called after babel, though.
1981 if (use_babel && !features.isRequired("jurabib")
1982 && !features.isRequired("hyperref")
1983 && !features.isRequired("varioref")
1984 && !features.isRequired("vietnamese")
1985 && !features.isRequired("japanese")) {
1987 lyxpreamble += from_utf8(features.getBabelPresettings());
1988 lyxpreamble += from_utf8(babelCall(language_options.str(),
1989 features.needBabelLangOptions())) + '\n';
1990 lyxpreamble += from_utf8(features.getBabelPostsettings());
1992 if (features.isRequired("bicaption"))
1993 lyxpreamble += "\\usepackage{bicaption}\n";
1994 if (!listings_params.empty() || features.isRequired("listings"))
1995 lyxpreamble += "\\usepackage{listings}\n";
1996 if (!listings_params.empty()) {
1997 lyxpreamble += "\\lstset{";
1998 // do not test validity because listings_params is
1999 // supposed to be valid
2001 InsetListingsParams(listings_params).separatedParams(true);
2002 lyxpreamble += from_utf8(par);
2003 lyxpreamble += "}\n";
2006 // xunicode needs to be loaded at least after amsmath, amssymb,
2007 // esint and the other packages that provide special glyphs
2008 if (features.runparams().flavor == OutputParams::XETEX
2010 lyxpreamble += "\\usepackage{xunicode}\n";
2012 // Polyglossia must be loaded last
2013 if (use_polyglossia) {
2015 lyxpreamble += "\\usepackage{polyglossia}\n";
2016 // set the main language
2017 lyxpreamble += "\\setdefaultlanguage";
2018 if (!language->polyglossiaOpts().empty())
2019 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
2020 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
2021 // now setup the other languages
2022 std::map<std::string, std::string> const polylangs =
2023 features.getPolyglossiaLanguages();
2024 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
2025 mit != polylangs.end() ; ++mit) {
2026 lyxpreamble += "\\setotherlanguage";
2027 if (!mit->second.empty())
2028 lyxpreamble += "[" + from_ascii(mit->second) + "]";
2029 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
2033 // Load custom language package here
2034 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2035 if (lang_package == "default")
2036 lyxpreamble += from_utf8(lyxrc.language_custom_package);
2038 lyxpreamble += from_utf8(lang_package);
2039 lyxpreamble += '\n';
2042 docstring const i18npreamble =
2043 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2044 if (!i18npreamble.empty())
2045 lyxpreamble += i18npreamble + '\n';
2053 void BufferParams::useClassDefaults()
2055 DocumentClass const & tclass = documentClass();
2057 sides = tclass.sides();
2058 columns = tclass.columns();
2059 pagestyle = tclass.pagestyle();
2060 use_default_options = true;
2061 // Only if class has a ToC hierarchy
2062 if (tclass.hasTocLevels()) {
2063 secnumdepth = tclass.secnumdepth();
2064 tocdepth = tclass.tocdepth();
2069 bool BufferParams::hasClassDefaults() const
2071 DocumentClass const & tclass = documentClass();
2073 return sides == tclass.sides()
2074 && columns == tclass.columns()
2075 && pagestyle == tclass.pagestyle()
2076 && use_default_options
2077 && secnumdepth == tclass.secnumdepth()
2078 && tocdepth == tclass.tocdepth();
2082 DocumentClass const & BufferParams::documentClass() const
2084 return *doc_class_.get();
2088 DocumentClassConstPtr BufferParams::documentClassPtr() const
2094 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2096 // evil, but this function is evil
2097 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2101 bool BufferParams::setBaseClass(string const & classname)
2103 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2104 LayoutFileList & bcl = LayoutFileList::get();
2105 if (!bcl.haveClass(classname)) {
2107 bformat(_("The layout file:\n"
2109 "could not be found. A default textclass with default\n"
2110 "layouts will be used. LyX will not be able to produce\n"
2112 from_utf8(classname));
2113 frontend::Alert::error(_("Document class not found"), s);
2114 bcl.addEmptyClass(classname);
2117 bool const success = bcl[classname].load();
2120 bformat(_("Due to some error in it, the layout file:\n"
2122 "could not be loaded. A default textclass with default\n"
2123 "layouts will be used. LyX will not be able to produce\n"
2125 from_utf8(classname));
2126 frontend::Alert::error(_("Could not load class"), s);
2127 bcl.addEmptyClass(classname);
2130 pimpl_->baseClass_ = classname;
2131 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2136 LayoutFile const * BufferParams::baseClass() const
2138 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2139 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2145 LayoutFileIndex const & BufferParams::baseClassID() const
2147 return pimpl_->baseClass_;
2151 void BufferParams::makeDocumentClass(bool const clone)
2156 LayoutModuleList mods;
2157 LayoutModuleList::iterator it = layout_modules_.begin();
2158 LayoutModuleList::iterator en = layout_modules_.end();
2159 for (; it != en; ++it)
2160 mods.push_back(*it);
2162 it = cite_engine_.begin();
2163 en = cite_engine_.end();
2164 for (; it != en; ++it)
2165 mods.push_back(*it);
2167 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2169 TextClass::ReturnValues success = TextClass::OK;
2170 if (!forced_local_layout_.empty())
2171 success = doc_class_->read(forced_local_layout_, TextClass::MODULE);
2172 if (!local_layout_.empty() &&
2173 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2174 success = doc_class_->read(local_layout_, TextClass::MODULE);
2175 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2176 docstring const msg = _("Error reading internal layout information");
2177 frontend::Alert::warning(_("Read Error"), msg);
2182 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2184 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2188 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2190 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2194 std::string BufferParams::getLocalLayout(bool forced) const
2197 return doc_class_->forcedLayouts();
2199 return local_layout_;
2203 void BufferParams::setLocalLayout(string const & layout, bool forced)
2206 forced_local_layout_ = layout;
2208 local_layout_ = layout;
2212 bool BufferParams::addLayoutModule(string const & modName)
2214 LayoutModuleList::const_iterator it = layout_modules_.begin();
2215 LayoutModuleList::const_iterator end = layout_modules_.end();
2216 for (; it != end; ++it)
2219 layout_modules_.push_back(modName);
2224 string BufferParams::bufferFormat() const
2226 string format = documentClass().outputFormat();
2227 if (format == "latex") {
2230 if (encoding().package() == Encoding::japanese)
2237 bool BufferParams::isExportable(string const & format) const
2239 vector<string> backs = backends();
2240 for (vector<string>::const_iterator it = backs.begin();
2241 it != backs.end(); ++it)
2242 if (theConverters().isReachable(*it, format))
2248 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2250 vector<string> const backs = backends();
2251 set<string> excludes;
2252 if (useNonTeXFonts) {
2253 excludes.insert("latex");
2254 excludes.insert("pdflatex");
2256 vector<Format const *> result =
2257 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2258 for (vector<string>::const_iterator it = backs.begin() + 1;
2259 it != backs.end(); ++it) {
2260 vector<Format const *> r =
2261 theConverters().getReachable(*it, only_viewable, false, excludes);
2262 result.insert(result.end(), r.begin(), r.end());
2268 bool BufferParams::isExportableFormat(string const & format) const
2270 typedef vector<Format const *> Formats;
2272 formats = exportableFormats(true);
2273 Formats::const_iterator fit = formats.begin();
2274 Formats::const_iterator end = formats.end();
2275 for (; fit != end ; ++fit) {
2276 if ((*fit)->name() == format)
2283 vector<string> BufferParams::backends() const
2286 string const buffmt = bufferFormat();
2288 // FIXME: Don't hardcode format names here, but use a flag
2289 if (buffmt == "latex") {
2290 if (!useNonTeXFonts) {
2291 v.push_back("pdflatex");
2292 v.push_back("latex");
2294 v.push_back("luatex");
2295 v.push_back("dviluatex");
2296 v.push_back("xetex");
2297 } else if (buffmt == "xetex") {
2298 v.push_back("xetex");
2299 // FIXME: need to test all languages (bug 8205)
2300 if (!language || !language->isPolyglossiaExclusive()) {
2301 v.push_back("luatex");
2302 v.push_back("dviluatex");
2305 v.push_back(buffmt);
2307 v.push_back("xhtml");
2308 v.push_back("text");
2314 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2316 string const dformat = (format.empty() || format == "default") ?
2317 getDefaultOutputFormat() : format;
2318 DefaultFlavorCache::const_iterator it =
2319 default_flavors_.find(dformat);
2321 if (it != default_flavors_.end())
2324 OutputParams::FLAVOR result = OutputParams::LATEX;
2326 // FIXME It'd be better not to hardcode this, but to do
2327 // something with formats.
2328 if (dformat == "xhtml")
2329 result = OutputParams::HTML;
2330 else if (dformat == "text")
2331 result = OutputParams::TEXT;
2332 else if (dformat == "lyx")
2333 result = OutputParams::LYX;
2334 else if (dformat == "pdflatex")
2335 result = OutputParams::PDFLATEX;
2336 else if (dformat == "xetex")
2337 result = OutputParams::XETEX;
2338 else if (dformat == "luatex")
2339 result = OutputParams::LUATEX;
2340 else if (dformat == "dviluatex")
2341 result = OutputParams::DVILUATEX;
2343 // Try to determine flavor of default output format
2344 vector<string> backs = backends();
2345 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2346 // Get shortest path to format
2347 Graph::EdgePath path;
2348 for (vector<string>::const_iterator it = backs.begin();
2349 it != backs.end(); ++it) {
2350 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2351 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2356 result = theConverters().getFlavor(path);
2359 // cache this flavor
2360 default_flavors_[dformat] = result;
2365 string BufferParams::getDefaultOutputFormat() const
2367 if (!default_output_format.empty()
2368 && default_output_format != "default")
2369 return default_output_format;
2371 || encoding().package() == Encoding::japanese) {
2372 vector<Format const *> const formats = exportableFormats(true);
2373 if (formats.empty())
2375 // return the first we find
2376 return formats.front()->name();
2379 return lyxrc.default_otf_view_format;
2380 return lyxrc.default_view_format;
2383 Font const BufferParams::getFont() const
2385 FontInfo f = documentClass().defaultfont();
2386 if (fonts_default_family == "rmdefault")
2387 f.setFamily(ROMAN_FAMILY);
2388 else if (fonts_default_family == "sfdefault")
2389 f.setFamily(SANS_FAMILY);
2390 else if (fonts_default_family == "ttdefault")
2391 f.setFamily(TYPEWRITER_FAMILY);
2392 return Font(f, language);
2396 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const & qs) const
2398 return quoteslangtranslator().find(qs);
2402 bool BufferParams::isLatex() const
2404 return documentClass().outputType() == LATEX;
2408 bool BufferParams::isLiterate() const
2410 return documentClass().outputType() == LITERATE;
2414 bool BufferParams::isDocBook() const
2416 return documentClass().outputType() == DOCBOOK;
2420 void BufferParams::readPreamble(Lexer & lex)
2422 if (lex.getString() != "\\begin_preamble")
2423 lyxerr << "Error (BufferParams::readPreamble):"
2424 "consistency check failed." << endl;
2426 preamble = lex.getLongString("\\end_preamble");
2430 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2432 string const expected = forced ? "\\begin_forced_local_layout" :
2433 "\\begin_local_layout";
2434 if (lex.getString() != expected)
2435 lyxerr << "Error (BufferParams::readLocalLayout):"
2436 "consistency check failed." << endl;
2439 forced_local_layout_ =
2440 lex.getLongString("\\end_forced_local_layout");
2442 local_layout_ = lex.getLongString("\\end_local_layout");
2446 bool BufferParams::setLanguage(string const & lang)
2448 Language const *new_language = languages.getLanguage(lang);
2449 if (!new_language) {
2450 // Language lang was not found
2453 language = new_language;
2458 void BufferParams::readLanguage(Lexer & lex)
2460 if (!lex.next()) return;
2462 string const tmptok = lex.getString();
2464 // check if tmptok is part of tex_babel in tex-defs.h
2465 if (!setLanguage(tmptok)) {
2466 // Language tmptok was not found
2467 language = default_language;
2468 lyxerr << "Warning: Setting language `"
2469 << tmptok << "' to `" << language->lang()
2475 void BufferParams::readGraphicsDriver(Lexer & lex)
2480 string const tmptok = lex.getString();
2481 // check if tmptok is part of tex_graphics in tex_defs.h
2484 string const test = tex_graphics[n++];
2486 if (test == tmptok) {
2487 graphics_driver = tmptok;
2492 "Warning: graphics driver `$$Token' not recognized!\n"
2493 " Setting graphics driver to `default'.\n");
2494 graphics_driver = "default";
2501 void BufferParams::readBullets(Lexer & lex)
2506 int const index = lex.getInteger();
2508 int temp_int = lex.getInteger();
2509 user_defined_bullet(index).setFont(temp_int);
2510 temp_bullet(index).setFont(temp_int);
2512 user_defined_bullet(index).setCharacter(temp_int);
2513 temp_bullet(index).setCharacter(temp_int);
2515 user_defined_bullet(index).setSize(temp_int);
2516 temp_bullet(index).setSize(temp_int);
2520 void BufferParams::readBulletsLaTeX(Lexer & lex)
2522 // The bullet class should be able to read this.
2525 int const index = lex.getInteger();
2527 docstring const temp_str = lex.getDocString();
2529 user_defined_bullet(index).setText(temp_str);
2530 temp_bullet(index).setText(temp_str);
2534 void BufferParams::readModules(Lexer & lex)
2536 if (!lex.eatLine()) {
2537 lyxerr << "Error (BufferParams::readModules):"
2538 "Unexpected end of input." << endl;
2542 string mod = lex.getString();
2543 if (mod == "\\end_modules")
2545 addLayoutModule(mod);
2551 void BufferParams::readRemovedModules(Lexer & lex)
2553 if (!lex.eatLine()) {
2554 lyxerr << "Error (BufferParams::readRemovedModules):"
2555 "Unexpected end of input." << endl;
2559 string mod = lex.getString();
2560 if (mod == "\\end_removed_modules")
2562 removed_modules_.push_back(mod);
2565 // now we want to remove any removed modules that were previously
2566 // added. normally, that will be because default modules were added in
2567 // setBaseClass(), which gets called when \textclass is read at the
2568 // start of the read.
2569 list<string>::const_iterator rit = removed_modules_.begin();
2570 list<string>::const_iterator const ren = removed_modules_.end();
2571 for (; rit != ren; ++rit) {
2572 LayoutModuleList::iterator const mit = layout_modules_.begin();
2573 LayoutModuleList::iterator const men = layout_modules_.end();
2574 LayoutModuleList::iterator found = find(mit, men, *rit);
2577 layout_modules_.erase(found);
2582 void BufferParams::readIncludeonly(Lexer & lex)
2584 if (!lex.eatLine()) {
2585 lyxerr << "Error (BufferParams::readIncludeonly):"
2586 "Unexpected end of input." << endl;
2590 string child = lex.getString();
2591 if (child == "\\end_includeonly")
2593 included_children_.push_back(child);
2599 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2601 switch (papersize) {
2603 // could be anything, so don't guess
2605 case PAPER_CUSTOM: {
2606 if (purpose == XDVI && !paperwidth.empty() &&
2607 !paperheight.empty()) {
2608 // heightxwidth<unit>
2609 string first = paperwidth;
2610 string second = paperheight;
2611 if (orientation == ORIENTATION_LANDSCAPE)
2614 return first.erase(first.length() - 2)
2620 // dvips and dvipdfm do not know this
2621 if (purpose == DVIPS || purpose == DVIPDFM)
2625 if (purpose == DVIPS || purpose == DVIPDFM)
2629 if (purpose == DVIPS || purpose == DVIPDFM)
2639 if (purpose == DVIPS || purpose == DVIPDFM)
2643 if (purpose == DVIPS || purpose == DVIPDFM)
2647 if (purpose == DVIPS || purpose == DVIPDFM)
2651 if (purpose == DVIPS || purpose == DVIPDFM)
2655 if (purpose == DVIPS || purpose == DVIPDFM)
2659 // dvipdfm does not know this
2660 if (purpose == DVIPDFM)
2664 if (purpose == DVIPDFM)
2668 if (purpose == DVIPS || purpose == DVIPDFM)
2672 if (purpose == DVIPS || purpose == DVIPDFM)
2676 if (purpose == DVIPS || purpose == DVIPDFM)
2680 if (purpose == DVIPS || purpose == DVIPDFM)
2684 if (purpose == DVIPS || purpose == DVIPDFM)
2688 if (purpose == DVIPS || purpose == DVIPDFM)
2692 if (purpose == DVIPS || purpose == DVIPDFM)
2696 if (purpose == DVIPS || purpose == DVIPDFM)
2700 if (purpose == DVIPS || purpose == DVIPDFM)
2704 if (purpose == DVIPS || purpose == DVIPDFM)
2708 if (purpose == DVIPS || purpose == DVIPDFM)
2712 if (purpose == DVIPS || purpose == DVIPDFM)
2716 if (purpose == DVIPS || purpose == DVIPDFM)
2720 if (purpose == DVIPS || purpose == DVIPDFM)
2724 if (purpose == DVIPS || purpose == DVIPDFM)
2727 case PAPER_USEXECUTIVE:
2728 // dvipdfm does not know this
2729 if (purpose == DVIPDFM)
2734 case PAPER_USLETTER:
2736 if (purpose == XDVI)
2743 string const BufferParams::dvips_options() const
2747 // If the class loads the geometry package, we do not know which
2748 // paper size is used, since we do not set it (bug 7013).
2749 // Therefore we must not specify any argument here.
2750 // dvips gets the correct paper size via DVI specials in this case
2751 // (if the class uses the geometry package correctly).
2752 if (documentClass().provides("geometry"))
2756 && papersize == PAPER_CUSTOM
2757 && !lyxrc.print_paper_dimension_flag.empty()
2758 && !paperwidth.empty()
2759 && !paperheight.empty()) {
2760 // using a custom papersize
2761 result = lyxrc.print_paper_dimension_flag;
2762 result += ' ' + paperwidth;
2763 result += ',' + paperheight;
2765 string const paper_option = paperSizeName(DVIPS);
2766 if (!paper_option.empty() && (paper_option != "letter" ||
2767 orientation != ORIENTATION_LANDSCAPE)) {
2768 // dvips won't accept -t letter -t landscape.
2769 // In all other cases, include the paper size
2771 result = lyxrc.print_paper_flag;
2772 result += ' ' + paper_option;
2775 if (orientation == ORIENTATION_LANDSCAPE &&
2776 papersize != PAPER_CUSTOM)
2777 result += ' ' + lyxrc.print_landscape_flag;
2782 string const BufferParams::font_encoding() const
2784 return font_encodings().empty() ? "default" : font_encodings().back();
2788 vector<string> const BufferParams::font_encodings() const
2790 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2792 vector<string> fontencs;
2794 // "default" means "no explicit font encoding"
2795 if (doc_fontenc != "default") {
2796 fontencs = getVectorFromString(doc_fontenc);
2797 if (!language->fontenc().empty()
2798 && ascii_lowercase(language->fontenc()) != "none") {
2799 vector<string> fencs = getVectorFromString(language->fontenc());
2800 vector<string>::const_iterator fit = fencs.begin();
2801 for (; fit != fencs.end(); ++fit) {
2802 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
2803 fontencs.push_back(*fit);
2812 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2814 // suppress the babel call if there is no BabelName defined
2815 // for the document language in the lib/languages file and if no
2816 // other languages are used (lang_opts is then empty)
2817 if (lang_opts.empty())
2819 // either a specific language (AsBabelOptions setting in
2820 // lib/languages) or the prefs require the languages to
2821 // be submitted to babel itself (not the class).
2823 return "\\usepackage[" + lang_opts + "]{babel}";
2824 return "\\usepackage{babel}";
2828 docstring BufferParams::getGraphicsDriver(string const & package) const
2832 if (package == "geometry") {
2833 if (graphics_driver == "dvips"
2834 || graphics_driver == "dvipdfm"
2835 || graphics_driver == "pdftex"
2836 || graphics_driver == "vtex")
2837 result = from_ascii(graphics_driver);
2838 else if (graphics_driver == "dvipdfmx")
2839 result = from_ascii("dvipdfm");
2846 void BufferParams::writeEncodingPreamble(otexstream & os,
2847 LaTeXFeatures & features) const
2849 // XeTeX does not need this
2850 if (features.runparams().flavor == OutputParams::XETEX)
2852 // LuaTeX neither, but with tex fonts, we need to load
2853 // the luainputenc package.
2854 if (features.runparams().flavor == OutputParams::LUATEX
2855 || features.runparams().flavor == OutputParams::DVILUATEX) {
2856 if (!useNonTeXFonts && inputenc != "default"
2857 && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc)
2858 || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) {
2859 os << "\\usepackage[utf8]{luainputenc}\n";
2863 if (inputenc == "auto") {
2864 string const doc_encoding =
2865 language->encoding()->latexName();
2866 Encoding::Package const package =
2867 language->encoding()->package();
2869 // Create a list with all the input encodings used
2871 set<string> encodings =
2872 features.getEncodingSet(doc_encoding);
2874 // If the "japanese" package (i.e. pLaTeX) is used,
2875 // inputenc must be omitted.
2876 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2877 if ((!encodings.empty() || package == Encoding::inputenc)
2878 && !features.isRequired("japanese")
2879 && !features.isProvided("inputenc")) {
2880 os << "\\usepackage[";
2881 set<string>::const_iterator it = encodings.begin();
2882 set<string>::const_iterator const end = encodings.end();
2884 os << from_ascii(*it);
2887 for (; it != end; ++it)
2888 os << ',' << from_ascii(*it);
2889 if (package == Encoding::inputenc) {
2890 if (!encodings.empty())
2892 os << from_ascii(doc_encoding);
2894 os << "]{inputenc}\n";
2896 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2897 if (language->encoding()->name() == "utf8-cjk"
2898 && LaTeXFeatures::isAvailable("CJKutf8"))
2899 os << "\\usepackage{CJKutf8}\n";
2901 os << "\\usepackage{CJK}\n";
2903 } else if (inputenc != "default") {
2904 switch (encoding().package()) {
2905 case Encoding::none:
2906 case Encoding::japanese:
2908 case Encoding::inputenc:
2909 // do not load inputenc if japanese is used
2910 // or if the class provides inputenc
2911 if (features.isRequired("japanese")
2912 || features.isProvided("inputenc"))
2914 os << "\\usepackage[" << from_ascii(encoding().latexName())
2918 if (encoding().name() == "utf8-cjk"
2919 && LaTeXFeatures::isAvailable("CJKutf8"))
2920 os << "\\usepackage{CJKutf8}\n";
2922 os << "\\usepackage{CJK}\n";
2925 // Load the CJK package if needed by a secondary language.
2926 // If the main encoding is some variant of UTF8, use CJKutf8.
2927 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
2928 if (encoding().iconvName() == "UTF-8"
2929 && LaTeXFeatures::isAvailable("CJKutf8"))
2930 os << "\\usepackage{CJKutf8}\n";
2932 os << "\\usepackage{CJK}\n";
2938 string const BufferParams::parseFontName(string const & name) const
2940 string mangled = name;
2941 size_t const idx = mangled.find('[');
2942 if (idx == string::npos || idx == 0)
2945 return mangled.substr(0, idx - 1);
2949 string const BufferParams::loadFonts(LaTeXFeatures & features) const
2951 if (fonts_roman == "default" && fonts_sans == "default"
2952 && fonts_typewriter == "default"
2953 && (fonts_math == "default" || fonts_math == "auto"))
2959 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
2960 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
2961 * Mapping=tex-text option assures TeX ligatures (such as "--")
2962 * are resolved. Note that tt does not use these ligatures.
2964 * -- add more GUI options?
2965 * -- add more fonts (fonts for other scripts)
2966 * -- if there's a way to find out if a font really supports
2967 * OldStyle, enable/disable the widget accordingly.
2969 if (useNonTeXFonts && features.isAvailable("fontspec")) {
2970 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
2971 // However, until v.2 (2010/07/11) fontspec only knew
2972 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
2973 // was introduced for both XeTeX and LuaTeX (LuaTeX
2974 // didn't understand "Mapping=tex-text", while XeTeX
2975 // understood both. With most recent versions, both
2976 // variants are understood by both engines. However,
2977 // we want to provide support for at least TeXLive 2009
2978 // (for XeTeX; LuaTeX is only supported as of v.2)
2979 string const texmapping =
2980 (features.runparams().flavor == OutputParams::XETEX) ?
2981 "Mapping=tex-text" : "Ligatures=TeX";
2982 if (fonts_roman != "default") {
2983 os << "\\setmainfont[" << texmapping;
2984 if (fonts_old_figures)
2985 os << ",Numbers=OldStyle";
2986 os << "]{" << parseFontName(fonts_roman) << "}\n";
2988 if (fonts_sans != "default") {
2989 string const sans = parseFontName(fonts_sans);
2990 if (fonts_sans_scale != 100)
2991 os << "\\setsansfont[Scale="
2992 << float(fonts_sans_scale) / 100
2993 << "," << texmapping << "]{"
2996 os << "\\setsansfont[" << texmapping << "]{"
2999 if (fonts_typewriter != "default") {
3000 string const mono = parseFontName(fonts_typewriter);
3001 if (fonts_typewriter_scale != 100)
3002 os << "\\setmonofont[Scale="
3003 << float(fonts_typewriter_scale) / 100
3007 os << "\\setmonofont{"
3014 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
3015 bool const dryrun = features.runparams().dryrun;
3016 bool const complete = (fonts_sans == "default" && fonts_typewriter == "default");
3017 bool const nomath = (fonts_math == "default");
3020 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_roman)).getLaTeXCode(
3021 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3025 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_sans)).getLaTeXCode(
3026 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3027 nomath, fonts_sans_scale);
3029 // MONOSPACED/TYPEWRITER
3030 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_typewriter)).getLaTeXCode(
3031 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3032 nomath, fonts_typewriter_scale);
3035 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getLaTeXCode(
3036 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3043 Encoding const & BufferParams::encoding() const
3045 // FIXME: actually, we should check for the flavor
3046 // or runparams.isFullyUnicode() here:
3047 // This check will not work with XeTeX/LuaTeX and tex fonts.
3048 // Thus we have to reset the encoding in Buffer::makeLaTeXFile
3049 // (for export) and Buffer::writeLaTeXSource (for preview).
3051 return *(encodings.fromLyXName("utf8-plain"));
3052 if (inputenc == "auto" || inputenc == "default")
3053 return *language->encoding();
3054 Encoding const * const enc = encodings.fromLyXName(inputenc);
3057 LYXERR0("Unknown inputenc value `" << inputenc
3058 << "'. Using `auto' instead.");
3059 return *language->encoding();
3063 bool BufferParams::addCiteEngine(string const & engine)
3065 LayoutModuleList::const_iterator it = cite_engine_.begin();
3066 LayoutModuleList::const_iterator en = cite_engine_.end();
3067 for (; it != en; ++it)
3070 cite_engine_.push_back(engine);
3075 bool BufferParams::addCiteEngine(vector<string> const & engine)
3077 vector<string>::const_iterator it = engine.begin();
3078 vector<string>::const_iterator en = engine.end();
3080 for (; it != en; ++it)
3081 if (!addCiteEngine(*it))
3087 string const & BufferParams::defaultBiblioStyle() const
3089 return documentClass().defaultBiblioStyle();
3093 bool const & BufferParams::fullAuthorList() const
3095 return documentClass().fullAuthorList();
3099 void BufferParams::setCiteEngine(string const & engine)
3102 addCiteEngine(engine);
3106 void BufferParams::setCiteEngine(vector<string> const & engine)
3109 addCiteEngine(engine);
3113 vector<string> BufferParams::citeCommands() const
3115 static CitationStyle const default_style;
3116 vector<string> commands =
3117 documentClass().citeCommands(citeEngineType());
3118 if (commands.empty())
3119 commands.push_back(default_style.cmd);
3124 vector<CitationStyle> BufferParams::citeStyles() const
3126 static CitationStyle const default_style;
3127 vector<CitationStyle> styles =
3128 documentClass().citeStyles(citeEngineType());
3130 styles.push_back(default_style);