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"
29 #include "IndicesList.h"
31 #include "LaTeXFeatures.h"
32 #include "ModuleList.h"
36 #include "OutputParams.h"
40 #include "PDFOptions.h"
42 #include "frontends/alert.h"
44 #include "insets/InsetListingsParams.h"
46 #include "support/convert.h"
47 #include "support/debug.h"
48 #include "support/docstream.h"
49 #include "support/FileName.h"
50 #include "support/filetools.h"
51 #include "support/gettext.h"
52 #include "support/Messages.h"
53 #include "support/Translator.h"
54 #include "support/lstrings.h"
60 using namespace lyx::support;
63 static char const * const string_paragraph_separation[] = {
68 static char const * const string_quotes_language[] = {
69 "english", "swedish", "german", "polish", "french", "danish", ""
73 static char const * const string_papersize[] = {
74 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
75 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
76 "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
77 "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
78 "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
83 static char const * const string_orientation[] = {
84 "portrait", "landscape", ""
88 static char const * const string_footnotekinds[] = {
89 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
93 static char const * const tex_graphics[] = {
94 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
95 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
96 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
97 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
108 // Paragraph separation
109 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
112 ParSepTranslator const init_parseptranslator()
114 ParSepTranslator translator
115 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
116 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
121 ParSepTranslator const & parseptranslator()
123 static ParSepTranslator translator = init_parseptranslator();
129 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
132 QuotesLangTranslator const init_quoteslangtranslator()
134 QuotesLangTranslator translator
135 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
136 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
137 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
138 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
139 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
140 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
145 QuotesLangTranslator const & quoteslangtranslator()
147 static QuotesLangTranslator translator = init_quoteslangtranslator();
153 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
156 static PaperSizeTranslator initPaperSizeTranslator()
158 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
159 translator.addPair(string_papersize[1], PAPER_CUSTOM);
160 translator.addPair(string_papersize[2], PAPER_USLETTER);
161 translator.addPair(string_papersize[3], PAPER_USLEGAL);
162 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
163 translator.addPair(string_papersize[5], PAPER_A0);
164 translator.addPair(string_papersize[6], PAPER_A1);
165 translator.addPair(string_papersize[7], PAPER_A2);
166 translator.addPair(string_papersize[8], PAPER_A3);
167 translator.addPair(string_papersize[9], PAPER_A4);
168 translator.addPair(string_papersize[10], PAPER_A5);
169 translator.addPair(string_papersize[11], PAPER_A6);
170 translator.addPair(string_papersize[12], PAPER_B0);
171 translator.addPair(string_papersize[13], PAPER_B1);
172 translator.addPair(string_papersize[14], PAPER_B2);
173 translator.addPair(string_papersize[15], PAPER_B3);
174 translator.addPair(string_papersize[16], PAPER_B4);
175 translator.addPair(string_papersize[17], PAPER_B5);
176 translator.addPair(string_papersize[18], PAPER_B6);
177 translator.addPair(string_papersize[19], PAPER_C0);
178 translator.addPair(string_papersize[20], PAPER_C1);
179 translator.addPair(string_papersize[21], PAPER_C2);
180 translator.addPair(string_papersize[22], PAPER_C3);
181 translator.addPair(string_papersize[23], PAPER_C4);
182 translator.addPair(string_papersize[24], PAPER_C5);
183 translator.addPair(string_papersize[25], PAPER_C6);
184 translator.addPair(string_papersize[26], PAPER_JISB0);
185 translator.addPair(string_papersize[27], PAPER_JISB1);
186 translator.addPair(string_papersize[28], PAPER_JISB2);
187 translator.addPair(string_papersize[29], PAPER_JISB3);
188 translator.addPair(string_papersize[30], PAPER_JISB4);
189 translator.addPair(string_papersize[31], PAPER_JISB5);
190 translator.addPair(string_papersize[32], PAPER_JISB6);
195 PaperSizeTranslator const & papersizetranslator()
197 static PaperSizeTranslator translator = 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 translator = init_paperorientationtranslator();
222 typedef Translator<int, PageSides> SidesTranslator;
225 SidesTranslator const init_sidestranslator()
227 SidesTranslator translator(1, OneSide);
228 translator.addPair(2, TwoSides);
233 SidesTranslator const & sidestranslator()
235 static SidesTranslator translator = init_sidestranslator();
241 typedef Translator<int, BufferParams::Package> PackageTranslator;
244 PackageTranslator const init_packagetranslator()
246 PackageTranslator translator(0, BufferParams::package_off);
247 translator.addPair(1, BufferParams::package_auto);
248 translator.addPair(2, BufferParams::package_on);
253 PackageTranslator const & packagetranslator()
255 static PackageTranslator translator = init_packagetranslator();
261 typedef Translator<string, CiteEngine> CiteEngineTranslator;
264 CiteEngineTranslator const init_citeenginetranslator()
266 CiteEngineTranslator translator("basic", ENGINE_BASIC);
267 translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
268 translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
269 translator.addPair("jurabib", ENGINE_JURABIB);
274 CiteEngineTranslator const & citeenginetranslator()
276 static CiteEngineTranslator translator = init_citeenginetranslator();
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)
340 return new BufferParams::Impl(*ptr);
344 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
350 BufferParams::BufferParams()
353 setBaseClass(defaultBaseclass());
355 paragraph_separation = ParagraphIndentSeparation;
356 quotes_language = InsetQuotes::EnglishQuotes;
357 fontsize = "default";
360 papersize = PAPER_DEFAULT;
361 orientation = ORIENTATION_PORTRAIT;
362 use_geometry = false;
363 use_amsmath = package_auto;
364 use_esint = package_auto;
365 use_mhchem = package_auto;
366 use_mathdots = package_auto;
367 cite_engine_ = ENGINE_BASIC;
368 use_bibtopic = false;
370 trackChanges = false;
371 outputChanges = false;
372 use_default_options = true;
373 maintain_unincluded_children = false;
376 language = default_language;
378 fontsRoman = "default";
379 fontsSans = "default";
380 fontsTypewriter = "default";
381 fontsDefaultFamily = "default";
385 fontsSansScale = 100;
386 fontsTypewriterScale = 100;
388 graphicsDriver = "default";
389 defaultOutputFormat = "default";
390 bibtex_command = "default";
391 index_command = "default";
394 listings_params = string();
395 pagestyle = "default";
396 suppress_date = false;
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;
422 docstring BufferParams::B_(string const & l10n) const
424 LASSERT(language, /**/);
425 return getMessages(language->code()).get(l10n);
429 AuthorList & BufferParams::authors()
431 return pimpl_->authorlist;
435 AuthorList const & BufferParams::authors() const
437 return pimpl_->authorlist;
441 BranchList & BufferParams::branchlist()
443 return pimpl_->branchlist;
447 BranchList const & BufferParams::branchlist() const
449 return pimpl_->branchlist;
453 IndicesList & BufferParams::indiceslist()
455 return pimpl_->indiceslist;
459 IndicesList const & BufferParams::indiceslist() const
461 return pimpl_->indiceslist;
465 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
467 LASSERT(index < 4, /**/);
468 return pimpl_->temp_bullets[index];
472 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
474 LASSERT(index < 4, /**/);
475 return pimpl_->temp_bullets[index];
479 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
481 LASSERT(index < 4, /**/);
482 return pimpl_->user_defined_bullets[index];
486 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
488 LASSERT(index < 4, /**/);
489 return pimpl_->user_defined_bullets[index];
493 Spacing & BufferParams::spacing()
495 return pimpl_->spacing;
499 Spacing const & BufferParams::spacing() const
501 return pimpl_->spacing;
505 PDFOptions & BufferParams::pdfoptions()
507 return pimpl_->pdfoptions;
511 PDFOptions const & BufferParams::pdfoptions() const
513 return pimpl_->pdfoptions;
517 HSpace const & BufferParams::getIndentation() const
519 return pimpl_->indentation;
523 void BufferParams::setIndentation(HSpace const & indent)
525 pimpl_->indentation = indent;
529 VSpace const & BufferParams::getDefSkip() const
531 return pimpl_->defskip;
535 void BufferParams::setDefSkip(VSpace const & vs)
537 // DEFSKIP will cause an infinite loop
538 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
539 pimpl_->defskip = vs;
543 string BufferParams::readToken(Lexer & lex, string const & token,
544 FileName const & filepath)
546 if (token == "\\textclass") {
548 string const classname = lex.getString();
549 // if there exists a local layout file, ignore the system one
550 // NOTE: in this case, the textclass (.cls file) is assumed to
553 LayoutFileList & bcl = LayoutFileList::get();
554 if (tcp.empty() && !filepath.empty())
555 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
559 setBaseClass(classname);
560 // We assume that a tex class exists for local or unknown
561 // layouts so this warning, will only be given for system layouts.
562 if (!baseClass()->isTeXClassAvailable()) {
563 docstring const desc =
564 translateIfPossible(from_utf8(baseClass()->description()));
565 docstring const prereqs =
566 from_utf8(baseClass()->prerequisites());
567 docstring const msg =
568 bformat(_("The selected document class\n"
570 "requires external files that are not available.\n"
571 "The document class can still be used, but the\n"
572 "document cannot be compiled until the following\n"
573 "prerequisites are installed:\n"
575 "See section 3.1.2.2 of the User's Guide for\n"
576 "more information."), desc, prereqs);
577 frontend::Alert::warning(_("Document class not available"),
580 } else if (token == "\\begin_preamble") {
582 } else if (token == "\\begin_local_layout") {
583 readLocalLayout(lex);
584 } else if (token == "\\begin_modules") {
586 } else if (token == "\\begin_removed_modules") {
587 readRemovedModules(lex);
588 } else if (token == "\\begin_includeonly") {
589 readIncludeonly(lex);
590 } else if (token == "\\maintain_unincluded_children") {
591 lex >> maintain_unincluded_children;
592 } else if (token == "\\options") {
594 options = lex.getString();
595 } else if (token == "\\use_default_options") {
596 lex >> use_default_options;
597 } else if (token == "\\master") {
599 master = lex.getString();
600 } else if (token == "\\suppress_date") {
601 lex >> suppress_date;
602 } else if (token == "\\language") {
604 } else if (token == "\\inputencoding") {
606 } else if (token == "\\graphics") {
607 readGraphicsDriver(lex);
608 } else if (token == "\\default_output_format") {
609 lex >> defaultOutputFormat;
610 } else if (token == "\\bibtex_command") {
612 bibtex_command = lex.getString();
613 } else if (token == "\\index_command") {
615 index_command = lex.getString();
616 } else if (token == "\\fontencoding") {
618 fontenc = lex.getString();
619 } else if (token == "\\font_roman") {
621 fontsRoman = lex.getString();
622 } else if (token == "\\font_sans") {
624 fontsSans = lex.getString();
625 } else if (token == "\\font_typewriter") {
627 fontsTypewriter = lex.getString();
628 } else if (token == "\\font_default_family") {
629 lex >> fontsDefaultFamily;
630 } else if (token == "\\use_xetex") {
632 } else if (token == "\\font_sc") {
634 } else if (token == "\\font_osf") {
636 } else if (token == "\\font_sf_scale") {
637 lex >> fontsSansScale;
638 } else if (token == "\\font_tt_scale") {
639 lex >> fontsTypewriterScale;
640 } else if (token == "\\font_cjk") {
642 } else if (token == "\\paragraph_separation") {
645 paragraph_separation = parseptranslator().find(parsep);
646 } else if (token == "\\paragraph_indentation") {
648 string indentation = lex.getString();
649 pimpl_->indentation = HSpace(indentation);
650 } else if (token == "\\defskip") {
652 string const defskip = lex.getString();
653 pimpl_->defskip = VSpace(defskip);
654 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
656 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
657 } else if (token == "\\quotes_language") {
660 quotes_language = quoteslangtranslator().find(quotes_lang);
661 } else if (token == "\\papersize") {
664 papersize = papersizetranslator().find(ppsize);
665 } else if (token == "\\use_geometry") {
667 } else if (token == "\\use_amsmath") {
670 use_amsmath = packagetranslator().find(use_ams);
671 } else if (token == "\\use_esint") {
674 use_esint = packagetranslator().find(useesint);
675 } else if (token == "\\use_mhchem") {
678 use_mhchem = packagetranslator().find(usemhchem);
679 } else if (token == "\\use_mathdots") {
682 use_mathdots = packagetranslator().find(usemathdots);
683 } else if (token == "\\cite_engine") {
686 cite_engine_ = citeenginetranslator().find(engine);
687 } else if (token == "\\use_bibtopic") {
689 } else if (token == "\\use_indices") {
691 } else if (token == "\\tracking_changes") {
693 } else if (token == "\\output_changes") {
694 lex >> outputChanges;
695 } else if (token == "\\branch") {
697 docstring branch = lex.getDocString();
698 branchlist().add(branch);
701 string const tok = lex.getString();
702 if (tok == "\\end_branch")
704 Branch * branch_ptr = branchlist().find(branch);
705 if (tok == "\\selected") {
708 branch_ptr->setSelected(lex.getInteger());
710 if (tok == "\\filename_suffix") {
713 branch_ptr->setFileNameSuffix(lex.getInteger());
715 if (tok == "\\color") {
717 string color = lex.getString();
719 branch_ptr->setColor(color);
720 // Update also the Color table:
722 color = lcolor.getX11Name(Color_background);
724 lcolor.setColor(to_utf8(branch), color);
727 } else if (token == "\\index") {
729 docstring index = lex.getDocString();
731 indiceslist().add(index);
734 string const tok = lex.getString();
735 if (tok == "\\end_index")
737 Index * index_ptr = indiceslist().find(index);
738 if (tok == "\\shortcut") {
740 shortcut = lex.getDocString();
742 index_ptr->setShortcut(shortcut);
744 if (tok == "\\color") {
746 string color = lex.getString();
748 index_ptr->setColor(color);
749 // Update also the Color table:
751 color = lcolor.getX11Name(Color_background);
753 if (!shortcut.empty())
754 lcolor.setColor(to_utf8(shortcut), color);
757 } else if (token == "\\author") {
759 istringstream ss(lex.getString());
762 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
763 } else if (token == "\\paperorientation") {
766 orientation = paperorientationtranslator().find(orient);
767 } else if (token == "\\backgroundcolor") {
769 backgroundcolor = lyx::rgbFromHexName(lex.getString());
770 isbackgroundcolor = true;
771 } else if (token == "\\fontcolor") {
773 fontcolor = lyx::rgbFromHexName(lex.getString());
775 } else if (token == "\\notefontcolor") {
777 string color = lex.getString();
778 notefontcolor = lyx::rgbFromHexName(color);
779 } else if (token == "\\boxbgcolor") {
781 string color = lex.getString();
782 boxbgcolor = lyx::rgbFromHexName(color);
783 } else if (token == "\\paperwidth") {
785 } else if (token == "\\paperheight") {
787 } else if (token == "\\leftmargin") {
789 } else if (token == "\\topmargin") {
791 } else if (token == "\\rightmargin") {
793 } else if (token == "\\bottommargin") {
795 } else if (token == "\\headheight") {
797 } else if (token == "\\headsep") {
799 } else if (token == "\\footskip") {
801 } else if (token == "\\columnsep") {
803 } else if (token == "\\paperfontsize") {
805 } else if (token == "\\papercolumns") {
807 } else if (token == "\\listings_params") {
810 listings_params = InsetListingsParams(par).params();
811 } else if (token == "\\papersides") {
814 sides = sidestranslator().find(psides);
815 } else if (token == "\\paperpagestyle") {
817 } else if (token == "\\bullet") {
819 } else if (token == "\\bulletLaTeX") {
820 readBulletsLaTeX(lex);
821 } else if (token == "\\secnumdepth") {
823 } else if (token == "\\tocdepth") {
825 } else if (token == "\\spacing") {
829 if (nspacing == "other") {
832 spacing().set(spacetranslator().find(nspacing), tmp_val);
833 } else if (token == "\\float_placement") {
834 lex >> float_placement;
836 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
837 string toktmp = pdfoptions().readToken(lex, token);
838 if (!toktmp.empty()) {
839 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
843 } else if (token == "\\html_math_output") {
846 html_math_output = static_cast<MathOutput>(temp);
847 } else if (token == "\\html_be_strict") {
848 lex >> html_be_strict;
849 } else if (token == "\\html_math_img_scale") {
850 lex >> html_math_img_scale;
851 } else if (token == "\\html_latex_start") {
853 html_latex_start = lex.getString();
854 } else if (token == "\\html_latex_end") {
856 html_latex_end = lex.getString();
857 } else if (token == "\\output_sync") {
859 } else if (token == "\\output_sync_macro") {
860 lex >> output_sync_macro;
861 } else if (token == "\\use_refstyle") {
864 lyxerr << "BufferParams::readToken(): Unknown token: " <<
873 void BufferParams::writeFile(ostream & os) const
875 // The top of the file is written by the buffer.
876 // Prints out the buffer info into the .lyx file given by file
879 os << "\\textclass " << baseClass()->name() << '\n';
882 if (!preamble.empty()) {
883 // remove '\n' from the end of preamble
884 string const tmppreamble = rtrim(preamble, "\n");
885 os << "\\begin_preamble\n"
887 << "\n\\end_preamble\n";
891 if (!options.empty()) {
892 os << "\\options " << options << '\n';
895 // use the class options defined in the layout?
896 os << "\\use_default_options "
897 << convert<string>(use_default_options) << "\n";
899 // the master document
900 if (!master.empty()) {
901 os << "\\master " << master << '\n';
905 if (!removedModules_.empty()) {
906 os << "\\begin_removed_modules" << '\n';
907 list<string>::const_iterator it = removedModules_.begin();
908 list<string>::const_iterator en = removedModules_.end();
909 for (; it != en; it++)
911 os << "\\end_removed_modules" << '\n';
915 if (!layoutModules_.empty()) {
916 os << "\\begin_modules" << '\n';
917 LayoutModuleList::const_iterator it = layoutModules_.begin();
918 LayoutModuleList::const_iterator en = layoutModules_.end();
919 for (; it != en; it++)
921 os << "\\end_modules" << '\n';
925 if (!includedChildren_.empty()) {
926 os << "\\begin_includeonly" << '\n';
927 list<string>::const_iterator it = includedChildren_.begin();
928 list<string>::const_iterator en = includedChildren_.end();
929 for (; it != en; it++)
931 os << "\\end_includeonly" << '\n';
933 os << "\\maintain_unincluded_children "
934 << convert<string>(maintain_unincluded_children) << '\n';
936 // local layout information
937 if (!local_layout.empty()) {
938 // remove '\n' from the end
939 string const tmplocal = rtrim(local_layout, "\n");
940 os << "\\begin_local_layout\n"
942 << "\n\\end_local_layout\n";
945 // then the text parameters
946 if (language != ignore_language)
947 os << "\\language " << language->lang() << '\n';
948 os << "\\inputencoding " << inputenc
949 << "\n\\fontencoding " << fontenc
950 << "\n\\font_roman " << fontsRoman
951 << "\n\\font_sans " << fontsSans
952 << "\n\\font_typewriter " << fontsTypewriter
953 << "\n\\font_default_family " << fontsDefaultFamily
954 << "\n\\use_xetex " << convert<string>(useXetex)
955 << "\n\\font_sc " << convert<string>(fontsSC)
956 << "\n\\font_osf " << convert<string>(fontsOSF)
957 << "\n\\font_sf_scale " << fontsSansScale
958 << "\n\\font_tt_scale " << fontsTypewriterScale
960 if (!fontsCJK.empty()) {
961 os << "\\font_cjk " << fontsCJK << '\n';
963 os << "\n\\graphics " << graphicsDriver << '\n';
964 os << "\\default_output_format " << defaultOutputFormat << '\n';
965 os << "\\output_sync " << output_sync << '\n';
966 if (!output_sync_macro.empty())
967 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
968 os << "\\bibtex_command " << bibtex_command << '\n';
969 os << "\\index_command " << index_command << '\n';
971 if (!float_placement.empty()) {
972 os << "\\float_placement " << float_placement << '\n';
974 os << "\\paperfontsize " << fontsize << '\n';
976 spacing().writeFile(os);
977 pdfoptions().writeFile(os);
979 os << "\\papersize " << string_papersize[papersize]
980 << "\n\\use_geometry " << convert<string>(use_geometry)
981 << "\n\\use_amsmath " << use_amsmath
982 << "\n\\use_esint " << use_esint
983 << "\n\\use_mhchem " << use_mhchem
984 << "\n\\use_mathdots " << use_mathdots
985 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
986 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
987 << "\n\\use_indices " << convert<string>(use_indices)
988 << "\n\\paperorientation " << string_orientation[orientation]
989 << "\n\\suppress_date " << convert<string>(suppress_date)
990 << "\n\\use_refstyle " << use_refstyle
992 if (isbackgroundcolor == true)
993 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
994 if (isfontcolor == true)
995 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
996 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
997 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
998 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
999 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1001 BranchList::const_iterator it = branchlist().begin();
1002 BranchList::const_iterator end = branchlist().end();
1003 for (; it != end; ++it) {
1004 os << "\\branch " << to_utf8(it->branch())
1005 << "\n\\selected " << it->isSelected()
1006 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1007 << "\n\\color " << lyx::X11hexname(it->color())
1012 IndicesList::const_iterator iit = indiceslist().begin();
1013 IndicesList::const_iterator iend = indiceslist().end();
1014 for (; iit != iend; ++iit) {
1015 os << "\\index " << to_utf8(iit->index())
1016 << "\n\\shortcut " << to_utf8(iit->shortcut())
1017 << "\n\\color " << lyx::X11hexname(iit->color())
1022 if (!paperwidth.empty())
1023 os << "\\paperwidth "
1024 << VSpace(paperwidth).asLyXCommand() << '\n';
1025 if (!paperheight.empty())
1026 os << "\\paperheight "
1027 << VSpace(paperheight).asLyXCommand() << '\n';
1028 if (!leftmargin.empty())
1029 os << "\\leftmargin "
1030 << VSpace(leftmargin).asLyXCommand() << '\n';
1031 if (!topmargin.empty())
1032 os << "\\topmargin "
1033 << VSpace(topmargin).asLyXCommand() << '\n';
1034 if (!rightmargin.empty())
1035 os << "\\rightmargin "
1036 << VSpace(rightmargin).asLyXCommand() << '\n';
1037 if (!bottommargin.empty())
1038 os << "\\bottommargin "
1039 << VSpace(bottommargin).asLyXCommand() << '\n';
1040 if (!headheight.empty())
1041 os << "\\headheight "
1042 << VSpace(headheight).asLyXCommand() << '\n';
1043 if (!headsep.empty())
1045 << VSpace(headsep).asLyXCommand() << '\n';
1046 if (!footskip.empty())
1048 << VSpace(footskip).asLyXCommand() << '\n';
1049 if (!columnsep.empty())
1050 os << "\\columnsep "
1051 << VSpace(columnsep).asLyXCommand() << '\n';
1052 os << "\\secnumdepth " << secnumdepth
1053 << "\n\\tocdepth " << tocdepth
1054 << "\n\\paragraph_separation "
1055 << string_paragraph_separation[paragraph_separation];
1056 if (!paragraph_separation)
1057 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1059 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1060 os << "\n\\quotes_language "
1061 << string_quotes_language[quotes_language]
1062 << "\n\\papercolumns " << columns
1063 << "\n\\papersides " << sides
1064 << "\n\\paperpagestyle " << pagestyle << '\n';
1065 if (!listings_params.empty())
1066 os << "\\listings_params \"" <<
1067 InsetListingsParams(listings_params).encodedString() << "\"\n";
1068 for (int i = 0; i < 4; ++i) {
1069 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1070 if (user_defined_bullet(i).getFont() != -1) {
1071 os << "\\bullet " << i << " "
1072 << user_defined_bullet(i).getFont() << " "
1073 << user_defined_bullet(i).getCharacter() << " "
1074 << user_defined_bullet(i).getSize() << "\n";
1078 os << "\\bulletLaTeX " << i << " \""
1079 << lyx::to_ascii(user_defined_bullet(i).getText())
1085 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1086 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1087 << "\\html_math_output " << html_math_output << '\n'
1088 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1090 if (html_math_img_scale != 1.0)
1091 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1092 if (!html_latex_start.empty())
1093 os << "\\html_latex_start " << html_latex_start << '\n';
1094 if (!html_latex_end.empty())
1095 os << "\\html_latex_end " << html_latex_end << '\n';
1097 os << pimpl_->authorlist;
1101 void BufferParams::validate(LaTeXFeatures & features) const
1103 features.require(documentClass().requires());
1105 if (outputChanges) {
1106 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1107 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1108 LaTeXFeatures::isAvailable("xcolor");
1110 switch (features.runparams().flavor) {
1111 case OutputParams::LATEX:
1113 features.require("ct-dvipost");
1114 features.require("dvipost");
1115 } else if (xcolorulem) {
1116 features.require("ct-xcolor-ulem");
1117 features.require("ulem");
1118 features.require("xcolor");
1120 features.require("ct-none");
1123 case OutputParams::LUATEX:
1124 case OutputParams::PDFLATEX:
1125 case OutputParams::XETEX:
1127 features.require("ct-xcolor-ulem");
1128 features.require("ulem");
1129 features.require("xcolor");
1130 // improves color handling in PDF output
1131 features.require("pdfcolmk");
1133 features.require("ct-none");
1141 // Floats with 'Here definitely' as default setting.
1142 if (float_placement.find('H') != string::npos)
1143 features.require("float");
1145 // AMS Style is at document level
1146 if (use_amsmath == package_on
1147 || documentClass().provides("amsmath"))
1148 features.require("amsmath");
1149 if (use_esint == package_on)
1150 features.require("esint");
1151 if (use_mhchem == package_on)
1152 features.require("mhchem");
1153 if (use_mathdots == package_on)
1154 features.require("mathdots");
1156 // Document-level line spacing
1157 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1158 features.require("setspace");
1160 // the bullet shapes are buffer level not paragraph level
1161 // so they are tested here
1162 for (int i = 0; i < 4; ++i) {
1163 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1165 int const font = user_defined_bullet(i).getFont();
1167 int const c = user_defined_bullet(i).getCharacter();
1173 features.require("latexsym");
1175 } else if (font == 1) {
1176 features.require("amssymb");
1177 } else if (font >= 2 && font <= 5) {
1178 features.require("pifont");
1182 if (pdfoptions().use_hyperref) {
1183 features.require("hyperref");
1184 // due to interferences with babel and hyperref, the color package has to
1185 // be loaded after hyperref when hyperref is used with the colorlinks
1186 // option, see http://www.lyx.org/trac/ticket/5291
1187 if (pdfoptions().colorlinks)
1188 features.require("color");
1191 if (features.runparams().flavor == OutputParams::XETEX)
1192 features.require("polyglossia");
1194 if (language->lang() == "vietnamese")
1195 features.require("vietnamese");
1196 else if (language->lang() == "japanese")
1197 features.require("japanese");
1201 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1202 TexRow & texrow, FileName const & filepath) const
1204 os << "\\documentclass";
1206 DocumentClass const & tclass = documentClass();
1208 ostringstream clsoptions; // the document class options.
1210 if (tokenPos(tclass.opt_fontsize(),
1211 '|', fontsize) >= 0) {
1212 // only write if existing in list (and not default)
1213 clsoptions << fontsize << "pt,";
1216 // all paper sizes except of A4, A5, B5 and the US sizes need the
1218 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1219 && papersize != PAPER_USLETTER
1220 && papersize != PAPER_USLEGAL
1221 && papersize != PAPER_USEXECUTIVE
1222 && papersize != PAPER_A4
1223 && papersize != PAPER_A5
1224 && papersize != PAPER_B5;
1226 if (!use_geometry) {
1227 switch (papersize) {
1229 clsoptions << "a4paper,";
1231 case PAPER_USLETTER:
1232 clsoptions << "letterpaper,";
1235 clsoptions << "a5paper,";
1238 clsoptions << "b5paper,";
1240 case PAPER_USEXECUTIVE:
1241 clsoptions << "executivepaper,";
1244 clsoptions << "legalpaper,";
1278 if (sides != tclass.sides()) {
1281 clsoptions << "oneside,";
1284 clsoptions << "twoside,";
1290 if (columns != tclass.columns()) {
1292 clsoptions << "twocolumn,";
1294 clsoptions << "onecolumn,";
1298 && orientation == ORIENTATION_LANDSCAPE)
1299 clsoptions << "landscape,";
1301 // language should be a parameter to \documentclass
1302 if (language->babel() == "hebrew"
1303 && default_language->babel() != "hebrew")
1304 // This seems necessary
1305 features.useLanguage(default_language);
1307 ostringstream language_options;
1308 bool const use_babel = features.useBabel() && !tclass.provides("babel");
1309 bool const use_polyglossia = features.usePolyglossia();
1310 bool const global = lyxrc.language_global_options;
1311 if (use_babel || (use_polyglossia && global)) {
1312 language_options << features.getLanguages();
1313 if (!language->babel().empty()) {
1314 if (!language_options.str().empty())
1315 language_options << ',';
1316 language_options << language->babel();
1318 if (global && !features.needBabelLangOptions())
1319 clsoptions << language_options.str() << ',';
1322 // the predefined options from the layout
1323 if (use_default_options && !tclass.options().empty())
1324 clsoptions << tclass.options() << ',';
1326 // the user-defined options
1327 if (!options.empty()) {
1328 clsoptions << options << ',';
1331 string strOptions(clsoptions.str());
1332 if (!strOptions.empty()) {
1333 strOptions = rtrim(strOptions, ",");
1335 os << '[' << from_utf8(strOptions) << ']';
1338 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1340 // end of \documentclass defs
1343 os << "\\usepackage{fontspec}\n";
1347 // font selection must be done before loading fontenc.sty
1348 string const fonts =
1349 loadFonts(fontsRoman, fontsSans,
1350 fontsTypewriter, fontsSC, fontsOSF,
1351 fontsSansScale, fontsTypewriterScale, useXetex);
1352 if (!fonts.empty()) {
1353 os << from_ascii(fonts);
1356 if (fontsDefaultFamily != "default")
1357 os << "\\renewcommand{\\familydefault}{\\"
1358 << from_ascii(fontsDefaultFamily) << "}\n";
1360 // set font encoding
1361 // for arabic_arabi and farsi we also need to load the LAE and
1363 // XeTeX and LuaTeX (isFullUnicode() flavor) work without fontenc
1364 if (font_encoding() != "default" && language->lang() != "japanese"
1365 && !features.runparams().isFullUnicode() && !tclass.provides("fontenc")) {
1366 size_t fars = language_options.str().find("farsi");
1367 size_t arab = language_options.str().find("arabic");
1368 if (language->lang() == "arabic_arabi"
1369 || language->lang() == "farsi" || fars != string::npos
1370 || arab != string::npos) {
1371 os << "\\usepackage[" << from_ascii(font_encoding())
1372 << ",LFE,LAE]{fontenc}\n";
1375 os << "\\usepackage[" << from_ascii(font_encoding())
1381 // handle inputenc etc.
1382 writeEncodingPreamble(os, features, texrow);
1385 if (!features.runparams().includeall && !includedChildren_.empty()) {
1386 os << "\\includeonly{";
1387 list<string>::const_iterator it = includedChildren_.begin();
1389 for (; it != includedChildren_.end() ; ++it) {
1390 string incfile = *it;
1391 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1392 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1394 if (!features.runparams().nice)
1396 // \includeonly doesn't want an extension
1397 incfile = changeExtension(incfile, string());
1398 incfile = support::latex_path(incfile);
1399 if (!incfile.empty()) {
1402 os << from_utf8(incfile);
1409 if (!listings_params.empty() || features.isRequired("listings")) {
1410 os << "\\usepackage{listings}\n";
1413 if (!listings_params.empty()) {
1415 // do not test validity because listings_params is
1416 // supposed to be valid
1418 InsetListingsParams(listings_params).separatedParams(true);
1419 // we can't support all packages, but we should load the color package
1420 if (par.find("\\color", 0) != string::npos)
1421 features.require("color");
1422 os << from_utf8(par);
1423 // count the number of newlines
1424 for (size_t i = 0; i < par.size(); ++i)
1430 if (!tclass.provides("geometry")
1431 && (use_geometry || nonstandard_papersize)) {
1432 odocstringstream ods;
1433 if (!getGraphicsDriver("geometry").empty())
1434 ods << getGraphicsDriver("geometry");
1435 if (orientation == ORIENTATION_LANDSCAPE)
1436 ods << ",landscape";
1437 switch (papersize) {
1439 if (!paperwidth.empty())
1440 ods << ",paperwidth="
1441 << from_ascii(paperwidth);
1442 if (!paperheight.empty())
1443 ods << ",paperheight="
1444 << from_ascii(paperheight);
1446 case PAPER_USLETTER:
1447 ods << ",letterpaper";
1450 ods << ",legalpaper";
1452 case PAPER_USEXECUTIVE:
1453 ods << ",executivepaper";
1540 // default papersize ie PAPER_DEFAULT
1541 switch (lyxrc.default_papersize) {
1542 case PAPER_DEFAULT: // keep compiler happy
1543 case PAPER_USLETTER:
1544 ods << ",letterpaper";
1547 ods << ",legalpaper";
1549 case PAPER_USEXECUTIVE:
1550 ods << ",executivepaper";
1592 docstring const g_options = trim(ods.str(), ",");
1593 os << "\\usepackage";
1594 if (!g_options.empty())
1595 os << '[' << g_options << ']';
1596 os << "{geometry}\n";
1598 // output this only if use_geometry is true
1600 os << "\\geometry{verbose";
1601 if (!topmargin.empty())
1602 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1603 if (!bottommargin.empty())
1604 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1605 if (!leftmargin.empty())
1606 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1607 if (!rightmargin.empty())
1608 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1609 if (!headheight.empty())
1610 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1611 if (!headsep.empty())
1612 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1613 if (!footskip.empty())
1614 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1615 if (!columnsep.empty())
1616 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1620 } else if (orientation == ORIENTATION_LANDSCAPE
1621 || papersize != PAPER_DEFAULT) {
1622 features.require("papersize");
1625 if (tokenPos(tclass.opt_pagestyle(),
1626 '|', pagestyle) >= 0) {
1627 if (pagestyle == "fancy") {
1628 os << "\\usepackage{fancyhdr}\n";
1631 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1635 // only output when the background color is not default
1636 if (isbackgroundcolor == true) {
1637 // only require color here, the background color will be defined
1638 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1640 features.require("color");
1641 features.require("pagecolor");
1644 // only output when the font color is not default
1645 if (isfontcolor == true) {
1646 // only require color here, the font color will be defined
1647 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1649 features.require("color");
1650 features.require("fontcolor");
1653 // Only if class has a ToC hierarchy
1654 if (tclass.hasTocLevels()) {
1655 if (secnumdepth != tclass.secnumdepth()) {
1656 os << "\\setcounter{secnumdepth}{"
1661 if (tocdepth != tclass.tocdepth()) {
1662 os << "\\setcounter{tocdepth}{"
1669 if (paragraph_separation) {
1670 // when skip separation
1671 switch (getDefSkip().kind()) {
1672 case VSpace::SMALLSKIP:
1673 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1675 case VSpace::MEDSKIP:
1676 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1678 case VSpace::BIGSKIP:
1679 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1681 case VSpace::LENGTH:
1682 os << "\\setlength{\\parskip}{"
1683 << from_utf8(getDefSkip().length().asLatexString())
1686 default: // should never happen // Then delete it.
1687 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1691 os << "\\setlength{\\parindent}{0pt}\n";
1694 // when separation by indentation
1695 // only output something when a width is given
1696 if (getIndentation().asLyXCommand() != "default") {
1697 os << "\\setlength{\\parindent}{"
1698 << from_utf8(getIndentation().asLatexCommand())
1704 // Now insert the LyX specific LaTeX commands...
1705 docstring lyxpreamble;
1708 if (!output_sync_macro.empty())
1709 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1710 else if (features.runparams().flavor == OutputParams::LATEX)
1711 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1712 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1713 lyxpreamble += "\\synctex=-1\n";
1716 // due to interferences with babel and hyperref, the color package has to
1717 // be loaded (when it is not already loaded) before babel when hyperref
1718 // is used with the colorlinks option, see
1719 // http://www.lyx.org/trac/ticket/5291
1720 // we decided therefore to load color always before babel, see
1721 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1722 lyxpreamble += from_ascii(features.getColorOptions());
1724 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1726 && (features.isRequired("jurabib")
1727 || features.isRequired("hyperref")
1728 || features.isRequired("vietnamese")
1729 || features.isRequired("japanese"))) {
1731 lyxpreamble += from_utf8(features.getBabelPresettings());
1732 lyxpreamble += from_utf8(babelCall(language_options.str(),
1733 features.needBabelLangOptions())) + '\n';
1734 lyxpreamble += from_utf8(features.getBabelPostsettings());
1737 // The optional packages;
1738 lyxpreamble += from_ascii(features.getPackages());
1740 // Additional Indices
1741 if (features.isRequired("splitidx")) {
1742 IndicesList::const_iterator iit = indiceslist().begin();
1743 IndicesList::const_iterator iend = indiceslist().end();
1744 for (; iit != iend; ++iit) {
1745 lyxpreamble += "\\newindex[";
1746 lyxpreamble += iit->index();
1747 lyxpreamble += "]{";
1748 lyxpreamble += iit->shortcut();
1749 lyxpreamble += "}\n";
1754 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1757 // * Hyperref manual: "Make sure it comes last of your loaded
1758 // packages, to give it a fighting chance of not being over-written,
1759 // since its job is to redefine many LaTeX commands."
1760 // * Email from Heiko Oberdiek: "It is usually better to load babel
1761 // before hyperref. Then hyperref has a chance to detect babel.
1762 // * Has to be loaded before the "LyX specific LaTeX commands" to
1763 // avoid errors with algorithm floats.
1764 // use hyperref explicitly if it is required
1765 if (features.isRequired("hyperref")) {
1766 // pass what we have to stream here, since we need
1767 // to access the stream itself in PDFOptions.
1771 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1773 OutputParams tmp_params = features.runparams();
1774 lines += pdfoptions().writeLaTeX(tmp_params, os,
1775 documentClass().provides("hyperref"));
1776 texrow.newlines(lines);
1777 // set back for the rest
1778 lyxpreamble.clear();
1779 } else if (features.isRequired("nameref"))
1780 // hyperref loads this automatically
1781 lyxpreamble += "\\usepackage{nameref}\n";
1783 // Will be surrounded by \makeatletter and \makeatother when not empty
1784 docstring atlyxpreamble;
1786 // Some macros LyX will need
1787 docstring tmppreamble(features.getMacros());
1789 if (!tmppreamble.empty())
1790 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1791 "LyX specific LaTeX commands.\n"
1792 + tmppreamble + '\n';
1794 // the text class specific preamble
1795 tmppreamble = features.getTClassPreamble();
1796 if (!tmppreamble.empty())
1797 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1798 "Textclass specific LaTeX commands.\n"
1799 + tmppreamble + '\n';
1801 // suppress date if selected
1802 // use \@ifundefined because we cannot be sure that every document class
1803 // has a \date command
1805 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1807 /* the user-defined preamble */
1808 if (!containsOnly(preamble, " \n\t"))
1810 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1811 "User specified LaTeX commands.\n"
1812 + from_utf8(preamble) + '\n';
1814 // subfig loads internally the LaTeX package "caption". As
1815 // caption is a very popular package, users will load it in
1816 // the preamble. Therefore we must load subfig behind the
1817 // user-defined preamble and check if the caption package was
1818 // loaded or not. For the case that caption is loaded before
1819 // subfig, there is the subfig option "caption=false". This
1820 // option also works when a koma-script class is used and
1821 // koma's own caption commands are used instead of caption. We
1822 // use \PassOptionsToPackage here because the user could have
1823 // already loaded subfig in the preamble.
1824 if (features.isRequired("subfig")) {
1825 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1826 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1827 "\\usepackage{subfig}\n";
1830 // Itemize bullet settings need to be last in case the user
1831 // defines their own bullets that use a package included
1832 // in the user-defined preamble -- ARRae
1833 // Actually it has to be done much later than that
1834 // since some packages like frenchb make modifications
1835 // at \begin{document} time -- JMarc
1836 docstring bullets_def;
1837 for (int i = 0; i < 4; ++i) {
1838 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1839 if (bullets_def.empty())
1840 bullets_def += "\\AtBeginDocument{\n";
1841 bullets_def += " \\def\\labelitemi";
1843 // `i' is one less than the item to modify
1850 bullets_def += "ii";
1856 bullets_def += '{' +
1857 user_defined_bullet(i).getText()
1862 if (!bullets_def.empty())
1863 atlyxpreamble += bullets_def + "}\n\n";
1865 if (!atlyxpreamble.empty())
1866 lyxpreamble += "\n\\makeatletter\n"
1867 + atlyxpreamble + "\\makeatother\n\n";
1869 // We try to load babel late, in case it interferes with other packages.
1870 // Jurabib and Hyperref have to be called after babel, though.
1871 if (use_babel && !features.isRequired("jurabib")
1872 && !features.isRequired("hyperref")
1873 && !features.isRequired("vietnamese")
1874 && !features.isRequired("japanese")) {
1876 lyxpreamble += from_utf8(features.getBabelPresettings());
1877 lyxpreamble += from_utf8(babelCall(language_options.str(),
1878 features.needBabelLangOptions())) + '\n';
1879 lyxpreamble += from_utf8(features.getBabelPostsettings());
1882 // FIXME Polyglossia?
1883 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1884 if (!i18npreamble.empty())
1885 lyxpreamble += i18npreamble + '\n';
1888 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1889 texrow.newlines(nlines);
1893 // these packages (xunicode, for that matter) need to be loaded at least
1894 // after amsmath, amssymb, esint and the other packages that provide
1896 if (features.runparams().flavor == OutputParams::XETEX) {
1897 os << "\\usepackage{xunicode}\n";
1899 os << "\\usepackage{xltxtra}\n";
1902 // Polyglossia must be loaded after xltxtra
1903 if (use_polyglossia) {
1905 os << "\\usepackage{polyglossia}\n";
1907 // set the main language
1908 os << "\\setdefaultlanguage";
1909 if (!language->polyglossiaOpts().empty())
1910 os << "[" << from_ascii(language->polyglossiaOpts()) << "]";
1911 os << "{" + from_ascii(language->polyglossia()) + "}\n";
1913 // now setup the other languages
1914 std::map<std::string, std::string> const polylangs =
1915 features.getPolyglossiaLanguages();
1916 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
1917 mit != polylangs.end() ; ++mit) {
1918 os << "\\setotherlanguage";
1919 if (!mit->second.empty())
1920 os << "[" << from_ascii(mit->second) << "]";
1921 os << "{" << from_ascii(mit->first) << "}\n";
1929 void BufferParams::useClassDefaults()
1931 DocumentClass const & tclass = documentClass();
1933 sides = tclass.sides();
1934 columns = tclass.columns();
1935 pagestyle = tclass.pagestyle();
1936 use_default_options = true;
1937 // Only if class has a ToC hierarchy
1938 if (tclass.hasTocLevels()) {
1939 secnumdepth = tclass.secnumdepth();
1940 tocdepth = tclass.tocdepth();
1945 bool BufferParams::hasClassDefaults() const
1947 DocumentClass const & tclass = documentClass();
1949 return sides == tclass.sides()
1950 && columns == tclass.columns()
1951 && pagestyle == tclass.pagestyle()
1952 && use_default_options
1953 && secnumdepth == tclass.secnumdepth()
1954 && tocdepth == tclass.tocdepth();
1958 DocumentClass const & BufferParams::documentClass() const
1964 DocumentClass const * BufferParams::documentClassPtr() const
1970 void BufferParams::setDocumentClass(DocumentClass const * const tc)
1972 // evil, but this function is evil
1973 doc_class_ = const_cast<DocumentClass *>(tc);
1977 bool BufferParams::setBaseClass(string const & classname)
1979 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1980 LayoutFileList & bcl = LayoutFileList::get();
1981 if (!bcl.haveClass(classname)) {
1983 bformat(_("The layout file:\n"
1985 "could not be found. A default textclass with default\n"
1986 "layouts will be used. LyX will not be able to produce\n"
1988 from_utf8(classname));
1989 frontend::Alert::error(_("Document class not found"), s);
1990 bcl.addEmptyClass(classname);
1993 bool const success = bcl[classname].load();
1996 bformat(_("Due to some error in it, the layout file:\n"
1998 "could not be loaded. A default textclass with default\n"
1999 "layouts will be used. LyX will not be able to produce\n"
2001 from_utf8(classname));
2002 frontend::Alert::error(_("Could not load class"), s);
2003 bcl.addEmptyClass(classname);
2006 pimpl_->baseClass_ = classname;
2007 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
2012 LayoutFile const * BufferParams::baseClass() const
2014 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2015 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2021 LayoutFileIndex const & BufferParams::baseClassID() const
2023 return pimpl_->baseClass_;
2027 void BufferParams::makeDocumentClass()
2032 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
2034 if (!local_layout.empty()) {
2035 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
2036 docstring const msg = _("Error reading internal layout information");
2037 frontend::Alert::warning(_("Read Error"), msg);
2043 bool BufferParams::moduleCanBeAdded(string const & modName) const
2045 return layoutModules_.moduleCanBeAdded(modName, baseClass());
2049 bool BufferParams::addLayoutModule(string const & modName)
2051 LayoutModuleList::const_iterator it = layoutModules_.begin();
2052 LayoutModuleList::const_iterator end = layoutModules_.end();
2053 for (; it != end; it++)
2056 layoutModules_.push_back(modName);
2061 Font const BufferParams::getFont() const
2063 FontInfo f = documentClass().defaultfont();
2064 if (fontsDefaultFamily == "rmdefault")
2065 f.setFamily(ROMAN_FAMILY);
2066 else if (fontsDefaultFamily == "sfdefault")
2067 f.setFamily(SANS_FAMILY);
2068 else if (fontsDefaultFamily == "ttdefault")
2069 f.setFamily(TYPEWRITER_FAMILY);
2070 return Font(f, language);
2074 void BufferParams::readPreamble(Lexer & lex)
2076 if (lex.getString() != "\\begin_preamble")
2077 lyxerr << "Error (BufferParams::readPreamble):"
2078 "consistency check failed." << endl;
2080 preamble = lex.getLongString("\\end_preamble");
2084 void BufferParams::readLocalLayout(Lexer & lex)
2086 if (lex.getString() != "\\begin_local_layout")
2087 lyxerr << "Error (BufferParams::readLocalLayout):"
2088 "consistency check failed." << endl;
2090 local_layout = lex.getLongString("\\end_local_layout");
2094 void BufferParams::readLanguage(Lexer & lex)
2096 if (!lex.next()) return;
2098 string const tmptok = lex.getString();
2100 // check if tmptok is part of tex_babel in tex-defs.h
2101 language = languages.getLanguage(tmptok);
2103 // Language tmptok was not found
2104 language = default_language;
2105 lyxerr << "Warning: Setting language `"
2106 << tmptok << "' to `" << language->lang()
2112 void BufferParams::readGraphicsDriver(Lexer & lex)
2117 string const tmptok = lex.getString();
2118 // check if tmptok is part of tex_graphics in tex_defs.h
2121 string const test = tex_graphics[n++];
2123 if (test == tmptok) {
2124 graphicsDriver = tmptok;
2129 "Warning: graphics driver `$$Token' not recognized!\n"
2130 " Setting graphics driver to `default'.\n");
2131 graphicsDriver = "default";
2138 void BufferParams::readBullets(Lexer & lex)
2143 int const index = lex.getInteger();
2145 int temp_int = lex.getInteger();
2146 user_defined_bullet(index).setFont(temp_int);
2147 temp_bullet(index).setFont(temp_int);
2149 user_defined_bullet(index).setCharacter(temp_int);
2150 temp_bullet(index).setCharacter(temp_int);
2152 user_defined_bullet(index).setSize(temp_int);
2153 temp_bullet(index).setSize(temp_int);
2157 void BufferParams::readBulletsLaTeX(Lexer & lex)
2159 // The bullet class should be able to read this.
2162 int const index = lex.getInteger();
2164 docstring const temp_str = lex.getDocString();
2166 user_defined_bullet(index).setText(temp_str);
2167 temp_bullet(index).setText(temp_str);
2171 void BufferParams::readModules(Lexer & lex)
2173 if (!lex.eatLine()) {
2174 lyxerr << "Error (BufferParams::readModules):"
2175 "Unexpected end of input." << endl;
2179 string mod = lex.getString();
2180 if (mod == "\\end_modules")
2182 addLayoutModule(mod);
2188 void BufferParams::readRemovedModules(Lexer & lex)
2190 if (!lex.eatLine()) {
2191 lyxerr << "Error (BufferParams::readRemovedModules):"
2192 "Unexpected end of input." << endl;
2196 string mod = lex.getString();
2197 if (mod == "\\end_removed_modules")
2199 removedModules_.push_back(mod);
2202 // now we want to remove any removed modules that were previously
2203 // added. normally, that will be because default modules were added in
2204 // setBaseClass(), which gets called when \textclass is read at the
2205 // start of the read.
2206 list<string>::const_iterator rit = removedModules_.begin();
2207 list<string>::const_iterator const ren = removedModules_.end();
2208 for (; rit != ren; rit++) {
2209 LayoutModuleList::iterator const mit = layoutModules_.begin();
2210 LayoutModuleList::iterator const men = layoutModules_.end();
2211 LayoutModuleList::iterator found = find(mit, men, *rit);
2214 layoutModules_.erase(found);
2219 void BufferParams::readIncludeonly(Lexer & lex)
2221 if (!lex.eatLine()) {
2222 lyxerr << "Error (BufferParams::readIncludeonly):"
2223 "Unexpected end of input." << endl;
2227 string child = lex.getString();
2228 if (child == "\\end_includeonly")
2230 includedChildren_.push_back(child);
2236 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2238 char real_papersize = papersize;
2239 if (real_papersize == PAPER_DEFAULT)
2240 real_papersize = lyxrc.default_papersize;
2242 switch (real_papersize) {
2244 // could be anything, so don't guess
2246 case PAPER_CUSTOM: {
2247 if (purpose == XDVI && !paperwidth.empty() &&
2248 !paperheight.empty()) {
2249 // heightxwidth<unit>
2250 string first = paperwidth;
2251 string second = paperheight;
2252 if (orientation == ORIENTATION_LANDSCAPE)
2255 return first.erase(first.length() - 2)
2261 // dvips and dvipdfm do not know this
2262 if (purpose == DVIPS || purpose == DVIPDFM)
2266 if (purpose == DVIPS || purpose == DVIPDFM)
2270 if (purpose == DVIPS || purpose == DVIPDFM)
2280 if (purpose == DVIPS || purpose == DVIPDFM)
2284 if (purpose == DVIPS || purpose == DVIPDFM)
2288 if (purpose == DVIPS || purpose == DVIPDFM)
2292 if (purpose == DVIPS || purpose == DVIPDFM)
2296 if (purpose == DVIPS || purpose == DVIPDFM)
2300 // dvipdfm does not know this
2301 if (purpose == DVIPDFM)
2305 if (purpose == DVIPDFM)
2309 if (purpose == DVIPS || purpose == DVIPDFM)
2313 if (purpose == DVIPS || purpose == DVIPDFM)
2317 if (purpose == DVIPS || purpose == DVIPDFM)
2321 if (purpose == DVIPS || purpose == DVIPDFM)
2325 if (purpose == DVIPS || purpose == DVIPDFM)
2329 if (purpose == DVIPS || purpose == DVIPDFM)
2333 if (purpose == DVIPS || purpose == DVIPDFM)
2337 if (purpose == DVIPS || purpose == DVIPDFM)
2341 if (purpose == DVIPS || purpose == DVIPDFM)
2345 if (purpose == DVIPS || purpose == DVIPDFM)
2349 if (purpose == DVIPS || purpose == DVIPDFM)
2353 if (purpose == DVIPS || purpose == DVIPDFM)
2357 if (purpose == DVIPS || purpose == DVIPDFM)
2361 if (purpose == DVIPS || purpose == DVIPDFM)
2365 if (purpose == DVIPS || purpose == DVIPDFM)
2368 case PAPER_USEXECUTIVE:
2369 // dvipdfm does not know this
2370 if (purpose == DVIPDFM)
2375 case PAPER_USLETTER:
2377 if (purpose == XDVI)
2384 string const BufferParams::dvips_options() const
2389 && papersize == PAPER_CUSTOM
2390 && !lyxrc.print_paper_dimension_flag.empty()
2391 && !paperwidth.empty()
2392 && !paperheight.empty()) {
2393 // using a custom papersize
2394 result = lyxrc.print_paper_dimension_flag;
2395 result += ' ' + paperwidth;
2396 result += ',' + paperheight;
2398 string const paper_option = paperSizeName(DVIPS);
2399 if (!paper_option.empty() && (paper_option != "letter" ||
2400 orientation != ORIENTATION_LANDSCAPE)) {
2401 // dvips won't accept -t letter -t landscape.
2402 // In all other cases, include the paper size
2404 result = lyxrc.print_paper_flag;
2405 result += ' ' + paper_option;
2408 if (orientation == ORIENTATION_LANDSCAPE &&
2409 papersize != PAPER_CUSTOM)
2410 result += ' ' + lyxrc.print_landscape_flag;
2415 string const BufferParams::font_encoding() const
2417 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2421 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2423 if (lyxrc.language_package_selection == LyXRC::LP_CUSTOM)
2424 return lyxrc.language_custom_package;
2425 // suppress the babel call if there is no BabelName defined
2426 // for the document language in the lib/languages file and if no
2427 // other languages are used (lang_opts is then empty)
2428 if (lang_opts.empty())
2430 // either a specific language (AsBabelOptions setting in
2431 // lib/languages) or the prefs require the languages to
2432 // be submitted to babel itself (not the class).
2434 return "\\usepackage[" + lang_opts + "]{babel}";
2435 return "\\usepackage{babel}";
2439 docstring BufferParams::getGraphicsDriver(string const & package) const
2443 if (package == "geometry") {
2444 if (graphicsDriver == "dvips"
2445 || graphicsDriver == "dvipdfm"
2446 || graphicsDriver == "pdftex"
2447 || graphicsDriver == "vtex")
2448 result = from_ascii(graphicsDriver);
2449 else if (graphicsDriver == "dvipdfmx")
2450 result = from_ascii("dvipdfm");
2457 void BufferParams::writeEncodingPreamble(odocstream & os,
2458 LaTeXFeatures & features, TexRow & texrow) const
2460 // fully unicode-aware backends (such as XeTeX) do not need this
2461 if (features.runparams().isFullUnicode())
2463 if (inputenc == "auto") {
2464 string const doc_encoding =
2465 language->encoding()->latexName();
2466 Encoding::Package const package =
2467 language->encoding()->package();
2469 // Create a list with all the input encodings used
2471 set<string> encodings =
2472 features.getEncodingSet(doc_encoding);
2474 // If the "japanese" package (i.e. pLaTeX) is used,
2475 // inputenc must be omitted.
2476 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2477 if (package == Encoding::japanese)
2478 features.require("japanese");
2480 if ((!encodings.empty() || package == Encoding::inputenc)
2481 && !features.isRequired("japanese")) {
2482 os << "\\usepackage[";
2483 set<string>::const_iterator it = encodings.begin();
2484 set<string>::const_iterator const end = encodings.end();
2486 os << from_ascii(*it);
2489 for (; it != end; ++it)
2490 os << ',' << from_ascii(*it);
2491 if (package == Encoding::inputenc) {
2492 if (!encodings.empty())
2494 os << from_ascii(doc_encoding);
2496 os << "]{inputenc}\n";
2499 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2500 if (language->encoding()->name() == "utf8-cjk"
2501 && LaTeXFeatures::isAvailable("CJKutf8"))
2502 os << "\\usepackage{CJKutf8}\n";
2504 os << "\\usepackage{CJK}\n";
2507 } else if (inputenc != "default") {
2508 switch (encoding().package()) {
2509 case Encoding::none:
2510 case Encoding::japanese:
2512 case Encoding::inputenc:
2513 // do not load inputenc if japanese is used
2514 if (features.isRequired("japanese"))
2516 os << "\\usepackage[" << from_ascii(inputenc)
2521 if (encoding().name() == "utf8-cjk"
2522 && LaTeXFeatures::isAvailable("CJKutf8"))
2523 os << "\\usepackage{CJKutf8}\n";
2525 os << "\\usepackage{CJK}\n";
2531 // The encoding "armscii8" (for Armenian) is only available when
2532 // the package "armtex" is loaded.
2533 if (language->encoding()->latexName() == "armscii8"
2534 || inputenc == "armscii8") {
2535 os << "\\usepackage{armtex}\n";
2541 string const BufferParams::parseFontName(string const & name) const
2543 string mangled = name;
2544 size_t const idx = mangled.find('[');
2545 if (idx == string::npos || idx == 0)
2548 return mangled.substr(0, idx - 1);
2552 string const BufferParams::loadFonts(string const & rm,
2553 string const & sf, string const & tt,
2554 bool const & sc, bool const & osf,
2555 int const & sfscale, int const & ttscale,
2556 bool const & xetex) const
2558 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2559 several packages have been replaced by others, that might not
2560 be installed on every system. We have to take care for that
2561 (see psnfss.pdf). We try to support all psnfss fonts as well
2562 as the fonts that have become de facto standard in the LaTeX
2563 world (e.g. Latin Modern). We do not support obsolete fonts
2564 (like PSLatex). In general, it should be possible to mix any
2565 rm font with any sf or tt font, respectively. (JSpitzm)
2567 -- separate math fonts.
2570 if (rm == "default" && sf == "default" && tt == "default")
2577 if (rm != "default") {
2578 os << "\\setmainfont[Mapping=tex-text";
2580 os << ",Numbers=OldStyle";
2581 os << "]{" << parseFontName(rm) << "}\n";
2583 if (sf != "default") {
2584 string const sans = parseFontName(sf);
2586 os << "\\setsansfont[Scale="
2587 << float(sfscale) / 100
2588 << ",Mapping=tex-text]{"
2591 os << "\\setsansfont[Mapping=tex-text]{"
2594 if (tt != "default") {
2595 string const mono = parseFontName(tt);
2597 os << "\\setmonofont[Scale="
2598 << float(sfscale) / 100
2602 os << "\\setmonofont[Mapping=tex-text]{"
2609 // Computer Modern (must be explicitly selectable -- there might be classes
2610 // that define a different default font!
2612 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2613 // osf for Computer Modern needs eco.sty
2615 os << "\\usepackage{eco}\n";
2617 // Latin Modern Roman
2618 else if (rm == "lmodern")
2619 os << "\\usepackage{lmodern}\n";
2621 else if (rm == "ae") {
2622 // not needed when using OT1 font encoding.
2623 if (font_encoding() != "default")
2624 os << "\\usepackage{ae,aecompl}\n";
2627 else if (rm == "times") {
2628 // try to load the best available package
2629 if (LaTeXFeatures::isAvailable("mathptmx"))
2630 os << "\\usepackage{mathptmx}\n";
2631 else if (LaTeXFeatures::isAvailable("mathptm"))
2632 os << "\\usepackage{mathptm}\n";
2634 os << "\\usepackage{times}\n";
2637 else if (rm == "palatino") {
2638 // try to load the best available package
2639 if (LaTeXFeatures::isAvailable("mathpazo")) {
2640 os << "\\usepackage";
2646 // "osf" includes "sc"!
2650 os << "{mathpazo}\n";
2652 else if (LaTeXFeatures::isAvailable("mathpple"))
2653 os << "\\usepackage{mathpple}\n";
2655 os << "\\usepackage{palatino}\n";
2658 else if (rm == "utopia") {
2659 // fourier supersedes utopia.sty, but does
2660 // not work with OT1 encoding.
2661 if (LaTeXFeatures::isAvailable("fourier")
2662 && font_encoding() != "default") {
2663 os << "\\usepackage";
2674 os << "{fourier}\n";
2677 os << "\\usepackage{utopia}\n";
2679 // Bera (complete fontset)
2680 else if (rm == "bera" && sf == "default" && tt == "default")
2681 os << "\\usepackage{bera}\n";
2683 else if (rm != "default")
2684 os << "\\usepackage" << "{" << rm << "}\n";
2687 // Helvetica, Bera Sans
2688 if (sf == "helvet" || sf == "berasans") {
2690 os << "\\usepackage[scaled=" << float(sfscale) / 100
2691 << "]{" << sf << "}\n";
2693 os << "\\usepackage{" << sf << "}\n";
2696 else if (sf == "avant")
2697 os << "\\usepackage{" << sf << "}\n";
2698 // Computer Modern, Latin Modern, CM Bright
2699 else if (sf != "default")
2700 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2702 // monospaced/typewriter
2703 // Courier, LuxiMono
2704 if (tt == "luximono" || tt == "beramono") {
2706 os << "\\usepackage[scaled=" << float(ttscale) / 100
2707 << "]{" << tt << "}\n";
2709 os << "\\usepackage{" << tt << "}\n";
2712 else if (tt == "courier" )
2713 os << "\\usepackage{" << tt << "}\n";
2714 // Computer Modern, Latin Modern, CM Bright
2715 else if (tt != "default")
2716 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2722 Encoding const & BufferParams::encoding() const
2725 return *(encodings.fromLaTeXName("utf8-plain"));
2726 if (inputenc == "auto" || inputenc == "default")
2727 return *language->encoding();
2728 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2731 LYXERR0("Unknown inputenc value `" << inputenc
2732 << "'. Using `auto' instead.");
2733 return *language->encoding();
2737 CiteEngine BufferParams::citeEngine() const
2739 // FIXME the class should provide the numerical/
2740 // authoryear choice
2741 if (documentClass().provides("natbib")
2742 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2743 return ENGINE_NATBIB_AUTHORYEAR;
2744 return cite_engine_;
2748 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2750 cite_engine_ = cite_engine;