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 tex_graphics[] = {
91 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
92 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
93 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
94 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
105 // Paragraph separation
106 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
109 ParSepTranslator const init_parseptranslator()
111 ParSepTranslator translator
112 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
113 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
118 ParSepTranslator const & parseptranslator()
120 static ParSepTranslator const translator =
121 init_parseptranslator();
127 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
130 QuotesLangTranslator const init_quoteslangtranslator()
132 QuotesLangTranslator translator
133 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
134 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
135 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
136 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
137 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
138 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
143 QuotesLangTranslator const & quoteslangtranslator()
145 static QuotesLangTranslator const translator =
146 init_quoteslangtranslator();
152 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
155 static PaperSizeTranslator initPaperSizeTranslator()
157 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
158 translator.addPair(string_papersize[1], PAPER_CUSTOM);
159 translator.addPair(string_papersize[2], PAPER_USLETTER);
160 translator.addPair(string_papersize[3], PAPER_USLEGAL);
161 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
162 translator.addPair(string_papersize[5], PAPER_A0);
163 translator.addPair(string_papersize[6], PAPER_A1);
164 translator.addPair(string_papersize[7], PAPER_A2);
165 translator.addPair(string_papersize[8], PAPER_A3);
166 translator.addPair(string_papersize[9], PAPER_A4);
167 translator.addPair(string_papersize[10], PAPER_A5);
168 translator.addPair(string_papersize[11], PAPER_A6);
169 translator.addPair(string_papersize[12], PAPER_B0);
170 translator.addPair(string_papersize[13], PAPER_B1);
171 translator.addPair(string_papersize[14], PAPER_B2);
172 translator.addPair(string_papersize[15], PAPER_B3);
173 translator.addPair(string_papersize[16], PAPER_B4);
174 translator.addPair(string_papersize[17], PAPER_B5);
175 translator.addPair(string_papersize[18], PAPER_B6);
176 translator.addPair(string_papersize[19], PAPER_C0);
177 translator.addPair(string_papersize[20], PAPER_C1);
178 translator.addPair(string_papersize[21], PAPER_C2);
179 translator.addPair(string_papersize[22], PAPER_C3);
180 translator.addPair(string_papersize[23], PAPER_C4);
181 translator.addPair(string_papersize[24], PAPER_C5);
182 translator.addPair(string_papersize[25], PAPER_C6);
183 translator.addPair(string_papersize[26], PAPER_JISB0);
184 translator.addPair(string_papersize[27], PAPER_JISB1);
185 translator.addPair(string_papersize[28], PAPER_JISB2);
186 translator.addPair(string_papersize[29], PAPER_JISB3);
187 translator.addPair(string_papersize[30], PAPER_JISB4);
188 translator.addPair(string_papersize[31], PAPER_JISB5);
189 translator.addPair(string_papersize[32], PAPER_JISB6);
194 PaperSizeTranslator const & papersizetranslator()
196 static PaperSizeTranslator const translator =
197 initPaperSizeTranslator();
203 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
206 PaperOrientationTranslator const init_paperorientationtranslator()
208 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
209 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
214 PaperOrientationTranslator const & paperorientationtranslator()
216 static PaperOrientationTranslator const translator =
217 init_paperorientationtranslator();
223 typedef Translator<int, PageSides> SidesTranslator;
226 SidesTranslator const init_sidestranslator()
228 SidesTranslator translator(1, OneSide);
229 translator.addPair(2, TwoSides);
234 SidesTranslator const & sidestranslator()
236 static SidesTranslator const translator = init_sidestranslator();
242 typedef Translator<int, BufferParams::Package> PackageTranslator;
245 PackageTranslator const init_packagetranslator()
247 PackageTranslator translator(0, BufferParams::package_off);
248 translator.addPair(1, BufferParams::package_auto);
249 translator.addPair(2, BufferParams::package_on);
254 PackageTranslator const & packagetranslator()
256 static PackageTranslator const translator =
257 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);
270 translator.addPair("default", ENGINE_TYPE_DEFAULT);
275 CiteEngineTypeTranslator const & citeenginetypetranslator()
277 static CiteEngineTypeTranslator const translator =
278 init_citeenginetypetranslator();
284 typedef Translator<string, Spacing::Space> SpaceTranslator;
287 SpaceTranslator const init_spacetranslator()
289 SpaceTranslator translator("default", Spacing::Default);
290 translator.addPair("single", Spacing::Single);
291 translator.addPair("onehalf", Spacing::Onehalf);
292 translator.addPair("double", Spacing::Double);
293 translator.addPair("other", Spacing::Other);
298 SpaceTranslator const & spacetranslator()
300 static SpaceTranslator const translator = init_spacetranslator();
307 class BufferParams::Impl
312 AuthorList authorlist;
313 BranchList branchlist;
314 Bullet temp_bullets[4];
315 Bullet user_defined_bullets[4];
316 IndicesList indiceslist;
318 /** This is the amount of space used for paragraph_separation "skip",
319 * and for detached paragraphs in "indented" documents.
323 PDFOptions pdfoptions;
324 LayoutFileIndex baseClass_;
328 BufferParams::Impl::Impl()
329 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
331 // set initial author
333 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
338 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
341 return new BufferParams::Impl(*ptr);
345 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
351 BufferParams::BufferParams()
354 setBaseClass(defaultBaseclass());
356 paragraph_separation = ParagraphIndentSeparation;
357 quotes_language = InsetQuotes::EnglishQuotes;
358 fontsize = "default";
361 papersize = PAPER_DEFAULT;
362 orientation = ORIENTATION_PORTRAIT;
363 use_geometry = false;
364 cite_engine_.push_back("basic");
365 cite_engine_type_ = ENGINE_TYPE_DEFAULT;
366 biblio_style = "plain";
367 use_bibtopic = false;
369 track_changes = false;
370 output_changes = false;
371 use_default_options = true;
372 maintain_unincluded_children = false;
375 language = default_language;
377 fonts_roman = "default";
378 fonts_sans = "default";
379 fonts_typewriter = "default";
381 fonts_default_family = "default";
382 useNonTeXFonts = false;
383 fonts_expert_sc = false;
384 fonts_old_figures = false;
385 fonts_sans_scale = 100;
386 fonts_typewriter_scale = 100;
388 lang_package = "default";
389 graphics_driver = "default";
390 default_output_format = "default";
391 bibtex_command = "default";
392 index_command = "default";
395 listings_params = string();
396 pagestyle = "default";
397 suppress_date = false;
398 justification = true;
399 // no color is the default (white)
400 backgroundcolor = lyx::rgbFromHexName("#ffffff");
401 isbackgroundcolor = false;
402 // no color is the default (black)
403 fontcolor = lyx::rgbFromHexName("#000000");
405 // light gray is the default font color for greyed-out notes
406 notefontcolor = lyx::rgbFromHexName("#cccccc");
407 boxbgcolor = lyx::rgbFromHexName("#ff0000");
408 compressed = lyxrc.save_compressed;
409 for (int iter = 0; iter < 4; ++iter) {
410 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
411 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
414 indiceslist().addDefault(B_("Index"));
415 html_be_strict = false;
416 html_math_output = MathML;
417 html_math_img_scale = 1.0;
418 html_css_as_file = false;
425 docstring BufferParams::B_(string const & l10n) const
427 LASSERT(language, return from_utf8(l10n));
428 return getMessages(language->code()).get(l10n);
432 BufferParams::Package BufferParams::use_package(std::string const & p) const
434 PackageMap::const_iterator it = use_packages.find(p);
435 if (it == use_packages.end())
441 void BufferParams::use_package(std::string const & p, BufferParams::Package u)
447 map<string, string> const & BufferParams::auto_packages()
450 // It is extremely unlikely that there could be a problem here, but...
451 static map<string, string> packages;
452 if (packages.empty()) {
453 // adding a package here implies a file format change!
454 packages["amsmath"] =
455 N_("The LaTeX package amsmath is only used if AMS formula types or symbols from the AMS math toolbars are inserted into formulas");
456 packages["amssymb"] =
457 N_("The LaTeX package amssymb is only used if symbols from the AMS math toolbars are inserted into formulas");
459 N_("The LaTeX package cancel is only used if \\cancel commands are used in formulas");
461 N_("The LaTeX package esint is only used if special integral symbols are inserted into formulas");
462 packages["mathdots"] =
463 N_("The LaTeX package mathdots is only used if the command \\iddots is inserted into formulas");
464 packages["mathtools"] =
465 N_("The LaTeX package mathtools is only used if some mathematical relations are inserted into formulas");
467 N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas");
468 packages["stackrel"] =
469 N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas");
470 packages["stmaryrd"] =
471 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");
472 packages["undertilde"] =
473 N_("The LaTeX package undertilde is only used if you use the math frame decoration 'utilde'");
479 AuthorList & BufferParams::authors()
481 return pimpl_->authorlist;
485 AuthorList const & BufferParams::authors() const
487 return pimpl_->authorlist;
491 BranchList & BufferParams::branchlist()
493 return pimpl_->branchlist;
497 BranchList const & BufferParams::branchlist() const
499 return pimpl_->branchlist;
503 IndicesList & BufferParams::indiceslist()
505 return pimpl_->indiceslist;
509 IndicesList const & BufferParams::indiceslist() const
511 return pimpl_->indiceslist;
515 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
517 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
518 return pimpl_->temp_bullets[index];
522 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
524 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
525 return pimpl_->temp_bullets[index];
529 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
531 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
532 return pimpl_->user_defined_bullets[index];
536 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
538 LASSERT(index < 4, return pimpl_->temp_bullets[0]);
539 return pimpl_->user_defined_bullets[index];
543 Spacing & BufferParams::spacing()
545 return pimpl_->spacing;
549 Spacing const & BufferParams::spacing() const
551 return pimpl_->spacing;
555 PDFOptions & BufferParams::pdfoptions()
557 return pimpl_->pdfoptions;
561 PDFOptions const & BufferParams::pdfoptions() const
563 return pimpl_->pdfoptions;
567 HSpace const & BufferParams::getIndentation() const
569 return pimpl_->indentation;
573 void BufferParams::setIndentation(HSpace const & indent)
575 pimpl_->indentation = indent;
579 VSpace const & BufferParams::getDefSkip() const
581 return pimpl_->defskip;
585 void BufferParams::setDefSkip(VSpace const & vs)
587 // DEFSKIP will cause an infinite loop
588 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
589 pimpl_->defskip = vs;
593 string BufferParams::readToken(Lexer & lex, string const & token,
594 FileName const & filepath)
596 if (token == "\\textclass") {
598 string const classname = lex.getString();
599 // if there exists a local layout file, ignore the system one
600 // NOTE: in this case, the textclass (.cls file) is assumed to
603 LayoutFileList & bcl = LayoutFileList::get();
604 if (!filepath.empty())
605 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
606 // that returns non-empty if a "local" layout file is found.
610 setBaseClass(classname);
611 // We assume that a tex class exists for local or unknown
612 // layouts so this warning, will only be given for system layouts.
613 if (!baseClass()->isTeXClassAvailable()) {
614 docstring const desc =
615 translateIfPossible(from_utf8(baseClass()->description()));
616 docstring const prereqs =
617 from_utf8(baseClass()->prerequisites());
618 docstring const msg =
619 bformat(_("The selected document class\n"
621 "requires external files that are not available.\n"
622 "The document class can still be used, but the\n"
623 "document cannot be compiled until the following\n"
624 "prerequisites are installed:\n"
626 "See section 3.1.2.2 (Class Availability) of the\n"
627 "User's Guide for more information."), desc, prereqs);
628 frontend::Alert::warning(_("Document class not available"),
631 } else if (token == "\\begin_preamble") {
633 } else if (token == "\\begin_local_layout") {
634 readLocalLayout(lex, false);
635 } else if (token == "\\begin_forced_local_layout") {
636 readLocalLayout(lex, true);
637 } else if (token == "\\begin_modules") {
639 } else if (token == "\\begin_removed_modules") {
640 readRemovedModules(lex);
641 } else if (token == "\\begin_includeonly") {
642 readIncludeonly(lex);
643 } else if (token == "\\maintain_unincluded_children") {
644 lex >> maintain_unincluded_children;
645 } else if (token == "\\options") {
647 options = lex.getString();
648 } else if (token == "\\use_default_options") {
649 lex >> use_default_options;
650 } else if (token == "\\master") {
652 master = lex.getString();
653 } else if (token == "\\suppress_date") {
654 lex >> suppress_date;
655 } else if (token == "\\justification") {
656 lex >> justification;
657 } else if (token == "\\language") {
659 } else if (token == "\\language_package") {
661 lang_package = lex.getString();
662 } else if (token == "\\inputencoding") {
664 } else if (token == "\\graphics") {
665 readGraphicsDriver(lex);
666 } else if (token == "\\default_output_format") {
667 lex >> default_output_format;
668 } else if (token == "\\bibtex_command") {
670 bibtex_command = lex.getString();
671 } else if (token == "\\index_command") {
673 index_command = lex.getString();
674 } else if (token == "\\fontencoding") {
676 fontenc = lex.getString();
677 } else if (token == "\\font_roman") {
679 fonts_roman = lex.getString();
680 } else if (token == "\\font_sans") {
682 fonts_sans = lex.getString();
683 } else if (token == "\\font_typewriter") {
685 fonts_typewriter = lex.getString();
686 } else if (token == "\\font_math") {
688 fonts_math = lex.getString();
689 } else if (token == "\\font_default_family") {
690 lex >> fonts_default_family;
691 } else if (token == "\\use_non_tex_fonts") {
692 lex >> useNonTeXFonts;
693 } else if (token == "\\font_sc") {
694 lex >> fonts_expert_sc;
695 } else if (token == "\\font_osf") {
696 lex >> fonts_old_figures;
697 } else if (token == "\\font_sf_scale") {
698 lex >> fonts_sans_scale;
699 } else if (token == "\\font_tt_scale") {
700 lex >> fonts_typewriter_scale;
701 } else if (token == "\\font_cjk") {
703 } else if (token == "\\paragraph_separation") {
706 paragraph_separation = parseptranslator().find(parsep);
707 } else if (token == "\\paragraph_indentation") {
709 string indentation = lex.getString();
710 pimpl_->indentation = HSpace(indentation);
711 } else if (token == "\\defskip") {
713 string const defskip = lex.getString();
714 pimpl_->defskip = VSpace(defskip);
715 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
717 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
718 } else if (token == "\\quotes_language") {
721 quotes_language = quoteslangtranslator().find(quotes_lang);
722 } else if (token == "\\papersize") {
725 papersize = papersizetranslator().find(ppsize);
726 } else if (token == "\\use_geometry") {
728 } else if (token == "\\use_package") {
733 use_package(package, packagetranslator().find(use));
734 } else if (token == "\\cite_engine") {
736 vector<string> engine = getVectorFromString(lex.getString());
737 setCiteEngine(engine);
738 } else if (token == "\\cite_engine_type") {
741 cite_engine_type_ = citeenginetypetranslator().find(engine_type);
742 } else if (token == "\\biblio_style") {
744 biblio_style = lex.getString();
745 } else if (token == "\\use_bibtopic") {
747 } else if (token == "\\use_indices") {
749 } else if (token == "\\tracking_changes") {
750 lex >> track_changes;
751 } else if (token == "\\output_changes") {
752 lex >> output_changes;
753 } else if (token == "\\branch") {
755 docstring branch = lex.getDocString();
756 branchlist().add(branch);
759 string const tok = lex.getString();
760 if (tok == "\\end_branch")
762 Branch * branch_ptr = branchlist().find(branch);
763 if (tok == "\\selected") {
766 branch_ptr->setSelected(lex.getInteger());
768 if (tok == "\\filename_suffix") {
771 branch_ptr->setFileNameSuffix(lex.getInteger());
773 if (tok == "\\color") {
775 string color = lex.getString();
777 branch_ptr->setColor(color);
778 // Update also the Color table:
780 color = lcolor.getX11Name(Color_background);
782 lcolor.setColor(to_utf8(branch), color);
785 } else if (token == "\\index") {
787 docstring index = lex.getDocString();
789 indiceslist().add(index);
792 string const tok = lex.getString();
793 if (tok == "\\end_index")
795 Index * index_ptr = indiceslist().find(index);
796 if (tok == "\\shortcut") {
798 shortcut = lex.getDocString();
800 index_ptr->setShortcut(shortcut);
802 if (tok == "\\color") {
804 string color = lex.getString();
806 index_ptr->setColor(color);
807 // Update also the Color table:
809 color = lcolor.getX11Name(Color_background);
811 if (!shortcut.empty())
812 lcolor.setColor(to_utf8(shortcut), color);
815 } else if (token == "\\author") {
817 istringstream ss(lex.getString());
820 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
821 } else if (token == "\\paperorientation") {
824 orientation = paperorientationtranslator().find(orient);
825 } else if (token == "\\backgroundcolor") {
827 backgroundcolor = lyx::rgbFromHexName(lex.getString());
828 isbackgroundcolor = true;
829 } else if (token == "\\fontcolor") {
831 fontcolor = lyx::rgbFromHexName(lex.getString());
833 } else if (token == "\\notefontcolor") {
835 string color = lex.getString();
836 notefontcolor = lyx::rgbFromHexName(color);
837 lcolor.setColor("notefontcolor", color);
838 } else if (token == "\\boxbgcolor") {
840 string color = lex.getString();
841 boxbgcolor = lyx::rgbFromHexName(color);
842 lcolor.setColor("boxbgcolor", color);
843 } else if (token == "\\paperwidth") {
845 } else if (token == "\\paperheight") {
847 } else if (token == "\\leftmargin") {
849 } else if (token == "\\topmargin") {
851 } else if (token == "\\rightmargin") {
853 } else if (token == "\\bottommargin") {
855 } else if (token == "\\headheight") {
857 } else if (token == "\\headsep") {
859 } else if (token == "\\footskip") {
861 } else if (token == "\\columnsep") {
863 } else if (token == "\\paperfontsize") {
865 } else if (token == "\\papercolumns") {
867 } else if (token == "\\listings_params") {
870 listings_params = InsetListingsParams(par).params();
871 } else if (token == "\\papersides") {
874 sides = sidestranslator().find(psides);
875 } else if (token == "\\paperpagestyle") {
877 } else if (token == "\\bullet") {
879 } else if (token == "\\bulletLaTeX") {
880 readBulletsLaTeX(lex);
881 } else if (token == "\\secnumdepth") {
883 } else if (token == "\\tocdepth") {
885 } else if (token == "\\spacing") {
889 if (nspacing == "other") {
892 spacing().set(spacetranslator().find(nspacing), tmp_val);
893 } else if (token == "\\float_placement") {
894 lex >> float_placement;
896 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
897 string toktmp = pdfoptions().readToken(lex, token);
898 if (!toktmp.empty()) {
899 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
903 } else if (token == "\\html_math_output") {
906 html_math_output = static_cast<MathOutput>(temp);
907 } else if (token == "\\html_be_strict") {
908 lex >> html_be_strict;
909 } else if (token == "\\html_css_as_file") {
910 lex >> html_css_as_file;
911 } else if (token == "\\html_math_img_scale") {
912 lex >> html_math_img_scale;
913 } else if (token == "\\html_latex_start") {
915 html_latex_start = lex.getString();
916 } else if (token == "\\html_latex_end") {
918 html_latex_end = lex.getString();
919 } else if (token == "\\output_sync") {
921 } else if (token == "\\output_sync_macro") {
922 lex >> output_sync_macro;
923 } else if (token == "\\use_refstyle") {
926 lyxerr << "BufferParams::readToken(): Unknown token: " <<
935 void BufferParams::writeFile(ostream & os) const
937 // The top of the file is written by the buffer.
938 // Prints out the buffer info into the .lyx file given by file
941 os << "\\textclass " << baseClass()->name() << '\n';
944 if (!preamble.empty()) {
945 // remove '\n' from the end of preamble
946 string const tmppreamble = rtrim(preamble, "\n");
947 os << "\\begin_preamble\n"
949 << "\n\\end_preamble\n";
953 if (!options.empty()) {
954 os << "\\options " << options << '\n';
957 // use the class options defined in the layout?
958 os << "\\use_default_options "
959 << convert<string>(use_default_options) << "\n";
961 // the master document
962 if (!master.empty()) {
963 os << "\\master " << master << '\n';
967 if (!removed_modules_.empty()) {
968 os << "\\begin_removed_modules" << '\n';
969 list<string>::const_iterator it = removed_modules_.begin();
970 list<string>::const_iterator en = removed_modules_.end();
971 for (; it != en; ++it)
973 os << "\\end_removed_modules" << '\n';
977 if (!layout_modules_.empty()) {
978 os << "\\begin_modules" << '\n';
979 LayoutModuleList::const_iterator it = layout_modules_.begin();
980 LayoutModuleList::const_iterator en = layout_modules_.end();
981 for (; it != en; ++it)
983 os << "\\end_modules" << '\n';
987 if (!included_children_.empty()) {
988 os << "\\begin_includeonly" << '\n';
989 list<string>::const_iterator it = included_children_.begin();
990 list<string>::const_iterator en = included_children_.end();
991 for (; it != en; ++it)
993 os << "\\end_includeonly" << '\n';
995 os << "\\maintain_unincluded_children "
996 << convert<string>(maintain_unincluded_children) << '\n';
998 // local layout information
999 string const local_layout = getLocalLayout(false);
1000 if (!local_layout.empty()) {
1001 // remove '\n' from the end
1002 string const tmplocal = rtrim(local_layout, "\n");
1003 os << "\\begin_local_layout\n"
1005 << "\n\\end_local_layout\n";
1007 string const forced_local_layout = getLocalLayout(true);
1008 if (!forced_local_layout.empty()) {
1009 // remove '\n' from the end
1010 string const tmplocal = rtrim(forced_local_layout, "\n");
1011 os << "\\begin_forced_local_layout\n"
1013 << "\n\\end_forced_local_layout\n";
1016 // then the text parameters
1017 if (language != ignore_language)
1018 os << "\\language " << language->lang() << '\n';
1019 os << "\\language_package " << lang_package
1020 << "\n\\inputencoding " << inputenc
1021 << "\n\\fontencoding " << fontenc
1022 << "\n\\font_roman " << fonts_roman
1023 << "\n\\font_sans " << fonts_sans
1024 << "\n\\font_typewriter " << fonts_typewriter
1025 << "\n\\font_math " << fonts_math
1026 << "\n\\font_default_family " << fonts_default_family
1027 << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
1028 << "\n\\font_sc " << convert<string>(fonts_expert_sc)
1029 << "\n\\font_osf " << convert<string>(fonts_old_figures)
1030 << "\n\\font_sf_scale " << fonts_sans_scale
1031 << "\n\\font_tt_scale " << fonts_typewriter_scale
1033 if (!fonts_cjk.empty()) {
1034 os << "\\font_cjk " << fonts_cjk << '\n';
1036 os << "\\graphics " << graphics_driver << '\n';
1037 os << "\\default_output_format " << default_output_format << '\n';
1038 os << "\\output_sync " << output_sync << '\n';
1039 if (!output_sync_macro.empty())
1040 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
1041 os << "\\bibtex_command " << bibtex_command << '\n';
1042 os << "\\index_command " << index_command << '\n';
1044 if (!float_placement.empty()) {
1045 os << "\\float_placement " << float_placement << '\n';
1047 os << "\\paperfontsize " << fontsize << '\n';
1049 spacing().writeFile(os);
1050 pdfoptions().writeFile(os);
1052 os << "\\papersize " << string_papersize[papersize]
1053 << "\n\\use_geometry " << convert<string>(use_geometry);
1054 map<string, string> const & packages = auto_packages();
1055 for (map<string, string>::const_iterator it = packages.begin();
1056 it != packages.end(); ++it)
1057 os << "\n\\use_package " << it->first << ' '
1058 << use_package(it->first);
1060 os << "\n\\cite_engine ";
1062 if (!cite_engine_.empty()) {
1063 LayoutModuleList::const_iterator be = cite_engine_.begin();
1064 LayoutModuleList::const_iterator en = cite_engine_.end();
1065 for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
1074 os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
1075 << "\n\\biblio_style " << biblio_style
1076 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
1077 << "\n\\use_indices " << convert<string>(use_indices)
1078 << "\n\\paperorientation " << string_orientation[orientation]
1079 << "\n\\suppress_date " << convert<string>(suppress_date)
1080 << "\n\\justification " << convert<string>(justification)
1081 << "\n\\use_refstyle " << use_refstyle
1083 if (isbackgroundcolor == true)
1084 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
1085 if (isfontcolor == true)
1086 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
1087 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
1088 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
1089 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
1090 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1092 BranchList::const_iterator it = branchlist().begin();
1093 BranchList::const_iterator end = branchlist().end();
1094 for (; it != end; ++it) {
1095 os << "\\branch " << to_utf8(it->branch())
1096 << "\n\\selected " << it->isSelected()
1097 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1098 << "\n\\color " << lyx::X11hexname(it->color())
1103 IndicesList::const_iterator iit = indiceslist().begin();
1104 IndicesList::const_iterator iend = indiceslist().end();
1105 for (; iit != iend; ++iit) {
1106 os << "\\index " << to_utf8(iit->index())
1107 << "\n\\shortcut " << to_utf8(iit->shortcut())
1108 << "\n\\color " << lyx::X11hexname(iit->color())
1113 if (!paperwidth.empty())
1114 os << "\\paperwidth "
1115 << VSpace(paperwidth).asLyXCommand() << '\n';
1116 if (!paperheight.empty())
1117 os << "\\paperheight "
1118 << VSpace(paperheight).asLyXCommand() << '\n';
1119 if (!leftmargin.empty())
1120 os << "\\leftmargin "
1121 << VSpace(leftmargin).asLyXCommand() << '\n';
1122 if (!topmargin.empty())
1123 os << "\\topmargin "
1124 << VSpace(topmargin).asLyXCommand() << '\n';
1125 if (!rightmargin.empty())
1126 os << "\\rightmargin "
1127 << VSpace(rightmargin).asLyXCommand() << '\n';
1128 if (!bottommargin.empty())
1129 os << "\\bottommargin "
1130 << VSpace(bottommargin).asLyXCommand() << '\n';
1131 if (!headheight.empty())
1132 os << "\\headheight "
1133 << VSpace(headheight).asLyXCommand() << '\n';
1134 if (!headsep.empty())
1136 << VSpace(headsep).asLyXCommand() << '\n';
1137 if (!footskip.empty())
1139 << VSpace(footskip).asLyXCommand() << '\n';
1140 if (!columnsep.empty())
1141 os << "\\columnsep "
1142 << VSpace(columnsep).asLyXCommand() << '\n';
1143 os << "\\secnumdepth " << secnumdepth
1144 << "\n\\tocdepth " << tocdepth
1145 << "\n\\paragraph_separation "
1146 << string_paragraph_separation[paragraph_separation];
1147 if (!paragraph_separation)
1148 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1150 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1151 os << "\n\\quotes_language "
1152 << string_quotes_language[quotes_language]
1153 << "\n\\papercolumns " << columns
1154 << "\n\\papersides " << sides
1155 << "\n\\paperpagestyle " << pagestyle << '\n';
1156 if (!listings_params.empty())
1157 os << "\\listings_params \"" <<
1158 InsetListingsParams(listings_params).encodedString() << "\"\n";
1159 for (int i = 0; i < 4; ++i) {
1160 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1161 if (user_defined_bullet(i).getFont() != -1) {
1162 os << "\\bullet " << i << " "
1163 << user_defined_bullet(i).getFont() << " "
1164 << user_defined_bullet(i).getCharacter() << " "
1165 << user_defined_bullet(i).getSize() << "\n";
1169 os << "\\bulletLaTeX " << i << " \""
1170 << lyx::to_ascii(user_defined_bullet(i).getText())
1176 os << "\\tracking_changes " << convert<string>(track_changes) << '\n'
1177 << "\\output_changes " << convert<string>(output_changes) << '\n'
1178 << "\\html_math_output " << html_math_output << '\n'
1179 << "\\html_css_as_file " << html_css_as_file << '\n'
1180 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1182 if (html_math_img_scale != 1.0)
1183 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1184 if (!html_latex_start.empty())
1185 os << "\\html_latex_start " << html_latex_start << '\n';
1186 if (!html_latex_end.empty())
1187 os << "\\html_latex_end " << html_latex_end << '\n';
1189 os << pimpl_->authorlist;
1193 void BufferParams::validate(LaTeXFeatures & features) const
1195 features.require(documentClass().requires());
1197 if (columns > 1 && language->rightToLeft())
1198 features.require("rtloutputdblcol");
1200 if (output_changes) {
1201 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1202 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1203 LaTeXFeatures::isAvailable("xcolor");
1205 switch (features.runparams().flavor) {
1206 case OutputParams::LATEX:
1207 case OutputParams::DVILUATEX:
1209 features.require("ct-dvipost");
1210 features.require("dvipost");
1211 } else if (xcolorulem) {
1212 features.require("ct-xcolor-ulem");
1213 features.require("ulem");
1214 features.require("xcolor");
1216 features.require("ct-none");
1219 case OutputParams::LUATEX:
1220 case OutputParams::PDFLATEX:
1221 case OutputParams::XETEX:
1223 features.require("ct-xcolor-ulem");
1224 features.require("ulem");
1225 features.require("xcolor");
1226 // improves color handling in PDF output
1227 features.require("pdfcolmk");
1229 features.require("ct-none");
1237 // Floats with 'Here definitely' as default setting.
1238 if (float_placement.find('H') != string::npos)
1239 features.require("float");
1241 for (PackageMap::const_iterator it = use_packages.begin();
1242 it != use_packages.end(); ++it) {
1243 if (it->first == "amsmath") {
1244 // AMS Style is at document level
1245 if (it->second == package_on ||
1246 features.isProvided("amsmath"))
1247 features.require(it->first);
1248 } else if (it->second == package_on)
1249 features.require(it->first);
1252 // Document-level line spacing
1253 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1254 features.require("setspace");
1256 // the bullet shapes are buffer level not paragraph level
1257 // so they are tested here
1258 for (int i = 0; i < 4; ++i) {
1259 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1261 int const font = user_defined_bullet(i).getFont();
1263 int const c = user_defined_bullet(i).getCharacter();
1269 features.require("latexsym");
1271 } else if (font == 1) {
1272 features.require("amssymb");
1273 } else if (font >= 2 && font <= 5) {
1274 features.require("pifont");
1278 if (pdfoptions().use_hyperref) {
1279 features.require("hyperref");
1280 // due to interferences with babel and hyperref, the color package has to
1281 // be loaded after hyperref when hyperref is used with the colorlinks
1282 // option, see http://www.lyx.org/trac/ticket/5291
1283 if (pdfoptions().colorlinks)
1284 features.require("color");
1286 if (!listings_params.empty()) {
1287 // do not test validity because listings_params is
1288 // supposed to be valid
1290 InsetListingsParams(listings_params).separatedParams(true);
1291 // we can't support all packages, but we should load the color package
1292 if (par.find("\\color", 0) != string::npos)
1293 features.require("color");
1296 // some languages are only available via polyglossia
1297 if (features.runparams().flavor == OutputParams::XETEX
1298 && (features.hasPolyglossiaExclusiveLanguages()
1300 features.require("polyglossia");
1302 if (useNonTeXFonts && fonts_math != "auto")
1303 features.require("unicode-math");
1305 if (!language->requires().empty())
1306 features.require(language->requires());
1310 bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
1311 FileName const & filepath) const
1313 // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1314 // !! To use the Fix-cm package, load it before \documentclass, and use the command
1315 // \RequirePackage to do so, rather than the normal \usepackage
1316 // Do not try to load any other package before the document class, unless you
1317 // have a thorough understanding of the LATEX internals and know exactly what you
1319 if (features.mustProvide("fix-cm"))
1320 os << "\\RequirePackage{fix-cm}\n";
1322 os << "\\documentclass";
1324 DocumentClass const & tclass = documentClass();
1326 ostringstream clsoptions; // the document class options.
1328 if (tokenPos(tclass.opt_fontsize(),
1329 '|', fontsize) >= 0) {
1330 // only write if existing in list (and not default)
1331 clsoptions << fontsize << "pt,";
1334 // all paper sizes except of A4, A5, B5 and the US sizes need the
1336 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1337 && papersize != PAPER_USLETTER
1338 && papersize != PAPER_USLEGAL
1339 && papersize != PAPER_USEXECUTIVE
1340 && papersize != PAPER_A4
1341 && papersize != PAPER_A5
1342 && papersize != PAPER_B5;
1344 if (!use_geometry) {
1345 switch (papersize) {
1347 clsoptions << "a4paper,";
1349 case PAPER_USLETTER:
1350 clsoptions << "letterpaper,";
1353 clsoptions << "a5paper,";
1356 clsoptions << "b5paper,";
1358 case PAPER_USEXECUTIVE:
1359 clsoptions << "executivepaper,";
1362 clsoptions << "legalpaper,";
1396 if (sides != tclass.sides()) {
1399 clsoptions << "oneside,";
1402 clsoptions << "twoside,";
1408 if (columns != tclass.columns()) {
1410 clsoptions << "twocolumn,";
1412 clsoptions << "onecolumn,";
1416 && orientation == ORIENTATION_LANDSCAPE)
1417 clsoptions << "landscape,";
1419 // language should be a parameter to \documentclass
1420 if (language->babel() == "hebrew"
1421 && default_language->babel() != "hebrew")
1422 // This seems necessary
1423 features.useLanguage(default_language);
1425 ostringstream language_options;
1426 bool const use_babel = features.useBabel() && !features.isProvided("babel");
1427 bool const use_polyglossia = features.usePolyglossia();
1428 bool const global = lyxrc.language_global_options;
1429 if (use_babel || (use_polyglossia && global)) {
1430 language_options << features.getBabelLanguages();
1431 if (!language->babel().empty()) {
1432 if (!language_options.str().empty())
1433 language_options << ',';
1434 language_options << language->babel();
1436 if (global && !features.needBabelLangOptions()
1437 && !language_options.str().empty())
1438 clsoptions << language_options.str() << ',';
1441 // the predefined options from the layout
1442 if (use_default_options && !tclass.options().empty())
1443 clsoptions << tclass.options() << ',';
1445 // the user-defined options
1446 if (!options.empty()) {
1447 clsoptions << options << ',';
1450 string strOptions(clsoptions.str());
1451 if (!strOptions.empty()) {
1452 strOptions = rtrim(strOptions, ",");
1454 os << '[' << from_utf8(strOptions) << ']';
1457 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1458 // end of \documentclass defs
1460 // if we use fontspec or newtxmath, we have to load the AMS packages here
1461 string const ams = features.loadAMSPackages();
1462 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
1463 bool const use_newtxmath =
1464 theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getUsedPackage(
1465 ot1, false, false) == "newtxmath";
1466 if ((useNonTeXFonts || use_newtxmath) && !ams.empty())
1467 os << from_ascii(ams);
1469 if (useNonTeXFonts) {
1470 os << "\\usepackage{fontspec}\n";
1471 if (features.mustProvide("unicode-math")
1472 && features.isAvailable("unicode-math"))
1473 os << "\\usepackage{unicode-math}\n";
1476 // font selection must be done before loading fontenc.sty
1477 string const fonts = loadFonts(features);
1479 os << from_utf8(fonts);
1481 if (fonts_default_family != "default")
1482 os << "\\renewcommand{\\familydefault}{\\"
1483 << from_ascii(fonts_default_family) << "}\n";
1485 // set font encoding
1486 // for arabic_arabi and farsi we also need to load the LAE and
1488 // XeTeX and LuaTeX (with OS fonts) work without fontenc
1489 if (font_encoding() != "default" && language->lang() != "japanese"
1490 && !useNonTeXFonts && !features.isProvided("fontenc")) {
1491 docstring extra_encoding;
1492 if (features.mustProvide("textgreek"))
1493 extra_encoding += from_ascii("LGR");
1494 if (features.mustProvide("textcyr")) {
1495 if (!extra_encoding.empty())
1496 extra_encoding.push_back(',');
1497 extra_encoding += from_ascii("T2A");
1499 if (!extra_encoding.empty() && !font_encoding().empty())
1500 extra_encoding.push_back(',');
1501 size_t fars = language_options.str().find("farsi");
1502 size_t arab = language_options.str().find("arabic");
1503 if (language->lang() == "arabic_arabi"
1504 || language->lang() == "farsi" || fars != string::npos
1505 || arab != string::npos) {
1506 os << "\\usepackage[" << extra_encoding
1507 << from_ascii(font_encoding())
1508 << ",LFE,LAE]{fontenc}\n";
1510 os << "\\usepackage[" << extra_encoding
1511 << from_ascii(font_encoding())
1516 // handle inputenc etc.
1517 writeEncodingPreamble(os, features);
1520 if (!features.runparams().includeall && !included_children_.empty()) {
1521 os << "\\includeonly{";
1522 list<string>::const_iterator it = included_children_.begin();
1523 list<string>::const_iterator en = included_children_.end();
1525 for (; it != en; ++it) {
1526 string incfile = *it;
1527 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1528 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1530 if (!features.runparams().nice)
1532 // \includeonly doesn't want an extension
1533 incfile = changeExtension(incfile, string());
1534 incfile = support::latex_path(incfile);
1535 if (!incfile.empty()) {
1538 os << from_utf8(incfile);
1545 if (!features.isProvided("geometry")
1546 && (use_geometry || nonstandard_papersize)) {
1547 odocstringstream ods;
1548 if (!getGraphicsDriver("geometry").empty())
1549 ods << getGraphicsDriver("geometry");
1550 if (orientation == ORIENTATION_LANDSCAPE)
1551 ods << ",landscape";
1552 switch (papersize) {
1554 if (!paperwidth.empty())
1555 ods << ",paperwidth="
1556 << from_ascii(paperwidth);
1557 if (!paperheight.empty())
1558 ods << ",paperheight="
1559 << from_ascii(paperheight);
1561 case PAPER_USLETTER:
1562 ods << ",letterpaper";
1565 ods << ",legalpaper";
1567 case PAPER_USEXECUTIVE:
1568 ods << ",executivepaper";
1657 docstring const g_options = trim(ods.str(), ",");
1658 os << "\\usepackage";
1659 if (!g_options.empty())
1660 os << '[' << g_options << ']';
1661 os << "{geometry}\n";
1662 // output this only if use_geometry is true
1664 os << "\\geometry{verbose";
1665 if (!topmargin.empty())
1666 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1667 if (!bottommargin.empty())
1668 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1669 if (!leftmargin.empty())
1670 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1671 if (!rightmargin.empty())
1672 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1673 if (!headheight.empty())
1674 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1675 if (!headsep.empty())
1676 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1677 if (!footskip.empty())
1678 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1679 if (!columnsep.empty())
1680 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1683 } else if (orientation == ORIENTATION_LANDSCAPE
1684 || papersize != PAPER_DEFAULT) {
1685 features.require("papersize");
1688 if (tokenPos(tclass.opt_pagestyle(), '|', pagestyle) >= 0) {
1689 if (pagestyle == "fancy")
1690 os << "\\usepackage{fancyhdr}\n";
1691 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1694 // only output when the background color is not default
1695 if (isbackgroundcolor == true) {
1696 // only require color here, the background color will be defined
1697 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1699 features.require("color");
1700 features.require("pagecolor");
1703 // only output when the font color is not default
1704 if (isfontcolor == true) {
1705 // only require color here, the font color will be defined
1706 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1708 features.require("color");
1709 features.require("fontcolor");
1712 // Only if class has a ToC hierarchy
1713 if (tclass.hasTocLevels()) {
1714 if (secnumdepth != tclass.secnumdepth()) {
1715 os << "\\setcounter{secnumdepth}{"
1719 if (tocdepth != tclass.tocdepth()) {
1720 os << "\\setcounter{tocdepth}{"
1726 if (paragraph_separation) {
1727 // when skip separation
1728 switch (getDefSkip().kind()) {
1729 case VSpace::SMALLSKIP:
1730 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1732 case VSpace::MEDSKIP:
1733 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1735 case VSpace::BIGSKIP:
1736 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1738 case VSpace::LENGTH:
1739 os << "\\setlength{\\parskip}{"
1740 << from_utf8(getDefSkip().length().asLatexString())
1743 default: // should never happen // Then delete it.
1744 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1747 os << "\\setlength{\\parindent}{0pt}\n";
1749 // when separation by indentation
1750 // only output something when a width is given
1751 if (getIndentation().asLyXCommand() != "default") {
1752 os << "\\setlength{\\parindent}{"
1753 << from_utf8(getIndentation().asLatexCommand())
1758 // Now insert the LyX specific LaTeX commands...
1759 docstring lyxpreamble;
1760 features.resolveAlternatives();
1763 if (!output_sync_macro.empty())
1764 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1765 else if (features.runparams().flavor == OutputParams::LATEX)
1766 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1767 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1768 lyxpreamble += "\\synctex=-1\n";
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 // subfig loads internally the LaTeX package "caption". As
1888 // caption is a very popular package, users will load it in
1889 // the preamble. Therefore we must load subfig behind the
1890 // user-defined preamble and check if the caption package was
1891 // loaded or not. For the case that caption is loaded before
1892 // subfig, there is the subfig option "caption=false". This
1893 // option also works when a koma-script class is used and
1894 // koma's own caption commands are used instead of caption. We
1895 // use \PassOptionsToPackage here because the user could have
1896 // already loaded subfig in the preamble.
1897 if (features.isRequired("subfig")) {
1898 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1899 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1900 "\\usepackage{subfig}\n";
1903 // Itemize bullet settings need to be last in case the user
1904 // defines their own bullets that use a package included
1905 // in the user-defined preamble -- ARRae
1906 // Actually it has to be done much later than that
1907 // since some packages like frenchb make modifications
1908 // at \begin{document} time -- JMarc
1909 docstring bullets_def;
1910 for (int i = 0; i < 4; ++i) {
1911 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1912 if (bullets_def.empty())
1913 bullets_def += "\\AtBeginDocument{\n";
1914 bullets_def += " \\def\\labelitemi";
1916 // `i' is one less than the item to modify
1923 bullets_def += "ii";
1929 bullets_def += '{' +
1930 user_defined_bullet(i).getText()
1935 if (!bullets_def.empty())
1936 atlyxpreamble += bullets_def + "}\n\n";
1938 if (!atlyxpreamble.empty())
1939 lyxpreamble += "\n\\makeatletter\n"
1940 + atlyxpreamble + "\\makeatother\n\n";
1942 // We try to load babel late, in case it interferes with other packages.
1943 // Jurabib, hyperref, varioref and listings (bug 8995) have to be
1944 // called after babel, though.
1945 if (use_babel && !features.isRequired("jurabib")
1946 && !features.isRequired("hyperref")
1947 && !features.isRequired("varioref")
1948 && !features.isRequired("vietnamese")
1949 && !features.isRequired("japanese")) {
1951 lyxpreamble += from_utf8(features.getBabelPresettings());
1952 lyxpreamble += from_utf8(babelCall(language_options.str(),
1953 features.needBabelLangOptions())) + '\n';
1954 lyxpreamble += from_utf8(features.getBabelPostsettings());
1956 if (!listings_params.empty() || features.isRequired("listings"))
1957 lyxpreamble += "\\usepackage{listings}\n";
1958 if (!listings_params.empty()) {
1959 lyxpreamble += "\\lstset{";
1960 // do not test validity because listings_params is
1961 // supposed to be valid
1963 InsetListingsParams(listings_params).separatedParams(true);
1964 lyxpreamble += from_utf8(par);
1965 lyxpreamble += "}\n";
1968 // xunicode needs to be loaded at least after amsmath, amssymb,
1969 // esint and the other packages that provide special glyphs
1970 if (features.runparams().flavor == OutputParams::XETEX
1972 lyxpreamble += "\\usepackage{xunicode}\n";
1974 // Polyglossia must be loaded last
1975 if (use_polyglossia) {
1977 lyxpreamble += "\\usepackage{polyglossia}\n";
1978 // set the main language
1979 lyxpreamble += "\\setdefaultlanguage";
1980 if (!language->polyglossiaOpts().empty())
1981 lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
1982 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
1983 // now setup the other languages
1984 std::map<std::string, std::string> const polylangs =
1985 features.getPolyglossiaLanguages();
1986 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
1987 mit != polylangs.end() ; ++mit) {
1988 lyxpreamble += "\\setotherlanguage";
1989 if (!mit->second.empty())
1990 lyxpreamble += "[" + from_ascii(mit->second) + "]";
1991 lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
1995 // Load custom language package here
1996 if (features.langPackage() == LaTeXFeatures::LANG_PACK_CUSTOM) {
1997 if (lang_package == "default")
1998 lyxpreamble += from_utf8(lyxrc.language_custom_package);
2000 lyxpreamble += from_utf8(lang_package);
2001 lyxpreamble += '\n';
2004 docstring const i18npreamble =
2005 features.getTClassI18nPreamble(use_babel, use_polyglossia);
2006 if (!i18npreamble.empty())
2007 lyxpreamble += i18npreamble + '\n';
2015 void BufferParams::useClassDefaults()
2017 DocumentClass const & tclass = documentClass();
2019 sides = tclass.sides();
2020 columns = tclass.columns();
2021 pagestyle = tclass.pagestyle();
2022 use_default_options = true;
2023 // Only if class has a ToC hierarchy
2024 if (tclass.hasTocLevels()) {
2025 secnumdepth = tclass.secnumdepth();
2026 tocdepth = tclass.tocdepth();
2031 bool BufferParams::hasClassDefaults() const
2033 DocumentClass const & tclass = documentClass();
2035 return sides == tclass.sides()
2036 && columns == tclass.columns()
2037 && pagestyle == tclass.pagestyle()
2038 && use_default_options
2039 && secnumdepth == tclass.secnumdepth()
2040 && tocdepth == tclass.tocdepth();
2044 DocumentClass const & BufferParams::documentClass() const
2046 return *doc_class_.get();
2050 DocumentClassConstPtr BufferParams::documentClassPtr() const
2056 void BufferParams::setDocumentClass(DocumentClassConstPtr tc)
2058 // evil, but this function is evil
2059 doc_class_ = const_pointer_cast<DocumentClass>(tc);
2063 bool BufferParams::setBaseClass(string const & classname)
2065 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2066 LayoutFileList & bcl = LayoutFileList::get();
2067 if (!bcl.haveClass(classname)) {
2069 bformat(_("The layout file:\n"
2071 "could not be found. A default textclass with default\n"
2072 "layouts will be used. LyX will not be able to produce\n"
2074 from_utf8(classname));
2075 frontend::Alert::error(_("Document class not found"), s);
2076 bcl.addEmptyClass(classname);
2079 bool const success = bcl[classname].load();
2082 bformat(_("Due to some error in it, the layout file:\n"
2084 "could not be loaded. A default textclass with default\n"
2085 "layouts will be used. LyX will not be able to produce\n"
2087 from_utf8(classname));
2088 frontend::Alert::error(_("Could not load class"), s);
2089 bcl.addEmptyClass(classname);
2092 pimpl_->baseClass_ = classname;
2093 layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2098 LayoutFile const * BufferParams::baseClass() const
2100 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2101 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2107 LayoutFileIndex const & BufferParams::baseClassID() const
2109 return pimpl_->baseClass_;
2113 void BufferParams::makeDocumentClass(bool const clone)
2118 LayoutModuleList mods;
2119 LayoutModuleList::iterator it = layout_modules_.begin();
2120 LayoutModuleList::iterator en = layout_modules_.end();
2121 for (; it != en; ++it)
2122 mods.push_back(*it);
2124 it = cite_engine_.begin();
2125 en = cite_engine_.end();
2126 for (; it != en; ++it)
2127 mods.push_back(*it);
2129 doc_class_ = getDocumentClass(*baseClass(), mods, clone);
2131 TextClass::ReturnValues success = TextClass::OK;
2132 if (!forced_local_layout_.empty())
2133 success = doc_class_->read(forced_local_layout_, TextClass::MODULE);
2134 if (!local_layout_.empty() &&
2135 (success == TextClass::OK || success == TextClass::OK_OLDFORMAT))
2136 success = doc_class_->read(local_layout_, TextClass::MODULE);
2137 if (success != TextClass::OK && success != TextClass::OK_OLDFORMAT) {
2138 docstring const msg = _("Error reading internal layout information");
2139 frontend::Alert::warning(_("Read Error"), msg);
2144 bool BufferParams::layoutModuleCanBeAdded(string const & modName) const
2146 return layout_modules_.moduleCanBeAdded(modName, baseClass());
2150 bool BufferParams::citationModuleCanBeAdded(string const & modName) const
2152 return cite_engine_.moduleCanBeAdded(modName, baseClass());
2156 std::string BufferParams::getLocalLayout(bool forced) const
2159 return doc_class_->forcedLayouts();
2161 return local_layout_;
2165 void BufferParams::setLocalLayout(string const & layout, bool forced)
2168 forced_local_layout_ = layout;
2170 local_layout_ = layout;
2174 bool BufferParams::addLayoutModule(string const & modName)
2176 LayoutModuleList::const_iterator it = layout_modules_.begin();
2177 LayoutModuleList::const_iterator end = layout_modules_.end();
2178 for (; it != end; ++it)
2181 layout_modules_.push_back(modName);
2186 string BufferParams::bufferFormat() const
2188 string format = documentClass().outputFormat();
2189 if (format == "latex") {
2192 if (encoding().package() == Encoding::japanese)
2199 bool BufferParams::isExportable(string const & format) const
2201 vector<string> backs = backends();
2202 for (vector<string>::const_iterator it = backs.begin();
2203 it != backs.end(); ++it)
2204 if (theConverters().isReachable(*it, format))
2210 vector<Format const *> BufferParams::exportableFormats(bool only_viewable) const
2212 vector<string> const backs = backends();
2213 set<string> excludes;
2214 if (useNonTeXFonts) {
2215 excludes.insert("latex");
2216 excludes.insert("pdflatex");
2218 vector<Format const *> result =
2219 theConverters().getReachable(backs[0], only_viewable, true, excludes);
2220 for (vector<string>::const_iterator it = backs.begin() + 1;
2221 it != backs.end(); ++it) {
2222 vector<Format const *> r =
2223 theConverters().getReachable(*it, only_viewable, false, excludes);
2224 result.insert(result.end(), r.begin(), r.end());
2230 bool BufferParams::isExportableFormat(string const & format) const
2232 typedef vector<Format const *> Formats;
2234 formats = exportableFormats(true);
2235 Formats::const_iterator fit = formats.begin();
2236 Formats::const_iterator end = formats.end();
2237 for (; fit != end ; ++fit) {
2238 if ((*fit)->name() == format)
2245 vector<string> BufferParams::backends() const
2248 string const buffmt = bufferFormat();
2250 // FIXME: Don't hardcode format names here, but use a flag
2251 if (buffmt == "latex") {
2252 if (!useNonTeXFonts) {
2253 v.push_back("pdflatex");
2254 v.push_back("latex");
2256 v.push_back("luatex");
2257 v.push_back("dviluatex");
2258 v.push_back("xetex");
2259 } else if (buffmt == "xetex") {
2260 v.push_back("xetex");
2261 // FIXME: need to test all languages (bug 8205)
2262 if (!language || !language->isPolyglossiaExclusive()) {
2263 v.push_back("luatex");
2264 v.push_back("dviluatex");
2267 v.push_back(buffmt);
2269 v.push_back("xhtml");
2270 v.push_back("text");
2276 OutputParams::FLAVOR BufferParams::getOutputFlavor(string const format) const
2278 string const dformat = (format.empty() || format == "default") ?
2279 getDefaultOutputFormat() : format;
2280 DefaultFlavorCache::const_iterator it =
2281 default_flavors_.find(dformat);
2283 if (it != default_flavors_.end())
2286 OutputParams::FLAVOR result = OutputParams::LATEX;
2288 // FIXME It'd be better not to hardcode this, but to do
2289 // something with formats.
2290 if (dformat == "xhtml")
2291 result = OutputParams::HTML;
2292 else if (dformat == "text")
2293 result = OutputParams::TEXT;
2294 else if (dformat == "lyx")
2295 result = OutputParams::LYX;
2296 else if (dformat == "pdflatex")
2297 result = OutputParams::PDFLATEX;
2298 else if (dformat == "xetex")
2299 result = OutputParams::XETEX;
2300 else if (dformat == "luatex")
2301 result = OutputParams::LUATEX;
2302 else if (dformat == "dviluatex")
2303 result = OutputParams::DVILUATEX;
2305 // Try to determine flavor of default output format
2306 vector<string> backs = backends();
2307 if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
2308 // Get shortest path to format
2309 Graph::EdgePath path;
2310 for (vector<string>::const_iterator it = backs.begin();
2311 it != backs.end(); ++it) {
2312 Graph::EdgePath p = theConverters().getPath(*it, dformat);
2313 if (!p.empty() && (path.empty() || p.size() < path.size())) {
2318 result = theConverters().getFlavor(path);
2321 // cache this flavor
2322 default_flavors_[dformat] = result;
2327 string BufferParams::getDefaultOutputFormat() const
2329 if (!default_output_format.empty()
2330 && default_output_format != "default")
2331 return default_output_format;
2333 || encoding().package() == Encoding::japanese) {
2334 vector<Format const *> const formats = exportableFormats(true);
2335 if (formats.empty())
2337 // return the first we find
2338 return formats.front()->name();
2341 return lyxrc.default_otf_view_format;
2342 return lyxrc.default_view_format;
2345 Font const BufferParams::getFont() const
2347 FontInfo f = documentClass().defaultfont();
2348 if (fonts_default_family == "rmdefault")
2349 f.setFamily(ROMAN_FAMILY);
2350 else if (fonts_default_family == "sfdefault")
2351 f.setFamily(SANS_FAMILY);
2352 else if (fonts_default_family == "ttdefault")
2353 f.setFamily(TYPEWRITER_FAMILY);
2354 return Font(f, language);
2358 InsetQuotes::QuoteLanguage BufferParams::getQuoteStyle(string const qs) const
2360 return quoteslangtranslator().find(qs);
2364 bool BufferParams::isLatex() const
2366 return documentClass().outputType() == LATEX;
2370 bool BufferParams::isLiterate() const
2372 return documentClass().outputType() == LITERATE;
2376 bool BufferParams::isDocBook() const
2378 return documentClass().outputType() == DOCBOOK;
2382 void BufferParams::readPreamble(Lexer & lex)
2384 if (lex.getString() != "\\begin_preamble")
2385 lyxerr << "Error (BufferParams::readPreamble):"
2386 "consistency check failed." << endl;
2388 preamble = lex.getLongString("\\end_preamble");
2392 void BufferParams::readLocalLayout(Lexer & lex, bool forced)
2394 string const expected = forced ? "\\begin_forced_local_layout" :
2395 "\\begin_local_layout";
2396 if (lex.getString() != expected)
2397 lyxerr << "Error (BufferParams::readLocalLayout):"
2398 "consistency check failed." << endl;
2401 forced_local_layout_ =
2402 lex.getLongString("\\end_forced_local_layout");
2404 local_layout_ = lex.getLongString("\\end_local_layout");
2408 bool BufferParams::setLanguage(string const & lang)
2410 Language const *new_language = languages.getLanguage(lang);
2411 if (!new_language) {
2412 // Language lang was not found
2415 language = new_language;
2420 void BufferParams::readLanguage(Lexer & lex)
2422 if (!lex.next()) return;
2424 string const tmptok = lex.getString();
2426 // check if tmptok is part of tex_babel in tex-defs.h
2427 if (!setLanguage(tmptok)) {
2428 // Language tmptok was not found
2429 language = default_language;
2430 lyxerr << "Warning: Setting language `"
2431 << tmptok << "' to `" << language->lang()
2437 void BufferParams::readGraphicsDriver(Lexer & lex)
2442 string const tmptok = lex.getString();
2443 // check if tmptok is part of tex_graphics in tex_defs.h
2446 string const test = tex_graphics[n++];
2448 if (test == tmptok) {
2449 graphics_driver = tmptok;
2454 "Warning: graphics driver `$$Token' not recognized!\n"
2455 " Setting graphics driver to `default'.\n");
2456 graphics_driver = "default";
2463 void BufferParams::readBullets(Lexer & lex)
2468 int const index = lex.getInteger();
2470 int temp_int = lex.getInteger();
2471 user_defined_bullet(index).setFont(temp_int);
2472 temp_bullet(index).setFont(temp_int);
2474 user_defined_bullet(index).setCharacter(temp_int);
2475 temp_bullet(index).setCharacter(temp_int);
2477 user_defined_bullet(index).setSize(temp_int);
2478 temp_bullet(index).setSize(temp_int);
2482 void BufferParams::readBulletsLaTeX(Lexer & lex)
2484 // The bullet class should be able to read this.
2487 int const index = lex.getInteger();
2489 docstring const temp_str = lex.getDocString();
2491 user_defined_bullet(index).setText(temp_str);
2492 temp_bullet(index).setText(temp_str);
2496 void BufferParams::readModules(Lexer & lex)
2498 if (!lex.eatLine()) {
2499 lyxerr << "Error (BufferParams::readModules):"
2500 "Unexpected end of input." << endl;
2504 string mod = lex.getString();
2505 if (mod == "\\end_modules")
2507 addLayoutModule(mod);
2513 void BufferParams::readRemovedModules(Lexer & lex)
2515 if (!lex.eatLine()) {
2516 lyxerr << "Error (BufferParams::readRemovedModules):"
2517 "Unexpected end of input." << endl;
2521 string mod = lex.getString();
2522 if (mod == "\\end_removed_modules")
2524 removed_modules_.push_back(mod);
2527 // now we want to remove any removed modules that were previously
2528 // added. normally, that will be because default modules were added in
2529 // setBaseClass(), which gets called when \textclass is read at the
2530 // start of the read.
2531 list<string>::const_iterator rit = removed_modules_.begin();
2532 list<string>::const_iterator const ren = removed_modules_.end();
2533 for (; rit != ren; ++rit) {
2534 LayoutModuleList::iterator const mit = layout_modules_.begin();
2535 LayoutModuleList::iterator const men = layout_modules_.end();
2536 LayoutModuleList::iterator found = find(mit, men, *rit);
2539 layout_modules_.erase(found);
2544 void BufferParams::readIncludeonly(Lexer & lex)
2546 if (!lex.eatLine()) {
2547 lyxerr << "Error (BufferParams::readIncludeonly):"
2548 "Unexpected end of input." << endl;
2552 string child = lex.getString();
2553 if (child == "\\end_includeonly")
2555 included_children_.push_back(child);
2561 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2563 switch (papersize) {
2565 // could be anything, so don't guess
2567 case PAPER_CUSTOM: {
2568 if (purpose == XDVI && !paperwidth.empty() &&
2569 !paperheight.empty()) {
2570 // heightxwidth<unit>
2571 string first = paperwidth;
2572 string second = paperheight;
2573 if (orientation == ORIENTATION_LANDSCAPE)
2576 return first.erase(first.length() - 2)
2582 // dvips and dvipdfm do not know this
2583 if (purpose == DVIPS || purpose == DVIPDFM)
2587 if (purpose == DVIPS || purpose == DVIPDFM)
2591 if (purpose == DVIPS || purpose == DVIPDFM)
2601 if (purpose == DVIPS || purpose == DVIPDFM)
2605 if (purpose == DVIPS || purpose == DVIPDFM)
2609 if (purpose == DVIPS || purpose == DVIPDFM)
2613 if (purpose == DVIPS || purpose == DVIPDFM)
2617 if (purpose == DVIPS || purpose == DVIPDFM)
2621 // dvipdfm does not know this
2622 if (purpose == DVIPDFM)
2626 if (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)
2674 if (purpose == DVIPS || purpose == DVIPDFM)
2678 if (purpose == DVIPS || purpose == DVIPDFM)
2682 if (purpose == DVIPS || purpose == DVIPDFM)
2686 if (purpose == DVIPS || purpose == DVIPDFM)
2689 case PAPER_USEXECUTIVE:
2690 // dvipdfm does not know this
2691 if (purpose == DVIPDFM)
2696 case PAPER_USLETTER:
2698 if (purpose == XDVI)
2705 string const BufferParams::dvips_options() const
2709 // If the class loads the geometry package, we do not know which
2710 // paper size is used, since we do not set it (bug 7013).
2711 // Therefore we must not specify any argument here.
2712 // dvips gets the correct paper size via DVI specials in this case
2713 // (if the class uses the geometry package correctly).
2714 if (documentClass().provides("geometry"))
2718 && papersize == PAPER_CUSTOM
2719 && !lyxrc.print_paper_dimension_flag.empty()
2720 && !paperwidth.empty()
2721 && !paperheight.empty()) {
2722 // using a custom papersize
2723 result = lyxrc.print_paper_dimension_flag;
2724 result += ' ' + paperwidth;
2725 result += ',' + paperheight;
2727 string const paper_option = paperSizeName(DVIPS);
2728 if (!paper_option.empty() && (paper_option != "letter" ||
2729 orientation != ORIENTATION_LANDSCAPE)) {
2730 // dvips won't accept -t letter -t landscape.
2731 // In all other cases, include the paper size
2733 result = lyxrc.print_paper_flag;
2734 result += ' ' + paper_option;
2737 if (orientation == ORIENTATION_LANDSCAPE &&
2738 papersize != PAPER_CUSTOM)
2739 result += ' ' + lyxrc.print_landscape_flag;
2744 string const BufferParams::font_encoding() const
2746 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2750 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2752 // suppress the babel call if there is no BabelName defined
2753 // for the document language in the lib/languages file and if no
2754 // other languages are used (lang_opts is then empty)
2755 if (lang_opts.empty())
2757 // either a specific language (AsBabelOptions setting in
2758 // lib/languages) or the prefs require the languages to
2759 // be submitted to babel itself (not the class).
2761 return "\\usepackage[" + lang_opts + "]{babel}";
2762 return "\\usepackage{babel}";
2766 docstring BufferParams::getGraphicsDriver(string const & package) const
2770 if (package == "geometry") {
2771 if (graphics_driver == "dvips"
2772 || graphics_driver == "dvipdfm"
2773 || graphics_driver == "pdftex"
2774 || graphics_driver == "vtex")
2775 result = from_ascii(graphics_driver);
2776 else if (graphics_driver == "dvipdfmx")
2777 result = from_ascii("dvipdfm");
2784 void BufferParams::writeEncodingPreamble(otexstream & os,
2785 LaTeXFeatures & features) const
2787 // XeTeX does not need this
2788 if (features.runparams().flavor == OutputParams::XETEX)
2790 // LuaTeX neither, but with tex fonts, we need to load
2791 // the luainputenc package.
2792 if (features.runparams().flavor == OutputParams::LUATEX
2793 || features.runparams().flavor == OutputParams::DVILUATEX) {
2794 if (!useNonTeXFonts && inputenc != "default"
2795 && ((inputenc == "auto" && language->encoding()->package() == Encoding::inputenc)
2796 || (inputenc != "auto" && encoding().package() == Encoding::inputenc))) {
2797 os << "\\usepackage[utf8]{luainputenc}\n";
2801 if (inputenc == "auto") {
2802 string const doc_encoding =
2803 language->encoding()->latexName();
2804 Encoding::Package const package =
2805 language->encoding()->package();
2807 // Create a list with all the input encodings used
2809 set<string> encodings =
2810 features.getEncodingSet(doc_encoding);
2812 // If the "japanese" package (i.e. pLaTeX) is used,
2813 // inputenc must be omitted.
2814 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2815 if ((!encodings.empty() || package == Encoding::inputenc)
2816 && !features.isRequired("japanese")) {
2817 os << "\\usepackage[";
2818 set<string>::const_iterator it = encodings.begin();
2819 set<string>::const_iterator const end = encodings.end();
2821 os << from_ascii(*it);
2824 for (; it != end; ++it)
2825 os << ',' << from_ascii(*it);
2826 if (package == Encoding::inputenc) {
2827 if (!encodings.empty())
2829 os << from_ascii(doc_encoding);
2831 os << "]{inputenc}\n";
2833 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2834 if (language->encoding()->name() == "utf8-cjk"
2835 && LaTeXFeatures::isAvailable("CJKutf8"))
2836 os << "\\usepackage{CJKutf8}\n";
2838 os << "\\usepackage{CJK}\n";
2840 } else if (inputenc != "default") {
2841 switch (encoding().package()) {
2842 case Encoding::none:
2843 case Encoding::japanese:
2845 case Encoding::inputenc:
2846 // do not load inputenc if japanese is used
2847 if (features.isRequired("japanese"))
2849 os << "\\usepackage[" << from_ascii(encoding().latexName())
2853 if (encoding().name() == "utf8-cjk"
2854 && LaTeXFeatures::isAvailable("CJKutf8"))
2855 os << "\\usepackage{CJKutf8}\n";
2857 os << "\\usepackage{CJK}\n";
2860 // Load the CJK package if needed by a secondary language.
2861 // If the main encoding is some variant of UTF8, use CJKutf8.
2862 if (encoding().package() != Encoding::CJK && features.mustProvide("CJK")) {
2863 if (encoding().iconvName() == "UTF-8"
2864 && LaTeXFeatures::isAvailable("CJKutf8"))
2865 os << "\\usepackage{CJKutf8}\n";
2867 os << "\\usepackage{CJK}\n";
2873 string const BufferParams::parseFontName(string const & name) const
2875 string mangled = name;
2876 size_t const idx = mangled.find('[');
2877 if (idx == string::npos || idx == 0)
2880 return mangled.substr(0, idx - 1);
2884 string const BufferParams::loadFonts(LaTeXFeatures & features) const
2886 if (fonts_roman == "default" && fonts_sans == "default"
2887 && fonts_typewriter == "default"
2888 && (fonts_math == "default" || fonts_math == "auto"))
2894 /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
2895 * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX/
2896 * Mapping=tex-text option assures TeX ligatures (such as "--")
2897 * are resolved. Note that tt does not use these ligatures.
2899 * -- add more GUI options?
2900 * -- add more fonts (fonts for other scripts)
2901 * -- if there's a way to find out if a font really supports
2902 * OldStyle, enable/disable the widget accordingly.
2904 if (useNonTeXFonts && features.isAvailable("fontspec")) {
2905 // "Mapping=tex-text" and "Ligatures=TeX" are equivalent.
2906 // However, until v.2 (2010/07/11) fontspec only knew
2907 // Mapping=tex-text (for XeTeX only); then "Ligatures=TeX"
2908 // was introduced for both XeTeX and LuaTeX (LuaTeX
2909 // didn't understand "Mapping=tex-text", while XeTeX
2910 // understood both. With most recent versions, both
2911 // variants are understood by both engines. However,
2912 // we want to provide support for at least TeXLive 2009
2913 // (for XeTeX; LuaTeX is only supported as of v.2)
2914 string const texmapping =
2915 (features.runparams().flavor == OutputParams::XETEX) ?
2916 "Mapping=tex-text" : "Ligatures=TeX";
2917 if (fonts_roman != "default") {
2918 os << "\\setmainfont[" << texmapping;
2919 if (fonts_old_figures)
2920 os << ",Numbers=OldStyle";
2921 os << "]{" << parseFontName(fonts_roman) << "}\n";
2923 if (fonts_sans != "default") {
2924 string const sans = parseFontName(fonts_sans);
2925 if (fonts_sans_scale != 100)
2926 os << "\\setsansfont[Scale="
2927 << float(fonts_sans_scale) / 100
2928 << "," << texmapping << "]{"
2931 os << "\\setsansfont[" << texmapping << "]{"
2934 if (fonts_typewriter != "default") {
2935 string const mono = parseFontName(fonts_typewriter);
2936 if (fonts_typewriter_scale != 100)
2937 os << "\\setmonofont[Scale="
2938 << float(fonts_typewriter_scale) / 100
2942 os << "\\setmonofont{"
2949 bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
2950 bool const dryrun = features.runparams().dryrun;
2951 bool const complete = (fonts_sans == "default" && fonts_typewriter == "default");
2952 bool const nomath = (fonts_math == "default");
2955 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_roman)).getLaTeXCode(
2956 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2960 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_sans)).getLaTeXCode(
2961 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2962 nomath, fonts_sans_scale);
2964 // MONOSPACED/TYPEWRITER
2965 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_typewriter)).getLaTeXCode(
2966 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2967 nomath, fonts_typewriter_scale);
2970 os << theLaTeXFonts().getLaTeXFont(from_ascii(fonts_math)).getLaTeXCode(
2971 dryrun, ot1, complete, fonts_expert_sc, fonts_old_figures,
2978 Encoding const & BufferParams::encoding() const
2980 // FIXME: actually, we should check for the flavor
2981 // or runparams.isFullyUnicode() here:
2982 // This check will not work with XeTeX/LuaTeX and tex fonts.
2983 // Thus we have to reset the encoding in Buffer::makeLaTeXFile.
2985 return *(encodings.fromLyXName("utf8-plain"));
2986 if (inputenc == "auto" || inputenc == "default")
2987 return *language->encoding();
2988 Encoding const * const enc = encodings.fromLyXName(inputenc);
2991 LYXERR0("Unknown inputenc value `" << inputenc
2992 << "'. Using `auto' instead.");
2993 return *language->encoding();
2997 bool BufferParams::addCiteEngine(string const & engine)
2999 LayoutModuleList::const_iterator it = cite_engine_.begin();
3000 LayoutModuleList::const_iterator en = cite_engine_.end();
3001 for (; it != en; ++it)
3004 cite_engine_.push_back(engine);
3009 bool BufferParams::addCiteEngine(vector<string> const & engine)
3011 vector<string>::const_iterator it = engine.begin();
3012 vector<string>::const_iterator en = engine.end();
3014 for (; it != en; ++it)
3015 if (!addCiteEngine(*it))
3021 string const & BufferParams::defaultBiblioStyle() const
3023 return documentClass().defaultBiblioStyle();
3027 bool const & BufferParams::fullAuthorList() const
3029 return documentClass().fullAuthorList();
3033 void BufferParams::setCiteEngine(string const & engine)
3036 addCiteEngine(engine);
3040 void BufferParams::setCiteEngine(vector<string> const & engine)
3043 addCiteEngine(engine);
3047 vector<string> BufferParams::citeCommands() const
3049 static CitationStyle const default_style;
3050 vector<string> commands =
3051 documentClass().citeCommands(citeEngineType());
3052 if (commands.empty())
3053 commands.push_back(default_style.cmd);
3058 vector<CitationStyle> BufferParams::citeStyles() const
3060 static CitationStyle const default_style;
3061 vector<CitationStyle> styles =
3062 documentClass().citeStyles(citeEngineType());
3064 styles.push_back(default_style);