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"
23 #include "buffer_funcs.h"
27 #include "Converter.h"
30 #include "IndicesList.h"
32 #include "LaTeXFeatures.h"
33 #include "LaTeXFonts.h"
34 #include "ModuleList.h"
38 #include "OutputParams.h"
42 #include "PDFOptions.h"
44 #include "frontends/alert.h"
46 #include "insets/InsetListingsParams.h"
48 #include "support/convert.h"
49 #include "support/debug.h"
50 #include "support/docstream.h"
51 #include "support/FileName.h"
52 #include "support/filetools.h"
53 #include "support/gettext.h"
54 #include "support/Messages.h"
55 #include "support/Translator.h"
56 #include "support/lstrings.h"
62 using namespace lyx::support;
65 static char const * const string_paragraph_separation[] = {
70 static char const * const string_quotes_language[] = {
71 "english", "swedish", "german", "polish", "french", "danish", ""
75 static char const * const string_papersize[] = {
76 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
77 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
78 "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
79 "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
80 "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
85 static char const * const string_orientation[] = {
86 "portrait", "landscape", ""
90 static char const * const string_footnotekinds[] = {
91 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
95 static char const * const tex_graphics[] = {
96 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
97 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
98 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
99 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
110 // Paragraph separation
111 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
114 ParSepTranslator const init_parseptranslator()
116 ParSepTranslator translator
117 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
118 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
123 ParSepTranslator const & parseptranslator()
125 static ParSepTranslator const translator =
126 init_parseptranslator();
132 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
135 QuotesLangTranslator const init_quoteslangtranslator()
137 QuotesLangTranslator translator
138 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
139 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
140 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
141 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
142 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
143 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
148 QuotesLangTranslator const & quoteslangtranslator()
150 static QuotesLangTranslator const translator =
151 init_quoteslangtranslator();
157 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
160 static PaperSizeTranslator initPaperSizeTranslator()
162 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
163 translator.addPair(string_papersize[1], PAPER_CUSTOM);
164 translator.addPair(string_papersize[2], PAPER_USLETTER);
165 translator.addPair(string_papersize[3], PAPER_USLEGAL);
166 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
167 translator.addPair(string_papersize[5], PAPER_A0);
168 translator.addPair(string_papersize[6], PAPER_A1);
169 translator.addPair(string_papersize[7], PAPER_A2);
170 translator.addPair(string_papersize[8], PAPER_A3);
171 translator.addPair(string_papersize[9], PAPER_A4);
172 translator.addPair(string_papersize[10], PAPER_A5);
173 translator.addPair(string_papersize[11], PAPER_A6);
174 translator.addPair(string_papersize[12], PAPER_B0);
175 translator.addPair(string_papersize[13], PAPER_B1);
176 translator.addPair(string_papersize[14], PAPER_B2);
177 translator.addPair(string_papersize[15], PAPER_B3);
178 translator.addPair(string_papersize[16], PAPER_B4);
179 translator.addPair(string_papersize[17], PAPER_B5);
180 translator.addPair(string_papersize[18], PAPER_B6);
181 translator.addPair(string_papersize[19], PAPER_C0);
182 translator.addPair(string_papersize[20], PAPER_C1);
183 translator.addPair(string_papersize[21], PAPER_C2);
184 translator.addPair(string_papersize[22], PAPER_C3);
185 translator.addPair(string_papersize[23], PAPER_C4);
186 translator.addPair(string_papersize[24], PAPER_C5);
187 translator.addPair(string_papersize[25], PAPER_C6);
188 translator.addPair(string_papersize[26], PAPER_JISB0);
189 translator.addPair(string_papersize[27], PAPER_JISB1);
190 translator.addPair(string_papersize[28], PAPER_JISB2);
191 translator.addPair(string_papersize[29], PAPER_JISB3);
192 translator.addPair(string_papersize[30], PAPER_JISB4);
193 translator.addPair(string_papersize[31], PAPER_JISB5);
194 translator.addPair(string_papersize[32], PAPER_JISB6);
199 PaperSizeTranslator const & papersizetranslator()
201 static PaperSizeTranslator const translator =
202 initPaperSizeTranslator();
208 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
211 PaperOrientationTranslator const init_paperorientationtranslator()
213 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
214 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
219 PaperOrientationTranslator const & paperorientationtranslator()
221 static PaperOrientationTranslator const translator =
222 init_paperorientationtranslator();
228 typedef Translator<int, PageSides> SidesTranslator;
231 SidesTranslator const init_sidestranslator()
233 SidesTranslator translator(1, OneSide);
234 translator.addPair(2, TwoSides);
239 SidesTranslator const & sidestranslator()
241 static SidesTranslator const translator = init_sidestranslator();
247 typedef Translator<int, BufferParams::Package> PackageTranslator;
250 PackageTranslator const init_packagetranslator()
252 PackageTranslator translator(0, BufferParams::package_off);
253 translator.addPair(1, BufferParams::package_auto);
254 translator.addPair(2, BufferParams::package_on);
259 PackageTranslator const & packagetranslator()
261 static PackageTranslator const translator =
262 init_packagetranslator();
268 typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator;
271 CiteEngineTypeTranslator const init_citeenginetypetranslator()
273 CiteEngineTypeTranslator translator("authoryear", ENGINE_TYPE_AUTHORYEAR);
274 translator.addPair("numerical", ENGINE_TYPE_NUMERICAL);
275 translator.addPair("default", ENGINE_TYPE_DEFAULT);
280 CiteEngineTypeTranslator const & citeenginetypetranslator()
282 static CiteEngineTypeTranslator const translator =
283 init_citeenginetypetranslator();
289 typedef Translator<string, Spacing::Space> SpaceTranslator;
292 SpaceTranslator const init_spacetranslator()
294 SpaceTranslator translator("default", Spacing::Default);
295 translator.addPair("single", Spacing::Single);
296 translator.addPair("onehalf", Spacing::Onehalf);
297 translator.addPair("double", Spacing::Double);
298 translator.addPair("other", Spacing::Other);
303 SpaceTranslator const & spacetranslator()
305 static SpaceTranslator const translator = init_spacetranslator();
312 class BufferParams::Impl
317 AuthorList authorlist;
318 BranchList branchlist;
319 Bullet temp_bullets[4];
320 Bullet user_defined_bullets[4];
321 IndicesList indiceslist;
323 /** This is the amount of space used for paragraph_separation "skip",
324 * and for detached paragraphs in "indented" documents.
328 PDFOptions pdfoptions;
329 LayoutFileIndex baseClass_;
333 BufferParams::Impl::Impl()
334 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
336 // set initial author
338 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
343 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
346 return new BufferParams::Impl(*ptr);
350 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
356 BufferParams::BufferParams()
359 setBaseClass(defaultBaseclass());
361 paragraph_separation = ParagraphIndentSeparation;
362 quotes_language = InsetQuotes::EnglishQuotes;
363 fontsize = "default";
366 papersize = PAPER_DEFAULT;
367 orientation = ORIENTATION_PORTRAIT;
368 use_geometry = false;
369 cite_engine_.push_back("basic");
370 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
371 biblio_style = "plain";
372 use_bibtopic = false;
374 trackChanges = false;
375 outputChanges = false;
376 use_default_options = true;
377 maintain_unincluded_children = false;
380 language = default_language;
382 fonts_roman = "default";
383 fonts_sans = "default";
384 fonts_typewriter = "default";
386 fonts_default_family = "default";
387 useNonTeXFonts = false;
388 fonts_expert_sc = false;
389 fonts_old_figures = false;
390 fonts_sans_scale = 100;
391 fonts_typewriter_scale = 100;
393 lang_package = "default";
394 graphics_driver = "default";
395 default_output_format = "default";
396 bibtex_command = "default";
397 index_command = "default";
400 listings_params = string();
401 pagestyle = "default";
402 suppress_date = false;
403 justification = true;
404 // no color is the default (white)
405 backgroundcolor = lyx::rgbFromHexName("#ffffff");
406 isbackgroundcolor = false;
407 // no color is the default (black)
408 fontcolor = lyx::rgbFromHexName("#000000");
410 // light gray is the default font color for greyed-out notes
411 notefontcolor = lyx::rgbFromHexName("#cccccc");
412 boxbgcolor = lyx::rgbFromHexName("#ff0000");
413 compressed = lyxrc.save_compressed;
414 for (int iter = 0; iter < 4; ++iter) {
415 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
416 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
419 indiceslist().addDefault(B_("Index"));
420 html_be_strict = false;
421 html_math_output = MathML;
422 html_math_img_scale = 1.0;
423 html_css_as_file = false;
430 docstring BufferParams::B_(string const & l10n) const
432 LASSERT(language, return from_utf8(l10n));
433 return getMessages(language->code()).get(l10n);
437 BufferParams::Package BufferParams::use_package(std::string const & p) const
439 PackageMap::const_iterator it = use_packages.find(p);
440 if (it == use_packages.end())
446 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
452 map<string, string> const & BufferParams::auto_packages()
455 // It is extremely unlikely that there could be a problem here, but...
456 static map<string, string> packages;
457 if (packages.empty()) {
458 // adding a package here implies a file format change!
459 packages["amsmath"] =
460 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
461 packages["amssymb"] =
462 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
464 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
466 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
467 packages["mathdots"] =
468 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
469 packages["mathtools"] =
470 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
472 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
473 packages["stackrel"] =
474 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
475 packages["stmaryrd"] =
476 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");
477 packages["undertilde"] =
478 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
484 AuthorList & BufferParams::authors()
486 return pimpl_->authorlist;
490 AuthorList const & BufferParams::authors() const
492 return pimpl_->authorlist;
496 BranchList & BufferParams::branchlist()
498 return pimpl_->branchlist;
502 BranchList const & BufferParams::branchlist() const
504 return pimpl_->branchlist;
508 IndicesList & BufferParams::indiceslist()
510 return pimpl_->indiceslist;
514 IndicesList const & BufferParams::indiceslist() const
516 return pimpl_->indiceslist;
520 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
522 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
523 return pimpl_->temp_bullets[index];
527 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
529 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
530 return pimpl_->temp_bullets[index];
534 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
536 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
537 return pimpl_->user_defined_bullets[index];
541 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
543 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
544 return pimpl_->user_defined_bullets[index];
548 Spacing & BufferParams::spacing()
550 return pimpl_->spacing;
554 Spacing const & BufferParams::spacing() const
556 return pimpl_->spacing;
560 PDFOptions & BufferParams::pdfoptions()
562 return pimpl_->pdfoptions;
566 PDFOptions const & BufferParams::pdfoptions() const
568 return pimpl_->pdfoptions;
572 HSpace const & BufferParams::getIndentation() const
574 return pimpl_->indentation;
578 void BufferParams::setIndentation(HSpace const & indent)
580 pimpl_->indentation = indent;
584 VSpace const & BufferParams::getDefSkip() const
586 return pimpl_->defskip;
590 void BufferParams::setDefSkip(VSpace const & vs)
592 // DEFSKIP will cause an infinite loop
593 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
594 pimpl_->defskip = vs;
598 string BufferParams::readToken(Lexer & lex, string const & token,
599 FileName const & filepath)
601 if (token == "\\textclass") {
603 string const classname = lex.getString();
604 // if there exists a local layout file, ignore the system one
605 // NOTE: in this case, the textclass (.cls file) is assumed to
608 LayoutFileList & bcl = LayoutFileList::get();
609 if (!filepath.empty())
610 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
611 // that returns non-empty if a "local" layout file is found.
615 setBaseClass(classname);
616 // We assume that a tex class exists for local or unknown
617 // layouts so this warning, will only be given for system layouts.
618 if (!baseClass()->isTeXClassAvailable()) {
619 docstring const desc =
620 translateIfPossible(from_utf8(baseClass()->description()));
621 docstring const prereqs =
622 from_utf8(baseClass()->prerequisites());
623 docstring const msg =
624 bformat(_("The selected document class\n"
626 "requires external files that are not available.\n"
627 "The document class can still be used, but the\n"
628 "document cannot be compiled until the following\n"
629 "prerequisites are installed:\n"
631 "See section 3.1.2.2 (Class Availability) of the\n"
632 "User's Guide for more information."), desc, prereqs);
633 frontend::Alert::warning(_("Document class not available"),
636 } else if (token == "\\begin_preamble") {
638 } else if (token == "\\begin_local_layout") {
639 readLocalLayout(lex, false);
640 } else if (token == "\\begin_forced_local_layout") {
641 readLocalLayout(lex, true);
642 } else if (token == "\\begin_modules") {
644 } else if (token == "\\begin_removed_modules") {
645 readRemovedModules(lex);
646 } else if (token == "\\begin_includeonly") {
647 readIncludeonly(lex);
648 } else if (token == "\\maintain_unincluded_children") {
649 lex >> maintain_unincluded_children;
650 } else if (token == "\\options") {
652 options = lex.getString();
653 } else if (token == "\\use_default_options") {
654 lex >> use_default_options;
655 } else if (token == "\\master") {
657 master = lex.getString();
658 } else if (token == "\\suppress_date") {
659 lex >> suppress_date;
660 } else if (token == "\\justification") {
661 lex >> justification;
662 } else if (token == "\\language") {
664 } else if (token == "\\language_package") {
666 lang_package = lex.getString();
667 } else if (token == "\\inputencoding") {
669 } else if (token == "\\graphics") {
670 readGraphicsDriver(lex);
671 } else if (token == "\\default_output_format") {
672 lex >> default_output_format;
673 } else if (token == "\\bibtex_command") {
675 bibtex_command = lex.getString();
676 } else if (token == "\\index_command") {
678 index_command = lex.getString();
679 } else if (token == "\\fontencoding") {
681 fontenc = lex.getString();
682 } else if (token == "\\font_roman") {
684 fonts_roman = lex.getString();
685 } else if (token == "\\font_sans") {
687 fonts_sans = lex.getString();
688 } else if (token == "\\font_typewriter") {
690 fonts_typewriter = lex.getString();
691 } else if (token == "\\font_math") {
693 fonts_math = lex.getString();
694 } else if (token == "\\font_default_family") {
695 lex >> fonts_default_family;
696 } else if (token == "\\use_non_tex_fonts") {
697 lex >> useNonTeXFonts;
698 } else if (token == "\\font_sc") {
699 lex >> fonts_expert_sc;
700 } else if (token == "\\font_osf") {
701 lex >> fonts_old_figures;
702 } else if (token == "\\font_sf_scale") {
703 lex >> fonts_sans_scale;
704 } else if (token == "\\font_tt_scale") {
705 lex >> fonts_typewriter_scale;
706 } else if (token == "\\font_cjk") {
708 } else if (token == "\\paragraph_separation") {
711 paragraph_separation = parseptranslator().find(parsep);
712 } else if (token == "\\paragraph_indentation") {
714 string indentation = lex.getString();
715 pimpl_->indentation = HSpace(indentation);
716 } else if (token == "\\defskip") {
718 string const defskip = lex.getString();
719 pimpl_->defskip = VSpace(defskip);
720 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
722 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
723 } else if (token == "\\quotes_language") {
726 quotes_language = quoteslangtranslator().find(quotes_lang);
727 } else if (token == "\\papersize") {
730 papersize = papersizetranslator().find(ppsize);
731 } else if (token == "\\use_geometry") {
733 } else if (token == "\\use_package") {
738 use_package(package, packagetranslator().find(use));
739 } else if (token == "\\cite_engine") {
741 vector<string> engine = getVectorFromString(lex.getString());
742 setCiteEngine(engine);
743 } else if (token == "\\cite_engine_type") {
746 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
747 } else if (token == "\\biblio_style") {
749 biblio_style = lex.getString();
750 } else if (token == "\\use_bibtopic") {
752 } else if (token == "\\use_indices") {
754 } else if (token == "\\tracking_changes") {
756 } else if (token == "\\output_changes") {
757 lex >> outputChanges;
758 } else if (token == "\\branch") {
760 docstring branch = lex.getDocString();
761 branchlist().add(branch);
764 string const tok = lex.getString();
765 if (tok == "\\end_branch")
767 Branch * branch_ptr = branchlist().find(branch);
768 if (tok == "\\selected") {
771 branch_ptr->setSelected(lex.getInteger());
773 if (tok == "\\filename_suffix") {
776 branch_ptr->setFileNameSuffix(lex.getInteger());
778 if (tok == "\\color") {
780 string color = lex.getString();
782 branch_ptr->setColor(color);
783 // Update also the Color table:
785 color = lcolor.getX11Name(Color_background);
787 lcolor.setColor(to_utf8(branch), color);
790 } else if (token == "\\index") {
792 docstring index = lex.getDocString();
794 indiceslist().add(index);
797 string const tok = lex.getString();
798 if (tok == "\\end_index")
800 Index * index_ptr = indiceslist().find(index);
801 if (tok == "\\shortcut") {
803 shortcut = lex.getDocString();
805 index_ptr->setShortcut(shortcut);
807 if (tok == "\\color") {
809 string color = lex.getString();
811 index_ptr->setColor(color);
812 // Update also the Color table:
814 color = lcolor.getX11Name(Color_background);
816 if (!shortcut.empty())
817 lcolor.setColor(to_utf8(shortcut), color);
820 } else if (token == "\\author") {
822 istringstream ss(lex.getString());
825 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
826 } else if (token == "\\paperorientation") {
829 orientation = paperorientationtranslator().find(orient);
830 } else if (token == "\\backgroundcolor") {
832 backgroundcolor = lyx::rgbFromHexName(lex.getString());
833 isbackgroundcolor = true;
834 } else if (token == "\\fontcolor") {
836 fontcolor = lyx::rgbFromHexName(lex.getString());
838 } else if (token == "\\notefontcolor") {
840 string color = lex.getString();
841 notefontcolor = lyx::rgbFromHexName(color);
842 lcolor.setColor("notefontcolor", color);
843 } else if (token == "\\boxbgcolor") {
845 string color = lex.getString();
846 boxbgcolor = lyx::rgbFromHexName(color);
847 lcolor.setColor("boxbgcolor", color);
848 } else if (token == "\\paperwidth") {
850 } else if (token == "\\paperheight") {
852 } else if (token == "\\leftmargin") {
854 } else if (token == "\\topmargin") {
856 } else if (token == "\\rightmargin") {
858 } else if (token == "\\bottommargin") {
860 } else if (token == "\\headheight") {
862 } else if (token == "\\headsep") {
864 } else if (token == "\\footskip") {
866 } else if (token == "\\columnsep") {
868 } else if (token == "\\paperfontsize") {
870 } else if (token == "\\papercolumns") {
872 } else if (token == "\\listings_params") {
875 listings_params = InsetListingsParams(par).params();
876 } else if (token == "\\papersides") {
879 sides = sidestranslator().find(psides);
880 } else if (token == "\\paperpagestyle") {
882 } else if (token == "\\bullet") {
884 } else if (token == "\\bulletLaTeX") {
885 readBulletsLaTeX(lex);
886 } else if (token == "\\secnumdepth") {
888 } else if (token == "\\tocdepth") {
890 } else if (token == "\\spacing") {
894 if (nspacing == "other") {
897 spacing().set(spacetranslator().find(nspacing), tmp_val);
898 } else if (token == "\\float_placement") {
899 lex >> float_placement;
901 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
902 string toktmp = pdfoptions().readToken(lex, token);
903 if (!toktmp.empty()) {
904 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
908 } else if (token == "\\html_math_output") {
911 html_math_output = static_cast<MathOutput>(temp);
912 } else if (token == "\\html_be_strict") {
913 lex >> html_be_strict;
914 } else if (token == "\\html_css_as_file") {
915 lex >> html_css_as_file;
916 } else if (token == "\\html_math_img_scale") {
917 lex >> html_math_img_scale;
918 } else if (token == "\\html_latex_start") {
920 html_latex_start = lex.getString();
921 } else if (token == "\\html_latex_end") {
923 html_latex_end = lex.getString();
924 } else if (token == "\\output_sync") {
926 } else if (token == "\\output_sync_macro") {
927 lex >> output_sync_macro;
928 } else if (token == "\\use_refstyle") {
931 lyxerr << "BufferParams::readToken(): Unknown token: " <<
940 void BufferParams::writeFile(ostream & os) const
942 // The top of the file is written by the buffer.
943 // Prints out the buffer info into the .lyx file given by file
946 os << "\\textclass " << baseClass()->name() << '\n';
949 if (!preamble.empty()) {
950 // remove '\n' from the end of preamble
951 string const tmppreamble = rtrim(preamble, "\n");
952 os << "\\begin_preamble\n"
954 << "\n\\end_preamble\n";
958 if (!options.empty()) {
959 os << "\\options " << options << '\n';
962 // use the class options defined in the layout?
963 os << "\\use_default_options "
964 << convert<string>(use_default_options) << "\n";
966 // the master document
967 if (!master.empty()) {
968 os << "\\master " << master << '\n';
972 if (!removed_modules_.empty()) {
973 os << "\\begin_removed_modules" << '\n';
974 list<string>::const_iterator it = removed_modules_.begin();
975 list<string>::const_iterator en = removed_modules_.end();
976 for (; it != en; ++it)
978 os << "\\end_removed_modules" << '\n';
982 if (!layout_modules_.empty()) {
983 os << "\\begin_modules" << '\n';
984 LayoutModuleList::const_iterator it = layout_modules_.begin();
985 LayoutModuleList::const_iterator en = layout_modules_.end();
986 for (; it != en; ++it)
988 os << "\\end_modules" << '\n';
992 if (!included_children_.empty()) {
993 os << "\\begin_includeonly" << '\n';
994 list<string>::const_iterator it = included_children_.begin();
995 list<string>::const_iterator en = included_children_.end();
996 for (; it != en; ++it)
998 os << "\\end_includeonly" << '\n';
1000 os << "\\maintain_unincluded_children "
1001 << convert<string>(maintain_unincluded_children) << '\n';
1003 // local layout information
1004 string const local_layout = getLocalLayout(false);
1005 if (!local_layout.empty()) {
1006 // remove '\n' from the end
1007 string const tmplocal = rtrim(local_layout, "\n");
1008 os << "\\begin_local_layout\n"
1010 << "\n\\end_local_layout\n";
1012 string const forced_local_layout = getLocalLayout(true);
1013 if (!forced_local_layout.empty()) {
1014 // remove '\n' from the end
1015 string const tmplocal = rtrim(forced_local_layout, "\n");
1016 os << "\\begin_forced_local_layout\n"
1018 << "\n\\end_forced_local_layout\n";
1021 // then the text parameters
1022 if (language != ignore_language)
1023 os << "\\language " << language->lang() << '\n';
1024 os << "\\language_package " << lang_package
1025 << "\n\\inputencoding " << inputenc
1026 << "\n\\fontencoding " << fontenc
1027 << "\n\\font_roman " << fonts_roman
1028 << "\n\\font_sans " << fonts_sans
1029 << "\n\\font_typewriter " << fonts_typewriter
1030 << "\n\\font_math " << fonts_math
1031 << "\n\\font_default_family " << fonts_default_family
1032 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1033 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1034 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1035 << "\n\\font_sf_scale " << fonts_sans_scale
1036 << "\n\\font_tt_scale " << fonts_typewriter_scale
1038 if (!fonts_cjk.empty()) {
1039 os << "\\font_cjk " << fonts_cjk << '\n';
1041 os << "\\graphics " << graphics_driver << '\n';
1042 os << "\\default_output_format " << default_output_format << '\n';
1043 os << "\\output_sync " << output_sync << '\n';
1044 if (!output_sync_macro.empty())
1045 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1046 os << "\\bibtex_command " << bibtex_command << '\n';
1047 os << "\\index_command " << index_command << '\n';
1049 if (!float_placement.empty()) {
1050 os << "\\float_placement " << float_placement << '\n';
1052 os << "\\paperfontsize " << fontsize << '\n';
1054 spacing().writeFile(os);
1055 pdfoptions().writeFile(os);
1057 os << "\\papersize " << string_papersize[papersize]
1058 << "\n\\use_geometry " << convert<string>(use_geometry);
1059 map<string, string> const & packages = auto_packages();
1060 for (map<string, string>::const_iterator it = packages.begin();
1061 it != packages.end(); ++it)
1062 os << "\n\\use_package " << it->first << ' '
1063 << use_package(it->first);
1065 os << "\n\\cite_engine ";
1067 if (!cite_engine_.empty()) {
1068 LayoutModuleList::const_iterator be = cite_engine_.begin();
1069 LayoutModuleList::const_iterator en = cite_engine_.end();
1070 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1079 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1080 << "\n\\biblio_style " << biblio_style
1081 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1082 << "\n\\use_indices " << convert<string>(use_indices)
1083 << "\n\\paperorientation " << string_orientation[orientation]
1084 << "\n\\suppress_date " << convert<string>(suppress_date)
1085 << "\n\\justification " << convert<string>(justification)
1086 << "\n\\use_refstyle " << use_refstyle
1088 if (isbackgroundcolor == true)
1089 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1090 if (isfontcolor == true)
1091 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1092 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1093 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1094 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1095 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1097 BranchList::const_iterator it = branchlist().begin();
1098 BranchList::const_iterator end = branchlist().end();
1099 for (; it != end; ++it) {
1100 os << "\\branch " << to_utf8(it->branch())
1101 << "\n\\selected " << it->isSelected()
1102 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1103 << "\n\\color " << lyx::X11hexname(it->color())
1108 IndicesList::const_iterator iit = indiceslist().begin();
1109 IndicesList::const_iterator iend = indiceslist().end();
1110 for (; iit != iend; ++iit) {
1111 os << "\\index " << to_utf8(iit->index())
1112 << "\n\\shortcut " << to_utf8(iit->shortcut())
1113 << "\n\\color " << lyx::X11hexname(iit->color())
1118 if (!paperwidth.empty())
1119 os << "\\paperwidth "
1120 << VSpace(paperwidth).asLyXCommand() << '\n';
1121 if (!paperheight.empty())
1122 os << "\\paperheight "
1123 << VSpace(paperheight).asLyXCommand() << '\n';
1124 if (!leftmargin.empty())
1125 os << "\\leftmargin "
1126 << VSpace(leftmargin).asLyXCommand() << '\n';
1127 if (!topmargin.empty())
1128 os << "\\topmargin "
1129 << VSpace(topmargin).asLyXCommand() << '\n';
1130 if (!rightmargin.empty())
1131 os << "\\rightmargin "
1132 << VSpace(rightmargin).asLyXCommand() << '\n';
1133 if (!bottommargin.empty())
1134 os << "\\bottommargin "
1135 << VSpace(bottommargin).asLyXCommand() << '\n';
1136 if (!headheight.empty())
1137 os << "\\headheight "
1138 << VSpace(headheight).asLyXCommand() << '\n';
1139 if (!headsep.empty())
1141 << VSpace(headsep).asLyXCommand() << '\n';
1142 if (!footskip.empty())
1144 << VSpace(footskip).asLyXCommand() << '\n';
1145 if (!columnsep.empty())
1146 os << "\\columnsep "
1147 << VSpace(columnsep).asLyXCommand() << '\n';
1148 os << "\\secnumdepth " << secnumdepth
1149 << "\n\\tocdepth " << tocdepth
1150 << "\n\\paragraph_separation "
1151 << string_paragraph_separation[paragraph_separation];
1152 if (!paragraph_separation)
1153 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1155 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1156 os << "\n\\quotes_language "
1157 << string_quotes_language[quotes_language]
1158 << "\n\\papercolumns " << columns
1159 << "\n\\papersides " << sides
1160 << "\n\\paperpagestyle " << pagestyle << '\n';
1161 if (!listings_params.empty())
1162 os << "\\listings_params \"" <<
1163 InsetListingsParams(listings_params).encodedString() << "\"\n";
1164 for (int i = 0; i < 4; ++i) {
1165 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1166 if (user_defined_bullet(i).getFont() != -1) {
1167 os << "\\bullet " << i << " "
1168 << user_defined_bullet(i).getFont() << " "
1169 << user_defined_bullet(i).getCharacter() << " "
1170 << user_defined_bullet(i).getSize() << "\n";
1174 os << "\\bulletLaTeX " << i << " \""
1175 << lyx::to_ascii(user_defined_bullet(i).getText())
1181 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1182 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1183 << "\\html_math_output " << html_math_output << '\n'
1184 << "\\html_css_as_file " << html_css_as_file << '\n'
1185 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1187 if (html_math_img_scale != 1.0)
1188 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1189 if (!html_latex_start.empty())
1190 os << "\\html_latex_start " << html_latex_start << '\n';
1191 if (!html_latex_end.empty())
1192 os << "\\html_latex_end " << html_latex_end << '\n';
1194 os << pimpl_->authorlist;
1198 void BufferParams::validate(LaTeXFeatures & features) const
1200 features.require(documentClass().requires());
1202 if (columns > 1 && language->rightToLeft())
1203 features.require("rtloutputdblcol");
1205 if (outputChanges) {
1206 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1207 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1208 LaTeXFeatures::isAvailable("xcolor");
1210 switch (features.runparams().flavor) {
1211 case OutputParams::LATEX:
1212 case OutputParams::DVILUATEX:
1214 features.require("ct-dvipost");
1215 features.require("dvipost");
1216 } else if (xcolorulem) {
1217 features.require("ct-xcolor-ulem");
1218 features.require("ulem");
1219 features.require("xcolor");
1221 features.require("ct-none");
1224 case OutputParams::LUATEX:
1225 case OutputParams::PDFLATEX:
1226 case OutputParams::XETEX:
1228 features.require("ct-xcolor-ulem");
1229 features.require("ulem");
1230 features.require("xcolor");
1231 // improves color handling in PDF output
1232 features.require("pdfcolmk");
1234 features.require("ct-none");
1242 // Floats with 'Here definitely' as default setting.
1243 if (float_placement.find('H') != string::npos)
1244 features.require("float");
1246 for (PackageMap::const_iterator it = use_packages.begin();
1247 it != use_packages.end(); ++it) {
1248 if (it->first == "amsmath") {
1249 // AMS Style is at document level
1250 if (it->second == package_on ||
1251 features.isProvided("amsmath"))
1252 features.require(it->first);
1253 } else if (it->second == package_on)
1254 features.require(it->first);
1257 // Document-level line spacing
1258 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1259 features.require("setspace");
1261 // the bullet shapes are buffer level not paragraph level
1262 // so they are tested here
1263 for (int i = 0; i < 4; ++i) {
1264 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1266 int const font = user_defined_bullet(i).getFont();
1268 int const c = user_defined_bullet(i).getCharacter();
1274 features.require("latexsym");
1276 } else if (font == 1) {
1277 features.require("amssymb");
1278 } else if (font >= 2 && font <= 5) {
1279 features.require("pifont");
1283 if (pdfoptions().use_hyperref) {
1284 features.require("hyperref");
1285 // due to interferences with babel and hyperref, the color package has to
1286 // be loaded after hyperref when hyperref is used with the colorlinks
1287 // option, see http://www.lyx.org/trac/ticket/5291
1288 if (pdfoptions().colorlinks)
1289 features.require("color");
1291 if (!listings_params.empty()) {
1292 // do not test validity because listings_params is
1293 // supposed to be valid
1295 InsetListingsParams(listings_params).separatedParams(true);
1296 // we can't support all packages, but we should load the color package
1297 if (par.find("\\color", 0) != string::npos)
1298 features.require("color");
1301 // some languages are only available via polyglossia
1302 if (features.runparams().flavor == OutputParams::XETEX
1303 && (features.hasPolyglossiaExclusiveLanguages()
1305 features.require("polyglossia");
1307 if (useNonTeXFonts && fonts_math != "auto")
1308 features.require("unicode-math");
1310 if (!language->requires().empty())
1311 features.require(language->requires());
1315 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1316 FileName const & filepath) const
1318 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1319 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1320 // \RequirePackage to do so, rather than the normal \usepackage
1321 // Do not try to load any other package before the document class, unless you
1322 // have a thorough understanding of the LATEX internals and know exactly what you
1324 if (features.mustProvide("fix-cm"))
1325 os << "\\RequirePackage{fix-cm}\n";
1327 os << "\\documentclass";
1329 DocumentClass const & tclass = documentClass();
1331 ostringstream clsoptions; // the document class options.
1333 if (tokenPos(tclass.opt_fontsize(),
1334 '|', fontsize) >= 0) {
1335 // only write if existing in list (and not default)
1336 clsoptions << fontsize << "pt,";
1339 // all paper sizes except of A4, A5, B5 and the US sizes need the
1341 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1342 && papersize != PAPER_USLETTER
1343 && papersize != PAPER_USLEGAL
1344 && papersize != PAPER_USEXECUTIVE
1345 && papersize != PAPER_A4
1346 && papersize != PAPER_A5
1347 && papersize != PAPER_B5;
1349 if (!use_geometry) {
1350 switch (papersize) {
1352 clsoptions << "a4paper,";
1354 case PAPER_USLETTER:
1355 clsoptions << "letterpaper,";
1358 clsoptions << "a5paper,";
1361 clsoptions << "b5paper,";
1363 case PAPER_USEXECUTIVE:
1364 clsoptions << "executivepaper,";
1367 clsoptions << "legalpaper,";
1401 if (sides != tclass.sides()) {
1404 clsoptions << "oneside,";
1407 clsoptions << "twoside,";
1413 if (columns != tclass.columns()) {
1415 clsoptions << "twocolumn,";
1417 clsoptions << "onecolumn,";
1421 && orientation == ORIENTATION_LANDSCAPE)
1422 clsoptions << "landscape,";
1424 // language should be a parameter to \documentclass
1425 if (language->babel() == "hebrew"
1426 && default_language->babel() != "hebrew")
1427 // This seems necessary
1428 features.useLanguage(default_language);
1430 ostringstream language_options;
1431 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1432 bool const use_polyglossia = features.usePolyglossia();
1433 bool const global = lyxrc.language_global_options;
1434 if (use_babel || (use_polyglossia && global)) {
1435 language_options << features.getBabelLanguages();
1436 if (!language->babel().empty()) {
1437 if (!language_options.str().empty())
1438 language_options << ',';
1439 language_options << language->babel();
1441 if (global && !features.needBabelLangOptions()
1442 && !language_options.str().empty())
1443 clsoptions << language_options.str() << ',';
1446 // the predefined options from the layout
1447 if (use_default_options && !tclass.options().empty())
1448 clsoptions << tclass.options() << ',';
1450 // the user-defined options
1451 if (!options.empty()) {
1452 clsoptions << options << ',';
1455 string strOptions(clsoptions.str());
1456 if (!strOptions.empty()) {
1457 strOptions = rtrim(strOptions, ",");
1459 os << '[' << from_utf8(strOptions) << ']';
1462 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1463 // end of \documentclass defs
1465 // if we use fontspec or newtxmath, we have to load the AMS packages here
1466 string const ams = features.loadAMSPackages();
1467 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1468 bool const use_newtxmath =
1469 theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getUsedPackage(
1470 ot1, false, false) == "newtxmath";
1471 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1472 os << from_ascii(ams);
1474 if (useNonTeXFonts) {
1475 os << "\\usepackage{fontspec}\n";
1476 if (features.mustProvide("unicode-math")
1477 && features.isAvailable("unicode-math"))
1478 os << "\\usepackage{unicode-math}\n";
1481 // font selection must be done before loading fontenc.sty
1482 string const fonts = loadFonts(features);
1484 os << from_utf8(fonts);
1486 if (fonts_default_family != "default")
1487 os << "\\renewcommand{\\familydefault}{\\"
1488 << from_ascii(fonts_default_family) << "}\n";
1490 // set font encoding
1491 // for arabic_arabi and farsi we also need to load the LAE and
1493 // XeTeX and LuaTeX (with OS fonts) work without fontenc
1494 if (font_encoding() != "default" && language->lang() != "japanese"
1495 && !useNonTeXFonts && !features.isProvided("fontenc")) {
1496 docstring extra_encoding;
1497 if (features.mustProvide("textgreek"))
1498 extra_encoding += from_ascii("LGR");
1499 if (features.mustProvide("textcyr")) {
1500 if (!extra_encoding.empty())
1501 extra_encoding.push_back(',');
1502 extra_encoding += from_ascii("T2A");
1504 if (!extra_encoding.empty() && !font_encoding().empty())
1505 extra_encoding.push_back(',');
1506 size_t fars = language_options.str().find("farsi");
1507 size_t arab = language_options.str().find("arabic");
1508 if (language->lang() == "arabic_arabi"
1509 || language->lang() == "farsi" || fars != string::npos
1510 || arab != string::npos) {
1511 os << "\\usepackage[" << extra_encoding
1512 << from_ascii(font_encoding())
1513 << ",LFE,LAE]{fontenc}\n";
1515 os << "\\usepackage[" << extra_encoding
1516 << from_ascii(font_encoding())
1521 // handle inputenc etc.
1522 writeEncodingPreamble(os, features);
1525 if (!features.runparams().includeall && !included_children_.empty()) {
1526 os << "\\includeonly{";
1527 list<string>::const_iterator it = included_children_.begin();
1528 list<string>::const_iterator en = included_children_.end();
1530 for (; it != en; ++it) {
1531 string incfile = *it;
1532 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1533 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1535 if (!features.runparams().nice)
1537 // \includeonly doesn't want an extension
1538 incfile = changeExtension(incfile, string());
1539 incfile = support::latex_path(incfile);
1540 if (!incfile.empty()) {
1543 os << from_utf8(incfile);
1550 if (!features.isProvided("geometry")
1551 && (use_geometry || nonstandard_papersize)) {
1552 odocstringstream ods;
1553 if (!getGraphicsDriver("geometry").empty())
1554 ods << getGraphicsDriver("geometry");
1555 if (orientation == ORIENTATION_LANDSCAPE)
1556 ods << ",landscape";
1557 switch (papersize) {
1559 if (!paperwidth.empty())
1560 ods << ",paperwidth="
1561 << from_ascii(paperwidth);
1562 if (!paperheight.empty())
1563 ods << ",paperheight="
1564 << from_ascii(paperheight);
1566 case PAPER_USLETTER:
1567 ods << ",letterpaper";
1570 ods << ",legalpaper";
1572 case PAPER_USEXECUTIVE:
1573 ods << ",executivepaper";
1662 docstring const g_options = trim(ods.str(), ",");
1663 os << "\\usepackage";
1664 if (!g_options.empty())
1665 os << '[' << g_options << ']';
1666 os << "{geometry}\n";
1667 // output this only if use_geometry is true
1669 os << "\\geometry{verbose";
1670 if (!topmargin.empty())
1671 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1672 if (!bottommargin.empty())
1673 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1674 if (!leftmargin.empty())
1675 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1676 if (!rightmargin.empty())
1677 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1678 if (!headheight.empty())
1679 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1680 if (!headsep.empty())
1681 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1682 if (!footskip.empty())
1683 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1684 if (!columnsep.empty())
1685 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1688 } else if (orientation == ORIENTATION_LANDSCAPE
1689 || papersize != PAPER_DEFAULT) {
1690 features.require("papersize");
1693 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1694 if (pagestyle == "fancy")
1695 os << "\\usepackage{fancyhdr}\n";
1696 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1699 // only output when the background color is not default
1700 if (isbackgroundcolor == true) {
1701 // only require color here, the background color will be defined
1702 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1704 features.require("color");
1705 features.require("pagecolor");
1708 // only output when the font color is not default
1709 if (isfontcolor == true) {
1710 // only require color here, the font color will be defined
1711 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1713 features.require("color");
1714 features.require("fontcolor");
1717 // Only if class has a ToC hierarchy
1718 if (tclass.hasTocLevels()) {
1719 if (secnumdepth != tclass.secnumdepth()) {
1720 os << "\\setcounter{secnumdepth}{"
1724 if (tocdepth != tclass.tocdepth()) {
1725 os << "\\setcounter{tocdepth}{"
1731 if (paragraph_separation) {
1732 // when skip separation
1733 switch (getDefSkip().kind()) {
1734 case VSpace::SMALLSKIP:
1735 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1737 case VSpace::MEDSKIP:
1738 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1740 case VSpace::BIGSKIP:
1741 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1743 case VSpace::LENGTH:
1744 os << "\\setlength{\\parskip}{"
1745 << from_utf8(getDefSkip().length().asLatexString())
1748 default: // should never happen // Then delete it.
1749 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1752 os << "\\setlength{\\parindent}{0pt}\n";
1754 // when separation by indentation
1755 // only output something when a width is given
1756 if (getIndentation().asLyXCommand() != "default") {
1757 os << "\\setlength{\\parindent}{"
1758 << from_utf8(getIndentation().asLatexCommand())
1763 // Now insert the LyX specific LaTeX commands...
1764 docstring lyxpreamble;
1765 features.resolveAlternatives();
1768 if (!output_sync_macro.empty())
1769 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1770 else if (features.runparams().flavor == OutputParams::LATEX)
1771 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1772 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1773 lyxpreamble += "\\synctex=-1\n";
1776 // due to interferences with babel and hyperref, the color package has to
1777 // be loaded (when it is not already loaded) before babel when hyperref
1778 // is used with the colorlinks option, see
1779 // http://www.lyx.org/trac/ticket/5291
1780 // we decided therefore to load color always before babel, see
1781 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1782 lyxpreamble += from_ascii(features.getColorOptions());
1784 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1785 // we have to call babel before
1787 && (features.isRequired("jurabib")
1788 || features.isRequired("hyperref")
1789 || features.isRequired("varioref")
1790 || features.isRequired("vietnamese")
1791 || features.isRequired("japanese"))) {
1793 lyxpreamble += from_utf8(features.getBabelPresettings());
1794 lyxpreamble += from_utf8(babelCall(language_options.str(),
1795 features.needBabelLangOptions())) + '\n';
1796 lyxpreamble += from_utf8(features.getBabelPostsettings());
1799 // The optional packages;
1800 lyxpreamble += from_ascii(features.getPackages());
1802 // Additional Indices
1803 if (features.isRequired("splitidx")) {
1804 IndicesList::const_iterator iit = indiceslist().begin();
1805 IndicesList::const_iterator iend = indiceslist().end();
1806 for (; iit != iend; ++iit) {
1807 pair<docstring, docstring> indexname_latex =
1808 features.runparams().encoding->latexString(iit->index(),
1809 features.runparams().dryrun);
1810 if (!indexname_latex.second.empty()) {
1811 // issue a warning about omitted characters
1812 // FIXME: should be passed to the error dialog
1813 frontend::Alert::warning(_("Uncodable characters"),
1814 bformat(_("The following characters that are used in an index name are not\n"
1815 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1816 indexname_latex.second));
1818 lyxpreamble += "\\newindex[";
1819 lyxpreamble += indexname_latex.first;
1820 lyxpreamble += "]{";
1821 lyxpreamble += escape(iit->shortcut());
1822 lyxpreamble += "}\n";
1827 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1830 // * Hyperref manual: "Make sure it comes last of your loaded
1831 // packages, to give it a fighting chance of not being over-written,
1832 // since its job is to redefine many LaTeX commands."
1833 // * Email from Heiko Oberdiek: "It is usually better to load babel
1834 // before hyperref. Then hyperref has a chance to detect babel.
1835 // * Has to be loaded before the "LyX specific LaTeX commands" to
1836 // avoid errors with algorithm floats.
1837 // use hyperref explicitly if it is required
1838 if (features.isRequired("hyperref")) {
1839 // pass what we have to stream here, since we need
1840 // to access the stream itself in PDFOptions.
1843 OutputParams tmp_params = features.runparams();
1844 pdfoptions().writeLaTeX(tmp_params, os,
1845 features.isProvided("hyperref"));
1846 // set back for the rest
1847 lyxpreamble.clear();
1848 // correctly break URLs with hyperref and dvi output
1849 if (features.runparams().flavor == OutputParams::LATEX
1850 && features.isAvailable("breakurl"))
1851 lyxpreamble += "\\usepackage{breakurl}\n";
1852 } else if (features.isRequired("nameref"))
1853 // hyperref loads this automatically
1854 lyxpreamble += "\\usepackage{nameref}\n";
1856 // bibtopic needs to be loaded after hyperref.
1857 // the dot provides the aux file naming which LyX can detect.
1858 if (features.mustProvide("bibtopic"))
1859 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1861 // Will be surrounded by \makeatletter and \makeatother when not empty
1862 docstring atlyxpreamble;
1864 // Some macros LyX will need
1865 docstring tmppreamble(features.getMacros());
1867 if (!tmppreamble.empty())
1868 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1869 "LyX specific LaTeX commands.\n"
1870 + tmppreamble + '\n';
1872 // the text class specific preamble
1873 tmppreamble = features.getTClassPreamble();
1874 if (!tmppreamble.empty())
1875 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1876 "Textclass specific LaTeX commands.\n"
1877 + tmppreamble + '\n';
1879 // suppress date if selected
1880 // use \@ifundefined because we cannot be sure that every document class
1881 // has a \date command
1883 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1885 /* the user-defined preamble */
1886 if (!containsOnly(preamble, " \n\t"))
1888 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1889 "User specified LaTeX commands.\n"
1890 + from_utf8(preamble) + '\n';
1892 // subfig loads internally the LaTeX package "caption". As
1893 // caption is a very popular package, users will load it in
1894 // the preamble. Therefore we must load subfig behind the
1895 // user-defined preamble and check if the caption package was
1896 // loaded or not. For the case that caption is loaded before
1897 // subfig, there is the subfig option "caption=false". This
1898 // option also works when a koma-script class is used and
1899 // koma's own caption commands are used instead of caption. We
1900 // use \PassOptionsToPackage here because the user could have
1901 // already loaded subfig in the preamble.
1902 if (features.isRequired("subfig")) {
1903 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1904 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1905 "\\usepackage{subfig}\n";
1908 // Itemize bullet settings need to be last in case the user
1909 // defines their own bullets that use a package included
1910 // in the user-defined preamble -- ARRae
1911 // Actually it has to be done much later than that
1912 // since some packages like frenchb make modifications
1913 // at \begin{document} time -- JMarc
1914 docstring bullets_def;
1915 for (int i = 0; i < 4; ++i) {
1916 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1917 if (bullets_def.empty())
1918 bullets_def += "\\AtBeginDocument{\n";
1919 bullets_def += " \\def\\labelitemi";
1921 // `i' is one less than the item to modify
1928 bullets_def += "ii";
1934 bullets_def += '{' +
1935 user_defined_bullet(i).getText()
1940 if (!bullets_def.empty())
1941 atlyxpreamble += bullets_def + "}\n\n";
1943 if (!atlyxpreamble.empty())
1944 lyxpreamble += "\n\\makeatletter\n"
1945 + atlyxpreamble + "\\makeatother\n\n";
1947 // We try to load babel late, in case it interferes with other packages.
1948 // Jurabib, hyperref, varioref and listings (bug 8995) have to be
1949 // called after babel, though.
1950 if (use_babel && !features.isRequired("jurabib")
1951 && !features.isRequired("hyperref")
1952 && !features.isRequired("varioref")
1953 && !features.isRequired("vietnamese")
1954 && !features.isRequired("japanese")) {
1956 lyxpreamble += from_utf8(features.getBabelPresettings());
1957 lyxpreamble += from_utf8(babelCall(language_options.str(),
1958 features.needBabelLangOptions())) + '\n';
1959 lyxpreamble += from_utf8(features.getBabelPostsettings());
1961 if (!listings_params.empty() || features.isRequired("listings"))
1962 lyxpreamble += "\\usepackage{listings}\n";
1963 if (!listings_params.empty()) {
1964 lyxpreamble += "\\lstset{";
1965 // do not test validity because listings_params is
1966 // supposed to be valid
1968 InsetListingsParams(listings_params).separatedParams(true);
1969 lyxpreamble += from_utf8(par);
1970 lyxpreamble += "}\n";
1973 // xunicode needs to be loaded at least after amsmath, amssymb,
1974 // esint and the other packages that provide special glyphs
1975 if (features.runparams().flavor == OutputParams::XETEX
1977 lyxpreamble += "\\usepackage{xunicode}\n";
1979 // Polyglossia must be loaded last
1980 if (use_polyglossia) {
1982 lyxpreamble += "\\usepackage{polyglossia}\n";
1983 // set the main language
1984 lyxpreamble += "\\setdefaultlanguage";
1985 if (!language->polyglossiaOpts().empty())
1986 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
1987 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
1988 // now setup the other languages
1989 std::map<std::string, std::string> const polylangs =
1990 features.getPolyglossiaLanguages();
1991 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
1992 mit != polylangs.end() ; ++mit) {
1993 lyxpreamble += "\\setotherlanguage";
1994 if (!mit->second.empty())
1995 lyxpreamble += "[" + from_ascii(mit->second) + "]";
1996 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
2000 // Load custom language package here
2001 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2002 if (lang_package == "default")
2003 lyxpreamble += from_utf8(lyxrc.language_custom_package);
2005 lyxpreamble += from_utf8(lang_package);
2006 lyxpreamble += '\n';
2009 docstring const i18npreamble =
2010 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2011 if (!i18npreamble.empty())
2012 lyxpreamble += i18npreamble + '\n';
2020 void BufferParams::useClassDefaults()
2022 DocumentClass const & tclass = documentClass();
2024 sides = tclass.sides();
2025 columns = tclass.columns();
2026 pagestyle = tclass.pagestyle();
2027 use_default_options = true;
2028 // Only if class has a ToC hierarchy
2029 if (tclass.hasTocLevels()) {
2030 secnumdepth = tclass.secnumdepth();
2031 tocdepth = tclass.tocdepth();
2036 bool BufferParams::hasClassDefaults() const
2038 DocumentClass const & tclass = documentClass();
2040 return sides == tclass.sides()
2041 && columns == tclass.columns()
2042 && pagestyle == tclass.pagestyle()
2043 && use_default_options
2044 && secnumdepth == tclass.secnumdepth()
2045 && tocdepth == tclass.tocdepth();
2049 DocumentClass const & BufferParams::documentClass() const
2051 return *doc_class_.get();
2055 DocumentClassConstPtr BufferParams::documentClassPtr() const
2061 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2063 // evil, but this function is evil
2064 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2068 bool BufferParams::setBaseClass(string const & classname)
2070 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2071 LayoutFileList & bcl = LayoutFileList::get();
2072 if (!bcl.haveClass(classname)) {
2074 bformat(_("The layout file:\n"
2076 "could not be found. A default textclass with default\n"
2077 "layouts will be used. LyX will not be able to produce\n"
2079 from_utf8(classname));
2080 frontend::Alert::error(_("Document class not found"), s);
2081 bcl.addEmptyClass(classname);
2084 bool const success = bcl[classname].load();
2087 bformat(_("Due to some error in it, the layout file:\n"
2089 "could not be loaded. A default textclass with default\n"
2090 "layouts will be used. LyX will not be able to produce\n"
2092 from_utf8(classname));
2093 frontend::Alert::error(_("Could not load class"), s);
2094 bcl.addEmptyClass(classname);
2097 pimpl_->baseClass_ = classname;
2098 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2103 LayoutFile const * BufferParams::baseClass() const
2105 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2106 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2112 LayoutFileIndex const & BufferParams::baseClassID() const
2114 return pimpl_->baseClass_;
2118 void BufferParams::makeDocumentClass(bool const clone)
2123 LayoutModuleList mods;
2124 LayoutModuleList::iterator it = layout_modules_.begin();
2125 LayoutModuleList::iterator en = layout_modules_.end();
2126 for (; it != en; ++it)
2127 mods.push_back(*it);
2129 it = cite_engine_.begin();
2130 en = cite_engine_.end();
2131 for (; it != en; ++it)
2132 mods.push_back(*it);
2134 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2136 TextClass::ReturnValues success = TextClass::OK;
2137 if (!forced_local_layout_.empty())
2138 success = doc_class_->read(forced_local_layout_, TextClass::MODULE);
2139 if (!local_layout_.empty() &&
2140 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2141 success = doc_class_->read(local_layout_, TextClass::MODULE);
2142 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2143 docstring const msg = _("Error reading internal layout information");
2144 frontend::Alert::warning(_("Read Error"), msg);
2149 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2151 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2155 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2157 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2161 std::string BufferParams::getLocalLayout(bool forced) const
2164 return doc_class_->forcedLayouts();
2166 return local_layout_;
2170 void BufferParams::setLocalLayout(string const & layout, bool forced)
2173 forced_local_layout_ = layout;
2175 local_layout_ = layout;
2179 bool BufferParams::addLayoutModule(string const & modName)
2181 LayoutModuleList::const_iterator it = layout_modules_.begin();
2182 LayoutModuleList::const_iterator end = layout_modules_.end();
2183 for (; it != end; ++it)
2186 layout_modules_.push_back(modName);
2191 string BufferParams::bufferFormat() const
2193 string format = documentClass().outputFormat();
2194 if (format == "latex") {
2197 if (encoding().package() == Encoding::japanese)
2204 bool BufferParams::isExportable(string const & format) const
2206 vector<string> backs = backends();
2207 for (vector<string>::const_iterator it = backs.begin();
2208 it != backs.end(); ++it)
2209 if (theConverters().isReachable(*it, format))
2215 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2217 vector<string> const backs = backends();
2218 set<string> excludes;
2219 if (useNonTeXFonts) {
2220 excludes.insert("latex");
2221 excludes.insert("pdflatex");
2223 vector<Format const *> result =
2224 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2225 for (vector<string>::const_iterator it = backs.begin() + 1;
2226 it != backs.end(); ++it) {
2227 vector<Format const *> r =
2228 theConverters().getReachable(*it, only_viewable, false, excludes);
2229 result.insert(result.end(), r.begin(), r.end());
2235 bool BufferParams::isExportableFormat(string const & format) const
2237 typedef vector<Format const *> Formats;
2239 formats = exportableFormats(true);
2240 Formats::const_iterator fit = formats.begin();
2241 Formats::const_iterator end = formats.end();
2242 for (; fit != end ; ++fit) {
2243 if ((*fit)->name() == format)
2250 vector<string> BufferParams::backends() const
2253 string const buffmt = bufferFormat();
2255 // FIXME: Don't hardcode format names here, but use a flag
2256 if (buffmt == "latex") {
2257 if (!useNonTeXFonts) {
2258 v.push_back("pdflatex");
2259 v.push_back("latex");
2261 v.push_back("luatex");
2262 v.push_back("dviluatex");
2263 v.push_back("xetex");
2264 } else if (buffmt == "xetex") {
2265 v.push_back("xetex");
2266 // FIXME: need to test all languages (bug 8205)
2267 if (!language || !language->isPolyglossiaExclusive()) {
2268 v.push_back("luatex");
2269 v.push_back("dviluatex");
2272 v.push_back(buffmt);
2274 v.push_back("xhtml");
2275 v.push_back("text");
2281 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const format) const
2283 string const dformat = (format.empty() || format == "default") ?
2284 getDefaultOutputFormat() : format;
2285 DefaultFlavorCache::const_iterator it =
2286 default_flavors_.find(dformat);
2288 if (it != default_flavors_.end())
2291 OutputParams::FLAVOR result = OutputParams::LATEX;
2293 // FIXME It'd be better not to hardcode this, but to do
2294 // something with formats.
2295 if (dformat == "xhtml")
2296 result = OutputParams::HTML;
2297 else if (dformat == "text")
2298 result = OutputParams::TEXT;
2299 else if (dformat == "lyx")
2300 result = OutputParams::LYX;
2301 else if (dformat == "pdflatex")
2302 result = OutputParams::PDFLATEX;
2303 else if (dformat == "xetex")
2304 result = OutputParams::XETEX;
2305 else if (dformat == "luatex")
2306 result = OutputParams::LUATEX;
2307 else if (dformat == "dviluatex")
2308 result = OutputParams::DVILUATEX;
2310 // Try to determine flavor of default output format
2311 vector<string> backs = backends();
2312 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2313 // Get shortest path to format
2314 Graph::EdgePath path;
2315 for (vector<string>::const_iterator it = backs.begin();
2316 it != backs.end(); ++it) {
2317 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2318 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2323 result = theConverters().getFlavor(path);
2326 // cache this flavor
2327 default_flavors_[dformat] = result;
2332 string BufferParams::getDefaultOutputFormat() const
2334 if (!default_output_format.empty()
2335 && default_output_format != "default")
2336 return default_output_format;
2338 || encoding().package() == Encoding::japanese) {
2339 vector<Format const *> const formats = exportableFormats(true);
2340 if (formats.empty())
2342 // return the first we find
2343 return formats.front()->name();
2346 return lyxrc.default_otf_view_format;
2347 return lyxrc.default_view_format;
2350 Font const BufferParams::getFont() const
2352 FontInfo f = documentClass().defaultfont();
2353 if (fonts_default_family == "rmdefault")
2354 f.setFamily(ROMAN_FAMILY);
2355 else if (fonts_default_family == "sfdefault")
2356 f.setFamily(SANS_FAMILY);
2357 else if (fonts_default_family == "ttdefault")
2358 f.setFamily(TYPEWRITER_FAMILY);
2359 return Font(f, language);
2363 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const qs) const
2365 return quoteslangtranslator().find(qs);
2369 bool BufferParams::isLatex() const
2371 return documentClass().outputType() == LATEX;
2375 bool BufferParams::isLiterate() const
2377 return documentClass().outputType() == LITERATE;
2381 bool BufferParams::isDocBook() const
2383 return documentClass().outputType() == DOCBOOK;
2387 void BufferParams::readPreamble(Lexer & lex)
2389 if (lex.getString() != "\\begin_preamble")
2390 lyxerr << "Error (BufferParams::readPreamble):"
2391 "consistency check failed." << endl;
2393 preamble = lex.getLongString("\\end_preamble");
2397 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2399 string const expected = forced ? "\\begin_forced_local_layout" :
2400 "\\begin_local_layout";
2401 if (lex.getString() != expected)
2402 lyxerr << "Error (BufferParams::readLocalLayout):"
2403 "consistency check failed." << endl;
2406 forced_local_layout_ =
2407 lex.getLongString("\\end_forced_local_layout");
2409 local_layout_ = lex.getLongString("\\end_local_layout");
2413 bool BufferParams::setLanguage(string const & lang)
2415 Language const *new_language = languages.getLanguage(lang);
2416 if (!new_language) {
2417 // Language lang was not found
2420 language = new_language;
2425 void BufferParams::readLanguage(Lexer & lex)
2427 if (!lex.next()) return;
2429 string const tmptok = lex.getString();
2431 // check if tmptok is part of tex_babel in tex-defs.h
2432 if (!setLanguage(tmptok)) {
2433 // Language tmptok was not found
2434 language = default_language;
2435 lyxerr << "Warning: Setting language `"
2436 << tmptok << "' to `" << language->lang()
2442 void BufferParams::readGraphicsDriver(Lexer & lex)
2447 string const tmptok = lex.getString();
2448 // check if tmptok is part of tex_graphics in tex_defs.h
2451 string const test = tex_graphics[n++];
2453 if (test == tmptok) {
2454 graphics_driver = tmptok;
2459 "Warning: graphics driver `$$Token' not recognized!\n"
2460 " Setting graphics driver to `default'.\n");
2461 graphics_driver = "default";
2468 void BufferParams::readBullets(Lexer & lex)
2473 int const index = lex.getInteger();
2475 int temp_int = lex.getInteger();
2476 user_defined_bullet(index).setFont(temp_int);
2477 temp_bullet(index).setFont(temp_int);
2479 user_defined_bullet(index).setCharacter(temp_int);
2480 temp_bullet(index).setCharacter(temp_int);
2482 user_defined_bullet(index).setSize(temp_int);
2483 temp_bullet(index).setSize(temp_int);
2487 void BufferParams::readBulletsLaTeX(Lexer & lex)
2489 // The bullet class should be able to read this.
2492 int const index = lex.getInteger();
2494 docstring const temp_str = lex.getDocString();
2496 user_defined_bullet(index).setText(temp_str);
2497 temp_bullet(index).setText(temp_str);
2501 void BufferParams::readModules(Lexer & lex)
2503 if (!lex.eatLine()) {
2504 lyxerr << "Error (BufferParams::readModules):"
2505 "Unexpected end of input." << endl;
2509 string mod = lex.getString();
2510 if (mod == "\\end_modules")
2512 addLayoutModule(mod);
2518 void BufferParams::readRemovedModules(Lexer & lex)
2520 if (!lex.eatLine()) {
2521 lyxerr << "Error (BufferParams::readRemovedModules):"
2522 "Unexpected end of input." << endl;
2526 string mod = lex.getString();
2527 if (mod == "\\end_removed_modules")
2529 removed_modules_.push_back(mod);
2532 // now we want to remove any removed modules that were previously
2533 // added. normally, that will be because default modules were added in
2534 // setBaseClass(), which gets called when \textclass is read at the
2535 // start of the read.
2536 list<string>::const_iterator rit = removed_modules_.begin();
2537 list<string>::const_iterator const ren = removed_modules_.end();
2538 for (; rit != ren; ++rit) {
2539 LayoutModuleList::iterator const mit = layout_modules_.begin();
2540 LayoutModuleList::iterator const men = layout_modules_.end();
2541 LayoutModuleList::iterator found = find(mit, men, *rit);
2544 layout_modules_.erase(found);
2549 void BufferParams::readIncludeonly(Lexer & lex)
2551 if (!lex.eatLine()) {
2552 lyxerr << "Error (BufferParams::readIncludeonly):"
2553 "Unexpected end of input." << endl;
2557 string child = lex.getString();
2558 if (child == "\\end_includeonly")
2560 included_children_.push_back(child);
2566 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2568 switch (papersize) {
2570 // could be anything, so don't guess
2572 case PAPER_CUSTOM: {
2573 if (purpose == XDVI && !paperwidth.empty() &&
2574 !paperheight.empty()) {
2575 // heightxwidth<unit>
2576 string first = paperwidth;
2577 string second = paperheight;
2578 if (orientation == ORIENTATION_LANDSCAPE)
2581 return first.erase(first.length() - 2)
2587 // dvips and dvipdfm do not know this
2588 if (purpose == DVIPS || purpose == DVIPDFM)
2592 if (purpose == DVIPS || purpose == DVIPDFM)
2596 if (purpose == DVIPS || purpose == DVIPDFM)
2606 if (purpose == DVIPS || purpose == DVIPDFM)
2610 if (purpose == DVIPS || purpose == DVIPDFM)
2614 if (purpose == DVIPS || purpose == DVIPDFM)
2618 if (purpose == DVIPS || purpose == DVIPDFM)
2622 if (purpose == DVIPS || purpose == DVIPDFM)
2626 // dvipdfm does not know this
2627 if (purpose == DVIPDFM)
2631 if (purpose == DVIPDFM)
2635 if (purpose == DVIPS || purpose == DVIPDFM)
2639 if (purpose == DVIPS || purpose == DVIPDFM)
2643 if (purpose == DVIPS || purpose == DVIPDFM)
2647 if (purpose == DVIPS || purpose == DVIPDFM)
2651 if (purpose == DVIPS || purpose == DVIPDFM)
2655 if (purpose == DVIPS || purpose == DVIPDFM)
2659 if (purpose == DVIPS || purpose == DVIPDFM)
2663 if (purpose == DVIPS || purpose == DVIPDFM)
2667 if (purpose == DVIPS || purpose == DVIPDFM)
2671 if (purpose == DVIPS || purpose == DVIPDFM)
2675 if (purpose == DVIPS || purpose == DVIPDFM)
2679 if (purpose == DVIPS || purpose == DVIPDFM)
2683 if (purpose == DVIPS || purpose == DVIPDFM)
2687 if (purpose == DVIPS || purpose == DVIPDFM)
2691 if (purpose == DVIPS || purpose == DVIPDFM)
2694 case PAPER_USEXECUTIVE:
2695 // dvipdfm does not know this
2696 if (purpose == DVIPDFM)
2701 case PAPER_USLETTER:
2703 if (purpose == XDVI)
2710 string const BufferParams::dvips_options() const
2714 // If the class loads the geometry package, we do not know which
2715 // paper size is used, since we do not set it (bug 7013).
2716 // Therefore we must not specify any argument here.
2717 // dvips gets the correct paper size via DVI specials in this case
2718 // (if the class uses the geometry package correctly).
2719 if (documentClass().provides("geometry"))
2723 && papersize == PAPER_CUSTOM
2724 && !lyxrc.print_paper_dimension_flag.empty()
2725 && !paperwidth.empty()
2726 && !paperheight.empty()) {
2727 // using a custom papersize
2728 result = lyxrc.print_paper_dimension_flag;
2729 result += ' ' + paperwidth;
2730 result += ',' + paperheight;
2732 string const paper_option = paperSizeName(DVIPS);
2733 if (!paper_option.empty() && (paper_option != "letter" ||
2734 orientation != ORIENTATION_LANDSCAPE)) {
2735 // dvips won't accept -t letter -t landscape.
2736 // In all other cases, include the paper size
2738 result = lyxrc.print_paper_flag;
2739 result += ' ' + paper_option;
2742 if (orientation == ORIENTATION_LANDSCAPE &&
2743 papersize != PAPER_CUSTOM)
2744 result += ' ' + lyxrc.print_landscape_flag;
2749 string const BufferParams::font_encoding() const
2751 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2755 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2757 // suppress the babel call if there is no BabelName defined
2758 // for the document language in the lib/languages file and if no
2759 // other languages are used (lang_opts is then empty)
2760 if (lang_opts.empty())
2762 // either a specific language (AsBabelOptions setting in
2763 // lib/languages) or the prefs require the languages to
2764 // be submitted to babel itself (not the class).
2766 return "\\usepackage[" + lang_opts + "]{babel}";
2767 return "\\usepackage{babel}";
2771 docstring BufferParams::getGraphicsDriver(string const & package) const
2775 if (package == "geometry") {
2776 if (graphics_driver == "dvips"
2777 || graphics_driver == "dvipdfm"
2778 || graphics_driver == "pdftex"
2779 || graphics_driver == "vtex")
2780 result = from_ascii(graphics_driver);
2781 else if (graphics_driver == "dvipdfmx")
2782 result = from_ascii("dvipdfm");
2789 void BufferParams::writeEncodingPreamble(otexstream & os,
2790 LaTeXFeatures & features) const
2792 // XeTeX does not need this
2793 if (features.runparams().flavor == OutputParams::XETEX)
2795 // LuaTeX neither, but with tex fonts, we need to load
2796 // the luainputenc package.
2797 if (features.runparams().flavor == OutputParams::LUATEX
2798 || features.runparams().flavor == OutputParams::DVILUATEX) {
2799 if (!useNonTeXFonts && inputenc != "default"
2800 && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc)
2801 || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) {
2802 os << "\\usepackage[utf8]{luainputenc}\n";
2806 if (inputenc == "auto") {
2807 string const doc_encoding =
2808 language->encoding()->latexName();
2809 Encoding::Package const package =
2810 language->encoding()->package();
2812 // Create a list with all the input encodings used
2814 set<string> encodings =
2815 features.getEncodingSet(doc_encoding);
2817 // If the "japanese" package (i.e. pLaTeX) is used,
2818 // inputenc must be omitted.
2819 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2820 if ((!encodings.empty() || package == Encoding::inputenc)
2821 && !features.isRequired("japanese")) {
2822 os << "\\usepackage[";
2823 set<string>::const_iterator it = encodings.begin();
2824 set<string>::const_iterator const end = encodings.end();
2826 os << from_ascii(*it);
2829 for (; it != end; ++it)
2830 os << ',' << from_ascii(*it);
2831 if (package == Encoding::inputenc) {
2832 if (!encodings.empty())
2834 os << from_ascii(doc_encoding);
2836 os << "]{inputenc}\n";
2838 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2839 if (language->encoding()->name() == "utf8-cjk"
2840 && LaTeXFeatures::isAvailable("CJKutf8"))
2841 os << "\\usepackage{CJKutf8}\n";
2843 os << "\\usepackage{CJK}\n";
2845 } else if (inputenc != "default") {
2846 switch (encoding().package()) {
2847 case Encoding::none:
2848 case Encoding::japanese:
2850 case Encoding::inputenc:
2851 // do not load inputenc if japanese is used
2852 if (features.isRequired("japanese"))
2854 os << "\\usepackage[" << from_ascii(encoding().latexName())
2858 if (encoding().name() == "utf8-cjk"
2859 && LaTeXFeatures::isAvailable("CJKutf8"))
2860 os << "\\usepackage{CJKutf8}\n";
2862 os << "\\usepackage{CJK}\n";
2865 // Load the CJK package if needed by a secondary language.
2866 // If the main encoding is some variant of UTF8, use CJKutf8.
2867 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
2868 if (encoding().iconvName() == "UTF-8"
2869 && LaTeXFeatures::isAvailable("CJKutf8"))
2870 os << "\\usepackage{CJKutf8}\n";
2872 os << "\\usepackage{CJK}\n";
2878 string const BufferParams::parseFontName(string const & name) const
2880 string mangled = name;
2881 size_t const idx = mangled.find('[');
2882 if (idx == string::npos || idx == 0)
2885 return mangled.substr(0, idx - 1);
2889 string const BufferParams::loadFonts(LaTeXFeatures & features) const
2891 if (fonts_roman == "default" && fonts_sans == "default"
2892 && fonts_typewriter == "default"
2893 && (fonts_math == "default" || fonts_math == "auto"))
2899 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
2900 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
2901 * Mapping=tex-text option assures TeX ligatures (such as "--")
2902 * are resolved. Note that tt does not use these ligatures.
2904 * -- add more GUI options?
2905 * -- add more fonts (fonts for other scripts)
2906 * -- if there's a way to find out if a font really supports
2907 * OldStyle, enable/disable the widget accordingly.
2909 if (useNonTeXFonts && features.isAvailable("fontspec")) {
2910 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
2911 // However, until v.2 (2010/07/11) fontspec only knew
2912 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
2913 // was introduced for both XeTeX and LuaTeX (LuaTeX
2914 // didn't understand "Mapping=tex-text", while XeTeX
2915 // understood both. With most recent versions, both
2916 // variants are understood by both engines. However,
2917 // we want to provide support for at least TeXLive 2009
2918 // (for XeTeX; LuaTeX is only supported as of v.2)
2919 string const texmapping =
2920 (features.runparams().flavor == OutputParams::XETEX) ?
2921 "Mapping=tex-text" : "Ligatures=TeX";
2922 if (fonts_roman != "default") {
2923 os << "\\setmainfont[" << texmapping;
2924 if (fonts_old_figures)
2925 os << ",Numbers=OldStyle";
2926 os << "]{" << parseFontName(fonts_roman) << "}\n";
2928 if (fonts_sans != "default") {
2929 string const sans = parseFontName(fonts_sans);
2930 if (fonts_sans_scale != 100)
2931 os << "\\setsansfont[Scale="
2932 << float(fonts_sans_scale) / 100
2933 << "," << texmapping << "]{"
2936 os << "\\setsansfont[" << texmapping << "]{"
2939 if (fonts_typewriter != "default") {
2940 string const mono = parseFontName(fonts_typewriter);
2941 if (fonts_typewriter_scale != 100)
2942 os << "\\setmonofont[Scale="
2943 << float(fonts_typewriter_scale) / 100
2947 os << "\\setmonofont{"
2954 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
2955 bool const dryrun = features.runparams().dryrun;
2956 bool const complete = (fonts_sans == "default" && fonts_typewriter == "default");
2957 bool const nomath = (fonts_math == "default");
2960 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_roman)).getLaTeXCode(
2961 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2965 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_sans)).getLaTeXCode(
2966 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2967 nomath, fonts_sans_scale);
2969 // MONOSPACED/TYPEWRITER
2970 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_typewriter)).getLaTeXCode(
2971 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2972 nomath, fonts_typewriter_scale);
2975 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getLaTeXCode(
2976 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2983 Encoding const & BufferParams::encoding() const
2985 // FIXME: actually, we should check for the flavor
2986 // or runparams.isFullyUnicode() here:
2987 // This check will not work with XeTeX/LuaTeX and tex fonts.
2988 // Thus we have to reset the encoding in Buffer::makeLaTeXFile.
2990 return *(encodings.fromLyXName("utf8-plain"));
2991 if (inputenc == "auto" || inputenc == "default")
2992 return *language->encoding();
2993 Encoding const * const enc = encodings.fromLyXName(inputenc);
2996 LYXERR0("Unknown inputenc value `" << inputenc
2997 << "'. Using `auto' instead.");
2998 return *language->encoding();
3002 bool BufferParams::addCiteEngine(string const & engine)
3004 LayoutModuleList::const_iterator it = cite_engine_.begin();
3005 LayoutModuleList::const_iterator en = cite_engine_.end();
3006 for (; it != en; ++it)
3009 cite_engine_.push_back(engine);
3014 bool BufferParams::addCiteEngine(vector<string> const & engine)
3016 vector<string>::const_iterator it = engine.begin();
3017 vector<string>::const_iterator en = engine.end();
3019 for (; it != en; ++it)
3020 if (!addCiteEngine(*it))
3026 string const & BufferParams::defaultBiblioStyle() const
3028 return documentClass().defaultBiblioStyle();
3032 bool const & BufferParams::fullAuthorList() const
3034 return documentClass().fullAuthorList();
3038 void BufferParams::setCiteEngine(string const & engine)
3041 addCiteEngine(engine);
3045 void BufferParams::setCiteEngine(vector<string> const & engine)
3048 addCiteEngine(engine);
3052 vector<string> BufferParams::citeCommands() const
3054 static CitationStyle const default_style;
3055 vector<string> commands =
3056 documentClass().citeCommands(citeEngineType());
3057 if (commands.empty())
3058 commands.push_back(default_style.cmd);
3063 vector<CitationStyle> BufferParams::citeStyles() const
3065 static CitationStyle const default_style;
3066 vector<CitationStyle> styles =
3067 documentClass().citeStyles(citeEngineType());
3069 styles.push_back(default_style);