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/mutex.h"
56 #include "support/Translator.h"
57 #include "support/lstrings.h"
63 using namespace lyx::support;
66 static char const * const string_paragraph_separation[] = {
71 static char const * const string_quotes_language[] = {
72 "english", "swedish", "german", "polish", "french", "danish", ""
76 static char const * const string_papersize[] = {
77 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
78 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
79 "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
80 "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
81 "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
86 static char const * const string_orientation[] = {
87 "portrait", "landscape", ""
91 static char const * const tex_graphics[] = {
92 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
93 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
94 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
95 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
106 // Paragraph separation
107 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
110 ParSepTranslator const init_parseptranslator()
112 ParSepTranslator translator
113 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
114 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
119 ParSepTranslator const & parseptranslator()
121 static ParSepTranslator const translator =
122 init_parseptranslator();
128 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
131 QuotesLangTranslator const init_quoteslangtranslator()
133 QuotesLangTranslator translator
134 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
135 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
136 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
137 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
138 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
139 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
144 QuotesLangTranslator const & quoteslangtranslator()
146 static QuotesLangTranslator const translator =
147 init_quoteslangtranslator();
153 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
156 static PaperSizeTranslator initPaperSizeTranslator()
158 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
159 translator.addPair(string_papersize[1], PAPER_CUSTOM);
160 translator.addPair(string_papersize[2], PAPER_USLETTER);
161 translator.addPair(string_papersize[3], PAPER_USLEGAL);
162 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
163 translator.addPair(string_papersize[5], PAPER_A0);
164 translator.addPair(string_papersize[6], PAPER_A1);
165 translator.addPair(string_papersize[7], PAPER_A2);
166 translator.addPair(string_papersize[8], PAPER_A3);
167 translator.addPair(string_papersize[9], PAPER_A4);
168 translator.addPair(string_papersize[10], PAPER_A5);
169 translator.addPair(string_papersize[11], PAPER_A6);
170 translator.addPair(string_papersize[12], PAPER_B0);
171 translator.addPair(string_papersize[13], PAPER_B1);
172 translator.addPair(string_papersize[14], PAPER_B2);
173 translator.addPair(string_papersize[15], PAPER_B3);
174 translator.addPair(string_papersize[16], PAPER_B4);
175 translator.addPair(string_papersize[17], PAPER_B5);
176 translator.addPair(string_papersize[18], PAPER_B6);
177 translator.addPair(string_papersize[19], PAPER_C0);
178 translator.addPair(string_papersize[20], PAPER_C1);
179 translator.addPair(string_papersize[21], PAPER_C2);
180 translator.addPair(string_papersize[22], PAPER_C3);
181 translator.addPair(string_papersize[23], PAPER_C4);
182 translator.addPair(string_papersize[24], PAPER_C5);
183 translator.addPair(string_papersize[25], PAPER_C6);
184 translator.addPair(string_papersize[26], PAPER_JISB0);
185 translator.addPair(string_papersize[27], PAPER_JISB1);
186 translator.addPair(string_papersize[28], PAPER_JISB2);
187 translator.addPair(string_papersize[29], PAPER_JISB3);
188 translator.addPair(string_papersize[30], PAPER_JISB4);
189 translator.addPair(string_papersize[31], PAPER_JISB5);
190 translator.addPair(string_papersize[32], PAPER_JISB6);
195 PaperSizeTranslator const & papersizetranslator()
197 static PaperSizeTranslator const translator =
198 initPaperSizeTranslator();
204 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
207 PaperOrientationTranslator const init_paperorientationtranslator()
209 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
210 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
215 PaperOrientationTranslator const & paperorientationtranslator()
217 static PaperOrientationTranslator const translator =
218 init_paperorientationtranslator();
224 typedef Translator<int, PageSides> SidesTranslator;
227 SidesTranslator const init_sidestranslator()
229 SidesTranslator translator(1, OneSide);
230 translator.addPair(2, TwoSides);
235 SidesTranslator const & sidestranslator()
237 static SidesTranslator const translator = init_sidestranslator();
243 typedef Translator<int, BufferParams::Package> PackageTranslator;
246 PackageTranslator const init_packagetranslator()
248 PackageTranslator translator(0, BufferParams::package_off);
249 translator.addPair(1, BufferParams::package_auto);
250 translator.addPair(2, BufferParams::package_on);
255 PackageTranslator const & packagetranslator()
257 static PackageTranslator const translator =
258 init_packagetranslator();
264 typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator;
267 CiteEngineTypeTranslator const init_citeenginetypetranslator()
269 CiteEngineTypeTranslator translator("authoryear", ENGINE_TYPE_AUTHORYEAR);
270 translator.addPair("numerical", ENGINE_TYPE_NUMERICAL);
271 translator.addPair("default", ENGINE_TYPE_DEFAULT);
276 CiteEngineTypeTranslator const & citeenginetypetranslator()
278 static CiteEngineTypeTranslator const translator =
279 init_citeenginetypetranslator();
285 typedef Translator<string, Spacing::Space> SpaceTranslator;
288 SpaceTranslator const init_spacetranslator()
290 SpaceTranslator translator("default", Spacing::Default);
291 translator.addPair("single", Spacing::Single);
292 translator.addPair("onehalf", Spacing::Onehalf);
293 translator.addPair("double", Spacing::Double);
294 translator.addPair("other", Spacing::Other);
299 SpaceTranslator const & spacetranslator()
301 static SpaceTranslator const translator = init_spacetranslator();
308 class BufferParams::Impl
313 AuthorList authorlist;
314 BranchList branchlist;
315 Bullet temp_bullets[4];
316 Bullet user_defined_bullets[4];
317 IndicesList indiceslist;
319 /** This is the amount of space used for paragraph_separation "skip",
320 * and for detached paragraphs in "indented" documents.
324 PDFOptions pdfoptions;
325 LayoutFileIndex baseClass_;
329 BufferParams::Impl::Impl()
330 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
332 // set initial author
334 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
339 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
342 return new BufferParams::Impl(*ptr);
346 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
352 BufferParams::BufferParams()
355 setBaseClass(defaultBaseclass());
357 paragraph_separation = ParagraphIndentSeparation;
358 quotes_language = InsetQuotes::EnglishQuotes;
359 fontsize = "default";
362 papersize = PAPER_DEFAULT;
363 orientation = ORIENTATION_PORTRAIT;
364 use_geometry = false;
365 cite_engine_.push_back("basic");
366 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
367 biblio_style = "plain";
368 use_bibtopic = false;
370 track_changes = false;
371 output_changes = false;
372 use_default_options = true;
373 maintain_unincluded_children = false;
376 language = default_language;
378 fonts_roman = "default";
379 fonts_sans = "default";
380 fonts_typewriter = "default";
382 fonts_default_family = "default";
383 useNonTeXFonts = false;
384 fonts_expert_sc = false;
385 fonts_old_figures = false;
386 fonts_sans_scale = 100;
387 fonts_typewriter_scale = 100;
389 lang_package = "default";
390 graphics_driver = "default";
391 default_output_format = "default";
392 bibtex_command = "default";
393 index_command = "default";
396 listings_params = string();
397 pagestyle = "default";
398 suppress_date = false;
399 justification = true;
400 // no color is the default (white)
401 backgroundcolor = lyx::rgbFromHexName("#ffffff");
402 isbackgroundcolor = false;
403 // no color is the default (black)
404 fontcolor = lyx::rgbFromHexName("#000000");
406 // light gray is the default font color for greyed-out notes
407 notefontcolor = lyx::rgbFromHexName("#cccccc");
408 boxbgcolor = lyx::rgbFromHexName("#ff0000");
409 compressed = lyxrc.save_compressed;
410 for (int iter = 0; iter < 4; ++iter) {
411 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
412 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
415 indiceslist().addDefault(B_("Index"));
416 html_be_strict = false;
417 html_math_output = MathML;
418 html_math_img_scale = 1.0;
419 html_css_as_file = false;
420 display_pixel_ratio = 1.0;
427 docstring BufferParams::B_(string const & l10n) const
429 LASSERT(language, return from_utf8(l10n));
430 return getMessages(language->code()).get(l10n);
434 BufferParams::Package BufferParams::use_package(std::string const & p) const
436 PackageMap::const_iterator it = use_packages.find(p);
437 if (it == use_packages.end())
443 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
449 map<string, string> const & BufferParams::auto_packages()
451 static map<string, string> packages;
452 if (packages.empty()) {
453 // We could have a race condition here that two threads
454 // discover an empty map at the same time and want to fill
455 // it, but that is no problem, since the same contents is
456 // filled in twice then. Having the locker inside the
457 // packages.empty() condition has the advantage that we
458 // don't need the mutex overhead for simple reading.
460 Mutex::Locker locker(&mutex);
461 // adding a package here implies a file format change!
462 packages["amsmath"] =
463 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
464 packages["amssymb"] =
465 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
467 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
469 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
470 packages["mathdots"] =
471 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
472 packages["mathtools"] =
473 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
475 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
476 packages["stackrel"] =
477 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
478 packages["stmaryrd"] =
479 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");
480 packages["undertilde"] =
481 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
487 AuthorList & BufferParams::authors()
489 return pimpl_->authorlist;
493 AuthorList const & BufferParams::authors() const
495 return pimpl_->authorlist;
499 BranchList & BufferParams::branchlist()
501 return pimpl_->branchlist;
505 BranchList const & BufferParams::branchlist() const
507 return pimpl_->branchlist;
511 IndicesList & BufferParams::indiceslist()
513 return pimpl_->indiceslist;
517 IndicesList const & BufferParams::indiceslist() const
519 return pimpl_->indiceslist;
523 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
525 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
526 return pimpl_->temp_bullets[index];
530 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
532 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
533 return pimpl_->temp_bullets[index];
537 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
539 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
540 return pimpl_->user_defined_bullets[index];
544 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
546 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
547 return pimpl_->user_defined_bullets[index];
551 Spacing & BufferParams::spacing()
553 return pimpl_->spacing;
557 Spacing const & BufferParams::spacing() const
559 return pimpl_->spacing;
563 PDFOptions & BufferParams::pdfoptions()
565 return pimpl_->pdfoptions;
569 PDFOptions const & BufferParams::pdfoptions() const
571 return pimpl_->pdfoptions;
575 HSpace const & BufferParams::getIndentation() const
577 return pimpl_->indentation;
581 void BufferParams::setIndentation(HSpace const & indent)
583 pimpl_->indentation = indent;
587 VSpace const & BufferParams::getDefSkip() const
589 return pimpl_->defskip;
593 void BufferParams::setDefSkip(VSpace const & vs)
595 // DEFSKIP will cause an infinite loop
596 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
597 pimpl_->defskip = vs;
601 string BufferParams::readToken(Lexer & lex, string const & token,
602 FileName const & filepath)
604 if (token == "\\textclass") {
606 string const classname = lex.getString();
607 // if there exists a local layout file, ignore the system one
608 // NOTE: in this case, the textclass (.cls file) is assumed to
611 LayoutFileList & bcl = LayoutFileList::get();
612 if (!filepath.empty())
613 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
614 // that returns non-empty if a "local" layout file is found.
618 setBaseClass(classname);
619 // We assume that a tex class exists for local or unknown
620 // layouts so this warning, will only be given for system layouts.
621 if (!baseClass()->isTeXClassAvailable()) {
622 docstring const desc =
623 translateIfPossible(from_utf8(baseClass()->description()));
624 docstring const prereqs =
625 from_utf8(baseClass()->prerequisites());
626 docstring const msg =
627 bformat(_("The selected document class\n"
629 "requires external files that are not available.\n"
630 "The document class can still be used, but the\n"
631 "document cannot be compiled until the following\n"
632 "prerequisites are installed:\n"
634 "See section 3.1.2.2 (Class Availability) of the\n"
635 "User's Guide for more information."), desc, prereqs);
636 frontend::Alert::warning(_("Document class not available"),
639 } else if (token == "\\begin_preamble") {
641 } else if (token == "\\begin_local_layout") {
642 readLocalLayout(lex, false);
643 } else if (token == "\\begin_forced_local_layout") {
644 readLocalLayout(lex, true);
645 } else if (token == "\\begin_modules") {
647 } else if (token == "\\begin_removed_modules") {
648 readRemovedModules(lex);
649 } else if (token == "\\begin_includeonly") {
650 readIncludeonly(lex);
651 } else if (token == "\\maintain_unincluded_children") {
652 lex >> maintain_unincluded_children;
653 } else if (token == "\\options") {
655 options = lex.getString();
656 } else if (token == "\\use_default_options") {
657 lex >> use_default_options;
658 } else if (token == "\\master") {
660 master = lex.getString();
661 } else if (token == "\\suppress_date") {
662 lex >> suppress_date;
663 } else if (token == "\\justification") {
664 lex >> justification;
665 } else if (token == "\\language") {
667 } else if (token == "\\language_package") {
669 lang_package = lex.getString();
670 } else if (token == "\\inputencoding") {
672 } else if (token == "\\graphics") {
673 readGraphicsDriver(lex);
674 } else if (token == "\\default_output_format") {
675 lex >> default_output_format;
676 } else if (token == "\\bibtex_command") {
678 bibtex_command = lex.getString();
679 } else if (token == "\\index_command") {
681 index_command = lex.getString();
682 } else if (token == "\\fontencoding") {
684 fontenc = lex.getString();
685 } else if (token == "\\font_roman") {
687 fonts_roman = lex.getString();
688 } else if (token == "\\font_sans") {
690 fonts_sans = lex.getString();
691 } else if (token == "\\font_typewriter") {
693 fonts_typewriter = lex.getString();
694 } else if (token == "\\font_math") {
696 fonts_math = lex.getString();
697 } else if (token == "\\font_default_family") {
698 lex >> fonts_default_family;
699 } else if (token == "\\use_non_tex_fonts") {
700 lex >> useNonTeXFonts;
701 } else if (token == "\\font_sc") {
702 lex >> fonts_expert_sc;
703 } else if (token == "\\font_osf") {
704 lex >> fonts_old_figures;
705 } else if (token == "\\font_sf_scale") {
706 lex >> fonts_sans_scale;
707 } else if (token == "\\font_tt_scale") {
708 lex >> fonts_typewriter_scale;
709 } else if (token == "\\font_cjk") {
711 } else if (token == "\\paragraph_separation") {
714 paragraph_separation = parseptranslator().find(parsep);
715 } else if (token == "\\paragraph_indentation") {
717 string indentation = lex.getString();
718 pimpl_->indentation = HSpace(indentation);
719 } else if (token == "\\defskip") {
721 string const defskip = lex.getString();
722 pimpl_->defskip = VSpace(defskip);
723 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
725 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
726 } else if (token == "\\quotes_language") {
729 quotes_language = quoteslangtranslator().find(quotes_lang);
730 } else if (token == "\\papersize") {
733 papersize = papersizetranslator().find(ppsize);
734 } else if (token == "\\use_geometry") {
736 } else if (token == "\\use_package") {
741 use_package(package, packagetranslator().find(use));
742 } else if (token == "\\cite_engine") {
744 vector<string> engine = getVectorFromString(lex.getString());
745 setCiteEngine(engine);
746 } else if (token == "\\cite_engine_type") {
749 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
750 } else if (token == "\\biblio_style") {
752 biblio_style = lex.getString();
753 } else if (token == "\\use_bibtopic") {
755 } else if (token == "\\use_indices") {
757 } else if (token == "\\tracking_changes") {
758 lex >> track_changes;
759 } else if (token == "\\output_changes") {
760 lex >> output_changes;
761 } else if (token == "\\branch") {
763 docstring branch = lex.getDocString();
764 branchlist().add(branch);
767 string const tok = lex.getString();
768 if (tok == "\\end_branch")
770 Branch * branch_ptr = branchlist().find(branch);
771 if (tok == "\\selected") {
774 branch_ptr->setSelected(lex.getInteger());
776 if (tok == "\\filename_suffix") {
779 branch_ptr->setFileNameSuffix(lex.getInteger());
781 if (tok == "\\color") {
783 string color = lex.getString();
785 branch_ptr->setColor(color);
786 // Update also the Color table:
788 color = lcolor.getX11Name(Color_background);
790 lcolor.setColor(to_utf8(branch), color);
793 } else if (token == "\\index") {
795 docstring index = lex.getDocString();
797 indiceslist().add(index);
800 string const tok = lex.getString();
801 if (tok == "\\end_index")
803 Index * index_ptr = indiceslist().find(index);
804 if (tok == "\\shortcut") {
806 shortcut = lex.getDocString();
808 index_ptr->setShortcut(shortcut);
810 if (tok == "\\color") {
812 string color = lex.getString();
814 index_ptr->setColor(color);
815 // Update also the Color table:
817 color = lcolor.getX11Name(Color_background);
819 if (!shortcut.empty())
820 lcolor.setColor(to_utf8(shortcut), color);
823 } else if (token == "\\author") {
825 istringstream ss(lex.getString());
828 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
829 } else if (token == "\\paperorientation") {
832 orientation = paperorientationtranslator().find(orient);
833 } else if (token == "\\backgroundcolor") {
835 backgroundcolor = lyx::rgbFromHexName(lex.getString());
836 isbackgroundcolor = true;
837 } else if (token == "\\fontcolor") {
839 fontcolor = lyx::rgbFromHexName(lex.getString());
841 } else if (token == "\\notefontcolor") {
843 string color = lex.getString();
844 notefontcolor = lyx::rgbFromHexName(color);
845 lcolor.setColor("notefontcolor", color);
846 } else if (token == "\\boxbgcolor") {
848 string color = lex.getString();
849 boxbgcolor = lyx::rgbFromHexName(color);
850 lcolor.setColor("boxbgcolor", color);
851 } else if (token == "\\paperwidth") {
853 } else if (token == "\\paperheight") {
855 } else if (token == "\\leftmargin") {
857 } else if (token == "\\topmargin") {
859 } else if (token == "\\rightmargin") {
861 } else if (token == "\\bottommargin") {
863 } else if (token == "\\headheight") {
865 } else if (token == "\\headsep") {
867 } else if (token == "\\footskip") {
869 } else if (token == "\\columnsep") {
871 } else if (token == "\\paperfontsize") {
873 } else if (token == "\\papercolumns") {
875 } else if (token == "\\listings_params") {
878 listings_params = InsetListingsParams(par).params();
879 } else if (token == "\\papersides") {
882 sides = sidestranslator().find(psides);
883 } else if (token == "\\paperpagestyle") {
885 } else if (token == "\\bullet") {
887 } else if (token == "\\bulletLaTeX") {
888 readBulletsLaTeX(lex);
889 } else if (token == "\\secnumdepth") {
891 } else if (token == "\\tocdepth") {
893 } else if (token == "\\spacing") {
897 if (nspacing == "other") {
900 spacing().set(spacetranslator().find(nspacing), tmp_val);
901 } else if (token == "\\float_placement") {
902 lex >> float_placement;
904 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
905 string toktmp = pdfoptions().readToken(lex, token);
906 if (!toktmp.empty()) {
907 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
911 } else if (token == "\\html_math_output") {
914 html_math_output = static_cast<MathOutput>(temp);
915 } else if (token == "\\html_be_strict") {
916 lex >> html_be_strict;
917 } else if (token == "\\html_css_as_file") {
918 lex >> html_css_as_file;
919 } else if (token == "\\html_math_img_scale") {
920 lex >> html_math_img_scale;
921 } else if (token == "\\html_latex_start") {
923 html_latex_start = lex.getString();
924 } else if (token == "\\html_latex_end") {
926 html_latex_end = lex.getString();
927 } else if (token == "\\output_sync") {
929 } else if (token == "\\output_sync_macro") {
930 lex >> output_sync_macro;
931 } else if (token == "\\use_refstyle") {
934 lyxerr << "BufferParams::readToken(): Unknown token: " <<
943 void BufferParams::writeFile(ostream & os) const
945 // The top of the file is written by the buffer.
946 // Prints out the buffer info into the .lyx file given by file
949 os << "\\textclass " << baseClass()->name() << '\n';
952 if (!preamble.empty()) {
953 // remove '\n' from the end of preamble
954 string const tmppreamble = rtrim(preamble, "\n");
955 os << "\\begin_preamble\n"
957 << "\n\\end_preamble\n";
961 if (!options.empty()) {
962 os << "\\options " << options << '\n';
965 // use the class options defined in the layout?
966 os << "\\use_default_options "
967 << convert<string>(use_default_options) << "\n";
969 // the master document
970 if (!master.empty()) {
971 os << "\\master " << master << '\n';
975 if (!removed_modules_.empty()) {
976 os << "\\begin_removed_modules" << '\n';
977 list<string>::const_iterator it = removed_modules_.begin();
978 list<string>::const_iterator en = removed_modules_.end();
979 for (; it != en; ++it)
981 os << "\\end_removed_modules" << '\n';
985 if (!layout_modules_.empty()) {
986 os << "\\begin_modules" << '\n';
987 LayoutModuleList::const_iterator it = layout_modules_.begin();
988 LayoutModuleList::const_iterator en = layout_modules_.end();
989 for (; it != en; ++it)
991 os << "\\end_modules" << '\n';
995 if (!included_children_.empty()) {
996 os << "\\begin_includeonly" << '\n';
997 list<string>::const_iterator it = included_children_.begin();
998 list<string>::const_iterator en = included_children_.end();
999 for (; it != en; ++it)
1001 os << "\\end_includeonly" << '\n';
1003 os << "\\maintain_unincluded_children "
1004 << convert<string>(maintain_unincluded_children) << '\n';
1006 // local layout information
1007 string const local_layout = getLocalLayout(false);
1008 if (!local_layout.empty()) {
1009 // remove '\n' from the end
1010 string const tmplocal = rtrim(local_layout, "\n");
1011 os << "\\begin_local_layout\n"
1013 << "\n\\end_local_layout\n";
1015 string const forced_local_layout = getLocalLayout(true);
1016 if (!forced_local_layout.empty()) {
1017 // remove '\n' from the end
1018 string const tmplocal = rtrim(forced_local_layout, "\n");
1019 os << "\\begin_forced_local_layout\n"
1021 << "\n\\end_forced_local_layout\n";
1024 // then the text parameters
1025 if (language != ignore_language)
1026 os << "\\language " << language->lang() << '\n';
1027 os << "\\language_package " << lang_package
1028 << "\n\\inputencoding " << inputenc
1029 << "\n\\fontencoding " << fontenc
1030 << "\n\\font_roman " << fonts_roman
1031 << "\n\\font_sans " << fonts_sans
1032 << "\n\\font_typewriter " << fonts_typewriter
1033 << "\n\\font_math " << fonts_math
1034 << "\n\\font_default_family " << fonts_default_family
1035 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1036 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1037 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1038 << "\n\\font_sf_scale " << fonts_sans_scale
1039 << "\n\\font_tt_scale " << fonts_typewriter_scale
1041 if (!fonts_cjk.empty()) {
1042 os << "\\font_cjk " << fonts_cjk << '\n';
1044 os << "\\graphics " << graphics_driver << '\n';
1045 os << "\\default_output_format " << default_output_format << '\n';
1046 os << "\\output_sync " << output_sync << '\n';
1047 if (!output_sync_macro.empty())
1048 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1049 os << "\\bibtex_command " << bibtex_command << '\n';
1050 os << "\\index_command " << index_command << '\n';
1052 if (!float_placement.empty()) {
1053 os << "\\float_placement " << float_placement << '\n';
1055 os << "\\paperfontsize " << fontsize << '\n';
1057 spacing().writeFile(os);
1058 pdfoptions().writeFile(os);
1060 os << "\\papersize " << string_papersize[papersize]
1061 << "\n\\use_geometry " << convert<string>(use_geometry);
1062 map<string, string> const & packages = auto_packages();
1063 for (map<string, string>::const_iterator it = packages.begin();
1064 it != packages.end(); ++it)
1065 os << "\n\\use_package " << it->first << ' '
1066 << use_package(it->first);
1068 os << "\n\\cite_engine ";
1070 if (!cite_engine_.empty()) {
1071 LayoutModuleList::const_iterator be = cite_engine_.begin();
1072 LayoutModuleList::const_iterator en = cite_engine_.end();
1073 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1082 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1083 << "\n\\biblio_style " << biblio_style
1084 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1085 << "\n\\use_indices " << convert<string>(use_indices)
1086 << "\n\\paperorientation " << string_orientation[orientation]
1087 << "\n\\suppress_date " << convert<string>(suppress_date)
1088 << "\n\\justification " << convert<string>(justification)
1089 << "\n\\use_refstyle " << use_refstyle
1091 if (isbackgroundcolor == true)
1092 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1093 if (isfontcolor == true)
1094 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1095 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1096 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1097 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1098 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1100 BranchList::const_iterator it = branchlist().begin();
1101 BranchList::const_iterator end = branchlist().end();
1102 for (; it != end; ++it) {
1103 os << "\\branch " << to_utf8(it->branch())
1104 << "\n\\selected " << it->isSelected()
1105 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1106 << "\n\\color " << lyx::X11hexname(it->color())
1111 IndicesList::const_iterator iit = indiceslist().begin();
1112 IndicesList::const_iterator iend = indiceslist().end();
1113 for (; iit != iend; ++iit) {
1114 os << "\\index " << to_utf8(iit->index())
1115 << "\n\\shortcut " << to_utf8(iit->shortcut())
1116 << "\n\\color " << lyx::X11hexname(iit->color())
1121 if (!paperwidth.empty())
1122 os << "\\paperwidth "
1123 << VSpace(paperwidth).asLyXCommand() << '\n';
1124 if (!paperheight.empty())
1125 os << "\\paperheight "
1126 << VSpace(paperheight).asLyXCommand() << '\n';
1127 if (!leftmargin.empty())
1128 os << "\\leftmargin "
1129 << VSpace(leftmargin).asLyXCommand() << '\n';
1130 if (!topmargin.empty())
1131 os << "\\topmargin "
1132 << VSpace(topmargin).asLyXCommand() << '\n';
1133 if (!rightmargin.empty())
1134 os << "\\rightmargin "
1135 << VSpace(rightmargin).asLyXCommand() << '\n';
1136 if (!bottommargin.empty())
1137 os << "\\bottommargin "
1138 << VSpace(bottommargin).asLyXCommand() << '\n';
1139 if (!headheight.empty())
1140 os << "\\headheight "
1141 << VSpace(headheight).asLyXCommand() << '\n';
1142 if (!headsep.empty())
1144 << VSpace(headsep).asLyXCommand() << '\n';
1145 if (!footskip.empty())
1147 << VSpace(footskip).asLyXCommand() << '\n';
1148 if (!columnsep.empty())
1149 os << "\\columnsep "
1150 << VSpace(columnsep).asLyXCommand() << '\n';
1151 os << "\\secnumdepth " << secnumdepth
1152 << "\n\\tocdepth " << tocdepth
1153 << "\n\\paragraph_separation "
1154 << string_paragraph_separation[paragraph_separation];
1155 if (!paragraph_separation)
1156 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1158 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1159 os << "\n\\quotes_language "
1160 << string_quotes_language[quotes_language]
1161 << "\n\\papercolumns " << columns
1162 << "\n\\papersides " << sides
1163 << "\n\\paperpagestyle " << pagestyle << '\n';
1164 if (!listings_params.empty())
1165 os << "\\listings_params \"" <<
1166 InsetListingsParams(listings_params).encodedString() << "\"\n";
1167 for (int i = 0; i < 4; ++i) {
1168 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1169 if (user_defined_bullet(i).getFont() != -1) {
1170 os << "\\bullet " << i << " "
1171 << user_defined_bullet(i).getFont() << " "
1172 << user_defined_bullet(i).getCharacter() << " "
1173 << user_defined_bullet(i).getSize() << "\n";
1177 os << "\\bulletLaTeX " << i << " \""
1178 << lyx::to_ascii(user_defined_bullet(i).getText())
1184 os << "\\tracking_changes " << convert<string>(track_changes) << '\n'
1185 << "\\output_changes " << convert<string>(output_changes) << '\n'
1186 << "\\html_math_output " << html_math_output << '\n'
1187 << "\\html_css_as_file " << html_css_as_file << '\n'
1188 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1190 if (html_math_img_scale != 1.0)
1191 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1192 if (!html_latex_start.empty())
1193 os << "\\html_latex_start " << html_latex_start << '\n';
1194 if (!html_latex_end.empty())
1195 os << "\\html_latex_end " << html_latex_end << '\n';
1197 os << pimpl_->authorlist;
1201 void BufferParams::validate(LaTeXFeatures & features) const
1203 features.require(documentClass().requires());
1205 if (columns > 1 && language->rightToLeft())
1206 features.require("rtloutputdblcol");
1208 if (output_changes) {
1209 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1210 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1211 LaTeXFeatures::isAvailable("xcolor");
1213 switch (features.runparams().flavor) {
1214 case OutputParams::LATEX:
1215 case OutputParams::DVILUATEX:
1217 features.require("ct-dvipost");
1218 features.require("dvipost");
1219 } else if (xcolorulem) {
1220 features.require("ct-xcolor-ulem");
1221 features.require("ulem");
1222 features.require("xcolor");
1224 features.require("ct-none");
1227 case OutputParams::LUATEX:
1228 case OutputParams::PDFLATEX:
1229 case OutputParams::XETEX:
1231 features.require("ct-xcolor-ulem");
1232 features.require("ulem");
1233 features.require("xcolor");
1234 // improves color handling in PDF output
1235 features.require("pdfcolmk");
1237 features.require("ct-none");
1245 // Floats with 'Here definitely' as default setting.
1246 if (float_placement.find('H') != string::npos)
1247 features.require("float");
1249 for (PackageMap::const_iterator it = use_packages.begin();
1250 it != use_packages.end(); ++it) {
1251 if (it->first == "amsmath") {
1252 // AMS Style is at document level
1253 if (it->second == package_on ||
1254 features.isProvided("amsmath"))
1255 features.require(it->first);
1256 } else if (it->second == package_on)
1257 features.require(it->first);
1260 // Document-level line spacing
1261 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1262 features.require("setspace");
1264 // the bullet shapes are buffer level not paragraph level
1265 // so they are tested here
1266 for (int i = 0; i < 4; ++i) {
1267 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1269 int const font = user_defined_bullet(i).getFont();
1271 int const c = user_defined_bullet(i).getCharacter();
1277 features.require("latexsym");
1279 } else if (font == 1) {
1280 features.require("amssymb");
1281 } else if (font >= 2 && font <= 5) {
1282 features.require("pifont");
1286 if (pdfoptions().use_hyperref) {
1287 features.require("hyperref");
1288 // due to interferences with babel and hyperref, the color package has to
1289 // be loaded after hyperref when hyperref is used with the colorlinks
1290 // option, see http://www.lyx.org/trac/ticket/5291
1291 if (pdfoptions().colorlinks)
1292 features.require("color");
1294 if (!listings_params.empty()) {
1295 // do not test validity because listings_params is
1296 // supposed to be valid
1298 InsetListingsParams(listings_params).separatedParams(true);
1299 // we can't support all packages, but we should load the color package
1300 if (par.find("\\color", 0) != string::npos)
1301 features.require("color");
1304 // some languages are only available via polyglossia
1305 if (features.runparams().flavor == OutputParams::XETEX
1306 && (features.hasPolyglossiaExclusiveLanguages()
1308 features.require("polyglossia");
1310 if (useNonTeXFonts && fonts_math != "auto")
1311 features.require("unicode-math");
1313 if (!language->requires().empty())
1314 features.require(language->requires());
1318 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1319 FileName const & filepath) const
1321 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1322 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1323 // \RequirePackage to do so, rather than the normal \usepackage
1324 // Do not try to load any other package before the document class, unless you
1325 // have a thorough understanding of the LATEX internals and know exactly what you
1327 if (features.mustProvide("fix-cm"))
1328 os << "\\RequirePackage{fix-cm}\n";
1329 // Likewise for fixltx2e. If other packages conflict with this policy,
1330 // treat it as a package bug (and report it!)
1331 // See http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4407
1332 if (features.mustProvide("fixltx2e"))
1333 os << "\\RequirePackage{fixltx2e}\n";
1335 os << "\\documentclass";
1337 DocumentClass const & tclass = documentClass();
1339 ostringstream clsoptions; // the document class options.
1341 if (tokenPos(tclass.opt_fontsize(),
1342 '|', fontsize) >= 0) {
1343 // only write if existing in list (and not default)
1344 clsoptions << fontsize << "pt,";
1347 // all paper sizes except of A4, A5, B5 and the US sizes need the
1349 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1350 && papersize != PAPER_USLETTER
1351 && papersize != PAPER_USLEGAL
1352 && papersize != PAPER_USEXECUTIVE
1353 && papersize != PAPER_A4
1354 && papersize != PAPER_A5
1355 && papersize != PAPER_B5;
1357 if (!use_geometry) {
1358 switch (papersize) {
1360 clsoptions << "a4paper,";
1362 case PAPER_USLETTER:
1363 clsoptions << "letterpaper,";
1366 clsoptions << "a5paper,";
1369 clsoptions << "b5paper,";
1371 case PAPER_USEXECUTIVE:
1372 clsoptions << "executivepaper,";
1375 clsoptions << "legalpaper,";
1409 if (sides != tclass.sides()) {
1412 clsoptions << "oneside,";
1415 clsoptions << "twoside,";
1421 if (columns != tclass.columns()) {
1423 clsoptions << "twocolumn,";
1425 clsoptions << "onecolumn,";
1429 && orientation == ORIENTATION_LANDSCAPE)
1430 clsoptions << "landscape,";
1432 // language should be a parameter to \documentclass
1433 if (language->babel() == "hebrew"
1434 && default_language->babel() != "hebrew")
1435 // This seems necessary
1436 features.useLanguage(default_language);
1438 ostringstream language_options;
1439 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1440 bool const use_polyglossia = features.usePolyglossia();
1441 bool const global = lyxrc.language_global_options;
1442 if (use_babel || (use_polyglossia && global)) {
1443 language_options << features.getBabelLanguages();
1444 if (!language->babel().empty()) {
1445 if (!language_options.str().empty())
1446 language_options << ',';
1447 language_options << language->babel();
1449 if (global && !features.needBabelLangOptions()
1450 && !language_options.str().empty())
1451 clsoptions << language_options.str() << ',';
1454 // the predefined options from the layout
1455 if (use_default_options && !tclass.options().empty())
1456 clsoptions << tclass.options() << ',';
1458 // the user-defined options
1459 if (!options.empty()) {
1460 clsoptions << options << ',';
1463 string strOptions(clsoptions.str());
1464 if (!strOptions.empty()) {
1465 strOptions = rtrim(strOptions, ",");
1467 os << '[' << from_utf8(strOptions) << ']';
1470 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1471 // end of \documentclass defs
1473 // if we use fontspec or newtxmath, we have to load the AMS packages here
1474 string const ams = features.loadAMSPackages();
1475 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1476 bool const use_newtxmath =
1477 theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getUsedPackage(
1478 ot1, false, false) == "newtxmath";
1479 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1480 os << from_ascii(ams);
1482 if (useNonTeXFonts) {
1483 os << "\\usepackage{fontspec}\n";
1484 if (features.mustProvide("unicode-math")
1485 && features.isAvailable("unicode-math"))
1486 os << "\\usepackage{unicode-math}\n";
1489 // font selection must be done before loading fontenc.sty
1490 string const fonts = loadFonts(features);
1492 os << from_utf8(fonts);
1494 if (fonts_default_family != "default")
1495 os << "\\renewcommand{\\familydefault}{\\"
1496 << from_ascii(fonts_default_family) << "}\n";
1498 // set font encoding
1499 // XeTeX and LuaTeX (with OS fonts) do not need fontenc
1500 if (!useNonTeXFonts && !features.isProvided("fontenc")
1501 && font_encoding() != "default") {
1502 // get main font encodings
1503 vector<string> fontencs = font_encodings();
1504 // get font encodings of secondary languages
1505 features.getFontEncodings(fontencs);
1506 if (!fontencs.empty()) {
1507 os << "\\usepackage["
1508 << from_ascii(getStringFromVector(fontencs))
1513 // handle inputenc etc.
1514 writeEncodingPreamble(os, features);
1517 if (!features.runparams().includeall && !included_children_.empty()) {
1518 os << "\\includeonly{";
1519 list<string>::const_iterator it = included_children_.begin();
1520 list<string>::const_iterator en = included_children_.end();
1522 for (; it != en; ++it) {
1523 string incfile = *it;
1524 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1525 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1527 if (!features.runparams().nice)
1529 // \includeonly doesn't want an extension
1530 incfile = changeExtension(incfile, string());
1531 incfile = support::latex_path(incfile);
1532 if (!incfile.empty()) {
1535 os << from_utf8(incfile);
1542 if (!features.isProvided("geometry")
1543 && (use_geometry || nonstandard_papersize)) {
1544 odocstringstream ods;
1545 if (!getGraphicsDriver("geometry").empty())
1546 ods << getGraphicsDriver("geometry");
1547 if (orientation == ORIENTATION_LANDSCAPE)
1548 ods << ",landscape";
1549 switch (papersize) {
1551 if (!paperwidth.empty())
1552 ods << ",paperwidth="
1553 << from_ascii(paperwidth);
1554 if (!paperheight.empty())
1555 ods << ",paperheight="
1556 << from_ascii(paperheight);
1558 case PAPER_USLETTER:
1559 ods << ",letterpaper";
1562 ods << ",legalpaper";
1564 case PAPER_USEXECUTIVE:
1565 ods << ",executivepaper";
1654 docstring const g_options = trim(ods.str(), ",");
1655 os << "\\usepackage";
1656 if (!g_options.empty())
1657 os << '[' << g_options << ']';
1658 os << "{geometry}\n";
1659 // output this only if use_geometry is true
1661 os << "\\geometry{verbose";
1662 if (!topmargin.empty())
1663 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1664 if (!bottommargin.empty())
1665 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1666 if (!leftmargin.empty())
1667 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1668 if (!rightmargin.empty())
1669 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1670 if (!headheight.empty())
1671 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1672 if (!headsep.empty())
1673 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1674 if (!footskip.empty())
1675 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1676 if (!columnsep.empty())
1677 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1680 } else if (orientation == ORIENTATION_LANDSCAPE
1681 || papersize != PAPER_DEFAULT) {
1682 features.require("papersize");
1685 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1686 if (pagestyle == "fancy")
1687 os << "\\usepackage{fancyhdr}\n";
1688 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1691 // only output when the background color is not default
1692 if (isbackgroundcolor == true) {
1693 // only require color here, the background color will be defined
1694 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1696 features.require("color");
1697 features.require("pagecolor");
1700 // only output when the font color is not default
1701 if (isfontcolor == true) {
1702 // only require color here, the font color will be defined
1703 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1705 features.require("color");
1706 features.require("fontcolor");
1709 // Only if class has a ToC hierarchy
1710 if (tclass.hasTocLevels()) {
1711 if (secnumdepth != tclass.secnumdepth()) {
1712 os << "\\setcounter{secnumdepth}{"
1716 if (tocdepth != tclass.tocdepth()) {
1717 os << "\\setcounter{tocdepth}{"
1723 if (paragraph_separation) {
1724 // when skip separation
1725 switch (getDefSkip().kind()) {
1726 case VSpace::SMALLSKIP:
1727 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1729 case VSpace::MEDSKIP:
1730 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1732 case VSpace::BIGSKIP:
1733 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1735 case VSpace::LENGTH:
1736 os << "\\setlength{\\parskip}{"
1737 << from_utf8(getDefSkip().length().asLatexString())
1740 default: // should never happen // Then delete it.
1741 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1744 os << "\\setlength{\\parindent}{0pt}\n";
1746 // when separation by indentation
1747 // only output something when a width is given
1748 if (getIndentation().asLyXCommand() != "default") {
1749 os << "\\setlength{\\parindent}{"
1750 << from_utf8(getIndentation().asLatexCommand())
1755 // Now insert the LyX specific LaTeX commands...
1756 docstring lyxpreamble;
1757 features.resolveAlternatives();
1760 if (!output_sync_macro.empty())
1761 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1762 else if (features.runparams().flavor == OutputParams::LATEX)
1763 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1764 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1765 lyxpreamble += "\\synctex=-1\n";
1768 // The package options (via \PassOptionsToPackage)
1769 lyxpreamble += from_ascii(features.getPackageOptions());
1771 // due to interferences with babel and hyperref, the color package has to
1772 // be loaded (when it is not already loaded) before babel when hyperref
1773 // is used with the colorlinks option, see
1774 // http://www.lyx.org/trac/ticket/5291
1775 // we decided therefore to load color always before babel, see
1776 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1777 lyxpreamble += from_ascii(features.getColorOptions());
1779 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1780 // we have to call babel before
1782 && (features.isRequired("jurabib")
1783 || features.isRequired("hyperref")
1784 || features.isRequired("varioref")
1785 || features.isRequired("vietnamese")
1786 || features.isRequired("japanese"))) {
1788 lyxpreamble += from_utf8(features.getBabelPresettings());
1789 lyxpreamble += from_utf8(babelCall(language_options.str(),
1790 features.needBabelLangOptions())) + '\n';
1791 lyxpreamble += from_utf8(features.getBabelPostsettings());
1794 // The optional packages;
1795 lyxpreamble += from_ascii(features.getPackages());
1797 // Additional Indices
1798 if (features.isRequired("splitidx")) {
1799 IndicesList::const_iterator iit = indiceslist().begin();
1800 IndicesList::const_iterator iend = indiceslist().end();
1801 for (; iit != iend; ++iit) {
1802 pair<docstring, docstring> indexname_latex =
1803 features.runparams().encoding->latexString(iit->index(),
1804 features.runparams().dryrun);
1805 if (!indexname_latex.second.empty()) {
1806 // issue a warning about omitted characters
1807 // FIXME: should be passed to the error dialog
1808 frontend::Alert::warning(_("Uncodable characters"),
1809 bformat(_("The following characters that are used in an index name are not\n"
1810 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1811 indexname_latex.second));
1813 lyxpreamble += "\\newindex[";
1814 lyxpreamble += indexname_latex.first;
1815 lyxpreamble += "]{";
1816 lyxpreamble += escape(iit->shortcut());
1817 lyxpreamble += "}\n";
1822 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1825 // * Hyperref manual: "Make sure it comes last of your loaded
1826 // packages, to give it a fighting chance of not being over-written,
1827 // since its job is to redefine many LaTeX commands."
1828 // * Email from Heiko Oberdiek: "It is usually better to load babel
1829 // before hyperref. Then hyperref has a chance to detect babel.
1830 // * Has to be loaded before the "LyX specific LaTeX commands" to
1831 // avoid errors with algorithm floats.
1832 // use hyperref explicitly if it is required
1833 if (features.isRequired("hyperref")) {
1834 // pass what we have to stream here, since we need
1835 // to access the stream itself in PDFOptions.
1838 OutputParams tmp_params = features.runparams();
1839 pdfoptions().writeLaTeX(tmp_params, os,
1840 features.isProvided("hyperref"));
1841 // set back for the rest
1842 lyxpreamble.clear();
1843 // correctly break URLs with hyperref and dvi output
1844 if (features.runparams().flavor == OutputParams::LATEX
1845 && features.isAvailable("breakurl"))
1846 lyxpreamble += "\\usepackage{breakurl}\n";
1847 } else if (features.isRequired("nameref"))
1848 // hyperref loads this automatically
1849 lyxpreamble += "\\usepackage{nameref}\n";
1851 // bibtopic needs to be loaded after hyperref.
1852 // the dot provides the aux file naming which LyX can detect.
1853 if (features.mustProvide("bibtopic"))
1854 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1856 // Will be surrounded by \makeatletter and \makeatother when not empty
1857 docstring atlyxpreamble;
1859 // Some macros LyX will need
1860 docstring tmppreamble(features.getMacros());
1862 if (!tmppreamble.empty())
1863 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1864 "LyX specific LaTeX commands.\n"
1865 + tmppreamble + '\n';
1867 // the text class specific preamble
1868 tmppreamble = features.getTClassPreamble();
1869 if (!tmppreamble.empty())
1870 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1871 "Textclass specific LaTeX commands.\n"
1872 + tmppreamble + '\n';
1874 // suppress date if selected
1875 // use \@ifundefined because we cannot be sure that every document class
1876 // has a \date command
1878 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1880 /* the user-defined preamble */
1881 if (!containsOnly(preamble, " \n\t"))
1883 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1884 "User specified LaTeX commands.\n"
1885 + from_utf8(preamble) + '\n';
1887 // footmisc must be loaded after setspace
1888 // Load it here to avoid clashes with footmisc loaded in the user
1889 // preamble. For that reason we also pass the options via
1890 // \PassOptionsToPackage in getPreamble() and not here.
1891 if (features.mustProvide("footmisc"))
1892 atlyxpreamble += "\\usepackage{footmisc}\n";
1894 // subfig loads internally the LaTeX package "caption". As
1895 // caption is a very popular package, users will load it in
1896 // the preamble. Therefore we must load subfig behind the
1897 // user-defined preamble and check if the caption package was
1898 // loaded or not. For the case that caption is loaded before
1899 // subfig, there is the subfig option "caption=false". This
1900 // option also works when a koma-script class is used and
1901 // koma's own caption commands are used instead of caption. We
1902 // use \PassOptionsToPackage here because the user could have
1903 // already loaded subfig in the preamble.
1904 if (features.isRequired("subfig")) {
1905 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1906 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1907 "\\usepackage{subfig}\n";
1910 // Itemize bullet settings need to be last in case the user
1911 // defines their own bullets that use a package included
1912 // in the user-defined preamble -- ARRae
1913 // Actually it has to be done much later than that
1914 // since some packages like frenchb make modifications
1915 // at \begin{document} time -- JMarc
1916 docstring bullets_def;
1917 for (int i = 0; i < 4; ++i) {
1918 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1919 if (bullets_def.empty())
1920 bullets_def += "\\AtBeginDocument{\n";
1921 bullets_def += " \\def\\labelitemi";
1923 // `i' is one less than the item to modify
1930 bullets_def += "ii";
1936 bullets_def += '{' +
1937 user_defined_bullet(i).getText()
1942 if (!bullets_def.empty())
1943 atlyxpreamble += bullets_def + "}\n\n";
1945 if (!atlyxpreamble.empty())
1946 lyxpreamble += "\n\\makeatletter\n"
1947 + atlyxpreamble + "\\makeatother\n\n";
1949 // We try to load babel late, in case it interferes with other packages.
1950 // Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
1951 // called after babel, though.
1952 if (use_babel && !features.isRequired("jurabib")
1953 && !features.isRequired("hyperref")
1954 && !features.isRequired("varioref")
1955 && !features.isRequired("vietnamese")
1956 && !features.isRequired("japanese")) {
1958 lyxpreamble += from_utf8(features.getBabelPresettings());
1959 lyxpreamble += from_utf8(babelCall(language_options.str(),
1960 features.needBabelLangOptions())) + '\n';
1961 lyxpreamble += from_utf8(features.getBabelPostsettings());
1963 if (features.isRequired("bicaption"))
1964 lyxpreamble += "\\usepackage{bicaption}\n";
1965 if (!listings_params.empty() || features.isRequired("listings"))
1966 lyxpreamble += "\\usepackage{listings}\n";
1967 if (!listings_params.empty()) {
1968 lyxpreamble += "\\lstset{";
1969 // do not test validity because listings_params is
1970 // supposed to be valid
1972 InsetListingsParams(listings_params).separatedParams(true);
1973 lyxpreamble += from_utf8(par);
1974 lyxpreamble += "}\n";
1977 // xunicode needs to be loaded at least after amsmath, amssymb,
1978 // esint and the other packages that provide special glyphs
1979 if (features.runparams().flavor == OutputParams::XETEX
1981 lyxpreamble += "\\usepackage{xunicode}\n";
1983 // Polyglossia must be loaded last
1984 if (use_polyglossia) {
1986 lyxpreamble += "\\usepackage{polyglossia}\n";
1987 // set the main language
1988 lyxpreamble += "\\setdefaultlanguage";
1989 if (!language->polyglossiaOpts().empty())
1990 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
1991 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
1992 // now setup the other languages
1993 std::map<std::string, std::string> const polylangs =
1994 features.getPolyglossiaLanguages();
1995 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
1996 mit != polylangs.end() ; ++mit) {
1997 lyxpreamble += "\\setotherlanguage";
1998 if (!mit->second.empty())
1999 lyxpreamble += "[" + from_ascii(mit->second) + "]";
2000 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
2004 // Load custom language package here
2005 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
2006 if (lang_package == "default")
2007 lyxpreamble += from_utf8(lyxrc.language_custom_package);
2009 lyxpreamble += from_utf8(lang_package);
2010 lyxpreamble += '\n';
2013 docstring const i18npreamble =
2014 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2015 if (!i18npreamble.empty())
2016 lyxpreamble += i18npreamble + '\n';
2024 void BufferParams::useClassDefaults()
2026 DocumentClass const & tclass = documentClass();
2028 sides = tclass.sides();
2029 columns = tclass.columns();
2030 pagestyle = tclass.pagestyle();
2031 use_default_options = true;
2032 // Only if class has a ToC hierarchy
2033 if (tclass.hasTocLevels()) {
2034 secnumdepth = tclass.secnumdepth();
2035 tocdepth = tclass.tocdepth();
2040 bool BufferParams::hasClassDefaults() const
2042 DocumentClass const & tclass = documentClass();
2044 return sides == tclass.sides()
2045 && columns == tclass.columns()
2046 && pagestyle == tclass.pagestyle()
2047 && use_default_options
2048 && secnumdepth == tclass.secnumdepth()
2049 && tocdepth == tclass.tocdepth();
2053 DocumentClass const & BufferParams::documentClass() const
2055 return *doc_class_.get();
2059 DocumentClassConstPtr BufferParams::documentClassPtr() const
2065 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2067 // evil, but this function is evil
2068 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2072 bool BufferParams::setBaseClass(string const & classname)
2074 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2075 LayoutFileList & bcl = LayoutFileList::get();
2076 if (!bcl.haveClass(classname)) {
2078 bformat(_("The layout file:\n"
2080 "could not be found. A default textclass with default\n"
2081 "layouts will be used. LyX will not be able to produce\n"
2083 from_utf8(classname));
2084 frontend::Alert::error(_("Document class not found"), s);
2085 bcl.addEmptyClass(classname);
2088 bool const success = bcl[classname].load();
2091 bformat(_("Due to some error in it, the layout file:\n"
2093 "could not be loaded. A default textclass with default\n"
2094 "layouts will be used. LyX will not be able to produce\n"
2096 from_utf8(classname));
2097 frontend::Alert::error(_("Could not load class"), s);
2098 bcl.addEmptyClass(classname);
2101 pimpl_->baseClass_ = classname;
2102 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2107 LayoutFile const * BufferParams::baseClass() const
2109 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2110 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2116 LayoutFileIndex const & BufferParams::baseClassID() const
2118 return pimpl_->baseClass_;
2122 void BufferParams::makeDocumentClass(bool const clone)
2127 LayoutModuleList mods;
2128 LayoutModuleList::iterator it = layout_modules_.begin();
2129 LayoutModuleList::iterator en = layout_modules_.end();
2130 for (; it != en; ++it)
2131 mods.push_back(*it);
2133 it = cite_engine_.begin();
2134 en = cite_engine_.end();
2135 for (; it != en; ++it)
2136 mods.push_back(*it);
2138 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2140 TextClass::ReturnValues success = TextClass::OK;
2141 if (!forced_local_layout_.empty())
2142 success = doc_class_->read(forced_local_layout_, TextClass::MODULE);
2143 if (!local_layout_.empty() &&
2144 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2145 success = doc_class_->read(local_layout_, TextClass::MODULE);
2146 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2147 docstring const msg = _("Error reading internal layout information");
2148 frontend::Alert::warning(_("Read Error"), msg);
2153 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2155 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2159 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2161 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2165 std::string BufferParams::getLocalLayout(bool forced) const
2168 return doc_class_->forcedLayouts();
2170 return local_layout_;
2174 void BufferParams::setLocalLayout(string const & layout, bool forced)
2177 forced_local_layout_ = layout;
2179 local_layout_ = layout;
2183 bool BufferParams::addLayoutModule(string const & modName)
2185 LayoutModuleList::const_iterator it = layout_modules_.begin();
2186 LayoutModuleList::const_iterator end = layout_modules_.end();
2187 for (; it != end; ++it)
2190 layout_modules_.push_back(modName);
2195 string BufferParams::bufferFormat() const
2197 string format = documentClass().outputFormat();
2198 if (format == "latex") {
2201 if (encoding().package() == Encoding::japanese)
2208 bool BufferParams::isExportable(string const & format) const
2210 vector<string> backs = backends();
2211 for (vector<string>::const_iterator it = backs.begin();
2212 it != backs.end(); ++it)
2213 if (theConverters().isReachable(*it, format))
2219 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2221 vector<string> const backs = backends();
2222 set<string> excludes;
2223 if (useNonTeXFonts) {
2224 excludes.insert("latex");
2225 excludes.insert("pdflatex");
2227 vector<Format const *> result =
2228 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2229 for (vector<string>::const_iterator it = backs.begin() + 1;
2230 it != backs.end(); ++it) {
2231 vector<Format const *> r =
2232 theConverters().getReachable(*it, only_viewable, false, excludes);
2233 result.insert(result.end(), r.begin(), r.end());
2239 bool BufferParams::isExportableFormat(string const & format) const
2241 typedef vector<Format const *> Formats;
2243 formats = exportableFormats(true);
2244 Formats::const_iterator fit = formats.begin();
2245 Formats::const_iterator end = formats.end();
2246 for (; fit != end ; ++fit) {
2247 if ((*fit)->name() == format)
2254 vector<string> BufferParams::backends() const
2257 string const buffmt = bufferFormat();
2259 // FIXME: Don't hardcode format names here, but use a flag
2260 if (buffmt == "latex") {
2261 if (!useNonTeXFonts) {
2262 v.push_back("pdflatex");
2263 v.push_back("latex");
2265 v.push_back("luatex");
2266 v.push_back("dviluatex");
2267 v.push_back("xetex");
2268 } else if (buffmt == "xetex") {
2269 v.push_back("xetex");
2270 // FIXME: need to test all languages (bug 8205)
2271 if (!language || !language->isPolyglossiaExclusive()) {
2272 v.push_back("luatex");
2273 v.push_back("dviluatex");
2276 v.push_back(buffmt);
2278 v.push_back("xhtml");
2279 v.push_back("text");
2285 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const & format) const
2287 string const dformat = (format.empty() || format == "default") ?
2288 getDefaultOutputFormat() : format;
2289 DefaultFlavorCache::const_iterator it =
2290 default_flavors_.find(dformat);
2292 if (it != default_flavors_.end())
2295 OutputParams::FLAVOR result = OutputParams::LATEX;
2297 // FIXME It'd be better not to hardcode this, but to do
2298 // something with formats.
2299 if (dformat == "xhtml")
2300 result = OutputParams::HTML;
2301 else if (dformat == "text")
2302 result = OutputParams::TEXT;
2303 else if (dformat == "lyx")
2304 result = OutputParams::LYX;
2305 else if (dformat == "pdflatex")
2306 result = OutputParams::PDFLATEX;
2307 else if (dformat == "xetex")
2308 result = OutputParams::XETEX;
2309 else if (dformat == "luatex")
2310 result = OutputParams::LUATEX;
2311 else if (dformat == "dviluatex")
2312 result = OutputParams::DVILUATEX;
2314 // Try to determine flavor of default output format
2315 vector<string> backs = backends();
2316 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2317 // Get shortest path to format
2318 Graph::EdgePath path;
2319 for (vector<string>::const_iterator it = backs.begin();
2320 it != backs.end(); ++it) {
2321 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2322 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2327 result = theConverters().getFlavor(path);
2330 // cache this flavor
2331 default_flavors_[dformat] = result;
2336 string BufferParams::getDefaultOutputFormat() const
2338 if (!default_output_format.empty()
2339 && default_output_format != "default")
2340 return default_output_format;
2342 || encoding().package() == Encoding::japanese) {
2343 vector<Format const *> const formats = exportableFormats(true);
2344 if (formats.empty())
2346 // return the first we find
2347 return formats.front()->name();
2350 return lyxrc.default_otf_view_format;
2351 return lyxrc.default_view_format;
2354 Font const BufferParams::getFont() const
2356 FontInfo f = documentClass().defaultfont();
2357 if (fonts_default_family == "rmdefault")
2358 f.setFamily(ROMAN_FAMILY);
2359 else if (fonts_default_family == "sfdefault")
2360 f.setFamily(SANS_FAMILY);
2361 else if (fonts_default_family == "ttdefault")
2362 f.setFamily(TYPEWRITER_FAMILY);
2363 return Font(f, language);
2367 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const & qs) const
2369 return quoteslangtranslator().find(qs);
2373 bool BufferParams::isLatex() const
2375 return documentClass().outputType() == LATEX;
2379 bool BufferParams::isLiterate() const
2381 return documentClass().outputType() == LITERATE;
2385 bool BufferParams::isDocBook() const
2387 return documentClass().outputType() == DOCBOOK;
2391 void BufferParams::readPreamble(Lexer & lex)
2393 if (lex.getString() != "\\begin_preamble")
2394 lyxerr << "Error (BufferParams::readPreamble):"
2395 "consistency check failed." << endl;
2397 preamble = lex.getLongString("\\end_preamble");
2401 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2403 string const expected = forced ? "\\begin_forced_local_layout" :
2404 "\\begin_local_layout";
2405 if (lex.getString() != expected)
2406 lyxerr << "Error (BufferParams::readLocalLayout):"
2407 "consistency check failed." << endl;
2410 forced_local_layout_ =
2411 lex.getLongString("\\end_forced_local_layout");
2413 local_layout_ = lex.getLongString("\\end_local_layout");
2417 bool BufferParams::setLanguage(string const & lang)
2419 Language const *new_language = languages.getLanguage(lang);
2420 if (!new_language) {
2421 // Language lang was not found
2424 language = new_language;
2429 void BufferParams::readLanguage(Lexer & lex)
2431 if (!lex.next()) return;
2433 string const tmptok = lex.getString();
2435 // check if tmptok is part of tex_babel in tex-defs.h
2436 if (!setLanguage(tmptok)) {
2437 // Language tmptok was not found
2438 language = default_language;
2439 lyxerr << "Warning: Setting language `"
2440 << tmptok << "' to `" << language->lang()
2446 void BufferParams::readGraphicsDriver(Lexer & lex)
2451 string const tmptok = lex.getString();
2452 // check if tmptok is part of tex_graphics in tex_defs.h
2455 string const test = tex_graphics[n++];
2457 if (test == tmptok) {
2458 graphics_driver = tmptok;
2463 "Warning: graphics driver `$$Token' not recognized!\n"
2464 " Setting graphics driver to `default'.\n");
2465 graphics_driver = "default";
2472 void BufferParams::readBullets(Lexer & lex)
2477 int const index = lex.getInteger();
2479 int temp_int = lex.getInteger();
2480 user_defined_bullet(index).setFont(temp_int);
2481 temp_bullet(index).setFont(temp_int);
2483 user_defined_bullet(index).setCharacter(temp_int);
2484 temp_bullet(index).setCharacter(temp_int);
2486 user_defined_bullet(index).setSize(temp_int);
2487 temp_bullet(index).setSize(temp_int);
2491 void BufferParams::readBulletsLaTeX(Lexer & lex)
2493 // The bullet class should be able to read this.
2496 int const index = lex.getInteger();
2498 docstring const temp_str = lex.getDocString();
2500 user_defined_bullet(index).setText(temp_str);
2501 temp_bullet(index).setText(temp_str);
2505 void BufferParams::readModules(Lexer & lex)
2507 if (!lex.eatLine()) {
2508 lyxerr << "Error (BufferParams::readModules):"
2509 "Unexpected end of input." << endl;
2513 string mod = lex.getString();
2514 if (mod == "\\end_modules")
2516 addLayoutModule(mod);
2522 void BufferParams::readRemovedModules(Lexer & lex)
2524 if (!lex.eatLine()) {
2525 lyxerr << "Error (BufferParams::readRemovedModules):"
2526 "Unexpected end of input." << endl;
2530 string mod = lex.getString();
2531 if (mod == "\\end_removed_modules")
2533 removed_modules_.push_back(mod);
2536 // now we want to remove any removed modules that were previously
2537 // added. normally, that will be because default modules were added in
2538 // setBaseClass(), which gets called when \textclass is read at the
2539 // start of the read.
2540 list<string>::const_iterator rit = removed_modules_.begin();
2541 list<string>::const_iterator const ren = removed_modules_.end();
2542 for (; rit != ren; ++rit) {
2543 LayoutModuleList::iterator const mit = layout_modules_.begin();
2544 LayoutModuleList::iterator const men = layout_modules_.end();
2545 LayoutModuleList::iterator found = find(mit, men, *rit);
2548 layout_modules_.erase(found);
2553 void BufferParams::readIncludeonly(Lexer & lex)
2555 if (!lex.eatLine()) {
2556 lyxerr << "Error (BufferParams::readIncludeonly):"
2557 "Unexpected end of input." << endl;
2561 string child = lex.getString();
2562 if (child == "\\end_includeonly")
2564 included_children_.push_back(child);
2570 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2572 switch (papersize) {
2574 // could be anything, so don't guess
2576 case PAPER_CUSTOM: {
2577 if (purpose == XDVI && !paperwidth.empty() &&
2578 !paperheight.empty()) {
2579 // heightxwidth<unit>
2580 string first = paperwidth;
2581 string second = paperheight;
2582 if (orientation == ORIENTATION_LANDSCAPE)
2585 return first.erase(first.length() - 2)
2591 // dvips and dvipdfm do not know this
2592 if (purpose == DVIPS || purpose == DVIPDFM)
2596 if (purpose == DVIPS || purpose == DVIPDFM)
2600 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 if (purpose == DVIPS || purpose == DVIPDFM)
2630 // dvipdfm does not know this
2631 if (purpose == DVIPDFM)
2635 if (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)
2695 if (purpose == DVIPS || purpose == DVIPDFM)
2698 case PAPER_USEXECUTIVE:
2699 // dvipdfm does not know this
2700 if (purpose == DVIPDFM)
2705 case PAPER_USLETTER:
2707 if (purpose == XDVI)
2714 string const BufferParams::dvips_options() const
2718 // If the class loads the geometry package, we do not know which
2719 // paper size is used, since we do not set it (bug 7013).
2720 // Therefore we must not specify any argument here.
2721 // dvips gets the correct paper size via DVI specials in this case
2722 // (if the class uses the geometry package correctly).
2723 if (documentClass().provides("geometry"))
2727 && papersize == PAPER_CUSTOM
2728 && !lyxrc.print_paper_dimension_flag.empty()
2729 && !paperwidth.empty()
2730 && !paperheight.empty()) {
2731 // using a custom papersize
2732 result = lyxrc.print_paper_dimension_flag;
2733 result += ' ' + paperwidth;
2734 result += ',' + paperheight;
2736 string const paper_option = paperSizeName(DVIPS);
2737 if (!paper_option.empty() && (paper_option != "letter" ||
2738 orientation != ORIENTATION_LANDSCAPE)) {
2739 // dvips won't accept -t letter -t landscape.
2740 // In all other cases, include the paper size
2742 result = lyxrc.print_paper_flag;
2743 result += ' ' + paper_option;
2746 if (orientation == ORIENTATION_LANDSCAPE &&
2747 papersize != PAPER_CUSTOM)
2748 result += ' ' + lyxrc.print_landscape_flag;
2753 string const BufferParams::font_encoding() const
2755 return font_encodings().empty() ? "default" : font_encodings().back();
2759 vector<string> const BufferParams::font_encodings() const
2761 string doc_fontenc = (fontenc == "global") ? lyxrc.fontenc : fontenc;
2763 vector<string> fontencs;
2765 // "default" means "no explicit font encoding"
2766 if (doc_fontenc != "default") {
2767 fontencs = getVectorFromString(doc_fontenc);
2768 if (!language->fontenc().empty()
2769 && ascii_lowercase(language->fontenc()) != "none") {
2770 vector<string> fencs = getVectorFromString(language->fontenc());
2771 vector<string>::const_iterator fit = fencs.begin();
2772 for (; fit != fencs.end(); ++fit) {
2773 if (find(fontencs.begin(), fontencs.end(), *fit) == fontencs.end())
2774 fontencs.push_back(*fit);
2783 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2785 // suppress the babel call if there is no BabelName defined
2786 // for the document language in the lib/languages file and if no
2787 // other languages are used (lang_opts is then empty)
2788 if (lang_opts.empty())
2790 // either a specific language (AsBabelOptions setting in
2791 // lib/languages) or the prefs require the languages to
2792 // be submitted to babel itself (not the class).
2794 return "\\usepackage[" + lang_opts + "]{babel}";
2795 return "\\usepackage{babel}";
2799 docstring BufferParams::getGraphicsDriver(string const & package) const
2803 if (package == "geometry") {
2804 if (graphics_driver == "dvips"
2805 || graphics_driver == "dvipdfm"
2806 || graphics_driver == "pdftex"
2807 || graphics_driver == "vtex")
2808 result = from_ascii(graphics_driver);
2809 else if (graphics_driver == "dvipdfmx")
2810 result = from_ascii("dvipdfm");
2817 void BufferParams::writeEncodingPreamble(otexstream & os,
2818 LaTeXFeatures & features) const
2820 // XeTeX does not need this
2821 if (features.runparams().flavor == OutputParams::XETEX)
2823 // LuaTeX neither, but with tex fonts, we need to load
2824 // the luainputenc package.
2825 if (features.runparams().flavor == OutputParams::LUATEX
2826 || features.runparams().flavor == OutputParams::DVILUATEX) {
2827 if (!useNonTeXFonts && inputenc != "default"
2828 && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc)
2829 || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) {
2830 os << "\\usepackage[utf8]{luainputenc}\n";
2834 if (inputenc == "auto") {
2835 string const doc_encoding =
2836 language->encoding()->latexName();
2837 Encoding::Package const package =
2838 language->encoding()->package();
2840 // Create a list with all the input encodings used
2842 set<string> encodings =
2843 features.getEncodingSet(doc_encoding);
2845 // If the "japanese" package (i.e. pLaTeX) is used,
2846 // inputenc must be omitted.
2847 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2848 if ((!encodings.empty() || package == Encoding::inputenc)
2849 && !features.isRequired("japanese")
2850 && !features.isProvided("inputenc")) {
2851 os << "\\usepackage[";
2852 set<string>::const_iterator it = encodings.begin();
2853 set<string>::const_iterator const end = encodings.end();
2855 os << from_ascii(*it);
2858 for (; it != end; ++it)
2859 os << ',' << from_ascii(*it);
2860 if (package == Encoding::inputenc) {
2861 if (!encodings.empty())
2863 os << from_ascii(doc_encoding);
2865 os << "]{inputenc}\n";
2867 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2868 if (language->encoding()->name() == "utf8-cjk"
2869 && LaTeXFeatures::isAvailable("CJKutf8"))
2870 os << "\\usepackage{CJKutf8}\n";
2872 os << "\\usepackage{CJK}\n";
2874 } else if (inputenc != "default") {
2875 switch (encoding().package()) {
2876 case Encoding::none:
2877 case Encoding::japanese:
2879 case Encoding::inputenc:
2880 // do not load inputenc if japanese is used
2881 // or if the class provides inputenc
2882 if (features.isRequired("japanese")
2883 || features.isProvided("inputenc"))
2885 os << "\\usepackage[" << from_ascii(encoding().latexName())
2889 if (encoding().name() == "utf8-cjk"
2890 && LaTeXFeatures::isAvailable("CJKutf8"))
2891 os << "\\usepackage{CJKutf8}\n";
2893 os << "\\usepackage{CJK}\n";
2896 // Load the CJK package if needed by a secondary language.
2897 // If the main encoding is some variant of UTF8, use CJKutf8.
2898 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
2899 if (encoding().iconvName() == "UTF-8"
2900 && LaTeXFeatures::isAvailable("CJKutf8"))
2901 os << "\\usepackage{CJKutf8}\n";
2903 os << "\\usepackage{CJK}\n";
2909 string const BufferParams::parseFontName(string const & name) const
2911 string mangled = name;
2912 size_t const idx = mangled.find('[');
2913 if (idx == string::npos || idx == 0)
2916 return mangled.substr(0, idx - 1);
2920 string const BufferParams::loadFonts(LaTeXFeatures & features) const
2922 if (fonts_roman == "default" && fonts_sans == "default"
2923 && fonts_typewriter == "default"
2924 && (fonts_math == "default" || fonts_math == "auto"))
2930 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
2931 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
2932 * Mapping=tex-text option assures TeX ligatures (such as "--")
2933 * are resolved. Note that tt does not use these ligatures.
2935 * -- add more GUI options?
2936 * -- add more fonts (fonts for other scripts)
2937 * -- if there's a way to find out if a font really supports
2938 * OldStyle, enable/disable the widget accordingly.
2940 if (useNonTeXFonts && features.isAvailable("fontspec")) {
2941 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
2942 // However, until v.2 (2010/07/11) fontspec only knew
2943 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
2944 // was introduced for both XeTeX and LuaTeX (LuaTeX
2945 // didn't understand "Mapping=tex-text", while XeTeX
2946 // understood both. With most recent versions, both
2947 // variants are understood by both engines. However,
2948 // we want to provide support for at least TeXLive 2009
2949 // (for XeTeX; LuaTeX is only supported as of v.2)
2950 string const texmapping =
2951 (features.runparams().flavor == OutputParams::XETEX) ?
2952 "Mapping=tex-text" : "Ligatures=TeX";
2953 if (fonts_roman != "default") {
2954 os << "\\setmainfont[" << texmapping;
2955 if (fonts_old_figures)
2956 os << ",Numbers=OldStyle";
2957 os << "]{" << parseFontName(fonts_roman) << "}\n";
2959 if (fonts_sans != "default") {
2960 string const sans = parseFontName(fonts_sans);
2961 if (fonts_sans_scale != 100)
2962 os << "\\setsansfont[Scale="
2963 << float(fonts_sans_scale) / 100
2964 << "," << texmapping << "]{"
2967 os << "\\setsansfont[" << texmapping << "]{"
2970 if (fonts_typewriter != "default") {
2971 string const mono = parseFontName(fonts_typewriter);
2972 if (fonts_typewriter_scale != 100)
2973 os << "\\setmonofont[Scale="
2974 << float(fonts_typewriter_scale) / 100
2978 os << "\\setmonofont{"
2985 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
2986 bool const dryrun = features.runparams().dryrun;
2987 bool const complete = (fonts_sans == "default" && fonts_typewriter == "default");
2988 bool const nomath = (fonts_math == "default");
2991 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_roman)).getLaTeXCode(
2992 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2996 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_sans)).getLaTeXCode(
2997 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2998 nomath, fonts_sans_scale);
3000 // MONOSPACED/TYPEWRITER
3001 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_typewriter)).getLaTeXCode(
3002 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3003 nomath, fonts_typewriter_scale);
3006 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getLaTeXCode(
3007 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
3014 Encoding const & BufferParams::encoding() const
3016 // FIXME: actually, we should check for the flavor
3017 // or runparams.isFullyUnicode() here:
3018 // This check will not work with XeTeX/LuaTeX and tex fonts.
3019 // Thus we have to reset the encoding in Buffer::makeLaTeXFile
3020 // (for export) and Buffer::writeLaTeXSource (for preview).
3022 return *(encodings.fromLyXName("utf8-plain"));
3023 if (inputenc == "auto" || inputenc == "default")
3024 return *language->encoding();
3025 Encoding const * const enc = encodings.fromLyXName(inputenc);
3028 LYXERR0("Unknown inputenc value `" << inputenc
3029 << "'. Using `auto' instead.");
3030 return *language->encoding();
3034 bool BufferParams::addCiteEngine(string const & engine)
3036 LayoutModuleList::const_iterator it = cite_engine_.begin();
3037 LayoutModuleList::const_iterator en = cite_engine_.end();
3038 for (; it != en; ++it)
3041 cite_engine_.push_back(engine);
3046 bool BufferParams::addCiteEngine(vector<string> const & engine)
3048 vector<string>::const_iterator it = engine.begin();
3049 vector<string>::const_iterator en = engine.end();
3051 for (; it != en; ++it)
3052 if (!addCiteEngine(*it))
3058 string const & BufferParams::defaultBiblioStyle() const
3060 return documentClass().defaultBiblioStyle();
3064 bool const & BufferParams::fullAuthorList() const
3066 return documentClass().fullAuthorList();
3070 void BufferParams::setCiteEngine(string const & engine)
3073 addCiteEngine(engine);
3077 void BufferParams::setCiteEngine(vector<string> const & engine)
3080 addCiteEngine(engine);
3084 vector<string> BufferParams::citeCommands() const
3086 static CitationStyle const default_style;
3087 vector<string> commands =
3088 documentClass().citeCommands(citeEngineType());
3089 if (commands.empty())
3090 commands.push_back(default_style.cmd);
3095 vector<CitationStyle> BufferParams::citeStyles() const
3097 static CitationStyle const default_style;
3098 vector<CitationStyle> styles =
3099 documentClass().citeStyles(citeEngineType());
3101 styles.push_back(default_style);