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 translator = init_parseptranslator();
131 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
134 QuotesLangTranslator const init_quoteslangtranslator()
136 QuotesLangTranslator translator
137 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
138 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
139 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
140 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
141 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
142 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
147 QuotesLangTranslator const & quoteslangtranslator()
149 static QuotesLangTranslator translator = init_quoteslangtranslator();
155 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
158 static PaperSizeTranslator initPaperSizeTranslator()
160 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
161 translator.addPair(string_papersize[1], PAPER_CUSTOM);
162 translator.addPair(string_papersize[2], PAPER_USLETTER);
163 translator.addPair(string_papersize[3], PAPER_USLEGAL);
164 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
165 translator.addPair(string_papersize[5], PAPER_A0);
166 translator.addPair(string_papersize[6], PAPER_A1);
167 translator.addPair(string_papersize[7], PAPER_A2);
168 translator.addPair(string_papersize[8], PAPER_A3);
169 translator.addPair(string_papersize[9], PAPER_A4);
170 translator.addPair(string_papersize[10], PAPER_A5);
171 translator.addPair(string_papersize[11], PAPER_A6);
172 translator.addPair(string_papersize[12], PAPER_B0);
173 translator.addPair(string_papersize[13], PAPER_B1);
174 translator.addPair(string_papersize[14], PAPER_B2);
175 translator.addPair(string_papersize[15], PAPER_B3);
176 translator.addPair(string_papersize[16], PAPER_B4);
177 translator.addPair(string_papersize[17], PAPER_B5);
178 translator.addPair(string_papersize[18], PAPER_B6);
179 translator.addPair(string_papersize[19], PAPER_C0);
180 translator.addPair(string_papersize[20], PAPER_C1);
181 translator.addPair(string_papersize[21], PAPER_C2);
182 translator.addPair(string_papersize[22], PAPER_C3);
183 translator.addPair(string_papersize[23], PAPER_C4);
184 translator.addPair(string_papersize[24], PAPER_C5);
185 translator.addPair(string_papersize[25], PAPER_C6);
186 translator.addPair(string_papersize[26], PAPER_JISB0);
187 translator.addPair(string_papersize[27], PAPER_JISB1);
188 translator.addPair(string_papersize[28], PAPER_JISB2);
189 translator.addPair(string_papersize[29], PAPER_JISB3);
190 translator.addPair(string_papersize[30], PAPER_JISB4);
191 translator.addPair(string_papersize[31], PAPER_JISB5);
192 translator.addPair(string_papersize[32], PAPER_JISB6);
197 PaperSizeTranslator const & papersizetranslator()
199 static PaperSizeTranslator translator = initPaperSizeTranslator();
205 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
208 PaperOrientationTranslator const init_paperorientationtranslator()
210 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
211 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
216 PaperOrientationTranslator const & paperorientationtranslator()
218 static PaperOrientationTranslator translator = 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 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 translator = init_packagetranslator();
263 typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator;
266 CiteEngineTypeTranslator const init_citeenginetypetranslator()
268 CiteEngineTypeTranslator translator("authoryear", ENGINE_TYPE_AUTHORYEAR);
269 translator.addPair("numerical", ENGINE_TYPE_NUMERICAL);
274 CiteEngineTypeTranslator const & citeenginetypetranslator()
276 static CiteEngineTypeTranslator translator = init_citeenginetypetranslator();
282 typedef Translator<string, Spacing::Space> SpaceTranslator;
285 SpaceTranslator const init_spacetranslator()
287 SpaceTranslator translator("default", Spacing::Default);
288 translator.addPair("single", Spacing::Single);
289 translator.addPair("onehalf", Spacing::Onehalf);
290 translator.addPair("double", Spacing::Double);
291 translator.addPair("other", Spacing::Other);
296 SpaceTranslator const & spacetranslator()
298 static SpaceTranslator translator = init_spacetranslator();
305 class BufferParams::Impl
310 AuthorList authorlist;
311 BranchList branchlist;
312 Bullet temp_bullets[4];
313 Bullet user_defined_bullets[4];
314 IndicesList indiceslist;
316 /** This is the amount of space used for paragraph_separation "skip",
317 * and for detached paragraphs in "indented" documents.
321 PDFOptions pdfoptions;
322 LayoutFileIndex baseClass_;
326 BufferParams::Impl::Impl()
327 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
329 // set initial author
331 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
336 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
339 return new BufferParams::Impl(*ptr);
343 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
349 BufferParams::BufferParams()
352 setBaseClass(defaultBaseclass());
354 paragraph_separation = ParagraphIndentSeparation;
355 quotes_language = InsetQuotes::EnglishQuotes;
356 fontsize = "default";
359 papersize = PAPER_DEFAULT;
360 orientation = ORIENTATION_PORTRAIT;
361 use_geometry = false;
362 cite_engine_.push_back("basic");
363 cite_engine_type_ = ENGINE_TYPE_NUMERICAL;
364 biblio_style = "plain";
365 use_bibtopic = false;
367 trackChanges = false;
368 outputChanges = false;
369 use_default_options = true;
370 maintain_unincluded_children = false;
373 language = default_language;
375 fonts_roman = "default";
376 fonts_sans = "default";
377 fonts_typewriter = "default";
379 fonts_default_family = "default";
380 useNonTeXFonts = false;
381 fonts_expert_sc = false;
382 fonts_old_figures = false;
383 fonts_sans_scale = 100;
384 fonts_typewriter_scale = 100;
386 lang_package = "default";
387 graphics_driver = "default";
388 default_output_format = "default";
389 bibtex_command = "default";
390 index_command = "default";
393 listings_params = string();
394 pagestyle = "default";
395 suppress_date = false;
396 justification = true;
397 // no color is the default (white)
398 backgroundcolor = lyx::rgbFromHexName("#ffffff");
399 isbackgroundcolor = false;
400 // no color is the default (black)
401 fontcolor = lyx::rgbFromHexName("#000000");
403 // light gray is the default font color for greyed-out notes
404 notefontcolor = lyx::rgbFromHexName("#cccccc");
405 boxbgcolor = lyx::rgbFromHexName("#ff0000");
406 compressed = lyxrc.save_compressed;
407 for (int iter = 0; iter < 4; ++iter) {
408 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
409 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
412 indiceslist().addDefault(B_("Index"));
413 html_be_strict = false;
414 html_math_output = MathML;
415 html_math_img_scale = 1.0;
416 html_css_as_file = false;
423 docstring BufferParams::B_(string const & l10n) const
425 LASSERT(language, return from_utf8(l10n));
426 return getMessages(language->code()).get(l10n);
430 BufferParams::Package BufferParams::use_package(std::string const & p) const
432 PackageMap::const_iterator it = use_packages.find(p);
433 if (it == use_packages.end())
439 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
445 map<string, string> const & BufferParams::auto_packages()
447 static map<string, string> packages;
448 if (packages.empty()) {
449 // adding a package here implies a file format change!
450 packages["amsmath"] =
451 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
452 packages["amssymb"] =
453 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
455 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
457 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
458 packages["mathdots"] =
459 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
460 packages["mathtools"] =
461 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
463 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
464 packages["stackrel"] =
465 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
466 packages["stmaryrd"] =
467 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");
468 packages["undertilde"] =
469 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
475 AuthorList & BufferParams::authors()
477 return pimpl_->authorlist;
481 AuthorList const & BufferParams::authors() const
483 return pimpl_->authorlist;
487 BranchList & BufferParams::branchlist()
489 return pimpl_->branchlist;
493 BranchList const & BufferParams::branchlist() const
495 return pimpl_->branchlist;
499 IndicesList & BufferParams::indiceslist()
501 return pimpl_->indiceslist;
505 IndicesList const & BufferParams::indiceslist() const
507 return pimpl_->indiceslist;
511 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
513 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
514 return pimpl_->temp_bullets[index];
518 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
520 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
521 return pimpl_->temp_bullets[index];
525 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
527 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
528 return pimpl_->user_defined_bullets[index];
532 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
534 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
535 return pimpl_->user_defined_bullets[index];
539 Spacing & BufferParams::spacing()
541 return pimpl_->spacing;
545 Spacing const & BufferParams::spacing() const
547 return pimpl_->spacing;
551 PDFOptions & BufferParams::pdfoptions()
553 return pimpl_->pdfoptions;
557 PDFOptions const & BufferParams::pdfoptions() const
559 return pimpl_->pdfoptions;
563 HSpace const & BufferParams::getIndentation() const
565 return pimpl_->indentation;
569 void BufferParams::setIndentation(HSpace const & indent)
571 pimpl_->indentation = indent;
575 VSpace const & BufferParams::getDefSkip() const
577 return pimpl_->defskip;
581 void BufferParams::setDefSkip(VSpace const & vs)
583 // DEFSKIP will cause an infinite loop
584 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
585 pimpl_->defskip = vs;
589 string BufferParams::readToken(Lexer & lex, string const & token,
590 FileName const & filepath)
592 if (token == "\\textclass") {
594 string const classname = lex.getString();
595 // if there exists a local layout file, ignore the system one
596 // NOTE: in this case, the textclass (.cls file) is assumed to
599 LayoutFileList & bcl = LayoutFileList::get();
600 if (!filepath.empty())
601 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
602 // that returns non-empty if a "local" layout file is found.
606 setBaseClass(classname);
607 // We assume that a tex class exists for local or unknown
608 // layouts so this warning, will only be given for system layouts.
609 if (!baseClass()->isTeXClassAvailable()) {
610 docstring const desc =
611 translateIfPossible(from_utf8(baseClass()->description()));
612 docstring const prereqs =
613 from_utf8(baseClass()->prerequisites());
614 docstring const msg =
615 bformat(_("The selected document class\n"
617 "requires external files that are not available.\n"
618 "The document class can still be used, but the\n"
619 "document cannot be compiled until the following\n"
620 "prerequisites are installed:\n"
622 "See section 3.1.2.2 (Class Availability) of the\n"
623 "User's Guide for more information."), desc, prereqs);
624 frontend::Alert::warning(_("Document class not available"),
627 } else if (token == "\\begin_preamble") {
629 } else if (token == "\\begin_local_layout") {
630 readLocalLayout(lex, false);
631 } else if (token == "\\begin_forced_local_layout") {
632 readLocalLayout(lex, true);
633 } else if (token == "\\begin_modules") {
635 } else if (token == "\\begin_removed_modules") {
636 readRemovedModules(lex);
637 } else if (token == "\\begin_includeonly") {
638 readIncludeonly(lex);
639 } else if (token == "\\maintain_unincluded_children") {
640 lex >> maintain_unincluded_children;
641 } else if (token == "\\options") {
643 options = lex.getString();
644 } else if (token == "\\use_default_options") {
645 lex >> use_default_options;
646 } else if (token == "\\master") {
648 master = lex.getString();
649 } else if (token == "\\suppress_date") {
650 lex >> suppress_date;
651 } else if (token == "\\justification") {
652 lex >> justification;
653 } else if (token == "\\language") {
655 } else if (token == "\\language_package") {
657 lang_package = lex.getString();
658 } else if (token == "\\inputencoding") {
660 } else if (token == "\\graphics") {
661 readGraphicsDriver(lex);
662 } else if (token == "\\default_output_format") {
663 lex >> default_output_format;
664 } else if (token == "\\bibtex_command") {
666 bibtex_command = lex.getString();
667 } else if (token == "\\index_command") {
669 index_command = lex.getString();
670 } else if (token == "\\fontencoding") {
672 fontenc = lex.getString();
673 } else if (token == "\\font_roman") {
675 fonts_roman = lex.getString();
676 } else if (token == "\\font_sans") {
678 fonts_sans = lex.getString();
679 } else if (token == "\\font_typewriter") {
681 fonts_typewriter = lex.getString();
682 } else if (token == "\\font_math") {
684 fonts_math = lex.getString();
685 } else if (token == "\\font_default_family") {
686 lex >> fonts_default_family;
687 } else if (token == "\\use_non_tex_fonts") {
688 lex >> useNonTeXFonts;
689 } else if (token == "\\font_sc") {
690 lex >> fonts_expert_sc;
691 } else if (token == "\\font_osf") {
692 lex >> fonts_old_figures;
693 } else if (token == "\\font_sf_scale") {
694 lex >> fonts_sans_scale;
695 } else if (token == "\\font_tt_scale") {
696 lex >> fonts_typewriter_scale;
697 } else if (token == "\\font_cjk") {
699 } else if (token == "\\paragraph_separation") {
702 paragraph_separation = parseptranslator().find(parsep);
703 } else if (token == "\\paragraph_indentation") {
705 string indentation = lex.getString();
706 pimpl_->indentation = HSpace(indentation);
707 } else if (token == "\\defskip") {
709 string const defskip = lex.getString();
710 pimpl_->defskip = VSpace(defskip);
711 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
713 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
714 } else if (token == "\\quotes_language") {
717 quotes_language = quoteslangtranslator().find(quotes_lang);
718 } else if (token == "\\papersize") {
721 papersize = papersizetranslator().find(ppsize);
722 } else if (token == "\\use_geometry") {
724 } else if (token == "\\use_package") {
729 use_package(package, packagetranslator().find(use));
730 } else if (token == "\\cite_engine") {
732 vector<string> engine = getVectorFromString(lex.getString());
733 setCiteEngine(engine);
734 } else if (token == "\\cite_engine_type") {
737 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
738 } else if (token == "\\biblio_style") {
740 biblio_style = lex.getString();
741 } else if (token == "\\use_bibtopic") {
743 } else if (token == "\\use_indices") {
745 } else if (token == "\\tracking_changes") {
747 } else if (token == "\\output_changes") {
748 lex >> outputChanges;
749 } else if (token == "\\branch") {
751 docstring branch = lex.getDocString();
752 branchlist().add(branch);
755 string const tok = lex.getString();
756 if (tok == "\\end_branch")
758 Branch * branch_ptr = branchlist().find(branch);
759 if (tok == "\\selected") {
762 branch_ptr->setSelected(lex.getInteger());
764 if (tok == "\\filename_suffix") {
767 branch_ptr->setFileNameSuffix(lex.getInteger());
769 if (tok == "\\color") {
771 string color = lex.getString();
773 branch_ptr->setColor(color);
774 // Update also the Color table:
776 color = lcolor.getX11Name(Color_background);
778 lcolor.setColor(to_utf8(branch), color);
781 } else if (token == "\\index") {
783 docstring index = lex.getDocString();
785 indiceslist().add(index);
788 string const tok = lex.getString();
789 if (tok == "\\end_index")
791 Index * index_ptr = indiceslist().find(index);
792 if (tok == "\\shortcut") {
794 shortcut = lex.getDocString();
796 index_ptr->setShortcut(shortcut);
798 if (tok == "\\color") {
800 string color = lex.getString();
802 index_ptr->setColor(color);
803 // Update also the Color table:
805 color = lcolor.getX11Name(Color_background);
807 if (!shortcut.empty())
808 lcolor.setColor(to_utf8(shortcut), color);
811 } else if (token == "\\author") {
813 istringstream ss(lex.getString());
816 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
817 } else if (token == "\\paperorientation") {
820 orientation = paperorientationtranslator().find(orient);
821 } else if (token == "\\backgroundcolor") {
823 backgroundcolor = lyx::rgbFromHexName(lex.getString());
824 isbackgroundcolor = true;
825 } else if (token == "\\fontcolor") {
827 fontcolor = lyx::rgbFromHexName(lex.getString());
829 } else if (token == "\\notefontcolor") {
831 string color = lex.getString();
832 notefontcolor = lyx::rgbFromHexName(color);
833 lcolor.setColor("notefontcolor", color);
834 } else if (token == "\\boxbgcolor") {
836 string color = lex.getString();
837 boxbgcolor = lyx::rgbFromHexName(color);
838 lcolor.setColor("boxbgcolor", color);
839 } else if (token == "\\paperwidth") {
841 } else if (token == "\\paperheight") {
843 } else if (token == "\\leftmargin") {
845 } else if (token == "\\topmargin") {
847 } else if (token == "\\rightmargin") {
849 } else if (token == "\\bottommargin") {
851 } else if (token == "\\headheight") {
853 } else if (token == "\\headsep") {
855 } else if (token == "\\footskip") {
857 } else if (token == "\\columnsep") {
859 } else if (token == "\\paperfontsize") {
861 } else if (token == "\\papercolumns") {
863 } else if (token == "\\listings_params") {
866 listings_params = InsetListingsParams(par).params();
867 } else if (token == "\\papersides") {
870 sides = sidestranslator().find(psides);
871 } else if (token == "\\paperpagestyle") {
873 } else if (token == "\\bullet") {
875 } else if (token == "\\bulletLaTeX") {
876 readBulletsLaTeX(lex);
877 } else if (token == "\\secnumdepth") {
879 } else if (token == "\\tocdepth") {
881 } else if (token == "\\spacing") {
885 if (nspacing == "other") {
888 spacing().set(spacetranslator().find(nspacing), tmp_val);
889 } else if (token == "\\float_placement") {
890 lex >> float_placement;
892 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
893 string toktmp = pdfoptions().readToken(lex, token);
894 if (!toktmp.empty()) {
895 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
899 } else if (token == "\\html_math_output") {
902 html_math_output = static_cast<MathOutput>(temp);
903 } else if (token == "\\html_be_strict") {
904 lex >> html_be_strict;
905 } else if (token == "\\html_css_as_file") {
906 lex >> html_css_as_file;
907 } else if (token == "\\html_math_img_scale") {
908 lex >> html_math_img_scale;
909 } else if (token == "\\html_latex_start") {
911 html_latex_start = lex.getString();
912 } else if (token == "\\html_latex_end") {
914 html_latex_end = lex.getString();
915 } else if (token == "\\output_sync") {
917 } else if (token == "\\output_sync_macro") {
918 lex >> output_sync_macro;
919 } else if (token == "\\use_refstyle") {
922 lyxerr << "BufferParams::readToken(): Unknown token: " <<
931 void BufferParams::writeFile(ostream & os) const
933 // The top of the file is written by the buffer.
934 // Prints out the buffer info into the .lyx file given by file
937 os << "\\textclass " << baseClass()->name() << '\n';
940 if (!preamble.empty()) {
941 // remove '\n' from the end of preamble
942 string const tmppreamble = rtrim(preamble, "\n");
943 os << "\\begin_preamble\n"
945 << "\n\\end_preamble\n";
949 if (!options.empty()) {
950 os << "\\options " << options << '\n';
953 // use the class options defined in the layout?
954 os << "\\use_default_options "
955 << convert<string>(use_default_options) << "\n";
957 // the master document
958 if (!master.empty()) {
959 os << "\\master " << master << '\n';
963 if (!removed_modules_.empty()) {
964 os << "\\begin_removed_modules" << '\n';
965 list<string>::const_iterator it = removed_modules_.begin();
966 list<string>::const_iterator en = removed_modules_.end();
967 for (; it != en; ++it)
969 os << "\\end_removed_modules" << '\n';
973 if (!layout_modules_.empty()) {
974 os << "\\begin_modules" << '\n';
975 LayoutModuleList::const_iterator it = layout_modules_.begin();
976 LayoutModuleList::const_iterator en = layout_modules_.end();
977 for (; it != en; ++it)
979 os << "\\end_modules" << '\n';
983 if (!included_children_.empty()) {
984 os << "\\begin_includeonly" << '\n';
985 list<string>::const_iterator it = included_children_.begin();
986 list<string>::const_iterator en = included_children_.end();
987 for (; it != en; ++it)
989 os << "\\end_includeonly" << '\n';
991 os << "\\maintain_unincluded_children "
992 << convert<string>(maintain_unincluded_children) << '\n';
994 // local layout information
995 string const local_layout = getLocalLayout(false);
996 if (!local_layout.empty()) {
997 // remove '\n' from the end
998 string const tmplocal = rtrim(local_layout, "\n");
999 os << "\\begin_local_layout\n"
1001 << "\n\\end_local_layout\n";
1003 string const forced_local_layout = getLocalLayout(true);
1004 if (!forced_local_layout.empty()) {
1005 // remove '\n' from the end
1006 string const tmplocal = rtrim(forced_local_layout, "\n");
1007 os << "\\begin_forced_local_layout\n"
1009 << "\n\\end_forced_local_layout\n";
1012 // then the text parameters
1013 if (language != ignore_language)
1014 os << "\\language " << language->lang() << '\n';
1015 os << "\\language_package " << lang_package
1016 << "\n\\inputencoding " << inputenc
1017 << "\n\\fontencoding " << fontenc
1018 << "\n\\font_roman " << fonts_roman
1019 << "\n\\font_sans " << fonts_sans
1020 << "\n\\font_typewriter " << fonts_typewriter
1021 << "\n\\font_math " << fonts_math
1022 << "\n\\font_default_family " << fonts_default_family
1023 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1024 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1025 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1026 << "\n\\font_sf_scale " << fonts_sans_scale
1027 << "\n\\font_tt_scale " << fonts_typewriter_scale
1029 if (!fonts_cjk.empty()) {
1030 os << "\\font_cjk " << fonts_cjk << '\n';
1032 os << "\\graphics " << graphics_driver << '\n';
1033 os << "\\default_output_format " << default_output_format << '\n';
1034 os << "\\output_sync " << output_sync << '\n';
1035 if (!output_sync_macro.empty())
1036 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1037 os << "\\bibtex_command " << bibtex_command << '\n';
1038 os << "\\index_command " << index_command << '\n';
1040 if (!float_placement.empty()) {
1041 os << "\\float_placement " << float_placement << '\n';
1043 os << "\\paperfontsize " << fontsize << '\n';
1045 spacing().writeFile(os);
1046 pdfoptions().writeFile(os);
1048 os << "\\papersize " << string_papersize[papersize]
1049 << "\n\\use_geometry " << convert<string>(use_geometry);
1050 map<string, string> const & packages = auto_packages();
1051 for (map<string, string>::const_iterator it = packages.begin();
1052 it != packages.end(); ++it)
1053 os << "\n\\use_package " << it->first << ' '
1054 << use_package(it->first);
1056 os << "\n\\cite_engine ";
1058 if (!cite_engine_.empty()) {
1059 LayoutModuleList::const_iterator be = cite_engine_.begin();
1060 LayoutModuleList::const_iterator en = cite_engine_.end();
1061 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1070 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1071 << "\n\\biblio_style " << biblio_style
1072 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1073 << "\n\\use_indices " << convert<string>(use_indices)
1074 << "\n\\paperorientation " << string_orientation[orientation]
1075 << "\n\\suppress_date " << convert<string>(suppress_date)
1076 << "\n\\justification " << convert<string>(justification)
1077 << "\n\\use_refstyle " << use_refstyle
1079 if (isbackgroundcolor == true)
1080 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1081 if (isfontcolor == true)
1082 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1083 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1084 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1085 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1086 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1088 BranchList::const_iterator it = branchlist().begin();
1089 BranchList::const_iterator end = branchlist().end();
1090 for (; it != end; ++it) {
1091 os << "\\branch " << to_utf8(it->branch())
1092 << "\n\\selected " << it->isSelected()
1093 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1094 << "\n\\color " << lyx::X11hexname(it->color())
1099 IndicesList::const_iterator iit = indiceslist().begin();
1100 IndicesList::const_iterator iend = indiceslist().end();
1101 for (; iit != iend; ++iit) {
1102 os << "\\index " << to_utf8(iit->index())
1103 << "\n\\shortcut " << to_utf8(iit->shortcut())
1104 << "\n\\color " << lyx::X11hexname(iit->color())
1109 if (!paperwidth.empty())
1110 os << "\\paperwidth "
1111 << VSpace(paperwidth).asLyXCommand() << '\n';
1112 if (!paperheight.empty())
1113 os << "\\paperheight "
1114 << VSpace(paperheight).asLyXCommand() << '\n';
1115 if (!leftmargin.empty())
1116 os << "\\leftmargin "
1117 << VSpace(leftmargin).asLyXCommand() << '\n';
1118 if (!topmargin.empty())
1119 os << "\\topmargin "
1120 << VSpace(topmargin).asLyXCommand() << '\n';
1121 if (!rightmargin.empty())
1122 os << "\\rightmargin "
1123 << VSpace(rightmargin).asLyXCommand() << '\n';
1124 if (!bottommargin.empty())
1125 os << "\\bottommargin "
1126 << VSpace(bottommargin).asLyXCommand() << '\n';
1127 if (!headheight.empty())
1128 os << "\\headheight "
1129 << VSpace(headheight).asLyXCommand() << '\n';
1130 if (!headsep.empty())
1132 << VSpace(headsep).asLyXCommand() << '\n';
1133 if (!footskip.empty())
1135 << VSpace(footskip).asLyXCommand() << '\n';
1136 if (!columnsep.empty())
1137 os << "\\columnsep "
1138 << VSpace(columnsep).asLyXCommand() << '\n';
1139 os << "\\secnumdepth " << secnumdepth
1140 << "\n\\tocdepth " << tocdepth
1141 << "\n\\paragraph_separation "
1142 << string_paragraph_separation[paragraph_separation];
1143 if (!paragraph_separation)
1144 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1146 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1147 os << "\n\\quotes_language "
1148 << string_quotes_language[quotes_language]
1149 << "\n\\papercolumns " << columns
1150 << "\n\\papersides " << sides
1151 << "\n\\paperpagestyle " << pagestyle << '\n';
1152 if (!listings_params.empty())
1153 os << "\\listings_params \"" <<
1154 InsetListingsParams(listings_params).encodedString() << "\"\n";
1155 for (int i = 0; i < 4; ++i) {
1156 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1157 if (user_defined_bullet(i).getFont() != -1) {
1158 os << "\\bullet " << i << " "
1159 << user_defined_bullet(i).getFont() << " "
1160 << user_defined_bullet(i).getCharacter() << " "
1161 << user_defined_bullet(i).getSize() << "\n";
1165 os << "\\bulletLaTeX " << i << " \""
1166 << lyx::to_ascii(user_defined_bullet(i).getText())
1172 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1173 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1174 << "\\html_math_output " << html_math_output << '\n'
1175 << "\\html_css_as_file " << html_css_as_file << '\n'
1176 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1178 if (html_math_img_scale != 1.0)
1179 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1180 if (!html_latex_start.empty())
1181 os << "\\html_latex_start " << html_latex_start << '\n';
1182 if (!html_latex_end.empty())
1183 os << "\\html_latex_end " << html_latex_end << '\n';
1185 os << pimpl_->authorlist;
1189 void BufferParams::validate(LaTeXFeatures & features) const
1191 features.require(documentClass().requires());
1193 if (columns > 1 && language->rightToLeft())
1194 features.require("rtloutputdblcol");
1196 if (outputChanges) {
1197 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1198 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1199 LaTeXFeatures::isAvailable("xcolor");
1201 switch (features.runparams().flavor) {
1202 case OutputParams::LATEX:
1203 case OutputParams::DVILUATEX:
1205 features.require("ct-dvipost");
1206 features.require("dvipost");
1207 } else if (xcolorulem) {
1208 features.require("ct-xcolor-ulem");
1209 features.require("ulem");
1210 features.require("xcolor");
1212 features.require("ct-none");
1215 case OutputParams::LUATEX:
1216 case OutputParams::PDFLATEX:
1217 case OutputParams::XETEX:
1219 features.require("ct-xcolor-ulem");
1220 features.require("ulem");
1221 features.require("xcolor");
1222 // improves color handling in PDF output
1223 features.require("pdfcolmk");
1225 features.require("ct-none");
1233 // Floats with 'Here definitely' as default setting.
1234 if (float_placement.find('H') != string::npos)
1235 features.require("float");
1237 for (PackageMap::const_iterator it = use_packages.begin();
1238 it != use_packages.end(); ++it) {
1239 if (it->first == "amsmath") {
1240 // AMS Style is at document level
1241 if (it->second == package_on ||
1242 features.isProvided("amsmath"))
1243 features.require(it->first);
1244 } else if (it->second == package_on)
1245 features.require(it->first);
1248 // Document-level line spacing
1249 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1250 features.require("setspace");
1252 // the bullet shapes are buffer level not paragraph level
1253 // so they are tested here
1254 for (int i = 0; i < 4; ++i) {
1255 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1257 int const font = user_defined_bullet(i).getFont();
1259 int const c = user_defined_bullet(i).getCharacter();
1265 features.require("latexsym");
1267 } else if (font == 1) {
1268 features.require("amssymb");
1269 } else if (font >= 2 && font <= 5) {
1270 features.require("pifont");
1274 if (pdfoptions().use_hyperref) {
1275 features.require("hyperref");
1276 // due to interferences with babel and hyperref, the color package has to
1277 // be loaded after hyperref when hyperref is used with the colorlinks
1278 // option, see http://www.lyx.org/trac/ticket/5291
1279 if (pdfoptions().colorlinks)
1280 features.require("color");
1283 // some languages are only available via polyglossia
1284 if (features.runparams().flavor == OutputParams::XETEX
1285 && (features.hasPolyglossiaExclusiveLanguages()
1287 features.require("polyglossia");
1289 if (useNonTeXFonts && fonts_math != "auto")
1290 features.require("unicode-math");
1292 if (!language->requires().empty())
1293 features.require(language->requires());
1297 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1298 FileName const & filepath) const
1300 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1301 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1302 // \RequirePackage to do so, rather than the normal \usepackage
1303 // Do not try to load any other package before the document class, unless you
1304 // have a thorough understanding of the LATEX internals and know exactly what you
1306 if (features.mustProvide("fix-cm"))
1307 os << "\\RequirePackage{fix-cm}\n";
1309 os << "\\documentclass";
1311 DocumentClass const & tclass = documentClass();
1313 ostringstream clsoptions; // the document class options.
1315 if (tokenPos(tclass.opt_fontsize(),
1316 '|', fontsize) >= 0) {
1317 // only write if existing in list (and not default)
1318 clsoptions << fontsize << "pt,";
1321 // all paper sizes except of A4, A5, B5 and the US sizes need the
1323 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1324 && papersize != PAPER_USLETTER
1325 && papersize != PAPER_USLEGAL
1326 && papersize != PAPER_USEXECUTIVE
1327 && papersize != PAPER_A4
1328 && papersize != PAPER_A5
1329 && papersize != PAPER_B5;
1331 if (!use_geometry) {
1332 switch (papersize) {
1334 clsoptions << "a4paper,";
1336 case PAPER_USLETTER:
1337 clsoptions << "letterpaper,";
1340 clsoptions << "a5paper,";
1343 clsoptions << "b5paper,";
1345 case PAPER_USEXECUTIVE:
1346 clsoptions << "executivepaper,";
1349 clsoptions << "legalpaper,";
1383 if (sides != tclass.sides()) {
1386 clsoptions << "oneside,";
1389 clsoptions << "twoside,";
1395 if (columns != tclass.columns()) {
1397 clsoptions << "twocolumn,";
1399 clsoptions << "onecolumn,";
1403 && orientation == ORIENTATION_LANDSCAPE)
1404 clsoptions << "landscape,";
1406 // language should be a parameter to \documentclass
1407 if (language->babel() == "hebrew"
1408 && default_language->babel() != "hebrew")
1409 // This seems necessary
1410 features.useLanguage(default_language);
1412 ostringstream language_options;
1413 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1414 bool const use_polyglossia = features.usePolyglossia();
1415 bool const global = lyxrc.language_global_options;
1416 if (use_babel || (use_polyglossia && global)) {
1417 language_options << features.getBabelLanguages();
1418 if (!language->babel().empty()) {
1419 if (!language_options.str().empty())
1420 language_options << ',';
1421 language_options << language->babel();
1423 if (global && !features.needBabelLangOptions()
1424 && !language_options.str().empty())
1425 clsoptions << language_options.str() << ',';
1428 // the predefined options from the layout
1429 if (use_default_options && !tclass.options().empty())
1430 clsoptions << tclass.options() << ',';
1432 // the user-defined options
1433 if (!options.empty()) {
1434 clsoptions << options << ',';
1437 string strOptions(clsoptions.str());
1438 if (!strOptions.empty()) {
1439 strOptions = rtrim(strOptions, ",");
1441 os << '[' << from_utf8(strOptions) << ']';
1444 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1445 // end of \documentclass defs
1447 // if we use fontspec, we have to load the AMS packages here
1448 string const ams = features.loadAMSPackages();
1449 if (useNonTeXFonts && !ams.empty())
1450 os << from_ascii(ams);
1452 if (useNonTeXFonts) {
1453 os << "\\usepackage{fontspec}\n";
1454 if (features.mustProvide("unicode-math")
1455 && features.isAvailable("unicode-math"))
1456 os << "\\usepackage{unicode-math}\n";
1459 // font selection must be done before loading fontenc.sty
1460 string const fonts = loadFonts(features);
1462 os << from_utf8(fonts);
1464 if (fonts_default_family != "default")
1465 os << "\\renewcommand{\\familydefault}{\\"
1466 << from_ascii(fonts_default_family) << "}\n";
1468 // set font encoding
1469 // for arabic_arabi and farsi we also need to load the LAE and
1471 // XeTeX and LuaTeX (with OS fonts) work without fontenc
1472 if (font_encoding() != "default" && language->lang() != "japanese"
1473 && !useNonTeXFonts && !features.isProvided("fontenc")) {
1474 docstring extra_encoding;
1475 if (features.mustProvide("textgreek"))
1476 extra_encoding += from_ascii("LGR");
1477 if (features.mustProvide("textcyr")) {
1478 if (!extra_encoding.empty())
1479 extra_encoding.push_back(',');
1480 extra_encoding += from_ascii("T2A");
1482 if (!extra_encoding.empty() && !font_encoding().empty())
1483 extra_encoding.push_back(',');
1484 size_t fars = language_options.str().find("farsi");
1485 size_t arab = language_options.str().find("arabic");
1486 if (language->lang() == "arabic_arabi"
1487 || language->lang() == "farsi" || fars != string::npos
1488 || arab != string::npos) {
1489 os << "\\usepackage[" << extra_encoding
1490 << from_ascii(font_encoding())
1491 << ",LFE,LAE]{fontenc}\n";
1493 os << "\\usepackage[" << extra_encoding
1494 << from_ascii(font_encoding())
1499 // handle inputenc etc.
1500 writeEncodingPreamble(os, features);
1503 if (!features.runparams().includeall && !included_children_.empty()) {
1504 os << "\\includeonly{";
1505 list<string>::const_iterator it = included_children_.begin();
1506 list<string>::const_iterator en = included_children_.end();
1508 for (; it != en; ++it) {
1509 string incfile = *it;
1510 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1511 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1513 if (!features.runparams().nice)
1515 // \includeonly doesn't want an extension
1516 incfile = changeExtension(incfile, string());
1517 incfile = support::latex_path(incfile);
1518 if (!incfile.empty()) {
1521 os << from_utf8(incfile);
1528 if (!listings_params.empty() || features.isRequired("listings"))
1529 os << "\\usepackage{listings}\n";
1531 if (!listings_params.empty()) {
1533 // do not test validity because listings_params is
1534 // supposed to be valid
1536 InsetListingsParams(listings_params).separatedParams(true);
1537 // we can't support all packages, but we should load the color package
1538 if (par.find("\\color", 0) != string::npos)
1539 features.require("color");
1540 os << from_utf8(par)
1543 if (!features.isProvided("geometry")
1544 && (use_geometry || nonstandard_papersize)) {
1545 odocstringstream ods;
1546 if (!getGraphicsDriver("geometry").empty())
1547 ods << getGraphicsDriver("geometry");
1548 if (orientation == ORIENTATION_LANDSCAPE)
1549 ods << ",landscape";
1550 switch (papersize) {
1552 if (!paperwidth.empty())
1553 ods << ",paperwidth="
1554 << from_ascii(paperwidth);
1555 if (!paperheight.empty())
1556 ods << ",paperheight="
1557 << from_ascii(paperheight);
1559 case PAPER_USLETTER:
1560 ods << ",letterpaper";
1563 ods << ",legalpaper";
1565 case PAPER_USEXECUTIVE:
1566 ods << ",executivepaper";
1655 docstring const g_options = trim(ods.str(), ",");
1656 os << "\\usepackage";
1657 if (!g_options.empty())
1658 os << '[' << g_options << ']';
1659 os << "{geometry}\n";
1660 // output this only if use_geometry is true
1662 os << "\\geometry{verbose";
1663 if (!topmargin.empty())
1664 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1665 if (!bottommargin.empty())
1666 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1667 if (!leftmargin.empty())
1668 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1669 if (!rightmargin.empty())
1670 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1671 if (!headheight.empty())
1672 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1673 if (!headsep.empty())
1674 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1675 if (!footskip.empty())
1676 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1677 if (!columnsep.empty())
1678 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1681 } else if (orientation == ORIENTATION_LANDSCAPE
1682 || papersize != PAPER_DEFAULT) {
1683 features.require("papersize");
1686 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1687 if (pagestyle == "fancy")
1688 os << "\\usepackage{fancyhdr}\n";
1689 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1692 // only output when the background color is not default
1693 if (isbackgroundcolor == true) {
1694 // only require color here, the background color will be defined
1695 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1697 features.require("color");
1698 features.require("pagecolor");
1701 // only output when the font color is not default
1702 if (isfontcolor == true) {
1703 // only require color here, the font color will be defined
1704 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1706 features.require("color");
1707 features.require("fontcolor");
1710 // Only if class has a ToC hierarchy
1711 if (tclass.hasTocLevels()) {
1712 if (secnumdepth != tclass.secnumdepth()) {
1713 os << "\\setcounter{secnumdepth}{"
1717 if (tocdepth != tclass.tocdepth()) {
1718 os << "\\setcounter{tocdepth}{"
1724 if (paragraph_separation) {
1725 // when skip separation
1726 switch (getDefSkip().kind()) {
1727 case VSpace::SMALLSKIP:
1728 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1730 case VSpace::MEDSKIP:
1731 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1733 case VSpace::BIGSKIP:
1734 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1736 case VSpace::LENGTH:
1737 os << "\\setlength{\\parskip}{"
1738 << from_utf8(getDefSkip().length().asLatexString())
1741 default: // should never happen // Then delete it.
1742 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1745 os << "\\setlength{\\parindent}{0pt}\n";
1747 // when separation by indentation
1748 // only output something when a width is given
1749 if (getIndentation().asLyXCommand() != "default") {
1750 os << "\\setlength{\\parindent}{"
1751 << from_utf8(getIndentation().asLatexCommand())
1756 // Now insert the LyX specific LaTeX commands...
1757 docstring lyxpreamble;
1758 features.resolveAlternatives();
1761 if (!output_sync_macro.empty())
1762 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1763 else if (features.runparams().flavor == OutputParams::LATEX)
1764 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1765 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1766 lyxpreamble += "\\synctex=-1\n";
1769 // due to interferences with babel and hyperref, the color package has to
1770 // be loaded (when it is not already loaded) before babel when hyperref
1771 // is used with the colorlinks option, see
1772 // http://www.lyx.org/trac/ticket/5291
1773 // we decided therefore to load color always before babel, see
1774 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1775 lyxpreamble += from_ascii(features.getColorOptions());
1777 // If we use hyperref, jurabib, japanese, varioref or vietnamese,
1778 // we have to call babel before
1780 && (features.isRequired("jurabib")
1781 || features.isRequired("hyperref")
1782 || features.isRequired("varioref")
1783 || features.isRequired("vietnamese")
1784 || features.isRequired("japanese"))) {
1786 lyxpreamble += from_utf8(features.getBabelPresettings());
1787 lyxpreamble += from_utf8(babelCall(language_options.str(),
1788 features.needBabelLangOptions())) + '\n';
1789 lyxpreamble += from_utf8(features.getBabelPostsettings());
1792 // The optional packages;
1793 lyxpreamble += from_ascii(features.getPackages());
1795 // Additional Indices
1796 if (features.isRequired("splitidx")) {
1797 IndicesList::const_iterator iit = indiceslist().begin();
1798 IndicesList::const_iterator iend = indiceslist().end();
1799 for (; iit != iend; ++iit) {
1800 pair<docstring, docstring> indexname_latex =
1801 features.runparams().encoding->latexString(iit->index(),
1802 features.runparams().dryrun);
1803 if (!indexname_latex.second.empty()) {
1804 // issue a warning about omitted characters
1805 // FIXME: should be passed to the error dialog
1806 frontend::Alert::warning(_("Uncodable characters"),
1807 bformat(_("The following characters that are used in an index name are not\n"
1808 "representable in the current encoding and therefore have been omitted:\n%1$s."),
1809 indexname_latex.second));
1811 lyxpreamble += "\\newindex[";
1812 lyxpreamble += indexname_latex.first;
1813 lyxpreamble += "]{";
1814 lyxpreamble += escape(iit->shortcut());
1815 lyxpreamble += "}\n";
1820 lyxpreamble += from_utf8(spacing().writePreamble(features.isProvided("SetSpace")));
1823 // * Hyperref manual: "Make sure it comes last of your loaded
1824 // packages, to give it a fighting chance of not being over-written,
1825 // since its job is to redefine many LaTeX commands."
1826 // * Email from Heiko Oberdiek: "It is usually better to load babel
1827 // before hyperref. Then hyperref has a chance to detect babel.
1828 // * Has to be loaded before the "LyX specific LaTeX commands" to
1829 // avoid errors with algorithm floats.
1830 // use hyperref explicitly if it is required
1831 if (features.isRequired("hyperref")) {
1832 // pass what we have to stream here, since we need
1833 // to access the stream itself in PDFOptions.
1836 OutputParams tmp_params = features.runparams();
1837 pdfoptions().writeLaTeX(tmp_params, os,
1838 features.isProvided("hyperref"));
1839 // set back for the rest
1840 lyxpreamble.clear();
1841 // correctly break URLs with hyperref and dvi output
1842 if (features.runparams().flavor == OutputParams::LATEX
1843 && features.isAvailable("breakurl"))
1844 lyxpreamble += "\\usepackage{breakurl}\n";
1845 } else if (features.isRequired("nameref"))
1846 // hyperref loads this automatically
1847 lyxpreamble += "\\usepackage{nameref}\n";
1849 // bibtopic needs to be loaded after hyperref.
1850 // the dot provides the aux file naming which LyX can detect.
1851 if (features.mustProvide("bibtopic"))
1852 lyxpreamble += "\\usepackage[dot]{bibtopic}\n";
1854 // Will be surrounded by \makeatletter and \makeatother when not empty
1855 docstring atlyxpreamble;
1857 // Some macros LyX will need
1858 docstring tmppreamble(features.getMacros());
1860 if (!tmppreamble.empty())
1861 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1862 "LyX specific LaTeX commands.\n"
1863 + tmppreamble + '\n';
1865 // the text class specific preamble
1866 tmppreamble = features.getTClassPreamble();
1867 if (!tmppreamble.empty())
1868 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1869 "Textclass specific LaTeX commands.\n"
1870 + tmppreamble + '\n';
1872 // suppress date if selected
1873 // use \@ifundefined because we cannot be sure that every document class
1874 // has a \date command
1876 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1878 /* the user-defined preamble */
1879 if (!containsOnly(preamble, " \n\t"))
1881 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1882 "User specified LaTeX commands.\n"
1883 + from_utf8(preamble) + '\n';
1885 // subfig loads internally the LaTeX package "caption". As
1886 // caption is a very popular package, users will load it in
1887 // the preamble. Therefore we must load subfig behind the
1888 // user-defined preamble and check if the caption package was
1889 // loaded or not. For the case that caption is loaded before
1890 // subfig, there is the subfig option "caption=false". This
1891 // option also works when a koma-script class is used and
1892 // koma's own caption commands are used instead of caption. We
1893 // use \PassOptionsToPackage here because the user could have
1894 // already loaded subfig in the preamble.
1895 if (features.isRequired("subfig")) {
1896 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1897 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1898 "\\usepackage{subfig}\n";
1901 // Itemize bullet settings need to be last in case the user
1902 // defines their own bullets that use a package included
1903 // in the user-defined preamble -- ARRae
1904 // Actually it has to be done much later than that
1905 // since some packages like frenchb make modifications
1906 // at \begin{document} time -- JMarc
1907 docstring bullets_def;
1908 for (int i = 0; i < 4; ++i) {
1909 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1910 if (bullets_def.empty())
1911 bullets_def += "\\AtBeginDocument{\n";
1912 bullets_def += " \\def\\labelitemi";
1914 // `i' is one less than the item to modify
1921 bullets_def += "ii";
1927 bullets_def += '{' +
1928 user_defined_bullet(i).getText()
1933 if (!bullets_def.empty())
1934 atlyxpreamble += bullets_def + "}\n\n";
1936 if (!atlyxpreamble.empty())
1937 lyxpreamble += "\n\\makeatletter\n"
1938 + atlyxpreamble + "\\makeatother\n\n";
1940 // We try to load babel late, in case it interferes with other packages.
1941 // Jurabib, hyperref and varioref have to be called after babel, though.
1942 if (use_babel && !features.isRequired("jurabib")
1943 && !features.isRequired("hyperref")
1944 && !features.isRequired("varioref")
1945 && !features.isRequired("vietnamese")
1946 && !features.isRequired("japanese")) {
1948 lyxpreamble += from_utf8(features.getBabelPresettings());
1949 lyxpreamble += from_utf8(babelCall(language_options.str(),
1950 features.needBabelLangOptions())) + '\n';
1951 lyxpreamble += from_utf8(features.getBabelPostsettings());
1954 // xunicode needs to be loaded at least after amsmath, amssymb,
1955 // esint and the other packages that provide special glyphs
1956 if (features.runparams().flavor == OutputParams::XETEX)
1957 lyxpreamble += "\\usepackage{xunicode}\n";
1959 // Polyglossia must be loaded last
1960 if (use_polyglossia) {
1962 lyxpreamble += "\\usepackage{polyglossia}\n";
1963 // set the main language
1964 lyxpreamble += "\\setdefaultlanguage";
1965 if (!language->polyglossiaOpts().empty())
1966 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
1967 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
1968 // now setup the other languages
1969 std::map<std::string, std::string> const polylangs =
1970 features.getPolyglossiaLanguages();
1971 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
1972 mit != polylangs.end() ; ++mit) {
1973 lyxpreamble += "\\setotherlanguage";
1974 if (!mit->second.empty())
1975 lyxpreamble += "[" + from_ascii(mit->second) + "]";
1976 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
1980 // Load custom language package here
1981 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
1982 if (lang_package == "default")
1983 lyxpreamble += from_utf8(lyxrc.language_custom_package);
1985 lyxpreamble += from_utf8(lang_package);
1986 lyxpreamble += '\n';
1989 docstring const i18npreamble =
1990 features.getTClassI18nPreamble(use_babel, use_polyglossia);
1991 if (!i18npreamble.empty())
1992 lyxpreamble += i18npreamble + '\n';
2000 void BufferParams::useClassDefaults()
2002 DocumentClass const & tclass = documentClass();
2004 sides = tclass.sides();
2005 columns = tclass.columns();
2006 pagestyle = tclass.pagestyle();
2007 use_default_options = true;
2008 // Only if class has a ToC hierarchy
2009 if (tclass.hasTocLevels()) {
2010 secnumdepth = tclass.secnumdepth();
2011 tocdepth = tclass.tocdepth();
2016 bool BufferParams::hasClassDefaults() const
2018 DocumentClass const & tclass = documentClass();
2020 return sides == tclass.sides()
2021 && columns == tclass.columns()
2022 && pagestyle == tclass.pagestyle()
2023 && use_default_options
2024 && secnumdepth == tclass.secnumdepth()
2025 && tocdepth == tclass.tocdepth();
2029 DocumentClass const & BufferParams::documentClass() const
2031 return *doc_class_.get();
2035 DocumentClassConstPtr BufferParams::documentClassPtr() const
2041 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2043 // evil, but this function is evil
2044 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2048 bool BufferParams::setBaseClass(string const & classname)
2050 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2051 LayoutFileList & bcl = LayoutFileList::get();
2052 if (!bcl.haveClass(classname)) {
2054 bformat(_("The layout file:\n"
2056 "could not be found. A default textclass with default\n"
2057 "layouts will be used. LyX will not be able to produce\n"
2059 from_utf8(classname));
2060 frontend::Alert::error(_("Document class not found"), s);
2061 bcl.addEmptyClass(classname);
2064 bool const success = bcl[classname].load();
2067 bformat(_("Due to some error in it, the layout file:\n"
2069 "could not be loaded. A default textclass with default\n"
2070 "layouts will be used. LyX will not be able to produce\n"
2072 from_utf8(classname));
2073 frontend::Alert::error(_("Could not load class"), s);
2074 bcl.addEmptyClass(classname);
2077 pimpl_->baseClass_ = classname;
2078 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2083 LayoutFile const * BufferParams::baseClass() const
2085 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2086 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2092 LayoutFileIndex const & BufferParams::baseClassID() const
2094 return pimpl_->baseClass_;
2098 void BufferParams::makeDocumentClass()
2103 LayoutModuleList mods;
2104 LayoutModuleList::iterator it = layout_modules_.begin();
2105 LayoutModuleList::iterator en = layout_modules_.end();
2106 for (; it != en; ++it)
2107 mods.push_back(*it);
2109 it = cite_engine_.begin();
2110 en = cite_engine_.end();
2111 for (; it != en; ++it)
2112 mods.push_back(*it);
2114 doc_class_ = getDocumentClass(*baseClass(), mods);
2116 TextClass::ReturnValues success = TextClass::OK;
2117 if (!forced_local_layout_.empty())
2118 success = doc_class_->read(forced_local_layout_, TextClass::MODULE);
2119 if (!local_layout_.empty() &&
2120 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2121 success = doc_class_->read(local_layout_, TextClass::MODULE);
2122 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2123 docstring const msg = _("Error reading internal layout information");
2124 frontend::Alert::warning(_("Read Error"), msg);
2129 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2131 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2135 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2137 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2141 std::string BufferParams::getLocalLayout(bool forced) const
2144 return doc_class_->forcedLayouts();
2146 return local_layout_;
2150 void BufferParams::setLocalLayout(string const & layout, bool forced)
2153 forced_local_layout_ = layout;
2155 local_layout_ = layout;
2159 bool BufferParams::addLayoutModule(string const & modName)
2161 LayoutModuleList::const_iterator it = layout_modules_.begin();
2162 LayoutModuleList::const_iterator end = layout_modules_.end();
2163 for (; it != end; ++it)
2166 layout_modules_.push_back(modName);
2171 string BufferParams::bufferFormat() const
2173 string format = documentClass().outputFormat();
2174 if (format == "latex") {
2177 if (encoding().package() == Encoding::japanese)
2184 bool BufferParams::isExportable(string const & format) const
2186 vector<string> backs = backends();
2187 for (vector<string>::const_iterator it = backs.begin();
2188 it != backs.end(); ++it)
2189 if (theConverters().isReachable(*it, format))
2195 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2197 vector<string> const backs = backends();
2198 set<string> excludes;
2199 if (useNonTeXFonts) {
2200 excludes.insert("latex");
2201 excludes.insert("pdflatex");
2203 vector<Format const *> result =
2204 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2205 for (vector<string>::const_iterator it = backs.begin() + 1;
2206 it != backs.end(); ++it) {
2207 vector<Format const *> r =
2208 theConverters().getReachable(*it, only_viewable, false, excludes);
2209 result.insert(result.end(), r.begin(), r.end());
2215 bool BufferParams::isExportableFormat(string const & format) const
2217 typedef vector<Format const *> Formats;
2219 formats = exportableFormats(true);
2220 Formats::const_iterator fit = formats.begin();
2221 Formats::const_iterator end = formats.end();
2222 for (; fit != end ; ++fit) {
2223 if ((*fit)->name() == format)
2230 vector<string> BufferParams::backends() const
2233 string const buffmt = bufferFormat();
2235 // FIXME: Don't hardcode format names here, but use a flag
2236 if (buffmt == "latex") {
2237 if (!useNonTeXFonts) {
2238 v.push_back("pdflatex");
2239 v.push_back("latex");
2241 v.push_back("luatex");
2242 v.push_back("dviluatex");
2243 v.push_back("xetex");
2244 } else if (buffmt == "xetex") {
2245 v.push_back("xetex");
2246 // FIXME: need to test all languages (bug 8205)
2247 if (!language || !language->isPolyglossiaExclusive()) {
2248 v.push_back("luatex");
2249 v.push_back("dviluatex");
2252 v.push_back(buffmt);
2254 v.push_back("xhtml");
2255 v.push_back("text");
2261 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const format) const
2263 string const dformat = (format.empty() || format == "default") ?
2264 getDefaultOutputFormat() : format;
2265 DefaultFlavorCache::const_iterator it =
2266 default_flavors_.find(dformat);
2268 if (it != default_flavors_.end())
2271 OutputParams::FLAVOR result = OutputParams::LATEX;
2273 // FIXME It'd be better not to hardcode this, but to do
2274 // something with formats.
2275 if (dformat == "xhtml")
2276 result = OutputParams::HTML;
2277 else if (dformat == "text")
2278 result = OutputParams::TEXT;
2279 else if (dformat == "lyx")
2280 result = OutputParams::LYX;
2281 else if (dformat == "pdflatex")
2282 result = OutputParams::PDFLATEX;
2283 else if (dformat == "xetex")
2284 result = OutputParams::XETEX;
2285 else if (dformat == "luatex")
2286 result = OutputParams::LUATEX;
2287 else if (dformat == "dviluatex")
2288 result = OutputParams::DVILUATEX;
2290 // Try to determine flavor of default output format
2291 vector<string> backs = backends();
2292 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2293 // Get shortest path to format
2294 Graph::EdgePath path;
2295 for (vector<string>::const_iterator it = backs.begin();
2296 it != backs.end(); ++it) {
2297 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2298 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2303 result = theConverters().getFlavor(path);
2306 // cache this flavor
2307 default_flavors_[dformat] = result;
2312 string BufferParams::getDefaultOutputFormat() const
2314 if (!default_output_format.empty()
2315 && default_output_format != "default")
2316 return default_output_format;
2319 || encoding().package() == Encoding::japanese) {
2320 vector<Format const *> const formats = exportableFormats(true);
2321 if (formats.empty())
2323 // return the first we find
2324 return formats.front()->name();
2326 return lyxrc.default_view_format;
2329 Font const BufferParams::getFont() const
2331 FontInfo f = documentClass().defaultfont();
2332 if (fonts_default_family == "rmdefault")
2333 f.setFamily(ROMAN_FAMILY);
2334 else if (fonts_default_family == "sfdefault")
2335 f.setFamily(SANS_FAMILY);
2336 else if (fonts_default_family == "ttdefault")
2337 f.setFamily(TYPEWRITER_FAMILY);
2338 return Font(f, language);
2342 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const qs) const
2344 return quoteslangtranslator().find(qs);
2348 bool BufferParams::isLatex() const
2350 return documentClass().outputType() == LATEX;
2354 bool BufferParams::isLiterate() const
2356 return documentClass().outputType() == LITERATE;
2360 bool BufferParams::isDocBook() const
2362 return documentClass().outputType() == DOCBOOK;
2366 void BufferParams::readPreamble(Lexer & lex)
2368 if (lex.getString() != "\\begin_preamble")
2369 lyxerr << "Error (BufferParams::readPreamble):"
2370 "consistency check failed." << endl;
2372 preamble = lex.getLongString("\\end_preamble");
2376 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2378 string const expected = forced ? "\\begin_forced_local_layout" :
2379 "\\begin_local_layout";
2380 if (lex.getString() != expected)
2381 lyxerr << "Error (BufferParams::readLocalLayout):"
2382 "consistency check failed." << endl;
2385 forced_local_layout_ =
2386 lex.getLongString("\\end_forced_local_layout");
2388 local_layout_ = lex.getLongString("\\end_local_layout");
2392 bool BufferParams::setLanguage(string const & lang)
2394 Language const *new_language = languages.getLanguage(lang);
2395 if (!new_language) {
2396 // Language lang was not found
2399 language = new_language;
2404 void BufferParams::readLanguage(Lexer & lex)
2406 if (!lex.next()) return;
2408 string const tmptok = lex.getString();
2410 // check if tmptok is part of tex_babel in tex-defs.h
2411 if (!setLanguage(tmptok)) {
2412 // Language tmptok was not found
2413 language = default_language;
2414 lyxerr << "Warning: Setting language `"
2415 << tmptok << "' to `" << language->lang()
2421 void BufferParams::readGraphicsDriver(Lexer & lex)
2426 string const tmptok = lex.getString();
2427 // check if tmptok is part of tex_graphics in tex_defs.h
2430 string const test = tex_graphics[n++];
2432 if (test == tmptok) {
2433 graphics_driver = tmptok;
2438 "Warning: graphics driver `$$Token' not recognized!\n"
2439 " Setting graphics driver to `default'.\n");
2440 graphics_driver = "default";
2447 void BufferParams::readBullets(Lexer & lex)
2452 int const index = lex.getInteger();
2454 int temp_int = lex.getInteger();
2455 user_defined_bullet(index).setFont(temp_int);
2456 temp_bullet(index).setFont(temp_int);
2458 user_defined_bullet(index).setCharacter(temp_int);
2459 temp_bullet(index).setCharacter(temp_int);
2461 user_defined_bullet(index).setSize(temp_int);
2462 temp_bullet(index).setSize(temp_int);
2466 void BufferParams::readBulletsLaTeX(Lexer & lex)
2468 // The bullet class should be able to read this.
2471 int const index = lex.getInteger();
2473 docstring const temp_str = lex.getDocString();
2475 user_defined_bullet(index).setText(temp_str);
2476 temp_bullet(index).setText(temp_str);
2480 void BufferParams::readModules(Lexer & lex)
2482 if (!lex.eatLine()) {
2483 lyxerr << "Error (BufferParams::readModules):"
2484 "Unexpected end of input." << endl;
2488 string mod = lex.getString();
2489 if (mod == "\\end_modules")
2491 addLayoutModule(mod);
2497 void BufferParams::readRemovedModules(Lexer & lex)
2499 if (!lex.eatLine()) {
2500 lyxerr << "Error (BufferParams::readRemovedModules):"
2501 "Unexpected end of input." << endl;
2505 string mod = lex.getString();
2506 if (mod == "\\end_removed_modules")
2508 removed_modules_.push_back(mod);
2511 // now we want to remove any removed modules that were previously
2512 // added. normally, that will be because default modules were added in
2513 // setBaseClass(), which gets called when \textclass is read at the
2514 // start of the read.
2515 list<string>::const_iterator rit = removed_modules_.begin();
2516 list<string>::const_iterator const ren = removed_modules_.end();
2517 for (; rit != ren; ++rit) {
2518 LayoutModuleList::iterator const mit = layout_modules_.begin();
2519 LayoutModuleList::iterator const men = layout_modules_.end();
2520 LayoutModuleList::iterator found = find(mit, men, *rit);
2523 layout_modules_.erase(found);
2528 void BufferParams::readIncludeonly(Lexer & lex)
2530 if (!lex.eatLine()) {
2531 lyxerr << "Error (BufferParams::readIncludeonly):"
2532 "Unexpected end of input." << endl;
2536 string child = lex.getString();
2537 if (child == "\\end_includeonly")
2539 included_children_.push_back(child);
2545 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2547 switch (papersize) {
2549 // could be anything, so don't guess
2551 case PAPER_CUSTOM: {
2552 if (purpose == XDVI && !paperwidth.empty() &&
2553 !paperheight.empty()) {
2554 // heightxwidth<unit>
2555 string first = paperwidth;
2556 string second = paperheight;
2557 if (orientation == ORIENTATION_LANDSCAPE)
2560 return first.erase(first.length() - 2)
2566 // dvips and dvipdfm do not know this
2567 if (purpose == DVIPS || purpose == DVIPDFM)
2571 if (purpose == DVIPS || purpose == DVIPDFM)
2575 if (purpose == DVIPS || purpose == DVIPDFM)
2585 if (purpose == DVIPS || purpose == DVIPDFM)
2589 if (purpose == DVIPS || purpose == DVIPDFM)
2593 if (purpose == DVIPS || purpose == DVIPDFM)
2597 if (purpose == DVIPS || purpose == DVIPDFM)
2601 if (purpose == DVIPS || purpose == DVIPDFM)
2605 // dvipdfm does not know this
2606 if (purpose == DVIPDFM)
2610 if (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 if (purpose == DVIPS || purpose == DVIPDFM)
2634 if (purpose == DVIPS || purpose == DVIPDFM)
2638 if (purpose == DVIPS || purpose == DVIPDFM)
2642 if (purpose == DVIPS || purpose == DVIPDFM)
2646 if (purpose == DVIPS || purpose == DVIPDFM)
2650 if (purpose == DVIPS || purpose == DVIPDFM)
2654 if (purpose == DVIPS || purpose == DVIPDFM)
2658 if (purpose == DVIPS || purpose == DVIPDFM)
2662 if (purpose == DVIPS || purpose == DVIPDFM)
2666 if (purpose == DVIPS || purpose == DVIPDFM)
2670 if (purpose == DVIPS || purpose == DVIPDFM)
2673 case PAPER_USEXECUTIVE:
2674 // dvipdfm does not know this
2675 if (purpose == DVIPDFM)
2680 case PAPER_USLETTER:
2682 if (purpose == XDVI)
2689 string const BufferParams::dvips_options() const
2693 // If the class loads the geometry package, we do not know which
2694 // paper size is used, since we do not set it (bug 7013).
2695 // Therefore we must not specify any argument here.
2696 // dvips gets the correct paper size via DVI specials in this case
2697 // (if the class uses the geometry package correctly).
2698 if (documentClass().provides("geometry"))
2702 && papersize == PAPER_CUSTOM
2703 && !lyxrc.print_paper_dimension_flag.empty()
2704 && !paperwidth.empty()
2705 && !paperheight.empty()) {
2706 // using a custom papersize
2707 result = lyxrc.print_paper_dimension_flag;
2708 result += ' ' + paperwidth;
2709 result += ',' + paperheight;
2711 string const paper_option = paperSizeName(DVIPS);
2712 if (!paper_option.empty() && (paper_option != "letter" ||
2713 orientation != ORIENTATION_LANDSCAPE)) {
2714 // dvips won't accept -t letter -t landscape.
2715 // In all other cases, include the paper size
2717 result = lyxrc.print_paper_flag;
2718 result += ' ' + paper_option;
2721 if (orientation == ORIENTATION_LANDSCAPE &&
2722 papersize != PAPER_CUSTOM)
2723 result += ' ' + lyxrc.print_landscape_flag;
2728 string const BufferParams::font_encoding() const
2730 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2734 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2736 // suppress the babel call if there is no BabelName defined
2737 // for the document language in the lib/languages file and if no
2738 // other languages are used (lang_opts is then empty)
2739 if (lang_opts.empty())
2741 // either a specific language (AsBabelOptions setting in
2742 // lib/languages) or the prefs require the languages to
2743 // be submitted to babel itself (not the class).
2745 return "\\usepackage[" + lang_opts + "]{babel}";
2746 return "\\usepackage{babel}";
2750 docstring BufferParams::getGraphicsDriver(string const & package) const
2754 if (package == "geometry") {
2755 if (graphics_driver == "dvips"
2756 || graphics_driver == "dvipdfm"
2757 || graphics_driver == "pdftex"
2758 || graphics_driver == "vtex")
2759 result = from_ascii(graphics_driver);
2760 else if (graphics_driver == "dvipdfmx")
2761 result = from_ascii("dvipdfm");
2768 void BufferParams::writeEncodingPreamble(otexstream & os,
2769 LaTeXFeatures & features) const
2771 // XeTeX does not need this
2772 if (features.runparams().flavor == OutputParams::XETEX)
2774 // LuaTeX neither, but with tex fonts, we need to load
2775 // the luainputenc package.
2776 if (features.runparams().flavor == OutputParams::LUATEX
2777 || features.runparams().flavor == OutputParams::DVILUATEX) {
2778 if (!useNonTeXFonts && inputenc != "default"
2779 && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc)
2780 || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) {
2781 os << "\\usepackage[utf8]{luainputenc}\n";
2785 if (inputenc == "auto") {
2786 string const doc_encoding =
2787 language->encoding()->latexName();
2788 Encoding::Package const package =
2789 language->encoding()->package();
2791 // Create a list with all the input encodings used
2793 set<string> encodings =
2794 features.getEncodingSet(doc_encoding);
2796 // If the "japanese" package (i.e. pLaTeX) is used,
2797 // inputenc must be omitted.
2798 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2799 if ((!encodings.empty() || package == Encoding::inputenc)
2800 && !features.isRequired("japanese")) {
2801 os << "\\usepackage[";
2802 set<string>::const_iterator it = encodings.begin();
2803 set<string>::const_iterator const end = encodings.end();
2805 os << from_ascii(*it);
2808 for (; it != end; ++it)
2809 os << ',' << from_ascii(*it);
2810 if (package == Encoding::inputenc) {
2811 if (!encodings.empty())
2813 os << from_ascii(doc_encoding);
2815 os << "]{inputenc}\n";
2817 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2818 if (language->encoding()->name() == "utf8-cjk"
2819 && LaTeXFeatures::isAvailable("CJKutf8"))
2820 os << "\\usepackage{CJKutf8}\n";
2822 os << "\\usepackage{CJK}\n";
2824 } else if (inputenc != "default") {
2825 switch (encoding().package()) {
2826 case Encoding::none:
2827 case Encoding::japanese:
2829 case Encoding::inputenc:
2830 // do not load inputenc if japanese is used
2831 if (features.isRequired("japanese"))
2833 os << "\\usepackage[" << from_ascii(encoding().latexName())
2837 if (encoding().name() == "utf8-cjk"
2838 && LaTeXFeatures::isAvailable("CJKutf8"))
2839 os << "\\usepackage{CJKutf8}\n";
2841 os << "\\usepackage{CJK}\n";
2848 string const BufferParams::parseFontName(string const & name) const
2850 string mangled = name;
2851 size_t const idx = mangled.find('[');
2852 if (idx == string::npos || idx == 0)
2855 return mangled.substr(0, idx - 1);
2859 string const BufferParams::loadFonts(LaTeXFeatures & features) const
2861 if (fonts_roman == "default" && fonts_sans == "default"
2862 && fonts_typewriter == "default"
2863 && (fonts_math == "default" || fonts_math == "auto"))
2869 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
2870 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
2871 * Mapping=tex-text option assures TeX ligatures (such as "--")
2872 * are resolved. Note that tt does not use these ligatures.
2874 * -- add more GUI options?
2875 * -- add more fonts (fonts for other scripts)
2876 * -- if there's a way to find out if a font really supports
2877 * OldStyle, enable/disable the widget accordingly.
2879 if (useNonTeXFonts && features.isAvailable("fontspec")) {
2880 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
2881 // However, until v.2 (2010/07/11) fontspec only knew
2882 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
2883 // was introduced for both XeTeX and LuaTeX (LuaTeX
2884 // didn't understand "Mapping=tex-text", while XeTeX
2885 // understood both. With most recent versions, both
2886 // variants are understood by both engines. However,
2887 // we want to provide support for at least TeXLive 2009
2888 // (for XeTeX; LuaTeX is only supported as of v.2)
2889 string const texmapping =
2890 (features.runparams().flavor == OutputParams::XETEX) ?
2891 "Mapping=tex-text" : "Ligatures=TeX";
2892 if (fonts_roman != "default") {
2893 os << "\\setmainfont[" << texmapping;
2894 if (fonts_old_figures)
2895 os << ",Numbers=OldStyle";
2896 os << "]{" << parseFontName(fonts_roman) << "}\n";
2898 if (fonts_sans != "default") {
2899 string const sans = parseFontName(fonts_sans);
2900 if (fonts_sans_scale != 100)
2901 os << "\\setsansfont[Scale="
2902 << float(fonts_sans_scale) / 100
2903 << "," << texmapping << "]{"
2906 os << "\\setsansfont[" << texmapping << "]{"
2909 if (fonts_typewriter != "default") {
2910 string const mono = parseFontName(fonts_typewriter);
2911 if (fonts_typewriter_scale != 100)
2912 os << "\\setmonofont[Scale="
2913 << float(fonts_typewriter_scale) / 100
2917 os << "\\setmonofont{"
2924 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
2925 bool const dryrun = features.runparams().dryrun;
2926 bool const complete = (fonts_sans == "default" && fonts_typewriter == "default");
2927 bool const nomath = (fonts_math == "default");
2930 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_roman)).getLaTeXCode(
2931 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2935 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_sans)).getLaTeXCode(
2936 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2937 nomath, fonts_sans_scale);
2939 // MONOSPACED/TYPEWRITER
2940 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_typewriter)).getLaTeXCode(
2941 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2942 nomath, fonts_typewriter_scale);
2945 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getLaTeXCode(
2946 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2953 Encoding const & BufferParams::encoding() const
2955 // FIXME: actually, we should check for the flavor
2956 // or runparams.isFullyUnicode() here:
2957 // This check will not work with XeTeX/LuaTeX and tex fonts.
2958 // Thus we have to reset the encoding in Buffer::makeLaTeXFile.
2960 return *(encodings.fromLyXName("utf8-plain"));
2961 if (inputenc == "auto" || inputenc == "default")
2962 return *language->encoding();
2963 Encoding const * const enc = encodings.fromLyXName(inputenc);
2966 LYXERR0("Unknown inputenc value `" << inputenc
2967 << "'. Using `auto' instead.");
2968 return *language->encoding();
2972 bool BufferParams::addCiteEngine(string const & engine)
2974 LayoutModuleList::const_iterator it = cite_engine_.begin();
2975 LayoutModuleList::const_iterator en = cite_engine_.end();
2976 for (; it != en; ++it)
2979 cite_engine_.push_back(engine);
2984 bool BufferParams::addCiteEngine(vector<string> const & engine)
2986 vector<string>::const_iterator it = engine.begin();
2987 vector<string>::const_iterator en = engine.end();
2989 for (; it != en; ++it)
2990 if (!addCiteEngine(*it))
2996 string const & BufferParams::defaultBiblioStyle() const
2998 return documentClass().defaultBiblioStyle();
3002 bool const & BufferParams::fullAuthorList() const
3004 return documentClass().fullAuthorList();
3008 void BufferParams::setCiteEngine(string const & engine)
3011 addCiteEngine(engine);
3015 void BufferParams::setCiteEngine(vector<string> const & engine)
3018 addCiteEngine(engine);
3022 vector<string> BufferParams::citeCommands() const
3024 static CitationStyle const default_style;
3025 vector<string> commands =
3026 documentClass().citeCommands(citeEngineType());
3027 if (commands.empty())
3028 commands.push_back(default_style.cmd);
3033 vector<CitationStyle> BufferParams::citeStyles() const
3035 static CitationStyle const default_style;
3036 vector<CitationStyle> styles =
3037 documentClass().citeStyles(citeEngineType());
3039 styles.push_back(default_style);