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 if (!filepath.empty() && FileName::isAbsolute(origin)) {
686 bool const isabs = FileName::isAbsolute(master);
687 FileName const abspath(isabs ? master : origin + master);
688 bool const moved = filepath != FileName(origin);
689 if (moved && abspath.exists()) {
690 docstring const path = isabs
692 : from_utf8(abspath.realPath());
693 docstring const refpath =
694 from_utf8(filepath.absFileName());
695 master = to_utf8(makeRelPath(path, refpath));
698 } else if (token == "\\suppress_date") {
699 lex >> suppress_date;
700 } else if (token == "\\justification") {
701 lex >> justification;
702 } else if (token == "\\language") {
704 } else if (token == "\\language_package") {
706 lang_package = lex.getString();
707 } else if (token == "\\inputencoding") {
709 } else if (token == "\\graphics") {
710 readGraphicsDriver(lex);
711 } else if (token == "\\default_output_format") {
712 lex >> default_output_format;
713 } else if (token == "\\bibtex_command") {
715 bibtex_command = lex.getString();
716 } else if (token == "\\index_command") {
718 index_command = lex.getString();
719 } else if (token == "\\fontencoding") {
721 fontenc = lex.getString();
722 } else if (token == "\\font_roman") {
724 fonts_roman = lex.getString();
725 } else if (token == "\\font_sans") {
727 fonts_sans = lex.getString();
728 } else if (token == "\\font_typewriter") {
730 fonts_typewriter = lex.getString();
731 } else if (token == "\\font_math") {
733 fonts_math = lex.getString();
734 } else if (token == "\\font_default_family") {
735 lex >> fonts_default_family;
736 } else if (token == "\\use_non_tex_fonts") {
737 lex >> useNonTeXFonts;
738 } else if (token == "\\font_sc") {
739 lex >> fonts_expert_sc;
740 } else if (token == "\\font_osf") {
741 lex >> fonts_old_figures;
742 } else if (token == "\\font_sf_scale") {
743 lex >> fonts_sans_scale;
744 } else if (token == "\\font_tt_scale") {
745 lex >> fonts_typewriter_scale;
746 } else if (token == "\\font_cjk") {
748 } else if (token == "\\paragraph_separation") {
751 paragraph_separation = parseptranslator().find(parsep);
752 } else if (token == "\\paragraph_indentation") {
754 string indentation = lex.getString();
755 pimpl_->indentation = HSpace(indentation);
756 } else if (token == "\\defskip") {
758 string const defskip = lex.getString();
759 pimpl_->defskip = VSpace(defskip);
760 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
762 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
763 } else if (token == "\\quotes_language") {
766 quotes_language = quoteslangtranslator().find(quotes_lang);
767 } else if (token == "\\papersize") {
770 papersize = papersizetranslator().find(ppsize);
771 } else if (token == "\\use_geometry") {
773 } else if (token == "\\use_package") {
778 use_package(package, packagetranslator().find(use));
779 } else if (token == "\\cite_engine") {
781 vector<string> engine = getVectorFromString(lex.getString());
782 setCiteEngine(engine);
783 } else if (token == "\\cite_engine_type") {
786 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
787 } else if (token == "\\biblio_style") {
789 biblio_style = lex.getString();
790 } else if (token == "\\use_bibtopic") {
792 } else if (token == "\\use_indices") {
794 } else if (token == "\\tracking_changes") {
795 lex >> track_changes;
796 } else if (token == "\\output_changes") {
797 lex >> output_changes;
798 } else if (token == "\\branch") {
800 docstring branch = lex.getDocString();
801 branchlist().add(branch);
804 string const tok = lex.getString();
805 if (tok == "\\end_branch")
807 Branch * branch_ptr = branchlist().find(branch);
808 if (tok == "\\selected") {
811 branch_ptr->setSelected(lex.getInteger());
813 if (tok == "\\filename_suffix") {
816 branch_ptr->setFileNameSuffix(lex.getInteger());
818 if (tok == "\\color") {
820 string color = lex.getString();
822 branch_ptr->setColor(color);
823 // Update also the Color table:
825 color = lcolor.getX11Name(Color_background);
827 lcolor.setColor(to_utf8(branch), color);
830 } else if (token == "\\index") {
832 docstring index = lex.getDocString();
834 indiceslist().add(index);
837 string const tok = lex.getString();
838 if (tok == "\\end_index")
840 Index * index_ptr = indiceslist().find(index);
841 if (tok == "\\shortcut") {
843 shortcut = lex.getDocString();
845 index_ptr->setShortcut(shortcut);
847 if (tok == "\\color") {
849 string color = lex.getString();
851 index_ptr->setColor(color);
852 // Update also the Color table:
854 color = lcolor.getX11Name(Color_background);
856 if (!shortcut.empty())
857 lcolor.setColor(to_utf8(shortcut), color);
860 } else if (token == "\\author") {
862 istringstream ss(lex.getString());
865 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
866 } else if (token == "\\paperorientation") {
869 orientation = paperorientationtranslator().find(orient);
870 } else if (token == "\\backgroundcolor") {
872 backgroundcolor = lyx::rgbFromHexName(lex.getString());
873 isbackgroundcolor = true;
874 } else if (token == "\\fontcolor") {
876 fontcolor = lyx::rgbFromHexName(lex.getString());
878 } else if (token == "\\notefontcolor") {
880 string color = lex.getString();
881 notefontcolor = lyx::rgbFromHexName(color);
882 lcolor.setColor("notefontcolor", color);
883 } else if (token == "\\boxbgcolor") {
885 string color = lex.getString();
886 boxbgcolor = lyx::rgbFromHexName(color);
887 lcolor.setColor("boxbgcolor", color);
888 } else if (token == "\\paperwidth") {
890 } else if (token == "\\paperheight") {
892 } else if (token == "\\leftmargin") {
894 } else if (token == "\\topmargin") {
896 } else if (token == "\\rightmargin") {
898 } else if (token == "\\bottommargin") {
900 } else if (token == "\\headheight") {
902 } else if (token == "\\headsep") {
904 } else if (token == "\\footskip") {
906 } else if (token == "\\columnsep") {
908 } else if (token == "\\paperfontsize") {
910 } else if (token == "\\papercolumns") {
912 } else if (token == "\\listings_params") {
915 listings_params = InsetListingsParams(par).params();
916 } else if (token == "\\papersides") {
919 sides = sidestranslator().find(psides);
920 } else if (token == "\\paperpagestyle") {
922 } else if (token == "\\bullet") {
924 } else if (token == "\\bulletLaTeX") {
925 readBulletsLaTeX(lex);
926 } else if (token == "\\secnumdepth") {
928 } else if (token == "\\tocdepth") {
930 } else if (token == "\\spacing") {
934 if (nspacing == "other") {
937 spacing().set(spacetranslator().find(nspacing), tmp_val);
938 } else if (token == "\\float_placement") {
939 lex >> float_placement;
941 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
942 string toktmp = pdfoptions().readToken(lex, token);
943 if (!toktmp.empty()) {
944 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
948 } else if (token == "\\html_math_output") {
951 html_math_output = static_cast<MathOutput>(temp);
952 } else if (token == "\\html_be_strict") {
953 lex >> html_be_strict;
954 } else if (token == "\\html_css_as_file") {
955 lex >> html_css_as_file;
956 } else if (token == "\\html_math_img_scale") {
957 lex >> html_math_img_scale;
958 } else if (token == "\\html_latex_start") {
960 html_latex_start = lex.getString();
961 } else if (token == "\\html_latex_end") {
963 html_latex_end = lex.getString();
964 } else if (token == "\\output_sync") {
966 } else if (token == "\\output_sync_macro") {
967 lex >> output_sync_macro;
968 } else if (token == "\\use_refstyle") {
971 lyxerr << "BufferParams::readToken(): Unknown token: " <<
980 void BufferParams::writeFile(ostream & os, Buffer const * buf) const
982 // The top of the file is written by the buffer.
983 // Prints out the buffer info into the .lyx file given by file
985 // the document directory
987 << (lyxrc.save_origin ? buf->filePath() : "unavailable") << '\n';
990 os << "\\textclass " << buf->includedFilePath(addName(buf->layoutPos(),
991 baseClass()->name()), "layout")
995 if (!preamble.empty()) {
996 // remove '\n' from the end of preamble
997 string const tmppreamble = rtrim(preamble, "\n");
998 os << "\\begin_preamble\n"
1000 << "\n\\end_preamble\n";
1004 if (!options.empty()) {
1005 os << "\\options " << options << '\n';
1008 // use the class options defined in the layout?
1009 os << "\\use_default_options "
1010 << convert<string>(use_default_options) << "\n";
1012 // the master document
1013 if (!master.empty()) {
1014 os << "\\master " << master << '\n';
1018 if (!removed_modules_.empty()) {
1019 os << "\\begin_removed_modules" << '\n';
1020 list<string>::const_iterator it = removed_modules_.begin();
1021 list<string>::const_iterator en = removed_modules_.end();
1022 for (; it != en; ++it)
1024 os << "\\end_removed_modules" << '\n';
1028 if (!layout_modules_.empty()) {
1029 os << "\\begin_modules" << '\n';
1030 LayoutModuleList::const_iterator it = layout_modules_.begin();
1031 LayoutModuleList::const_iterator en = layout_modules_.end();
1032 for (; it != en; ++it)
1034 os << "\\end_modules" << '\n';
1038 if (!included_children_.empty()) {
1039 os << "\\begin_includeonly" << '\n';
1040 list<string>::const_iterator it = included_children_.begin();
1041 list<string>::const_iterator en = included_children_.end();
1042 for (; it != en; ++it)
1044 os << "\\end_includeonly" << '\n';
1046 os << "\\maintain_unincluded_children "
1047 << convert<string>(maintain_unincluded_children) << '\n';
1049 // local layout information
1050 string const local_layout = getLocalLayout(false);
1051 if (!local_layout.empty()) {
1052 // remove '\n' from the end
1053 string const tmplocal = rtrim(local_layout, "\n");
1054 os << "\\begin_local_layout\n"
1056 << "\n\\end_local_layout\n";
1058 string const forced_local_layout = getLocalLayout(true);
1059 if (!forced_local_layout.empty()) {
1060 // remove '\n' from the end
1061 string const tmplocal = rtrim(forced_local_layout, "\n");
1062 os << "\\begin_forced_local_layout\n"
1064 << "\n\\end_forced_local_layout\n";
1067 // then the text parameters
1068 if (language != ignore_language)
1069 os << "\\language " << language->lang() << '\n';
1070 os << "\\language_package " << lang_package
1071 << "\n\\inputencoding " << inputenc
1072 << "\n\\fontencoding " << fontenc
1073 << "\n\\font_roman " << fonts_roman
1074 << "\n\\font_sans " << fonts_sans
1075 << "\n\\font_typewriter " << fonts_typewriter
1076 << "\n\\font_math " << fonts_math
1077 << "\n\\font_default_family " << fonts_default_family
1078 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1079 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1080 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1081 << "\n\\font_sf_scale " << fonts_sans_scale
1082 << "\n\\font_tt_scale " << fonts_typewriter_scale
1084 if (!fonts_cjk.empty()) {
1085 os << "\\font_cjk " << fonts_cjk << '\n';
1087 os << "\\graphics " << graphics_driver << '\n';
1088 os << "\\default_output_format " << default_output_format << '\n';
1089 os << "\\output_sync " << output_sync << '\n';
1090 if (!output_sync_macro.empty())
1091 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1092 os << "\\bibtex_command " << bibtex_command << '\n';
1093 os << "\\index_command " << index_command << '\n';
1095 if (!float_placement.empty()) {
1096 os << "\\float_placement " << float_placement << '\n';
1098 os << "\\paperfontsize " << fontsize << '\n';
1100 spacing().writeFile(os);
1101 pdfoptions().writeFile(os);
1103 os << "\\papersize " << string_papersize[papersize]
1104 << "\n\\use_geometry " << convert<string>(use_geometry);
1105 map<string, string> const & packages = auto_packages();
1106 for (map<string, string>::const_iterator it = packages.begin();
1107 it != packages.end(); ++it)
1108 os << "\n\\use_package " << it->first << ' '
1109 << use_package(it->first);
1111 os << "\n\\cite_engine ";
1113 if (!cite_engine_.empty()) {
1114 LayoutModuleList::const_iterator be = cite_engine_.begin();
1115 LayoutModuleList::const_iterator en = cite_engine_.end();
1116 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1125 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1126 << "\n\\biblio_style " << biblio_style
1127 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1128 << "\n\\use_indices " << convert<string>(use_indices)
1129 << "\n\\paperorientation " << string_orientation[orientation]
1130 << "\n\\suppress_date " << convert<string>(suppress_date)
1131 << "\n\\justification " << convert<string>(justification)
1132 << "\n\\use_refstyle " << use_refstyle
1134 if (isbackgroundcolor == true)
1135 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1136 if (isfontcolor == true)
1137 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1138 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1139 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1140 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1141 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1143 BranchList::const_iterator it = branchlist().begin();
1144 BranchList::const_iterator end = branchlist().end();
1145 for (; it != end; ++it) {
1146 os << "\\branch " << to_utf8(it->branch())
1147 << "\n\\selected " << it->isSelected()
1148 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1149 << "\n\\color " << lyx::X11hexname(it->color())
1154 IndicesList::const_iterator iit = indiceslist().begin();
1155 IndicesList::const_iterator iend = indiceslist().end();
1156 for (; iit != iend; ++iit) {
1157 os << "\\index " << to_utf8(iit->index())
1158 << "\n\\shortcut " << to_utf8(iit->shortcut())
1159 << "\n\\color " << lyx::X11hexname(iit->color())
1164 if (!paperwidth.empty())
1165 os << "\\paperwidth "
1166 << VSpace(paperwidth).asLyXCommand() << '\n';
1167 if (!paperheight.empty())
1168 os << "\\paperheight "
1169 << VSpace(paperheight).asLyXCommand() << '\n';
1170 if (!leftmargin.empty())
1171 os << "\\leftmargin "
1172 << VSpace(leftmargin).asLyXCommand() << '\n';
1173 if (!topmargin.empty())
1174 os << "\\topmargin "
1175 << VSpace(topmargin).asLyXCommand() << '\n';
1176 if (!rightmargin.empty())
1177 os << "\\rightmargin "
1178 << VSpace(rightmargin).asLyXCommand() << '\n';
1179 if (!bottommargin.empty())
1180 os << "\\bottommargin "
1181 << VSpace(bottommargin).asLyXCommand() << '\n';
1182 if (!headheight.empty())
1183 os << "\\headheight "
1184 << VSpace(headheight).asLyXCommand() << '\n';
1185 if (!headsep.empty())
1187 << VSpace(headsep).asLyXCommand() << '\n';
1188 if (!footskip.empty())
1190 << VSpace(footskip).asLyXCommand() << '\n';
1191 if (!columnsep.empty())
1192 os << "\\columnsep "
1193 << VSpace(columnsep).asLyXCommand() << '\n';
1194 os << "\\secnumdepth " << secnumdepth
1195 << "\n\\tocdepth " << tocdepth
1196 << "\n\\paragraph_separation "
1197 << string_paragraph_separation[paragraph_separation];
1198 if (!paragraph_separation)
1199 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1201 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1202 os << "\n\\quotes_language "
1203 << string_quotes_language[quotes_language]
1204 << "\n\\papercolumns " << columns
1205 << "\n\\papersides " << sides
1206 << "\n\\paperpagestyle " << pagestyle << '\n';
1207 if (!listings_params.empty())
1208 os << "\\listings_params \"" <<
1209 InsetListingsParams(listings_params).encodedString() << "\"\n";
1210 for (int i = 0; i < 4; ++i) {
1211 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1212 if (user_defined_bullet(i).getFont() != -1) {
1213 os << "\\bullet " << i << " "
1214 << user_defined_bullet(i).getFont() << " "
1215 << user_defined_bullet(i).getCharacter() << " "
1216 << user_defined_bullet(i).getSize() << "\n";
1220 os << "\\bulletLaTeX " << i << " \""
1221 << lyx::to_ascii(user_defined_bullet(i).getText())
1227 os << "\\tracking_changes " << convert<string>(track_changes) << '\n'
1228 << "\\output_changes " << convert<string>(output_changes) << '\n'
1229 << "\\html_math_output " << html_math_output << '\n'
1230 << "\\html_css_as_file " << html_css_as_file << '\n'
1231 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1233 if (html_math_img_scale != 1.0)
1234 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1235 if (!html_latex_start.empty())
1236 os << "\\html_latex_start " << html_latex_start << '\n';
1237 if (!html_latex_end.empty())
1238 os << "\\html_latex_end " << html_latex_end << '\n';
1240 os << pimpl_->authorlist;
1244 void BufferParams::validate(LaTeXFeatures & features) const
1246 features.require(documentClass().requires());
1248 if (columns > 1 && language->rightToLeft())
1249 features.require("rtloutputdblcol");
1251 if (output_changes) {
1252 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1253 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1254 LaTeXFeatures::isAvailable("xcolor");
1256 switch (features.runparams().flavor) {
1257 case OutputParams::LATEX:
1258 case OutputParams::DVILUATEX:
1260 features.require("ct-dvipost");
1261 features.require("dvipost");
1262 } else if (xcolorulem) {
1263 features.require("ct-xcolor-ulem");
1264 features.require("ulem");
1265 features.require("xcolor");
1267 features.require("ct-none");
1270 case OutputParams::LUATEX:
1271 case OutputParams::PDFLATEX:
1272 case OutputParams::XETEX:
1274 features.require("ct-xcolor-ulem");
1275 features.require("ulem");
1276 features.require("xcolor");
1277 // improves color handling in PDF output
1278 features.require("pdfcolmk");
1280 features.require("ct-none");
1288 // Floats with 'Here definitely' as default setting.
1289 if (float_placement.find('H') != string::npos)
1290 features.require("float");
1292 for (PackageMap::const_iterator it = use_packages.begin();
1293 it != use_packages.end(); ++it) {
1294 if (it->first == "amsmath") {
1295 // AMS Style is at document level
1296 if (it->second == package_on ||
1297 features.isProvided("amsmath"))
1298 features.require(it->first);
1299 } else if (it->second == package_on)
1300 features.require(it->first);
1303 // Document-level line spacing
1304 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1305 features.require("setspace");
1307 // the bullet shapes are buffer level not paragraph level
1308 // so they are tested here
1309 for (int i = 0; i < 4; ++i) {
1310 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1312 int const font = user_defined_bullet(i).getFont();
1314 int const c = user_defined_bullet(i).getCharacter();
1320 features.require("latexsym");
1322 } else if (font == 1) {
1323 features.require("amssymb");
1324 } else if (font >= 2 && font <= 5) {
1325 features.require("pifont");
1329 if (pdfoptions().use_hyperref) {
1330 features.require("hyperref");
1331 // due to interferences with babel and hyperref, the color package has to
1332 // be loaded after hyperref when hyperref is used with the colorlinks
1333 // option, see http://www.lyx.org/trac/ticket/5291
1334 if (pdfoptions().colorlinks)
1335 features.require("color");
1337 if (!listings_params.empty()) {
1338 // do not test validity because listings_params is
1339 // supposed to be valid
1341 InsetListingsParams(listings_params).separatedParams(true);
1342 // we can't support all packages, but we should load the color package
1343 if (par.find("\\color", 0) != string::npos)
1344 features.require("color");
1347 // some languages are only available via polyglossia
1348 if (features.runparams().flavor == OutputParams::XETEX
1349 && (features.hasPolyglossiaExclusiveLanguages()
1351 features.require("polyglossia");
1353 if (useNonTeXFonts && fonts_math != "auto")
1354 features.require("unicode-math");
1356 if (!language->requires().empty())
1357 features.require(language->requires());
1361 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1362 FileName const & filepath) const
1364 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1365 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1366 // \RequirePackage to do so, rather than the normal \usepackage
1367 // Do not try to load any other package before the document class, unless you
1368 // have a thorough understanding of the LATEX internals and know exactly what you
1370 if (features.mustProvide("fix-cm"))
1371 os << "\\RequirePackage{fix-cm}\n";
1372 // Likewise for fixltx2e. If other packages conflict with this policy,
1373 // treat it as a package bug (and report it!)
1374 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1375 if (features.mustProvide("fixltx2e"))
1376 os << "\\RequirePackage{fixltx2e}\n";
1378 os << "\\documentclass";
1380 DocumentClass const & tclass = documentClass();
1382 ostringstream clsoptions; // the document class options.
1384 if (tokenPos(tclass.opt_fontsize(),
1385 '|', fontsize) >= 0) {
1386 // only write if existing in list (and not default)
1387 clsoptions << fontsize << "pt,";
1390 // all paper sizes except of A4, A5, B5 and the US sizes need the
1392 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1393 && papersize != PAPER_USLETTER
1394 && papersize != PAPER_USLEGAL
1395 && papersize != PAPER_USEXECUTIVE
1396 && papersize != PAPER_A4
1397 && papersize != PAPER_A5
1398 && papersize != PAPER_B5;
1400 if (!use_geometry) {
1401 switch (papersize) {
1403 clsoptions << "a4paper,";
1405 case PAPER_USLETTER:
1406 clsoptions << "letterpaper,";
1409 clsoptions << "a5paper,";
1412 clsoptions << "b5paper,";
1414 case PAPER_USEXECUTIVE:
1415 clsoptions << "executivepaper,";
1418 clsoptions << "legalpaper,";
1452 if (sides != tclass.sides()) {
1455 clsoptions << "oneside,";
1458 clsoptions << "twoside,";
1464 if (columns != tclass.columns()) {
1466 clsoptions << "twocolumn,";
1468 clsoptions << "onecolumn,";
1472 && orientation == ORIENTATION_LANDSCAPE)
1473 clsoptions << "landscape,";
1475 // language should be a parameter to \documentclass
1476 if (language->babel() == "hebrew"
1477 && default_language->babel() != "hebrew")
1478 // This seems necessary
1479 features.useLanguage(default_language);
1481 ostringstream language_options;
1482 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1483 bool const use_polyglossia = features.usePolyglossia();
1484 bool const global = lyxrc.language_global_options;
1485 if (use_babel || (use_polyglossia && global)) {
1486 language_options << features.getBabelLanguages();
1487 if (!language->babel().empty()) {
1488 if (!language_options.str().empty())
1489 language_options << ',';
1490 language_options << language->babel();
1492 if (global && !features.needBabelLangOptions()
1493 && !language_options.str().empty())
1494 clsoptions << language_options.str() << ',';
1497 // the predefined options from the layout
1498 if (use_default_options && !tclass.options().empty())
1499 clsoptions << tclass.options() << ',';
1501 // the user-defined options
1502 if (!options.empty()) {
1503 clsoptions << options << ',';
1506 string strOptions(clsoptions.str());
1507 if (!strOptions.empty()) {
1508 strOptions = rtrim(strOptions, ",");
1510 os << '[' << from_utf8(strOptions) << ']';
1513 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1514 // end of \documentclass defs
1516 // if we use fontspec or newtxmath, we have to load the AMS packages here
1517 string const ams = features.loadAMSPackages();
1518 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1519 bool const use_newtxmath =
1520 theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getUsedPackage(
1521 ot1, false, false) == "newtxmath";
1522 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1523 os << from_ascii(ams);
1525 if (useNonTeXFonts) {
1526 os << "\\usepackage{fontspec}\n";
1527 if (features.mustProvide("unicode-math")
1528 && features.isAvailable("unicode-math"))
1529 os << "\\usepackage{unicode-math}\n";
1532 // font selection must be done before loading fontenc.sty
1533 string const fonts = loadFonts(features);
1535 os << from_utf8(fonts);
1537 if (fonts_default_family != "default")
1538 os << "\\renewcommand{\\familydefault}{\\"
1539 << from_ascii(fonts_default_family) << "}\n";
1541 // set font encoding
1542 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1543 if (!useNonTeXFonts && !features.isProvided("fontenc")
1544 && font_encoding() != "default") {
1545 // get main font encodings
1546 vector<string> fontencs = font_encodings();
1547 // get font encodings of secondary languages
1548 features.getFontEncodings(fontencs);
1549 if (!fontencs.empty()) {
1550 os << "\\usepackage["
1551 << from_ascii(getStringFromVector(fontencs))
1556 // handle inputenc etc.
1557 writeEncodingPreamble(os, features);
1560 if (!features.runparams().includeall && !included_children_.empty()) {
1561 os << "\\includeonly{";
1562 list<string>::const_iterator it = included_children_.begin();
1563 list<string>::const_iterator en = included_children_.end();
1565 for (; it != en; ++it) {
1566 string incfile = *it;
1567 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1568 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1570 if (!features.runparams().nice)
1572 // \includeonly doesn't want an extension
1573 incfile = changeExtension(incfile, string());
1574 incfile = support::latex_path(incfile);
1575 if (!incfile.empty()) {
1578 os << from_utf8(incfile);
1585 if (!features.isProvided("geometry")
1586 && (use_geometry || nonstandard_papersize)) {
1587 odocstringstream ods;
1588 if (!getGraphicsDriver("geometry").empty())
1589 ods << getGraphicsDriver("geometry");
1590 if (orientation == ORIENTATION_LANDSCAPE)
1591 ods << ",landscape";
1592 switch (papersize) {
1594 if (!paperwidth.empty())
1595 ods << ",paperwidth="
1596 << from_ascii(paperwidth);
1597 if (!paperheight.empty())
1598 ods << ",paperheight="
1599 << from_ascii(paperheight);
1601 case PAPER_USLETTER:
1602 ods << ",letterpaper";
1605 ods << ",legalpaper";
1607 case PAPER_USEXECUTIVE:
1608 ods << ",executivepaper";
1697 docstring const g_options = trim(ods.str(), ",");
1698 os << "\\usepackage";
1699 if (!g_options.empty())
1700 os << '[' << g_options << ']';
1701 os << "{geometry}\n";
1702 // output this only if use_geometry is true
1704 os << "\\geometry{verbose";
1705 if (!topmargin.empty())
1706 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1707 if (!bottommargin.empty())
1708 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1709 if (!leftmargin.empty())
1710 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1711 if (!rightmargin.empty())
1712 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1713 if (!headheight.empty())
1714 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1715 if (!headsep.empty())
1716 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1717 if (!footskip.empty())
1718 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1719 if (!columnsep.empty())
1720 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1723 } else if (orientation == ORIENTATION_LANDSCAPE
1724 || papersize != PAPER_DEFAULT) {
1725 features.require("papersize");
1728 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1729 if (pagestyle == "fancy")
1730 os << "\\usepackage{fancyhdr}\n";
1731 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1734 // only output when the background color is not default
1735 if (isbackgroundcolor == true) {
1736 // only require color here, the background color will be defined
1737 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1739 features.require("color");
1740 features.require("pagecolor");
1743 // only output when the font color is not default
1744 if (isfontcolor == true) {
1745 // only require color here, the font color will be defined
1746 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1748 features.require("color");
1749 features.require("fontcolor");
1752 // Only if class has a ToC hierarchy
1753 if (tclass.hasTocLevels()) {
1754 if (secnumdepth != tclass.secnumdepth()) {
1755 os << "\\setcounter{secnumdepth}{"
1759 if (tocdepth != tclass.tocdepth()) {
1760 os << "\\setcounter{tocdepth}{"
1766 if (paragraph_separation) {
1767 // when skip separation
1768 switch (getDefSkip().kind()) {
1769 case VSpace::SMALLSKIP:
1770 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1772 case VSpace::MEDSKIP:
1773 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1775 case VSpace::BIGSKIP:
1776 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1778 case VSpace::LENGTH:
1779 os << "\\setlength{\\parskip}{"
1780 << from_utf8(getDefSkip().length().asLatexString())
1783 default: // should never happen // Then delete it.
1784 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1787 os << "\\setlength{\\parindent}{0pt}\n";
1789 // when separation by indentation
1790 // only output something when a width is given
1791 if (getIndentation().asLyXCommand() != "default") {
1792 os << "\\setlength{\\parindent}{"
1793 << from_utf8(getIndentation().asLatexCommand())
1798 // Now insert the LyX specific LaTeX commands...
1799 docstring lyxpreamble;
1800 features.resolveAlternatives();
1803 if (!output_sync_macro.empty())
1804 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1805 else if (features.runparams().flavor == OutputParams::LATEX)
1806 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1807 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1808 lyxpreamble += "\\synctex=-1\n";
1811 // The package options (via \PassOptionsToPackage)
1812 lyxpreamble += from_ascii(features.getPackageOptions());
1814 // due to interferences with babel and hyperref, the color package has to
1815 // be loaded (when it is not already loaded) before babel when hyperref
1816 // is used with the colorlinks option, see
1817 // http://www.lyx.org/trac/ticket/5291
1818 // we decided therefore to load color always before babel, see
1819 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1820 lyxpreamble += from_ascii(features.getColorOptions());
1822 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1823 // we have to call babel before
1825 && (features.isRequired("jurabib")
1826 || features.isRequired("hyperref")
1827 || features.isRequired("varioref")
1828 || features.isRequired("vietnamese")
1829 || features.isRequired("japanese"))) {
1831 lyxpreamble += from_utf8(features.getBabelPresettings());
1832 lyxpreamble += from_utf8(babelCall(language_options.str(),
1833 features.needBabelLangOptions())) + '\n';
1834 lyxpreamble += from_utf8(features.getBabelPostsettings());
1837 // The optional packages;
1838 lyxpreamble += from_ascii(features.getPackages());
1840 // Additional Indices
1841 if (features.isRequired("splitidx")) {
1842 IndicesList::const_iterator iit = indiceslist().begin();
1843 IndicesList::const_iterator iend = indiceslist().end();
1844 for (; iit != iend; ++iit) {
1845 pair<docstring, docstring> indexname_latex =
1846 features.runparams().encoding->latexString(iit->index(),
1847 features.runparams().dryrun);
1848 if (!indexname_latex.second.empty()) {
1849 // issue a warning about omitted characters
1850 // FIXME: should be passed to the error dialog
1851 frontend::Alert::warning(_("Uncodable characters"),
1852 bformat(_("The following characters that are used in an index name are not\n"
1853 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1854 indexname_latex.second));
1856 lyxpreamble += "\\newindex[";
1857 lyxpreamble += indexname_latex.first;
1858 lyxpreamble += "]{";
1859 lyxpreamble += escape(iit->shortcut());
1860 lyxpreamble += "}\n";
1865 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1868 // * Hyperref manual: "Make sure it comes last of your loaded
1869 // packages, to give it a fighting chance of not being over-written,
1870 // since its job is to redefine many LaTeX commands."
1871 // * Email from Heiko Oberdiek: "It is usually better to load babel
1872 // before hyperref. Then hyperref has a chance to detect babel.
1873 // * Has to be loaded before the "LyX specific LaTeX commands" to
1874 // avoid errors with algorithm floats.
1875 // use hyperref explicitly if it is required
1876 if (features.isRequired("hyperref")) {
1877 // pass what we have to stream here, since we need
1878 // to access the stream itself in PDFOptions.
1881 OutputParams tmp_params = features.runparams();
1882 pdfoptions().writeLaTeX(tmp_params, os,
1883 features.isProvided("hyperref"));
1884 // set back for the rest
1885 lyxpreamble.clear();
1886 // correctly break URLs with hyperref and dvi output
1887 if (features.runparams().flavor == OutputParams::LATEX
1888 && features.isAvailable("breakurl"))
1889 lyxpreamble += "\\usepackage{breakurl}\n";
1890 } else if (features.isRequired("nameref"))
1891 // hyperref loads this automatically
1892 lyxpreamble += "\\usepackage{nameref}\n";
1894 // bibtopic needs to be loaded after hyperref.
1895 // the dot provides the aux file naming which LyX can detect.
1896 if (features.mustProvide("bibtopic"))
1897 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1899 // Will be surrounded by \makeatletter and \makeatother when not empty
1900 docstring atlyxpreamble;
1902 // Some macros LyX will need
1903 docstring tmppreamble(features.getMacros());
1905 if (!tmppreamble.empty())
1906 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1907 "LyX specific LaTeX commands.\n"
1908 + tmppreamble + '\n';
1910 // the text class specific preamble
1911 tmppreamble = features.getTClassPreamble();
1912 if (!tmppreamble.empty())
1913 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1914 "Textclass specific LaTeX commands.\n"
1915 + tmppreamble + '\n';
1917 // suppress date if selected
1918 // use \@ifundefined because we cannot be sure that every document class
1919 // has a \date command
1921 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1923 /* the user-defined preamble */
1924 if (!containsOnly(preamble, " \n\t"))
1926 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1927 "User specified LaTeX commands.\n"
1928 + from_utf8(preamble) + '\n';
1930 // footmisc must be loaded after setspace
1931 // Load it here to avoid clashes with footmisc loaded in the user
1932 // preamble. For that reason we also pass the options via
1933 // \PassOptionsToPackage in getPreamble() and not here.
1934 if (features.mustProvide("footmisc"))
1935 atlyxpreamble += "\\usepackage{footmisc}\n";
1937 // subfig loads internally the LaTeX package "caption". As
1938 // caption is a very popular package, users will load it in
1939 // the preamble. Therefore we must load subfig behind the
1940 // user-defined preamble and check if the caption package was
1941 // loaded or not. For the case that caption is loaded before
1942 // subfig, there is the subfig option "caption=false". This
1943 // option also works when a koma-script class is used and
1944 // koma's own caption commands are used instead of caption. We
1945 // use \PassOptionsToPackage here because the user could have
1946 // already loaded subfig in the preamble.
1947 if (features.isRequired("subfig")) {
1948 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1949 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1950 "\\usepackage{subfig}\n";
1953 // Itemize bullet settings need to be last in case the user
1954 // defines their own bullets that use a package included
1955 // in the user-defined preamble -- ARRae
1956 // Actually it has to be done much later than that
1957 // since some packages like frenchb make modifications
1958 // at \begin{document} time -- JMarc
1959 docstring bullets_def;
1960 for (int i = 0; i < 4; ++i) {
1961 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1962 if (bullets_def.empty())
1963 bullets_def += "\\AtBeginDocument{\n";
1964 bullets_def += " \\def\\labelitemi";
1966 // `i' is one less than the item to modify
1973 bullets_def += "ii";
1979 bullets_def += '{' +
1980 user_defined_bullet(i).getText()
1985 if (!bullets_def.empty())
1986 atlyxpreamble += bullets_def + "}\n\n";
1988 if (!atlyxpreamble.empty())
1989 lyxpreamble += "\n\\makeatletter\n"
1990 + atlyxpreamble + "\\makeatother\n\n";
1992 // We try to load babel late, in case it interferes with other packages.
1993 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
1994 // called after babel, though.
1995 if (use_babel && !features.isRequired("jurabib")
1996 && !features.isRequired("hyperref")
1997 && !features.isRequired("varioref")
1998 && !features.isRequired("vietnamese")
1999 && !features.isRequired("japanese")) {
2001 lyxpreamble += from_utf8(features.getBabelPresettings());
2002 lyxpreamble += from_utf8(babelCall(language_options.str(),
2003 features.needBabelLangOptions())) + '\n';
2004 lyxpreamble += from_utf8(features.getBabelPostsettings());
2006 if (features.isRequired("bicaption"))
2007 lyxpreamble += "\\usepackage{bicaption}\n";
2008 if (!listings_params.empty() || features.isRequired("listings"))
2009 lyxpreamble += "\\usepackage{listings}\n";
2010 if (!listings_params.empty()) {
2011 lyxpreamble += "\\lstset{";
2012 // do not test validity because listings_params is
2013 // supposed to be valid
2015 InsetListingsParams(listings_params).separatedParams(true);
2016 lyxpreamble += from_utf8(par);
2017 lyxpreamble += "}\n";
2020 // xunicode needs to be loaded at least after amsmath, amssymb,
2021 // esint and the other packages that provide special glyphs
2022 if (features.runparams().flavor == OutputParams::XETEX
2024 lyxpreamble += "\\usepackage{xunicode}\n";
2026 // Polyglossia must be loaded last
2027 if (use_polyglossia) {
2029 lyxpreamble += "\\usepackage{polyglossia}\n";
2030 // set the main language
2031 lyxpreamble += "\\setdefaultlanguage";
2032 if (!language->polyglossiaOpts().empty())
2033 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
2034 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
2035 // now setup the other languages
2036 std::map<std::string, std::string> const polylangs =
2037 features.getPolyglossiaLanguages();
2038 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
2039 mit != polylangs.end() ; ++mit) {
2040 lyxpreamble += "\\setotherlanguage";
2041 if (!mit->second.empty())
2042 lyxpreamble += "[" + from_ascii(mit->second) + "]";
2043 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
2047 // Load custom language package here
2048 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2049 if (lang_package == "default")
2050 lyxpreamble += from_utf8(lyxrc.language_custom_package);
2052 lyxpreamble += from_utf8(lang_package);
2053 lyxpreamble += '\n';
2056 docstring const i18npreamble =
2057 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2058 if (!i18npreamble.empty())
2059 lyxpreamble += i18npreamble + '\n';
2067 void BufferParams::useClassDefaults()
2069 DocumentClass const & tclass = documentClass();
2071 sides = tclass.sides();
2072 columns = tclass.columns();
2073 pagestyle = tclass.pagestyle();
2074 use_default_options = true;
2075 // Only if class has a ToC hierarchy
2076 if (tclass.hasTocLevels()) {
2077 secnumdepth = tclass.secnumdepth();
2078 tocdepth = tclass.tocdepth();
2083 bool BufferParams::hasClassDefaults() const
2085 DocumentClass const & tclass = documentClass();
2087 return sides == tclass.sides()
2088 && columns == tclass.columns()
2089 && pagestyle == tclass.pagestyle()
2090 && use_default_options
2091 && secnumdepth == tclass.secnumdepth()
2092 && tocdepth == tclass.tocdepth();
2096 DocumentClass const & BufferParams::documentClass() const
2098 return *doc_class_.get();
2102 DocumentClassConstPtr BufferParams::documentClassPtr() const
2108 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2110 // evil, but this function is evil
2111 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2115 bool BufferParams::setBaseClass(string const & classname)
2117 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2118 LayoutFileList & bcl = LayoutFileList::get();
2119 if (!bcl.haveClass(classname)) {
2121 bformat(_("The layout file:\n"
2123 "could not be found. A default textclass with default\n"
2124 "layouts will be used. LyX will not be able to produce\n"
2126 from_utf8(classname));
2127 frontend::Alert::error(_("Document class not found"), s);
2128 bcl.addEmptyClass(classname);
2131 bool const success = bcl[classname].load();
2134 bformat(_("Due to some error in it, the layout file:\n"
2136 "could not be loaded. A default textclass with default\n"
2137 "layouts will be used. LyX will not be able to produce\n"
2139 from_utf8(classname));
2140 frontend::Alert::error(_("Could not load class"), s);
2141 bcl.addEmptyClass(classname);
2144 pimpl_->baseClass_ = classname;
2145 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2150 LayoutFile const * BufferParams::baseClass() const
2152 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2153 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2159 LayoutFileIndex const & BufferParams::baseClassID() const
2161 return pimpl_->baseClass_;
2165 void BufferParams::makeDocumentClass(bool const clone)
2170 LayoutModuleList mods;
2171 LayoutModuleList::iterator it = layout_modules_.begin();
2172 LayoutModuleList::iterator en = layout_modules_.end();
2173 for (; it != en; ++it)
2174 mods.push_back(*it);
2176 it = cite_engine_.begin();
2177 en = cite_engine_.end();
2178 for (; it != en; ++it)
2179 mods.push_back(*it);
2181 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2183 TextClass::ReturnValues success = TextClass::OK;
2184 if (!forced_local_layout_.empty())
2185 success = doc_class_->read(forced_local_layout_, TextClass::MODULE);
2186 if (!local_layout_.empty() &&
2187 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2188 success = doc_class_->read(local_layout_, TextClass::MODULE);
2189 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2190 docstring const msg = _("Error reading internal layout information");
2191 frontend::Alert::warning(_("Read Error"), msg);
2196 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2198 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2202 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2204 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2208 std::string BufferParams::getLocalLayout(bool forced) const
2211 return doc_class_->forcedLayouts();
2213 return local_layout_;
2217 void BufferParams::setLocalLayout(string const & layout, bool forced)
2220 forced_local_layout_ = layout;
2222 local_layout_ = layout;
2226 bool BufferParams::addLayoutModule(string const & modName)
2228 LayoutModuleList::const_iterator it = layout_modules_.begin();
2229 LayoutModuleList::const_iterator end = layout_modules_.end();
2230 for (; it != end; ++it)
2233 layout_modules_.push_back(modName);
2238 string BufferParams::bufferFormat() const
2240 string format = documentClass().outputFormat();
2241 if (format == "latex") {
2244 if (encoding().package() == Encoding::japanese)
2251 bool BufferParams::isExportable(string const & format) const
2253 vector<string> backs = backends();
2254 for (vector<string>::const_iterator it = backs.begin();
2255 it != backs.end(); ++it)
2256 if (theConverters().isReachable(*it, format))
2262 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2264 vector<string> const backs = backends();
2265 set<string> excludes;
2266 if (useNonTeXFonts) {
2267 excludes.insert("latex");
2268 excludes.insert("pdflatex");
2270 vector<Format const *> result =
2271 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2272 for (vector<string>::const_iterator it = backs.begin() + 1;
2273 it != backs.end(); ++it) {
2274 vector<Format const *> r =
2275 theConverters().getReachable(*it, only_viewable, false, excludes);
2276 result.insert(result.end(), r.begin(), r.end());
2282 bool BufferParams::isExportableFormat(string const & format) const
2284 typedef vector<Format const *> Formats;
2286 formats = exportableFormats(true);
2287 Formats::const_iterator fit = formats.begin();
2288 Formats::const_iterator end = formats.end();
2289 for (; fit != end ; ++fit) {
2290 if ((*fit)->name() == format)
2297 vector<string> BufferParams::backends() const
2300 string const buffmt = bufferFormat();
2302 // FIXME: Don't hardcode format names here, but use a flag
2303 if (buffmt == "latex") {
2304 if (!useNonTeXFonts) {
2305 v.push_back("pdflatex");
2306 v.push_back("latex");
2308 v.push_back("luatex");
2309 v.push_back("dviluatex");
2310 v.push_back("xetex");
2311 } else if (buffmt == "xetex") {
2312 v.push_back("xetex");
2313 // FIXME: need to test all languages (bug 8205)
2314 if (!language || !language->isPolyglossiaExclusive()) {
2315 v.push_back("luatex");
2316 v.push_back("dviluatex");
2319 v.push_back(buffmt);
2321 v.push_back("xhtml");
2322 v.push_back("text");
2328 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2330 string const dformat = (format.empty() || format == "default") ?
2331 getDefaultOutputFormat() : format;
2332 DefaultFlavorCache::const_iterator it =
2333 default_flavors_.find(dformat);
2335 if (it != default_flavors_.end())
2338 OutputParams::FLAVOR result = OutputParams::LATEX;
2340 // FIXME It'd be better not to hardcode this, but to do
2341 // something with formats.
2342 if (dformat == "xhtml")
2343 result = OutputParams::HTML;
2344 else if (dformat == "text")
2345 result = OutputParams::TEXT;
2346 else if (dformat == "lyx")
2347 result = OutputParams::LYX;
2348 else if (dformat == "pdflatex")
2349 result = OutputParams::PDFLATEX;
2350 else if (dformat == "xetex")
2351 result = OutputParams::XETEX;
2352 else if (dformat == "luatex")
2353 result = OutputParams::LUATEX;
2354 else if (dformat == "dviluatex")
2355 result = OutputParams::DVILUATEX;
2357 // Try to determine flavor of default output format
2358 vector<string> backs = backends();
2359 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2360 // Get shortest path to format
2361 Graph::EdgePath path;
2362 for (vector<string>::const_iterator it = backs.begin();
2363 it != backs.end(); ++it) {
2364 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2365 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2370 result = theConverters().getFlavor(path);
2373 // cache this flavor
2374 default_flavors_[dformat] = result;
2379 string BufferParams::getDefaultOutputFormat() const
2381 if (!default_output_format.empty()
2382 && default_output_format != "default")
2383 return default_output_format;
2385 || encoding().package() == Encoding::japanese) {
2386 vector<Format const *> const formats = exportableFormats(true);
2387 if (formats.empty())
2389 // return the first we find
2390 return formats.front()->name();
2393 return lyxrc.default_otf_view_format;
2394 return lyxrc.default_view_format;
2397 Font const BufferParams::getFont() const
2399 FontInfo f = documentClass().defaultfont();
2400 if (fonts_default_family == "rmdefault")
2401 f.setFamily(ROMAN_FAMILY);
2402 else if (fonts_default_family == "sfdefault")
2403 f.setFamily(SANS_FAMILY);
2404 else if (fonts_default_family == "ttdefault")
2405 f.setFamily(TYPEWRITER_FAMILY);
2406 return Font(f, language);
2410 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const & qs) const
2412 return quoteslangtranslator().find(qs);
2416 bool BufferParams::isLatex() const
2418 return documentClass().outputType() == LATEX;
2422 bool BufferParams::isLiterate() const
2424 return documentClass().outputType() == LITERATE;
2428 bool BufferParams::isDocBook() const
2430 return documentClass().outputType() == DOCBOOK;
2434 void BufferParams::readPreamble(Lexer & lex)
2436 if (lex.getString() != "\\begin_preamble")
2437 lyxerr << "Error (BufferParams::readPreamble):"
2438 "consistency check failed." << endl;
2440 preamble = lex.getLongString("\\end_preamble");
2444 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2446 string const expected = forced ? "\\begin_forced_local_layout" :
2447 "\\begin_local_layout";
2448 if (lex.getString() != expected)
2449 lyxerr << "Error (BufferParams::readLocalLayout):"
2450 "consistency check failed." << endl;
2453 forced_local_layout_ =
2454 lex.getLongString("\\end_forced_local_layout");
2456 local_layout_ = lex.getLongString("\\end_local_layout");
2460 bool BufferParams::setLanguage(string const & lang)
2462 Language const *new_language = languages.getLanguage(lang);
2463 if (!new_language) {
2464 // Language lang was not found
2467 language = new_language;
2472 void BufferParams::readLanguage(Lexer & lex)
2474 if (!lex.next()) return;
2476 string const tmptok = lex.getString();
2478 // check if tmptok is part of tex_babel in tex-defs.h
2479 if (!setLanguage(tmptok)) {
2480 // Language tmptok was not found
2481 language = default_language;
2482 lyxerr << "Warning: Setting language `"
2483 << tmptok << "' to `" << language->lang()
2489 void BufferParams::readGraphicsDriver(Lexer & lex)
2494 string const tmptok = lex.getString();
2495 // check if tmptok is part of tex_graphics in tex_defs.h
2498 string const test = tex_graphics[n++];
2500 if (test == tmptok) {
2501 graphics_driver = tmptok;
2506 "Warning: graphics driver `$$Token' not recognized!\n"
2507 " Setting graphics driver to `default'.\n");
2508 graphics_driver = "default";
2515 void BufferParams::readBullets(Lexer & lex)
2520 int const index = lex.getInteger();
2522 int temp_int = lex.getInteger();
2523 user_defined_bullet(index).setFont(temp_int);
2524 temp_bullet(index).setFont(temp_int);
2526 user_defined_bullet(index).setCharacter(temp_int);
2527 temp_bullet(index).setCharacter(temp_int);
2529 user_defined_bullet(index).setSize(temp_int);
2530 temp_bullet(index).setSize(temp_int);
2534 void BufferParams::readBulletsLaTeX(Lexer & lex)
2536 // The bullet class should be able to read this.
2539 int const index = lex.getInteger();
2541 docstring const temp_str = lex.getDocString();
2543 user_defined_bullet(index).setText(temp_str);
2544 temp_bullet(index).setText(temp_str);
2548 void BufferParams::readModules(Lexer & lex)
2550 if (!lex.eatLine()) {
2551 lyxerr << "Error (BufferParams::readModules):"
2552 "Unexpected end of input." << endl;
2556 string mod = lex.getString();
2557 if (mod == "\\end_modules")
2559 addLayoutModule(mod);
2565 void BufferParams::readRemovedModules(Lexer & lex)
2567 if (!lex.eatLine()) {
2568 lyxerr << "Error (BufferParams::readRemovedModules):"
2569 "Unexpected end of input." << endl;
2573 string mod = lex.getString();
2574 if (mod == "\\end_removed_modules")
2576 removed_modules_.push_back(mod);
2579 // now we want to remove any removed modules that were previously
2580 // added. normally, that will be because default modules were added in
2581 // setBaseClass(), which gets called when \textclass is read at the
2582 // start of the read.
2583 list<string>::const_iterator rit = removed_modules_.begin();
2584 list<string>::const_iterator const ren = removed_modules_.end();
2585 for (; rit != ren; ++rit) {
2586 LayoutModuleList::iterator const mit = layout_modules_.begin();
2587 LayoutModuleList::iterator const men = layout_modules_.end();
2588 LayoutModuleList::iterator found = find(mit, men, *rit);
2591 layout_modules_.erase(found);
2596 void BufferParams::readIncludeonly(Lexer & lex)
2598 if (!lex.eatLine()) {
2599 lyxerr << "Error (BufferParams::readIncludeonly):"
2600 "Unexpected end of input." << endl;
2604 string child = lex.getString();
2605 if (child == "\\end_includeonly")
2607 included_children_.push_back(child);
2613 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2615 switch (papersize) {
2617 // could be anything, so don't guess
2619 case PAPER_CUSTOM: {
2620 if (purpose == XDVI && !paperwidth.empty() &&
2621 !paperheight.empty()) {
2622 // heightxwidth<unit>
2623 string first = paperwidth;
2624 string second = paperheight;
2625 if (orientation == ORIENTATION_LANDSCAPE)
2628 return first.erase(first.length() - 2)
2634 // dvips and dvipdfm do not know this
2635 if (purpose == DVIPS || purpose == DVIPDFM)
2639 if (purpose == DVIPS || purpose == DVIPDFM)
2643 if (purpose == DVIPS || purpose == DVIPDFM)
2653 if (purpose == DVIPS || purpose == DVIPDFM)
2657 if (purpose == DVIPS || purpose == DVIPDFM)
2661 if (purpose == DVIPS || purpose == DVIPDFM)
2665 if (purpose == DVIPS || purpose == DVIPDFM)
2669 if (purpose == DVIPS || purpose == DVIPDFM)
2673 // dvipdfm does not know this
2674 if (purpose == DVIPDFM)
2678 if (purpose == DVIPDFM)
2682 if (purpose == DVIPS || purpose == DVIPDFM)
2686 if (purpose == DVIPS || purpose == DVIPDFM)
2690 if (purpose == DVIPS || purpose == DVIPDFM)
2694 if (purpose == DVIPS || purpose == DVIPDFM)
2698 if (purpose == DVIPS || purpose == DVIPDFM)
2702 if (purpose == DVIPS || purpose == DVIPDFM)
2706 if (purpose == DVIPS || purpose == DVIPDFM)
2710 if (purpose == DVIPS || purpose == DVIPDFM)
2714 if (purpose == DVIPS || purpose == DVIPDFM)
2718 if (purpose == DVIPS || purpose == DVIPDFM)
2722 if (purpose == DVIPS || purpose == DVIPDFM)
2726 if (purpose == DVIPS || purpose == DVIPDFM)
2730 if (purpose == DVIPS || purpose == DVIPDFM)
2734 if (purpose == DVIPS || purpose == DVIPDFM)
2738 if (purpose == DVIPS || purpose == DVIPDFM)
2741 case PAPER_USEXECUTIVE:
2742 // dvipdfm does not know this
2743 if (purpose == DVIPDFM)
2748 case PAPER_USLETTER:
2750 if (purpose == XDVI)
2757 string const BufferParams::dvips_options() const
2761 // If the class loads the geometry package, we do not know which
2762 // paper size is used, since we do not set it (bug 7013).
2763 // Therefore we must not specify any argument here.
2764 // dvips gets the correct paper size via DVI specials in this case
2765 // (if the class uses the geometry package correctly).
2766 if (documentClass().provides("geometry"))
2770 && papersize == PAPER_CUSTOM
2771 && !lyxrc.print_paper_dimension_flag.empty()
2772 && !paperwidth.empty()
2773 && !paperheight.empty()) {
2774 // using a custom papersize
2775 result = lyxrc.print_paper_dimension_flag;
2776 result += ' ' + paperwidth;
2777 result += ',' + paperheight;
2779 string const paper_option = paperSizeName(DVIPS);
2780 if (!paper_option.empty() && (paper_option != "letter" ||
2781 orientation != ORIENTATION_LANDSCAPE)) {
2782 // dvips won't accept -t letter -t landscape.
2783 // In all other cases, include the paper size
2785 result = lyxrc.print_paper_flag;
2786 result += ' ' + paper_option;
2789 if (orientation == ORIENTATION_LANDSCAPE &&
2790 papersize != PAPER_CUSTOM)
2791 result += ' ' + lyxrc.print_landscape_flag;
2796 string const BufferParams::font_encoding() const
2798 return font_encodings().empty() ? "default" : font_encodings().back();
2802 vector<string> const BufferParams::font_encodings() const
2804 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2806 vector<string> fontencs;
2808 // "default" means "no explicit font encoding"
2809 if (doc_fontenc != "default") {
2810 fontencs = getVectorFromString(doc_fontenc);
2811 if (!language->fontenc().empty()
2812 && ascii_lowercase(language->fontenc()) != "none") {
2813 vector<string> fencs = getVectorFromString(language->fontenc());
2814 vector<string>::const_iterator fit = fencs.begin();
2815 for (; fit != fencs.end(); ++fit) {
2816 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
2817 fontencs.push_back(*fit);
2826 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2828 // suppress the babel call if there is no BabelName defined
2829 // for the document language in the lib/languages file and if no
2830 // other languages are used (lang_opts is then empty)
2831 if (lang_opts.empty())
2833 // either a specific language (AsBabelOptions setting in
2834 // lib/languages) or the prefs require the languages to
2835 // be submitted to babel itself (not the class).
2837 return "\\usepackage[" + lang_opts + "]{babel}";
2838 return "\\usepackage{babel}";
2842 docstring BufferParams::getGraphicsDriver(string const & package) const
2846 if (package == "geometry") {
2847 if (graphics_driver == "dvips"
2848 || graphics_driver == "dvipdfm"
2849 || graphics_driver == "pdftex"
2850 || graphics_driver == "vtex")
2851 result = from_ascii(graphics_driver);
2852 else if (graphics_driver == "dvipdfmx")
2853 result = from_ascii("dvipdfm");
2860 void BufferParams::writeEncodingPreamble(otexstream & os,
2861 LaTeXFeatures & features) const
2863 // XeTeX does not need this
2864 if (features.runparams().flavor == OutputParams::XETEX)
2866 // LuaTeX neither, but with tex fonts, we need to load
2867 // the luainputenc package.
2868 if (features.runparams().flavor == OutputParams::LUATEX
2869 || features.runparams().flavor == OutputParams::DVILUATEX) {
2870 if (!useNonTeXFonts && inputenc != "default"
2871 && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc)
2872 || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) {
2873 os << "\\usepackage[utf8]{luainputenc}\n";
2877 if (inputenc == "auto") {
2878 string const doc_encoding =
2879 language->encoding()->latexName();
2880 Encoding::Package const package =
2881 language->encoding()->package();
2883 // Create a list with all the input encodings used
2885 set<string> encodings =
2886 features.getEncodingSet(doc_encoding);
2888 // If the "japanese" package (i.e. pLaTeX) is used,
2889 // inputenc must be omitted.
2890 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2891 if ((!encodings.empty() || package == Encoding::inputenc)
2892 && !features.isRequired("japanese")
2893 && !features.isProvided("inputenc")) {
2894 os << "\\usepackage[";
2895 set<string>::const_iterator it = encodings.begin();
2896 set<string>::const_iterator const end = encodings.end();
2898 os << from_ascii(*it);
2901 for (; it != end; ++it)
2902 os << ',' << from_ascii(*it);
2903 if (package == Encoding::inputenc) {
2904 if (!encodings.empty())
2906 os << from_ascii(doc_encoding);
2908 os << "]{inputenc}\n";
2910 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2911 if (language->encoding()->name() == "utf8-cjk"
2912 && LaTeXFeatures::isAvailable("CJKutf8"))
2913 os << "\\usepackage{CJKutf8}\n";
2915 os << "\\usepackage{CJK}\n";
2917 } else if (inputenc != "default") {
2918 switch (encoding().package()) {
2919 case Encoding::none:
2920 case Encoding::japanese:
2922 case Encoding::inputenc:
2923 // do not load inputenc if japanese is used
2924 // or if the class provides inputenc
2925 if (features.isRequired("japanese")
2926 || features.isProvided("inputenc"))
2928 os << "\\usepackage[" << from_ascii(encoding().latexName())
2932 if (encoding().name() == "utf8-cjk"
2933 && LaTeXFeatures::isAvailable("CJKutf8"))
2934 os << "\\usepackage{CJKutf8}\n";
2936 os << "\\usepackage{CJK}\n";
2939 // Load the CJK package if needed by a secondary language.
2940 // If the main encoding is some variant of UTF8, use CJKutf8.
2941 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
2942 if (encoding().iconvName() == "UTF-8"
2943 && LaTeXFeatures::isAvailable("CJKutf8"))
2944 os << "\\usepackage{CJKutf8}\n";
2946 os << "\\usepackage{CJK}\n";
2952 string const BufferParams::parseFontName(string const & name) const
2954 string mangled = name;
2955 size_t const idx = mangled.find('[');
2956 if (idx == string::npos || idx == 0)
2959 return mangled.substr(0, idx - 1);
2963 string const BufferParams::loadFonts(LaTeXFeatures & features) const
2965 if (fonts_roman == "default" && fonts_sans == "default"
2966 && fonts_typewriter == "default"
2967 && (fonts_math == "default" || fonts_math == "auto"))
2973 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
2974 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
2975 * Mapping=tex-text option assures TeX ligatures (such as "--")
2976 * are resolved. Note that tt does not use these ligatures.
2978 * -- add more GUI options?
2979 * -- add more fonts (fonts for other scripts)
2980 * -- if there's a way to find out if a font really supports
2981 * OldStyle, enable/disable the widget accordingly.
2983 if (useNonTeXFonts && features.isAvailable("fontspec")) {
2984 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
2985 // However, until v.2 (2010/07/11) fontspec only knew
2986 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
2987 // was introduced for both XeTeX and LuaTeX (LuaTeX
2988 // didn't understand "Mapping=tex-text", while XeTeX
2989 // understood both. With most recent versions, both
2990 // variants are understood by both engines. However,
2991 // we want to provide support for at least TeXLive 2009
2992 // (for XeTeX; LuaTeX is only supported as of v.2)
2993 string const texmapping =
2994 (features.runparams().flavor == OutputParams::XETEX) ?
2995 "Mapping=tex-text" : "Ligatures=TeX";
2996 if (fonts_roman != "default") {
2997 os << "\\setmainfont[" << texmapping;
2998 if (fonts_old_figures)
2999 os << ",Numbers=OldStyle";
3000 os << "]{" << parseFontName(fonts_roman) << "}\n";
3002 if (fonts_sans != "default") {
3003 string const sans = parseFontName(fonts_sans);
3004 if (fonts_sans_scale != 100)
3005 os << "\\setsansfont[Scale="
3006 << float(fonts_sans_scale) / 100
3007 << "," << texmapping << "]{"
3010 os << "\\setsansfont[" << texmapping << "]{"
3013 if (fonts_typewriter != "default") {
3014 string const mono = parseFontName(fonts_typewriter);
3015 if (fonts_typewriter_scale != 100)
3016 os << "\\setmonofont[Scale="
3017 << float(fonts_typewriter_scale) / 100
3021 os << "\\setmonofont{"
3028 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
3029 bool const dryrun = features.runparams().dryrun;
3030 bool const complete = (fonts_sans == "default" && fonts_typewriter == "default");
3031 bool const nomath = (fonts_math == "default");
3034 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_roman)).getLaTeXCode(
3035 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3039 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_sans)).getLaTeXCode(
3040 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3041 nomath, fonts_sans_scale);
3043 // MONOSPACED/TYPEWRITER
3044 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_typewriter)).getLaTeXCode(
3045 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3046 nomath, fonts_typewriter_scale);
3049 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getLaTeXCode(
3050 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3057 Encoding const & BufferParams::encoding() const
3059 // FIXME: actually, we should check for the flavor
3060 // or runparams.isFullyUnicode() here:
3061 // This check will not work with XeTeX/LuaTeX and tex fonts.
3062 // Thus we have to reset the encoding in Buffer::makeLaTeXFile
3063 // (for export) and Buffer::writeLaTeXSource (for preview).
3065 return *(encodings.fromLyXName("utf8-plain"));
3066 if (inputenc == "auto" || inputenc == "default")
3067 return *language->encoding();
3068 Encoding const * const enc = encodings.fromLyXName(inputenc);
3071 LYXERR0("Unknown inputenc value `" << inputenc
3072 << "'. Using `auto' instead.");
3073 return *language->encoding();
3077 bool BufferParams::addCiteEngine(string const & engine)
3079 LayoutModuleList::const_iterator it = cite_engine_.begin();
3080 LayoutModuleList::const_iterator en = cite_engine_.end();
3081 for (; it != en; ++it)
3084 cite_engine_.push_back(engine);
3089 bool BufferParams::addCiteEngine(vector<string> const & engine)
3091 vector<string>::const_iterator it = engine.begin();
3092 vector<string>::const_iterator en = engine.end();
3094 for (; it != en; ++it)
3095 if (!addCiteEngine(*it))
3101 string const & BufferParams::defaultBiblioStyle() const
3103 return documentClass().defaultBiblioStyle();
3107 bool const & BufferParams::fullAuthorList() const
3109 return documentClass().fullAuthorList();
3113 void BufferParams::setCiteEngine(string const & engine)
3116 addCiteEngine(engine);
3120 void BufferParams::setCiteEngine(vector<string> const & engine)
3123 addCiteEngine(engine);
3127 vector<string> BufferParams::citeCommands() const
3129 static CitationStyle const default_style;
3130 vector<string> commands =
3131 documentClass().citeCommands(citeEngineType());
3132 if (commands.empty())
3133 commands.push_back(default_style.cmd);
3138 vector<CitationStyle> BufferParams::citeStyles() const
3140 static CitationStyle const default_style;
3141 vector<CitationStyle> styles =
3142 documentClass().citeStyles(citeEngineType());
3144 styles.push_back(default_style);