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
986 os << "\\origin " << buf->filePath() << '\n';
989 os << "\\textclass " << buf->includedFilePath(addName(buf->layoutPos(),
990 baseClass()->name()), "layout")
994 if (!preamble.empty()) {
995 // remove '\n' from the end of preamble
996 string const tmppreamble = rtrim(preamble, "\n");
997 os << "\\begin_preamble\n"
999 << "\n\\end_preamble\n";
1003 if (!options.empty()) {
1004 os << "\\options " << options << '\n';
1007 // use the class options defined in the layout?
1008 os << "\\use_default_options "
1009 << convert<string>(use_default_options) << "\n";
1011 // the master document
1012 if (!master.empty()) {
1013 os << "\\master " << master << '\n';
1017 if (!removed_modules_.empty()) {
1018 os << "\\begin_removed_modules" << '\n';
1019 list<string>::const_iterator it = removed_modules_.begin();
1020 list<string>::const_iterator en = removed_modules_.end();
1021 for (; it != en; ++it)
1023 os << "\\end_removed_modules" << '\n';
1027 if (!layout_modules_.empty()) {
1028 os << "\\begin_modules" << '\n';
1029 LayoutModuleList::const_iterator it = layout_modules_.begin();
1030 LayoutModuleList::const_iterator en = layout_modules_.end();
1031 for (; it != en; ++it)
1033 os << "\\end_modules" << '\n';
1037 if (!included_children_.empty()) {
1038 os << "\\begin_includeonly" << '\n';
1039 list<string>::const_iterator it = included_children_.begin();
1040 list<string>::const_iterator en = included_children_.end();
1041 for (; it != en; ++it)
1043 os << "\\end_includeonly" << '\n';
1045 os << "\\maintain_unincluded_children "
1046 << convert<string>(maintain_unincluded_children) << '\n';
1048 // local layout information
1049 string const local_layout = getLocalLayout(false);
1050 if (!local_layout.empty()) {
1051 // remove '\n' from the end
1052 string const tmplocal = rtrim(local_layout, "\n");
1053 os << "\\begin_local_layout\n"
1055 << "\n\\end_local_layout\n";
1057 string const forced_local_layout = getLocalLayout(true);
1058 if (!forced_local_layout.empty()) {
1059 // remove '\n' from the end
1060 string const tmplocal = rtrim(forced_local_layout, "\n");
1061 os << "\\begin_forced_local_layout\n"
1063 << "\n\\end_forced_local_layout\n";
1066 // then the text parameters
1067 if (language != ignore_language)
1068 os << "\\language " << language->lang() << '\n';
1069 os << "\\language_package " << lang_package
1070 << "\n\\inputencoding " << inputenc
1071 << "\n\\fontencoding " << fontenc
1072 << "\n\\font_roman " << fonts_roman
1073 << "\n\\font_sans " << fonts_sans
1074 << "\n\\font_typewriter " << fonts_typewriter
1075 << "\n\\font_math " << fonts_math
1076 << "\n\\font_default_family " << fonts_default_family
1077 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1078 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1079 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1080 << "\n\\font_sf_scale " << fonts_sans_scale
1081 << "\n\\font_tt_scale " << fonts_typewriter_scale
1083 if (!fonts_cjk.empty()) {
1084 os << "\\font_cjk " << fonts_cjk << '\n';
1086 os << "\\graphics " << graphics_driver << '\n';
1087 os << "\\default_output_format " << default_output_format << '\n';
1088 os << "\\output_sync " << output_sync << '\n';
1089 if (!output_sync_macro.empty())
1090 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1091 os << "\\bibtex_command " << bibtex_command << '\n';
1092 os << "\\index_command " << index_command << '\n';
1094 if (!float_placement.empty()) {
1095 os << "\\float_placement " << float_placement << '\n';
1097 os << "\\paperfontsize " << fontsize << '\n';
1099 spacing().writeFile(os);
1100 pdfoptions().writeFile(os);
1102 os << "\\papersize " << string_papersize[papersize]
1103 << "\n\\use_geometry " << convert<string>(use_geometry);
1104 map<string, string> const & packages = auto_packages();
1105 for (map<string, string>::const_iterator it = packages.begin();
1106 it != packages.end(); ++it)
1107 os << "\n\\use_package " << it->first << ' '
1108 << use_package(it->first);
1110 os << "\n\\cite_engine ";
1112 if (!cite_engine_.empty()) {
1113 LayoutModuleList::const_iterator be = cite_engine_.begin();
1114 LayoutModuleList::const_iterator en = cite_engine_.end();
1115 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1124 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1125 << "\n\\biblio_style " << biblio_style
1126 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1127 << "\n\\use_indices " << convert<string>(use_indices)
1128 << "\n\\paperorientation " << string_orientation[orientation]
1129 << "\n\\suppress_date " << convert<string>(suppress_date)
1130 << "\n\\justification " << convert<string>(justification)
1131 << "\n\\use_refstyle " << use_refstyle
1133 if (isbackgroundcolor == true)
1134 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1135 if (isfontcolor == true)
1136 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1137 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1138 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1139 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1140 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1142 BranchList::const_iterator it = branchlist().begin();
1143 BranchList::const_iterator end = branchlist().end();
1144 for (; it != end; ++it) {
1145 os << "\\branch " << to_utf8(it->branch())
1146 << "\n\\selected " << it->isSelected()
1147 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1148 << "\n\\color " << lyx::X11hexname(it->color())
1153 IndicesList::const_iterator iit = indiceslist().begin();
1154 IndicesList::const_iterator iend = indiceslist().end();
1155 for (; iit != iend; ++iit) {
1156 os << "\\index " << to_utf8(iit->index())
1157 << "\n\\shortcut " << to_utf8(iit->shortcut())
1158 << "\n\\color " << lyx::X11hexname(iit->color())
1163 if (!paperwidth.empty())
1164 os << "\\paperwidth "
1165 << VSpace(paperwidth).asLyXCommand() << '\n';
1166 if (!paperheight.empty())
1167 os << "\\paperheight "
1168 << VSpace(paperheight).asLyXCommand() << '\n';
1169 if (!leftmargin.empty())
1170 os << "\\leftmargin "
1171 << VSpace(leftmargin).asLyXCommand() << '\n';
1172 if (!topmargin.empty())
1173 os << "\\topmargin "
1174 << VSpace(topmargin).asLyXCommand() << '\n';
1175 if (!rightmargin.empty())
1176 os << "\\rightmargin "
1177 << VSpace(rightmargin).asLyXCommand() << '\n';
1178 if (!bottommargin.empty())
1179 os << "\\bottommargin "
1180 << VSpace(bottommargin).asLyXCommand() << '\n';
1181 if (!headheight.empty())
1182 os << "\\headheight "
1183 << VSpace(headheight).asLyXCommand() << '\n';
1184 if (!headsep.empty())
1186 << VSpace(headsep).asLyXCommand() << '\n';
1187 if (!footskip.empty())
1189 << VSpace(footskip).asLyXCommand() << '\n';
1190 if (!columnsep.empty())
1191 os << "\\columnsep "
1192 << VSpace(columnsep).asLyXCommand() << '\n';
1193 os << "\\secnumdepth " << secnumdepth
1194 << "\n\\tocdepth " << tocdepth
1195 << "\n\\paragraph_separation "
1196 << string_paragraph_separation[paragraph_separation];
1197 if (!paragraph_separation)
1198 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1200 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1201 os << "\n\\quotes_language "
1202 << string_quotes_language[quotes_language]
1203 << "\n\\papercolumns " << columns
1204 << "\n\\papersides " << sides
1205 << "\n\\paperpagestyle " << pagestyle << '\n';
1206 if (!listings_params.empty())
1207 os << "\\listings_params \"" <<
1208 InsetListingsParams(listings_params).encodedString() << "\"\n";
1209 for (int i = 0; i < 4; ++i) {
1210 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1211 if (user_defined_bullet(i).getFont() != -1) {
1212 os << "\\bullet " << i << " "
1213 << user_defined_bullet(i).getFont() << " "
1214 << user_defined_bullet(i).getCharacter() << " "
1215 << user_defined_bullet(i).getSize() << "\n";
1219 os << "\\bulletLaTeX " << i << " \""
1220 << lyx::to_ascii(user_defined_bullet(i).getText())
1226 os << "\\tracking_changes " << convert<string>(track_changes) << '\n'
1227 << "\\output_changes " << convert<string>(output_changes) << '\n'
1228 << "\\html_math_output " << html_math_output << '\n'
1229 << "\\html_css_as_file " << html_css_as_file << '\n'
1230 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1232 if (html_math_img_scale != 1.0)
1233 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1234 if (!html_latex_start.empty())
1235 os << "\\html_latex_start " << html_latex_start << '\n';
1236 if (!html_latex_end.empty())
1237 os << "\\html_latex_end " << html_latex_end << '\n';
1239 os << pimpl_->authorlist;
1243 void BufferParams::validate(LaTeXFeatures & features) const
1245 features.require(documentClass().requires());
1247 if (columns > 1 && language->rightToLeft())
1248 features.require("rtloutputdblcol");
1250 if (output_changes) {
1251 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1252 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1253 LaTeXFeatures::isAvailable("xcolor");
1255 switch (features.runparams().flavor) {
1256 case OutputParams::LATEX:
1257 case OutputParams::DVILUATEX:
1259 features.require("ct-dvipost");
1260 features.require("dvipost");
1261 } else if (xcolorulem) {
1262 features.require("ct-xcolor-ulem");
1263 features.require("ulem");
1264 features.require("xcolor");
1266 features.require("ct-none");
1269 case OutputParams::LUATEX:
1270 case OutputParams::PDFLATEX:
1271 case OutputParams::XETEX:
1273 features.require("ct-xcolor-ulem");
1274 features.require("ulem");
1275 features.require("xcolor");
1276 // improves color handling in PDF output
1277 features.require("pdfcolmk");
1279 features.require("ct-none");
1287 // Floats with 'Here definitely' as default setting.
1288 if (float_placement.find('H') != string::npos)
1289 features.require("float");
1291 for (PackageMap::const_iterator it = use_packages.begin();
1292 it != use_packages.end(); ++it) {
1293 if (it->first == "amsmath") {
1294 // AMS Style is at document level
1295 if (it->second == package_on ||
1296 features.isProvided("amsmath"))
1297 features.require(it->first);
1298 } else if (it->second == package_on)
1299 features.require(it->first);
1302 // Document-level line spacing
1303 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1304 features.require("setspace");
1306 // the bullet shapes are buffer level not paragraph level
1307 // so they are tested here
1308 for (int i = 0; i < 4; ++i) {
1309 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1311 int const font = user_defined_bullet(i).getFont();
1313 int const c = user_defined_bullet(i).getCharacter();
1319 features.require("latexsym");
1321 } else if (font == 1) {
1322 features.require("amssymb");
1323 } else if (font >= 2 && font <= 5) {
1324 features.require("pifont");
1328 if (pdfoptions().use_hyperref) {
1329 features.require("hyperref");
1330 // due to interferences with babel and hyperref, the color package has to
1331 // be loaded after hyperref when hyperref is used with the colorlinks
1332 // option, see http://www.lyx.org/trac/ticket/5291
1333 if (pdfoptions().colorlinks)
1334 features.require("color");
1336 if (!listings_params.empty()) {
1337 // do not test validity because listings_params is
1338 // supposed to be valid
1340 InsetListingsParams(listings_params).separatedParams(true);
1341 // we can't support all packages, but we should load the color package
1342 if (par.find("\\color", 0) != string::npos)
1343 features.require("color");
1346 // some languages are only available via polyglossia
1347 if (features.runparams().flavor == OutputParams::XETEX
1348 && (features.hasPolyglossiaExclusiveLanguages()
1350 features.require("polyglossia");
1352 if (useNonTeXFonts && fonts_math != "auto")
1353 features.require("unicode-math");
1355 if (!language->requires().empty())
1356 features.require(language->requires());
1360 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1361 FileName const & filepath) const
1363 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1364 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1365 // \RequirePackage to do so, rather than the normal \usepackage
1366 // Do not try to load any other package before the document class, unless you
1367 // have a thorough understanding of the LATEX internals and know exactly what you
1369 if (features.mustProvide("fix-cm"))
1370 os << "\\RequirePackage{fix-cm}\n";
1371 // Likewise for fixltx2e. If other packages conflict with this policy,
1372 // treat it as a package bug (and report it!)
1373 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1374 if (features.mustProvide("fixltx2e"))
1375 os << "\\RequirePackage{fixltx2e}\n";
1377 os << "\\documentclass";
1379 DocumentClass const & tclass = documentClass();
1381 ostringstream clsoptions; // the document class options.
1383 if (tokenPos(tclass.opt_fontsize(),
1384 '|', fontsize) >= 0) {
1385 // only write if existing in list (and not default)
1386 clsoptions << fontsize << "pt,";
1389 // all paper sizes except of A4, A5, B5 and the US sizes need the
1391 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1392 && papersize != PAPER_USLETTER
1393 && papersize != PAPER_USLEGAL
1394 && papersize != PAPER_USEXECUTIVE
1395 && papersize != PAPER_A4
1396 && papersize != PAPER_A5
1397 && papersize != PAPER_B5;
1399 if (!use_geometry) {
1400 switch (papersize) {
1402 clsoptions << "a4paper,";
1404 case PAPER_USLETTER:
1405 clsoptions << "letterpaper,";
1408 clsoptions << "a5paper,";
1411 clsoptions << "b5paper,";
1413 case PAPER_USEXECUTIVE:
1414 clsoptions << "executivepaper,";
1417 clsoptions << "legalpaper,";
1451 if (sides != tclass.sides()) {
1454 clsoptions << "oneside,";
1457 clsoptions << "twoside,";
1463 if (columns != tclass.columns()) {
1465 clsoptions << "twocolumn,";
1467 clsoptions << "onecolumn,";
1471 && orientation == ORIENTATION_LANDSCAPE)
1472 clsoptions << "landscape,";
1474 // language should be a parameter to \documentclass
1475 if (language->babel() == "hebrew"
1476 && default_language->babel() != "hebrew")
1477 // This seems necessary
1478 features.useLanguage(default_language);
1480 ostringstream language_options;
1481 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1482 bool const use_polyglossia = features.usePolyglossia();
1483 bool const global = lyxrc.language_global_options;
1484 if (use_babel || (use_polyglossia && global)) {
1485 language_options << features.getBabelLanguages();
1486 if (!language->babel().empty()) {
1487 if (!language_options.str().empty())
1488 language_options << ',';
1489 language_options << language->babel();
1491 if (global && !features.needBabelLangOptions()
1492 && !language_options.str().empty())
1493 clsoptions << language_options.str() << ',';
1496 // the predefined options from the layout
1497 if (use_default_options && !tclass.options().empty())
1498 clsoptions << tclass.options() << ',';
1500 // the user-defined options
1501 if (!options.empty()) {
1502 clsoptions << options << ',';
1505 string strOptions(clsoptions.str());
1506 if (!strOptions.empty()) {
1507 strOptions = rtrim(strOptions, ",");
1509 os << '[' << from_utf8(strOptions) << ']';
1512 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1513 // end of \documentclass defs
1515 // if we use fontspec or newtxmath, we have to load the AMS packages here
1516 string const ams = features.loadAMSPackages();
1517 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1518 bool const use_newtxmath =
1519 theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getUsedPackage(
1520 ot1, false, false) == "newtxmath";
1521 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1522 os << from_ascii(ams);
1524 if (useNonTeXFonts) {
1525 os << "\\usepackage{fontspec}\n";
1526 if (features.mustProvide("unicode-math")
1527 && features.isAvailable("unicode-math"))
1528 os << "\\usepackage{unicode-math}\n";
1531 // font selection must be done before loading fontenc.sty
1532 string const fonts = loadFonts(features);
1534 os << from_utf8(fonts);
1536 if (fonts_default_family != "default")
1537 os << "\\renewcommand{\\familydefault}{\\"
1538 << from_ascii(fonts_default_family) << "}\n";
1540 // set font encoding
1541 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1542 if (!useNonTeXFonts && !features.isProvided("fontenc")
1543 && font_encoding() != "default") {
1544 // get main font encodings
1545 vector<string> fontencs = font_encodings();
1546 // get font encodings of secondary languages
1547 features.getFontEncodings(fontencs);
1548 if (!fontencs.empty()) {
1549 os << "\\usepackage["
1550 << from_ascii(getStringFromVector(fontencs))
1555 // handle inputenc etc.
1556 writeEncodingPreamble(os, features);
1559 if (!features.runparams().includeall && !included_children_.empty()) {
1560 os << "\\includeonly{";
1561 list<string>::const_iterator it = included_children_.begin();
1562 list<string>::const_iterator en = included_children_.end();
1564 for (; it != en; ++it) {
1565 string incfile = *it;
1566 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1567 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1569 if (!features.runparams().nice)
1571 // \includeonly doesn't want an extension
1572 incfile = changeExtension(incfile, string());
1573 incfile = support::latex_path(incfile);
1574 if (!incfile.empty()) {
1577 os << from_utf8(incfile);
1584 if (!features.isProvided("geometry")
1585 && (use_geometry || nonstandard_papersize)) {
1586 odocstringstream ods;
1587 if (!getGraphicsDriver("geometry").empty())
1588 ods << getGraphicsDriver("geometry");
1589 if (orientation == ORIENTATION_LANDSCAPE)
1590 ods << ",landscape";
1591 switch (papersize) {
1593 if (!paperwidth.empty())
1594 ods << ",paperwidth="
1595 << from_ascii(paperwidth);
1596 if (!paperheight.empty())
1597 ods << ",paperheight="
1598 << from_ascii(paperheight);
1600 case PAPER_USLETTER:
1601 ods << ",letterpaper";
1604 ods << ",legalpaper";
1606 case PAPER_USEXECUTIVE:
1607 ods << ",executivepaper";
1696 docstring const g_options = trim(ods.str(), ",");
1697 os << "\\usepackage";
1698 if (!g_options.empty())
1699 os << '[' << g_options << ']';
1700 os << "{geometry}\n";
1701 // output this only if use_geometry is true
1703 os << "\\geometry{verbose";
1704 if (!topmargin.empty())
1705 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1706 if (!bottommargin.empty())
1707 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1708 if (!leftmargin.empty())
1709 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1710 if (!rightmargin.empty())
1711 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1712 if (!headheight.empty())
1713 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1714 if (!headsep.empty())
1715 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1716 if (!footskip.empty())
1717 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1718 if (!columnsep.empty())
1719 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1722 } else if (orientation == ORIENTATION_LANDSCAPE
1723 || papersize != PAPER_DEFAULT) {
1724 features.require("papersize");
1727 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1728 if (pagestyle == "fancy")
1729 os << "\\usepackage{fancyhdr}\n";
1730 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1733 // only output when the background color is not default
1734 if (isbackgroundcolor == true) {
1735 // only require color here, the background color will be defined
1736 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1738 features.require("color");
1739 features.require("pagecolor");
1742 // only output when the font color is not default
1743 if (isfontcolor == true) {
1744 // only require color here, the font color will be defined
1745 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1747 features.require("color");
1748 features.require("fontcolor");
1751 // Only if class has a ToC hierarchy
1752 if (tclass.hasTocLevels()) {
1753 if (secnumdepth != tclass.secnumdepth()) {
1754 os << "\\setcounter{secnumdepth}{"
1758 if (tocdepth != tclass.tocdepth()) {
1759 os << "\\setcounter{tocdepth}{"
1765 if (paragraph_separation) {
1766 // when skip separation
1767 switch (getDefSkip().kind()) {
1768 case VSpace::SMALLSKIP:
1769 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1771 case VSpace::MEDSKIP:
1772 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1774 case VSpace::BIGSKIP:
1775 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1777 case VSpace::LENGTH:
1778 os << "\\setlength{\\parskip}{"
1779 << from_utf8(getDefSkip().length().asLatexString())
1782 default: // should never happen // Then delete it.
1783 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1786 os << "\\setlength{\\parindent}{0pt}\n";
1788 // when separation by indentation
1789 // only output something when a width is given
1790 if (getIndentation().asLyXCommand() != "default") {
1791 os << "\\setlength{\\parindent}{"
1792 << from_utf8(getIndentation().asLatexCommand())
1797 // Now insert the LyX specific LaTeX commands...
1798 docstring lyxpreamble;
1799 features.resolveAlternatives();
1802 if (!output_sync_macro.empty())
1803 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1804 else if (features.runparams().flavor == OutputParams::LATEX)
1805 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1806 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1807 lyxpreamble += "\\synctex=-1\n";
1810 // The package options (via \PassOptionsToPackage)
1811 lyxpreamble += from_ascii(features.getPackageOptions());
1813 // due to interferences with babel and hyperref, the color package has to
1814 // be loaded (when it is not already loaded) before babel when hyperref
1815 // is used with the colorlinks option, see
1816 // http://www.lyx.org/trac/ticket/5291
1817 // we decided therefore to load color always before babel, see
1818 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1819 lyxpreamble += from_ascii(features.getColorOptions());
1821 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1822 // we have to call babel before
1824 && (features.isRequired("jurabib")
1825 || features.isRequired("hyperref")
1826 || features.isRequired("varioref")
1827 || features.isRequired("vietnamese")
1828 || features.isRequired("japanese"))) {
1830 lyxpreamble += from_utf8(features.getBabelPresettings());
1831 lyxpreamble += from_utf8(babelCall(language_options.str(),
1832 features.needBabelLangOptions())) + '\n';
1833 lyxpreamble += from_utf8(features.getBabelPostsettings());
1836 // The optional packages;
1837 lyxpreamble += from_ascii(features.getPackages());
1839 // Additional Indices
1840 if (features.isRequired("splitidx")) {
1841 IndicesList::const_iterator iit = indiceslist().begin();
1842 IndicesList::const_iterator iend = indiceslist().end();
1843 for (; iit != iend; ++iit) {
1844 pair<docstring, docstring> indexname_latex =
1845 features.runparams().encoding->latexString(iit->index(),
1846 features.runparams().dryrun);
1847 if (!indexname_latex.second.empty()) {
1848 // issue a warning about omitted characters
1849 // FIXME: should be passed to the error dialog
1850 frontend::Alert::warning(_("Uncodable characters"),
1851 bformat(_("The following characters that are used in an index name are not\n"
1852 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1853 indexname_latex.second));
1855 lyxpreamble += "\\newindex[";
1856 lyxpreamble += indexname_latex.first;
1857 lyxpreamble += "]{";
1858 lyxpreamble += escape(iit->shortcut());
1859 lyxpreamble += "}\n";
1864 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1867 // * Hyperref manual: "Make sure it comes last of your loaded
1868 // packages, to give it a fighting chance of not being over-written,
1869 // since its job is to redefine many LaTeX commands."
1870 // * Email from Heiko Oberdiek: "It is usually better to load babel
1871 // before hyperref. Then hyperref has a chance to detect babel.
1872 // * Has to be loaded before the "LyX specific LaTeX commands" to
1873 // avoid errors with algorithm floats.
1874 // use hyperref explicitly if it is required
1875 if (features.isRequired("hyperref")) {
1876 // pass what we have to stream here, since we need
1877 // to access the stream itself in PDFOptions.
1880 OutputParams tmp_params = features.runparams();
1881 pdfoptions().writeLaTeX(tmp_params, os,
1882 features.isProvided("hyperref"));
1883 // set back for the rest
1884 lyxpreamble.clear();
1885 // correctly break URLs with hyperref and dvi output
1886 if (features.runparams().flavor == OutputParams::LATEX
1887 && features.isAvailable("breakurl"))
1888 lyxpreamble += "\\usepackage{breakurl}\n";
1889 } else if (features.isRequired("nameref"))
1890 // hyperref loads this automatically
1891 lyxpreamble += "\\usepackage{nameref}\n";
1893 // bibtopic needs to be loaded after hyperref.
1894 // the dot provides the aux file naming which LyX can detect.
1895 if (features.mustProvide("bibtopic"))
1896 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1898 // Will be surrounded by \makeatletter and \makeatother when not empty
1899 docstring atlyxpreamble;
1901 // Some macros LyX will need
1902 docstring tmppreamble(features.getMacros());
1904 if (!tmppreamble.empty())
1905 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1906 "LyX specific LaTeX commands.\n"
1907 + tmppreamble + '\n';
1909 // the text class specific preamble
1910 tmppreamble = features.getTClassPreamble();
1911 if (!tmppreamble.empty())
1912 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1913 "Textclass specific LaTeX commands.\n"
1914 + tmppreamble + '\n';
1916 // suppress date if selected
1917 // use \@ifundefined because we cannot be sure that every document class
1918 // has a \date command
1920 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1922 /* the user-defined preamble */
1923 if (!containsOnly(preamble, " \n\t"))
1925 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1926 "User specified LaTeX commands.\n"
1927 + from_utf8(preamble) + '\n';
1929 // footmisc must be loaded after setspace
1930 // Load it here to avoid clashes with footmisc loaded in the user
1931 // preamble. For that reason we also pass the options via
1932 // \PassOptionsToPackage in getPreamble() and not here.
1933 if (features.mustProvide("footmisc"))
1934 atlyxpreamble += "\\usepackage{footmisc}\n";
1936 // subfig loads internally the LaTeX package "caption". As
1937 // caption is a very popular package, users will load it in
1938 // the preamble. Therefore we must load subfig behind the
1939 // user-defined preamble and check if the caption package was
1940 // loaded or not. For the case that caption is loaded before
1941 // subfig, there is the subfig option "caption=false". This
1942 // option also works when a koma-script class is used and
1943 // koma's own caption commands are used instead of caption. We
1944 // use \PassOptionsToPackage here because the user could have
1945 // already loaded subfig in the preamble.
1946 if (features.isRequired("subfig")) {
1947 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1948 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1949 "\\usepackage{subfig}\n";
1952 // Itemize bullet settings need to be last in case the user
1953 // defines their own bullets that use a package included
1954 // in the user-defined preamble -- ARRae
1955 // Actually it has to be done much later than that
1956 // since some packages like frenchb make modifications
1957 // at \begin{document} time -- JMarc
1958 docstring bullets_def;
1959 for (int i = 0; i < 4; ++i) {
1960 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1961 if (bullets_def.empty())
1962 bullets_def += "\\AtBeginDocument{\n";
1963 bullets_def += " \\def\\labelitemi";
1965 // `i' is one less than the item to modify
1972 bullets_def += "ii";
1978 bullets_def += '{' +
1979 user_defined_bullet(i).getText()
1984 if (!bullets_def.empty())
1985 atlyxpreamble += bullets_def + "}\n\n";
1987 if (!atlyxpreamble.empty())
1988 lyxpreamble += "\n\\makeatletter\n"
1989 + atlyxpreamble + "\\makeatother\n\n";
1991 // We try to load babel late, in case it interferes with other packages.
1992 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
1993 // called after babel, though.
1994 if (use_babel && !features.isRequired("jurabib")
1995 && !features.isRequired("hyperref")
1996 && !features.isRequired("varioref")
1997 && !features.isRequired("vietnamese")
1998 && !features.isRequired("japanese")) {
2000 lyxpreamble += from_utf8(features.getBabelPresettings());
2001 lyxpreamble += from_utf8(babelCall(language_options.str(),
2002 features.needBabelLangOptions())) + '\n';
2003 lyxpreamble += from_utf8(features.getBabelPostsettings());
2005 if (features.isRequired("bicaption"))
2006 lyxpreamble += "\\usepackage{bicaption}\n";
2007 if (!listings_params.empty() || features.isRequired("listings"))
2008 lyxpreamble += "\\usepackage{listings}\n";
2009 if (!listings_params.empty()) {
2010 lyxpreamble += "\\lstset{";
2011 // do not test validity because listings_params is
2012 // supposed to be valid
2014 InsetListingsParams(listings_params).separatedParams(true);
2015 lyxpreamble += from_utf8(par);
2016 lyxpreamble += "}\n";
2019 // xunicode needs to be loaded at least after amsmath, amssymb,
2020 // esint and the other packages that provide special glyphs
2021 if (features.runparams().flavor == OutputParams::XETEX
2023 lyxpreamble += "\\usepackage{xunicode}\n";
2025 // Polyglossia must be loaded last
2026 if (use_polyglossia) {
2028 lyxpreamble += "\\usepackage{polyglossia}\n";
2029 // set the main language
2030 lyxpreamble += "\\setdefaultlanguage";
2031 if (!language->polyglossiaOpts().empty())
2032 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
2033 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
2034 // now setup the other languages
2035 std::map<std::string, std::string> const polylangs =
2036 features.getPolyglossiaLanguages();
2037 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
2038 mit != polylangs.end() ; ++mit) {
2039 lyxpreamble += "\\setotherlanguage";
2040 if (!mit->second.empty())
2041 lyxpreamble += "[" + from_ascii(mit->second) + "]";
2042 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
2046 // Load custom language package here
2047 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2048 if (lang_package == "default")
2049 lyxpreamble += from_utf8(lyxrc.language_custom_package);
2051 lyxpreamble += from_utf8(lang_package);
2052 lyxpreamble += '\n';
2055 docstring const i18npreamble =
2056 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2057 if (!i18npreamble.empty())
2058 lyxpreamble += i18npreamble + '\n';
2066 void BufferParams::useClassDefaults()
2068 DocumentClass const & tclass = documentClass();
2070 sides = tclass.sides();
2071 columns = tclass.columns();
2072 pagestyle = tclass.pagestyle();
2073 use_default_options = true;
2074 // Only if class has a ToC hierarchy
2075 if (tclass.hasTocLevels()) {
2076 secnumdepth = tclass.secnumdepth();
2077 tocdepth = tclass.tocdepth();
2082 bool BufferParams::hasClassDefaults() const
2084 DocumentClass const & tclass = documentClass();
2086 return sides == tclass.sides()
2087 && columns == tclass.columns()
2088 && pagestyle == tclass.pagestyle()
2089 && use_default_options
2090 && secnumdepth == tclass.secnumdepth()
2091 && tocdepth == tclass.tocdepth();
2095 DocumentClass const & BufferParams::documentClass() const
2097 return *doc_class_.get();
2101 DocumentClassConstPtr BufferParams::documentClassPtr() const
2107 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2109 // evil, but this function is evil
2110 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2114 bool BufferParams::setBaseClass(string const & classname)
2116 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2117 LayoutFileList & bcl = LayoutFileList::get();
2118 if (!bcl.haveClass(classname)) {
2120 bformat(_("The layout file:\n"
2122 "could not be found. 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(_("Document class not found"), s);
2127 bcl.addEmptyClass(classname);
2130 bool const success = bcl[classname].load();
2133 bformat(_("Due to some error in it, the layout file:\n"
2135 "could not be loaded. A default textclass with default\n"
2136 "layouts will be used. LyX will not be able to produce\n"
2138 from_utf8(classname));
2139 frontend::Alert::error(_("Could not load class"), s);
2140 bcl.addEmptyClass(classname);
2143 pimpl_->baseClass_ = classname;
2144 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2149 LayoutFile const * BufferParams::baseClass() const
2151 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2152 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2158 LayoutFileIndex const & BufferParams::baseClassID() const
2160 return pimpl_->baseClass_;
2164 void BufferParams::makeDocumentClass(bool const clone)
2169 LayoutModuleList mods;
2170 LayoutModuleList::iterator it = layout_modules_.begin();
2171 LayoutModuleList::iterator en = layout_modules_.end();
2172 for (; it != en; ++it)
2173 mods.push_back(*it);
2175 it = cite_engine_.begin();
2176 en = cite_engine_.end();
2177 for (; it != en; ++it)
2178 mods.push_back(*it);
2180 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2182 TextClass::ReturnValues success = TextClass::OK;
2183 if (!forced_local_layout_.empty())
2184 success = doc_class_->read(forced_local_layout_, TextClass::MODULE);
2185 if (!local_layout_.empty() &&
2186 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2187 success = doc_class_->read(local_layout_, TextClass::MODULE);
2188 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2189 docstring const msg = _("Error reading internal layout information");
2190 frontend::Alert::warning(_("Read Error"), msg);
2195 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2197 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2201 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2203 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2207 std::string BufferParams::getLocalLayout(bool forced) const
2210 return doc_class_->forcedLayouts();
2212 return local_layout_;
2216 void BufferParams::setLocalLayout(string const & layout, bool forced)
2219 forced_local_layout_ = layout;
2221 local_layout_ = layout;
2225 bool BufferParams::addLayoutModule(string const & modName)
2227 LayoutModuleList::const_iterator it = layout_modules_.begin();
2228 LayoutModuleList::const_iterator end = layout_modules_.end();
2229 for (; it != end; ++it)
2232 layout_modules_.push_back(modName);
2237 string BufferParams::bufferFormat() const
2239 string format = documentClass().outputFormat();
2240 if (format == "latex") {
2243 if (encoding().package() == Encoding::japanese)
2250 bool BufferParams::isExportable(string const & format) const
2252 vector<string> backs = backends();
2253 for (vector<string>::const_iterator it = backs.begin();
2254 it != backs.end(); ++it)
2255 if (theConverters().isReachable(*it, format))
2261 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2263 vector<string> const backs = backends();
2264 set<string> excludes;
2265 if (useNonTeXFonts) {
2266 excludes.insert("latex");
2267 excludes.insert("pdflatex");
2269 vector<Format const *> result =
2270 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2271 for (vector<string>::const_iterator it = backs.begin() + 1;
2272 it != backs.end(); ++it) {
2273 vector<Format const *> r =
2274 theConverters().getReachable(*it, only_viewable, false, excludes);
2275 result.insert(result.end(), r.begin(), r.end());
2281 bool BufferParams::isExportableFormat(string const & format) const
2283 typedef vector<Format const *> Formats;
2285 formats = exportableFormats(true);
2286 Formats::const_iterator fit = formats.begin();
2287 Formats::const_iterator end = formats.end();
2288 for (; fit != end ; ++fit) {
2289 if ((*fit)->name() == format)
2296 vector<string> BufferParams::backends() const
2299 string const buffmt = bufferFormat();
2301 // FIXME: Don't hardcode format names here, but use a flag
2302 if (buffmt == "latex") {
2303 if (!useNonTeXFonts) {
2304 v.push_back("pdflatex");
2305 v.push_back("latex");
2307 v.push_back("luatex");
2308 v.push_back("dviluatex");
2309 v.push_back("xetex");
2310 } else if (buffmt == "xetex") {
2311 v.push_back("xetex");
2312 // FIXME: need to test all languages (bug 8205)
2313 if (!language || !language->isPolyglossiaExclusive()) {
2314 v.push_back("luatex");
2315 v.push_back("dviluatex");
2318 v.push_back(buffmt);
2320 v.push_back("xhtml");
2321 v.push_back("text");
2327 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2329 string const dformat = (format.empty() || format == "default") ?
2330 getDefaultOutputFormat() : format;
2331 DefaultFlavorCache::const_iterator it =
2332 default_flavors_.find(dformat);
2334 if (it != default_flavors_.end())
2337 OutputParams::FLAVOR result = OutputParams::LATEX;
2339 // FIXME It'd be better not to hardcode this, but to do
2340 // something with formats.
2341 if (dformat == "xhtml")
2342 result = OutputParams::HTML;
2343 else if (dformat == "text")
2344 result = OutputParams::TEXT;
2345 else if (dformat == "lyx")
2346 result = OutputParams::LYX;
2347 else if (dformat == "pdflatex")
2348 result = OutputParams::PDFLATEX;
2349 else if (dformat == "xetex")
2350 result = OutputParams::XETEX;
2351 else if (dformat == "luatex")
2352 result = OutputParams::LUATEX;
2353 else if (dformat == "dviluatex")
2354 result = OutputParams::DVILUATEX;
2356 // Try to determine flavor of default output format
2357 vector<string> backs = backends();
2358 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2359 // Get shortest path to format
2360 Graph::EdgePath path;
2361 for (vector<string>::const_iterator it = backs.begin();
2362 it != backs.end(); ++it) {
2363 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2364 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2369 result = theConverters().getFlavor(path);
2372 // cache this flavor
2373 default_flavors_[dformat] = result;
2378 string BufferParams::getDefaultOutputFormat() const
2380 if (!default_output_format.empty()
2381 && default_output_format != "default")
2382 return default_output_format;
2384 || encoding().package() == Encoding::japanese) {
2385 vector<Format const *> const formats = exportableFormats(true);
2386 if (formats.empty())
2388 // return the first we find
2389 return formats.front()->name();
2392 return lyxrc.default_otf_view_format;
2393 return lyxrc.default_view_format;
2396 Font const BufferParams::getFont() const
2398 FontInfo f = documentClass().defaultfont();
2399 if (fonts_default_family == "rmdefault")
2400 f.setFamily(ROMAN_FAMILY);
2401 else if (fonts_default_family == "sfdefault")
2402 f.setFamily(SANS_FAMILY);
2403 else if (fonts_default_family == "ttdefault")
2404 f.setFamily(TYPEWRITER_FAMILY);
2405 return Font(f, language);
2409 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const & qs) const
2411 return quoteslangtranslator().find(qs);
2415 bool BufferParams::isLatex() const
2417 return documentClass().outputType() == LATEX;
2421 bool BufferParams::isLiterate() const
2423 return documentClass().outputType() == LITERATE;
2427 bool BufferParams::isDocBook() const
2429 return documentClass().outputType() == DOCBOOK;
2433 void BufferParams::readPreamble(Lexer & lex)
2435 if (lex.getString() != "\\begin_preamble")
2436 lyxerr << "Error (BufferParams::readPreamble):"
2437 "consistency check failed." << endl;
2439 preamble = lex.getLongString("\\end_preamble");
2443 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2445 string const expected = forced ? "\\begin_forced_local_layout" :
2446 "\\begin_local_layout";
2447 if (lex.getString() != expected)
2448 lyxerr << "Error (BufferParams::readLocalLayout):"
2449 "consistency check failed." << endl;
2452 forced_local_layout_ =
2453 lex.getLongString("\\end_forced_local_layout");
2455 local_layout_ = lex.getLongString("\\end_local_layout");
2459 bool BufferParams::setLanguage(string const & lang)
2461 Language const *new_language = languages.getLanguage(lang);
2462 if (!new_language) {
2463 // Language lang was not found
2466 language = new_language;
2471 void BufferParams::readLanguage(Lexer & lex)
2473 if (!lex.next()) return;
2475 string const tmptok = lex.getString();
2477 // check if tmptok is part of tex_babel in tex-defs.h
2478 if (!setLanguage(tmptok)) {
2479 // Language tmptok was not found
2480 language = default_language;
2481 lyxerr << "Warning: Setting language `"
2482 << tmptok << "' to `" << language->lang()
2488 void BufferParams::readGraphicsDriver(Lexer & lex)
2493 string const tmptok = lex.getString();
2494 // check if tmptok is part of tex_graphics in tex_defs.h
2497 string const test = tex_graphics[n++];
2499 if (test == tmptok) {
2500 graphics_driver = tmptok;
2505 "Warning: graphics driver `$$Token' not recognized!\n"
2506 " Setting graphics driver to `default'.\n");
2507 graphics_driver = "default";
2514 void BufferParams::readBullets(Lexer & lex)
2519 int const index = lex.getInteger();
2521 int temp_int = lex.getInteger();
2522 user_defined_bullet(index).setFont(temp_int);
2523 temp_bullet(index).setFont(temp_int);
2525 user_defined_bullet(index).setCharacter(temp_int);
2526 temp_bullet(index).setCharacter(temp_int);
2528 user_defined_bullet(index).setSize(temp_int);
2529 temp_bullet(index).setSize(temp_int);
2533 void BufferParams::readBulletsLaTeX(Lexer & lex)
2535 // The bullet class should be able to read this.
2538 int const index = lex.getInteger();
2540 docstring const temp_str = lex.getDocString();
2542 user_defined_bullet(index).setText(temp_str);
2543 temp_bullet(index).setText(temp_str);
2547 void BufferParams::readModules(Lexer & lex)
2549 if (!lex.eatLine()) {
2550 lyxerr << "Error (BufferParams::readModules):"
2551 "Unexpected end of input." << endl;
2555 string mod = lex.getString();
2556 if (mod == "\\end_modules")
2558 addLayoutModule(mod);
2564 void BufferParams::readRemovedModules(Lexer & lex)
2566 if (!lex.eatLine()) {
2567 lyxerr << "Error (BufferParams::readRemovedModules):"
2568 "Unexpected end of input." << endl;
2572 string mod = lex.getString();
2573 if (mod == "\\end_removed_modules")
2575 removed_modules_.push_back(mod);
2578 // now we want to remove any removed modules that were previously
2579 // added. normally, that will be because default modules were added in
2580 // setBaseClass(), which gets called when \textclass is read at the
2581 // start of the read.
2582 list<string>::const_iterator rit = removed_modules_.begin();
2583 list<string>::const_iterator const ren = removed_modules_.end();
2584 for (; rit != ren; ++rit) {
2585 LayoutModuleList::iterator const mit = layout_modules_.begin();
2586 LayoutModuleList::iterator const men = layout_modules_.end();
2587 LayoutModuleList::iterator found = find(mit, men, *rit);
2590 layout_modules_.erase(found);
2595 void BufferParams::readIncludeonly(Lexer & lex)
2597 if (!lex.eatLine()) {
2598 lyxerr << "Error (BufferParams::readIncludeonly):"
2599 "Unexpected end of input." << endl;
2603 string child = lex.getString();
2604 if (child == "\\end_includeonly")
2606 included_children_.push_back(child);
2612 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2614 switch (papersize) {
2616 // could be anything, so don't guess
2618 case PAPER_CUSTOM: {
2619 if (purpose == XDVI && !paperwidth.empty() &&
2620 !paperheight.empty()) {
2621 // heightxwidth<unit>
2622 string first = paperwidth;
2623 string second = paperheight;
2624 if (orientation == ORIENTATION_LANDSCAPE)
2627 return first.erase(first.length() - 2)
2633 // dvips and dvipdfm do not know this
2634 if (purpose == DVIPS || purpose == DVIPDFM)
2638 if (purpose == DVIPS || purpose == DVIPDFM)
2642 if (purpose == DVIPS || purpose == DVIPDFM)
2652 if (purpose == DVIPS || purpose == DVIPDFM)
2656 if (purpose == DVIPS || purpose == DVIPDFM)
2660 if (purpose == DVIPS || purpose == DVIPDFM)
2664 if (purpose == DVIPS || purpose == DVIPDFM)
2668 if (purpose == DVIPS || purpose == DVIPDFM)
2672 // dvipdfm does not know this
2673 if (purpose == DVIPDFM)
2677 if (purpose == DVIPDFM)
2681 if (purpose == DVIPS || purpose == DVIPDFM)
2685 if (purpose == DVIPS || purpose == DVIPDFM)
2689 if (purpose == DVIPS || purpose == DVIPDFM)
2693 if (purpose == DVIPS || purpose == DVIPDFM)
2697 if (purpose == DVIPS || purpose == DVIPDFM)
2701 if (purpose == DVIPS || purpose == DVIPDFM)
2705 if (purpose == DVIPS || purpose == DVIPDFM)
2709 if (purpose == DVIPS || purpose == DVIPDFM)
2713 if (purpose == DVIPS || purpose == DVIPDFM)
2717 if (purpose == DVIPS || purpose == DVIPDFM)
2721 if (purpose == DVIPS || purpose == DVIPDFM)
2725 if (purpose == DVIPS || purpose == DVIPDFM)
2729 if (purpose == DVIPS || purpose == DVIPDFM)
2733 if (purpose == DVIPS || purpose == DVIPDFM)
2737 if (purpose == DVIPS || purpose == DVIPDFM)
2740 case PAPER_USEXECUTIVE:
2741 // dvipdfm does not know this
2742 if (purpose == DVIPDFM)
2747 case PAPER_USLETTER:
2749 if (purpose == XDVI)
2756 string const BufferParams::dvips_options() const
2760 // If the class loads the geometry package, we do not know which
2761 // paper size is used, since we do not set it (bug 7013).
2762 // Therefore we must not specify any argument here.
2763 // dvips gets the correct paper size via DVI specials in this case
2764 // (if the class uses the geometry package correctly).
2765 if (documentClass().provides("geometry"))
2769 && papersize == PAPER_CUSTOM
2770 && !lyxrc.print_paper_dimension_flag.empty()
2771 && !paperwidth.empty()
2772 && !paperheight.empty()) {
2773 // using a custom papersize
2774 result = lyxrc.print_paper_dimension_flag;
2775 result += ' ' + paperwidth;
2776 result += ',' + paperheight;
2778 string const paper_option = paperSizeName(DVIPS);
2779 if (!paper_option.empty() && (paper_option != "letter" ||
2780 orientation != ORIENTATION_LANDSCAPE)) {
2781 // dvips won't accept -t letter -t landscape.
2782 // In all other cases, include the paper size
2784 result = lyxrc.print_paper_flag;
2785 result += ' ' + paper_option;
2788 if (orientation == ORIENTATION_LANDSCAPE &&
2789 papersize != PAPER_CUSTOM)
2790 result += ' ' + lyxrc.print_landscape_flag;
2795 string const BufferParams::font_encoding() const
2797 return font_encodings().empty() ? "default" : font_encodings().back();
2801 vector<string> const BufferParams::font_encodings() const
2803 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2805 vector<string> fontencs;
2807 // "default" means "no explicit font encoding"
2808 if (doc_fontenc != "default") {
2809 fontencs = getVectorFromString(doc_fontenc);
2810 if (!language->fontenc().empty()
2811 && ascii_lowercase(language->fontenc()) != "none") {
2812 vector<string> fencs = getVectorFromString(language->fontenc());
2813 vector<string>::const_iterator fit = fencs.begin();
2814 for (; fit != fencs.end(); ++fit) {
2815 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
2816 fontencs.push_back(*fit);
2825 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2827 // suppress the babel call if there is no BabelName defined
2828 // for the document language in the lib/languages file and if no
2829 // other languages are used (lang_opts is then empty)
2830 if (lang_opts.empty())
2832 // either a specific language (AsBabelOptions setting in
2833 // lib/languages) or the prefs require the languages to
2834 // be submitted to babel itself (not the class).
2836 return "\\usepackage[" + lang_opts + "]{babel}";
2837 return "\\usepackage{babel}";
2841 docstring BufferParams::getGraphicsDriver(string const & package) const
2845 if (package == "geometry") {
2846 if (graphics_driver == "dvips"
2847 || graphics_driver == "dvipdfm"
2848 || graphics_driver == "pdftex"
2849 || graphics_driver == "vtex")
2850 result = from_ascii(graphics_driver);
2851 else if (graphics_driver == "dvipdfmx")
2852 result = from_ascii("dvipdfm");
2859 void BufferParams::writeEncodingPreamble(otexstream & os,
2860 LaTeXFeatures & features) const
2862 // XeTeX does not need this
2863 if (features.runparams().flavor == OutputParams::XETEX)
2865 // LuaTeX neither, but with tex fonts, we need to load
2866 // the luainputenc package.
2867 if (features.runparams().flavor == OutputParams::LUATEX
2868 || features.runparams().flavor == OutputParams::DVILUATEX) {
2869 if (!useNonTeXFonts && inputenc != "default"
2870 && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc)
2871 || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) {
2872 os << "\\usepackage[utf8]{luainputenc}\n";
2876 if (inputenc == "auto") {
2877 string const doc_encoding =
2878 language->encoding()->latexName();
2879 Encoding::Package const package =
2880 language->encoding()->package();
2882 // Create a list with all the input encodings used
2884 set<string> encodings =
2885 features.getEncodingSet(doc_encoding);
2887 // If the "japanese" package (i.e. pLaTeX) is used,
2888 // inputenc must be omitted.
2889 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2890 if ((!encodings.empty() || package == Encoding::inputenc)
2891 && !features.isRequired("japanese")
2892 && !features.isProvided("inputenc")) {
2893 os << "\\usepackage[";
2894 set<string>::const_iterator it = encodings.begin();
2895 set<string>::const_iterator const end = encodings.end();
2897 os << from_ascii(*it);
2900 for (; it != end; ++it)
2901 os << ',' << from_ascii(*it);
2902 if (package == Encoding::inputenc) {
2903 if (!encodings.empty())
2905 os << from_ascii(doc_encoding);
2907 os << "]{inputenc}\n";
2909 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2910 if (language->encoding()->name() == "utf8-cjk"
2911 && LaTeXFeatures::isAvailable("CJKutf8"))
2912 os << "\\usepackage{CJKutf8}\n";
2914 os << "\\usepackage{CJK}\n";
2916 } else if (inputenc != "default") {
2917 switch (encoding().package()) {
2918 case Encoding::none:
2919 case Encoding::japanese:
2921 case Encoding::inputenc:
2922 // do not load inputenc if japanese is used
2923 // or if the class provides inputenc
2924 if (features.isRequired("japanese")
2925 || features.isProvided("inputenc"))
2927 os << "\\usepackage[" << from_ascii(encoding().latexName())
2931 if (encoding().name() == "utf8-cjk"
2932 && LaTeXFeatures::isAvailable("CJKutf8"))
2933 os << "\\usepackage{CJKutf8}\n";
2935 os << "\\usepackage{CJK}\n";
2938 // Load the CJK package if needed by a secondary language.
2939 // If the main encoding is some variant of UTF8, use CJKutf8.
2940 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
2941 if (encoding().iconvName() == "UTF-8"
2942 && LaTeXFeatures::isAvailable("CJKutf8"))
2943 os << "\\usepackage{CJKutf8}\n";
2945 os << "\\usepackage{CJK}\n";
2951 string const BufferParams::parseFontName(string const & name) const
2953 string mangled = name;
2954 size_t const idx = mangled.find('[');
2955 if (idx == string::npos || idx == 0)
2958 return mangled.substr(0, idx - 1);
2962 string const BufferParams::loadFonts(LaTeXFeatures & features) const
2964 if (fonts_roman == "default" && fonts_sans == "default"
2965 && fonts_typewriter == "default"
2966 && (fonts_math == "default" || fonts_math == "auto"))
2972 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
2973 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
2974 * Mapping=tex-text option assures TeX ligatures (such as "--")
2975 * are resolved. Note that tt does not use these ligatures.
2977 * -- add more GUI options?
2978 * -- add more fonts (fonts for other scripts)
2979 * -- if there's a way to find out if a font really supports
2980 * OldStyle, enable/disable the widget accordingly.
2982 if (useNonTeXFonts && features.isAvailable("fontspec")) {
2983 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
2984 // However, until v.2 (2010/07/11) fontspec only knew
2985 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
2986 // was introduced for both XeTeX and LuaTeX (LuaTeX
2987 // didn't understand "Mapping=tex-text", while XeTeX
2988 // understood both. With most recent versions, both
2989 // variants are understood by both engines. However,
2990 // we want to provide support for at least TeXLive 2009
2991 // (for XeTeX; LuaTeX is only supported as of v.2)
2992 string const texmapping =
2993 (features.runparams().flavor == OutputParams::XETEX) ?
2994 "Mapping=tex-text" : "Ligatures=TeX";
2995 if (fonts_roman != "default") {
2996 os << "\\setmainfont[" << texmapping;
2997 if (fonts_old_figures)
2998 os << ",Numbers=OldStyle";
2999 os << "]{" << parseFontName(fonts_roman) << "}\n";
3001 if (fonts_sans != "default") {
3002 string const sans = parseFontName(fonts_sans);
3003 if (fonts_sans_scale != 100)
3004 os << "\\setsansfont[Scale="
3005 << float(fonts_sans_scale) / 100
3006 << "," << texmapping << "]{"
3009 os << "\\setsansfont[" << texmapping << "]{"
3012 if (fonts_typewriter != "default") {
3013 string const mono = parseFontName(fonts_typewriter);
3014 if (fonts_typewriter_scale != 100)
3015 os << "\\setmonofont[Scale="
3016 << float(fonts_typewriter_scale) / 100
3020 os << "\\setmonofont{"
3027 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
3028 bool const dryrun = features.runparams().dryrun;
3029 bool const complete = (fonts_sans == "default" && fonts_typewriter == "default");
3030 bool const nomath = (fonts_math == "default");
3033 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_roman)).getLaTeXCode(
3034 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3038 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_sans)).getLaTeXCode(
3039 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3040 nomath, fonts_sans_scale);
3042 // MONOSPACED/TYPEWRITER
3043 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_typewriter)).getLaTeXCode(
3044 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3045 nomath, fonts_typewriter_scale);
3048 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getLaTeXCode(
3049 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3056 Encoding const & BufferParams::encoding() const
3058 // FIXME: actually, we should check for the flavor
3059 // or runparams.isFullyUnicode() here:
3060 // This check will not work with XeTeX/LuaTeX and tex fonts.
3061 // Thus we have to reset the encoding in Buffer::makeLaTeXFile
3062 // (for export) and Buffer::writeLaTeXSource (for preview).
3064 return *(encodings.fromLyXName("utf8-plain"));
3065 if (inputenc == "auto" || inputenc == "default")
3066 return *language->encoding();
3067 Encoding const * const enc = encodings.fromLyXName(inputenc);
3070 LYXERR0("Unknown inputenc value `" << inputenc
3071 << "'. Using `auto' instead.");
3072 return *language->encoding();
3076 bool BufferParams::addCiteEngine(string const & engine)
3078 LayoutModuleList::const_iterator it = cite_engine_.begin();
3079 LayoutModuleList::const_iterator en = cite_engine_.end();
3080 for (; it != en; ++it)
3083 cite_engine_.push_back(engine);
3088 bool BufferParams::addCiteEngine(vector<string> const & engine)
3090 vector<string>::const_iterator it = engine.begin();
3091 vector<string>::const_iterator en = engine.end();
3093 for (; it != en; ++it)
3094 if (!addCiteEngine(*it))
3100 string const & BufferParams::defaultBiblioStyle() const
3102 return documentClass().defaultBiblioStyle();
3106 bool const & BufferParams::fullAuthorList() const
3108 return documentClass().fullAuthorList();
3112 void BufferParams::setCiteEngine(string const & engine)
3115 addCiteEngine(engine);
3119 void BufferParams::setCiteEngine(vector<string> const & engine)
3122 addCiteEngine(engine);
3126 vector<string> BufferParams::citeCommands() const
3128 static CitationStyle const default_style;
3129 vector<string> commands =
3130 documentClass().citeCommands(citeEngineType());
3131 if (commands.empty())
3132 commands.push_back(default_style.cmd);
3137 vector<CitationStyle> BufferParams::citeStyles() const
3139 static CitationStyle const default_style;
3140 vector<CitationStyle> styles =
3141 documentClass().citeStyles(citeEngineType());
3143 styles.push_back(default_style);