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", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
82 static char const * const string_orientation[] = {
83 "portrait", "landscape", ""
87 static char const * const string_footnotekinds[] = {
88 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
92 static char const * const tex_graphics[] = {
93 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
94 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
95 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
96 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
107 // Paragraph separation
108 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
111 ParSepTranslator const init_parseptranslator()
113 ParSepTranslator translator
114 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
115 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
120 ParSepTranslator const & parseptranslator()
122 static ParSepTranslator translator = init_parseptranslator();
128 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
131 QuotesLangTranslator const init_quoteslangtranslator()
133 QuotesLangTranslator translator
134 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
135 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
136 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
137 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
138 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
139 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
144 QuotesLangTranslator const & quoteslangtranslator()
146 static QuotesLangTranslator translator = 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_JISB0);
177 translator.addPair(string_papersize[20], PAPER_JISB1);
178 translator.addPair(string_papersize[21], PAPER_JISB2);
179 translator.addPair(string_papersize[22], PAPER_JISB3);
180 translator.addPair(string_papersize[23], PAPER_JISB4);
181 translator.addPair(string_papersize[24], PAPER_JISB5);
182 translator.addPair(string_papersize[25], PAPER_JISB6);
187 PaperSizeTranslator const & papersizetranslator()
189 static PaperSizeTranslator translator = initPaperSizeTranslator();
195 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
198 PaperOrientationTranslator const init_paperorientationtranslator()
200 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
201 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
206 PaperOrientationTranslator const & paperorientationtranslator()
208 static PaperOrientationTranslator translator = init_paperorientationtranslator();
214 typedef Translator<int, PageSides> SidesTranslator;
217 SidesTranslator const init_sidestranslator()
219 SidesTranslator translator(1, OneSide);
220 translator.addPair(2, TwoSides);
225 SidesTranslator const & sidestranslator()
227 static SidesTranslator translator = init_sidestranslator();
233 typedef Translator<int, BufferParams::Package> PackageTranslator;
236 PackageTranslator const init_packagetranslator()
238 PackageTranslator translator(0, BufferParams::package_off);
239 translator.addPair(1, BufferParams::package_auto);
240 translator.addPair(2, BufferParams::package_on);
245 PackageTranslator const & packagetranslator()
247 static PackageTranslator translator = init_packagetranslator();
253 typedef Translator<string, CiteEngine> CiteEngineTranslator;
256 CiteEngineTranslator const init_citeenginetranslator()
258 CiteEngineTranslator translator("basic", ENGINE_BASIC);
259 translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
260 translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
261 translator.addPair("jurabib", ENGINE_JURABIB);
266 CiteEngineTranslator const & citeenginetranslator()
268 static CiteEngineTranslator translator = init_citeenginetranslator();
274 typedef Translator<string, Spacing::Space> SpaceTranslator;
277 SpaceTranslator const init_spacetranslator()
279 SpaceTranslator translator("default", Spacing::Default);
280 translator.addPair("single", Spacing::Single);
281 translator.addPair("onehalf", Spacing::Onehalf);
282 translator.addPair("double", Spacing::Double);
283 translator.addPair("other", Spacing::Other);
288 SpaceTranslator const & spacetranslator()
290 static SpaceTranslator translator = init_spacetranslator();
297 class BufferParams::Impl
302 AuthorList authorlist;
303 BranchList branchlist;
304 Bullet temp_bullets[4];
305 Bullet user_defined_bullets[4];
306 IndicesList indiceslist;
308 /** This is the amount of space used for paragraph_separation "skip",
309 * and for detached paragraphs in "indented" documents.
313 PDFOptions pdfoptions;
314 LayoutFileIndex baseClass_;
318 BufferParams::Impl::Impl()
319 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
321 // set initial author
323 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
328 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
332 return new BufferParams::Impl(*ptr);
336 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
342 BufferParams::BufferParams()
345 setBaseClass(defaultBaseclass());
347 paragraph_separation = ParagraphIndentSeparation;
348 quotes_language = InsetQuotes::EnglishQuotes;
349 fontsize = "default";
352 papersize = PAPER_DEFAULT;
353 orientation = ORIENTATION_PORTRAIT;
354 use_geometry = false;
355 use_amsmath = package_auto;
356 use_esint = package_auto;
357 use_mhchem = package_auto;
358 cite_engine_ = ENGINE_BASIC;
359 use_bibtopic = false;
361 trackChanges = false;
362 outputChanges = false;
363 use_default_options = true;
364 maintain_unincluded_children = false;
367 language = default_language;
369 fontsRoman = "default";
370 fontsSans = "default";
371 fontsTypewriter = "default";
372 fontsDefaultFamily = "default";
376 fontsSansScale = 100;
377 fontsTypewriterScale = 100;
379 graphicsDriver = "default";
380 defaultOutputFormat = "default";
381 bibtex_command = "default";
382 index_command = "default";
385 listings_params = string();
386 pagestyle = "default";
387 suppress_date = false;
388 // no color is the default (white)
389 backgroundcolor = lyx::rgbFromHexName("#ffffff");
390 isbackgroundcolor = false;
391 // no color is the default (black)
392 fontcolor = lyx::rgbFromHexName("#000000");
394 // light gray is the default font color for greyed-out notes
395 notefontcolor = lyx::rgbFromHexName("#cccccc");
396 boxbgcolor = lyx::rgbFromHexName("#ff0000");
397 compressed = lyxrc.save_compressed;
398 for (int iter = 0; iter < 4; ++iter) {
399 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
400 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
403 indiceslist().addDefault(B_("Index"));
404 html_be_strict = false;
405 html_math_output = MathML;
406 html_math_img_scale = 1.0;
412 docstring BufferParams::B_(string const & l10n) const
414 LASSERT(language, /**/);
415 return getMessages(language->code()).get(l10n);
419 AuthorList & BufferParams::authors()
421 return pimpl_->authorlist;
425 AuthorList const & BufferParams::authors() const
427 return pimpl_->authorlist;
431 BranchList & BufferParams::branchlist()
433 return pimpl_->branchlist;
437 BranchList const & BufferParams::branchlist() const
439 return pimpl_->branchlist;
443 IndicesList & BufferParams::indiceslist()
445 return pimpl_->indiceslist;
449 IndicesList const & BufferParams::indiceslist() const
451 return pimpl_->indiceslist;
455 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
457 LASSERT(index < 4, /**/);
458 return pimpl_->temp_bullets[index];
462 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
464 LASSERT(index < 4, /**/);
465 return pimpl_->temp_bullets[index];
469 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
471 LASSERT(index < 4, /**/);
472 return pimpl_->user_defined_bullets[index];
476 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
478 LASSERT(index < 4, /**/);
479 return pimpl_->user_defined_bullets[index];
483 Spacing & BufferParams::spacing()
485 return pimpl_->spacing;
489 Spacing const & BufferParams::spacing() const
491 return pimpl_->spacing;
495 PDFOptions & BufferParams::pdfoptions()
497 return pimpl_->pdfoptions;
501 PDFOptions const & BufferParams::pdfoptions() const
503 return pimpl_->pdfoptions;
507 HSpace const & BufferParams::getIndentation() const
509 return pimpl_->indentation;
513 void BufferParams::setIndentation(HSpace const & indent)
515 pimpl_->indentation = indent;
519 VSpace const & BufferParams::getDefSkip() const
521 return pimpl_->defskip;
525 void BufferParams::setDefSkip(VSpace const & vs)
527 pimpl_->defskip = vs;
531 string BufferParams::readToken(Lexer & lex, string const & token,
532 FileName const & filepath)
534 if (token == "\\textclass") {
536 string const classname = lex.getString();
537 // if there exists a local layout file, ignore the system one
538 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
540 LayoutFileList & bcl = LayoutFileList::get();
541 if (tcp.empty() && !filepath.empty())
542 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
546 setBaseClass(classname);
547 // We assume that a tex class exists for local or unknown layouts so this warning
548 // will only be given for system layouts.
549 if (!baseClass()->isTeXClassAvailable()) {
551 translateIfPossible(from_utf8(baseClass()->description()));
552 docstring const msg =
553 bformat(_("The used document class\n"
555 "requires external files that are not available.\n"
556 "The document class can still be used, but LyX\n"
557 "will not be able to produce output until the\n"
558 "following prerequisites are installed:\n"
560 "See section 3.1.2.2 of the User's Guide for\n"
561 "more information."),
562 desc, from_utf8(baseClass()->prerequisites()));
563 frontend::Alert::warning(_("Document class not available"),
566 } else if (token == "\\begin_preamble") {
568 } else if (token == "\\begin_local_layout") {
569 readLocalLayout(lex);
570 } else if (token == "\\begin_modules") {
572 } else if (token == "\\begin_removed_modules") {
573 readRemovedModules(lex);
574 } else if (token == "\\begin_includeonly") {
575 readIncludeonly(lex);
576 } else if (token == "\\maintain_unincluded_children") {
577 lex >> maintain_unincluded_children;
578 } else if (token == "\\options") {
580 options = lex.getString();
581 } else if (token == "\\use_default_options") {
582 lex >> use_default_options;
583 } else if (token == "\\master") {
585 master = lex.getString();
586 } else if (token == "\\suppress_date") {
587 lex >> suppress_date;
588 } else if (token == "\\language") {
590 } else if (token == "\\inputencoding") {
592 } else if (token == "\\graphics") {
593 readGraphicsDriver(lex);
594 } else if (token == "\\default_output_format") {
595 lex >> defaultOutputFormat;
596 } else if (token == "\\bibtex_command") {
598 bibtex_command = lex.getString();
599 } else if (token == "\\index_command") {
601 index_command = lex.getString();
602 } else if (token == "\\fontencoding") {
604 fontenc = lex.getString();
605 } else if (token == "\\font_roman") {
607 fontsRoman = lex.getString();
608 } else if (token == "\\font_sans") {
610 fontsSans = lex.getString();
611 } else if (token == "\\font_typewriter") {
613 fontsTypewriter = lex.getString();
614 } else if (token == "\\font_default_family") {
615 lex >> fontsDefaultFamily;
616 } else if (token == "\\use_xetex") {
618 } else if (token == "\\font_sc") {
620 } else if (token == "\\font_osf") {
622 } else if (token == "\\font_sf_scale") {
623 lex >> fontsSansScale;
624 } else if (token == "\\font_tt_scale") {
625 lex >> fontsTypewriterScale;
626 } else if (token == "\\font_cjk") {
628 } else if (token == "\\paragraph_separation") {
631 paragraph_separation = parseptranslator().find(parsep);
632 } else if (token == "\\paragraph_indentation") {
634 string indentation = lex.getString();
635 pimpl_->indentation = HSpace(indentation);
636 } else if (token == "\\defskip") {
638 string defskip = lex.getString();
639 if (defskip == "defskip")
642 pimpl_->defskip = VSpace(defskip);
643 } else if (token == "\\quotes_language") {
646 quotes_language = quoteslangtranslator().find(quotes_lang);
647 } else if (token == "\\papersize") {
650 papersize = papersizetranslator().find(ppsize);
651 } else if (token == "\\use_geometry") {
653 } else if (token == "\\use_amsmath") {
656 use_amsmath = packagetranslator().find(use_ams);
657 } else if (token == "\\use_esint") {
660 use_esint = packagetranslator().find(useesint);
661 } else if (token == "\\use_mhchem") {
664 use_mhchem = packagetranslator().find(usemhchem);
665 } else if (token == "\\cite_engine") {
668 cite_engine_ = citeenginetranslator().find(engine);
669 } else if (token == "\\use_bibtopic") {
671 } else if (token == "\\use_indices") {
673 } else if (token == "\\tracking_changes") {
675 } else if (token == "\\output_changes") {
676 lex >> outputChanges;
677 } else if (token == "\\branch") {
679 docstring branch = lex.getDocString();
680 branchlist().add(branch);
683 string const tok = lex.getString();
684 if (tok == "\\end_branch")
686 Branch * branch_ptr = branchlist().find(branch);
687 if (tok == "\\selected") {
690 branch_ptr->setSelected(lex.getInteger());
692 if (tok == "\\filename_suffix") {
695 branch_ptr->setFileNameSuffix(lex.getInteger());
697 if (tok == "\\color") {
699 string color = lex.getString();
701 branch_ptr->setColor(color);
702 // Update also the Color table:
704 color = lcolor.getX11Name(Color_background);
706 lcolor.setColor(to_utf8(branch), color);
709 } else if (token == "\\index") {
711 docstring index = lex.getDocString();
713 indiceslist().add(index);
716 string const tok = lex.getString();
717 if (tok == "\\end_index")
719 Index * index_ptr = indiceslist().find(index);
720 if (tok == "\\shortcut") {
722 shortcut = lex.getDocString();
724 index_ptr->setShortcut(shortcut);
726 if (tok == "\\color") {
728 string color = lex.getString();
730 index_ptr->setColor(color);
731 // Update also the Color table:
733 color = lcolor.getX11Name(Color_background);
735 if (!shortcut.empty())
736 lcolor.setColor(to_utf8(shortcut), color);
739 } else if (token == "\\author") {
741 istringstream ss(lex.getString());
744 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
745 } else if (token == "\\paperorientation") {
748 orientation = paperorientationtranslator().find(orient);
749 } else if (token == "\\backgroundcolor") {
751 backgroundcolor = lyx::rgbFromHexName(lex.getString());
752 isbackgroundcolor = true;
753 } else if (token == "\\fontcolor") {
755 fontcolor = lyx::rgbFromHexName(lex.getString());
757 } else if (token == "\\notefontcolor") {
759 string color = lex.getString();
760 notefontcolor = lyx::rgbFromHexName(color);
761 } else if (token == "\\boxbgcolor") {
763 string color = lex.getString();
764 boxbgcolor = lyx::rgbFromHexName(color);
765 } else if (token == "\\paperwidth") {
767 } else if (token == "\\paperheight") {
769 } else if (token == "\\leftmargin") {
771 } else if (token == "\\topmargin") {
773 } else if (token == "\\rightmargin") {
775 } else if (token == "\\bottommargin") {
777 } else if (token == "\\headheight") {
779 } else if (token == "\\headsep") {
781 } else if (token == "\\footskip") {
783 } else if (token == "\\columnsep") {
785 } else if (token == "\\paperfontsize") {
787 } else if (token == "\\papercolumns") {
789 } else if (token == "\\listings_params") {
792 listings_params = InsetListingsParams(par).params();
793 } else if (token == "\\papersides") {
796 sides = sidestranslator().find(psides);
797 } else if (token == "\\paperpagestyle") {
799 } else if (token == "\\bullet") {
801 } else if (token == "\\bulletLaTeX") {
802 readBulletsLaTeX(lex);
803 } else if (token == "\\secnumdepth") {
805 } else if (token == "\\tocdepth") {
807 } else if (token == "\\spacing") {
811 if (nspacing == "other") {
814 spacing().set(spacetranslator().find(nspacing), tmp_val);
815 } else if (token == "\\float_placement") {
816 lex >> float_placement;
818 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
819 string toktmp = pdfoptions().readToken(lex, token);
820 if (!toktmp.empty()) {
821 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
825 } else if (token == "\\html_math_output") {
828 html_math_output = static_cast<MathOutput>(temp);
829 } else if (token == "\\html_be_strict") {
830 lex >> html_be_strict;
831 } else if (token == "\\html_math_img_scale") {
832 lex >> html_math_img_scale;
833 } else if (token == "\\html_latex_start") {
835 html_latex_start = lex.getString();
836 } else if (token == "\\html_latex_end") {
838 html_latex_end = lex.getString();
839 } else if (token == "\\output_sync") {
841 } else if (token == "\\output_sync_macro") {
842 lex >> output_sync_macro;
844 lyxerr << "BufferParams::readToken(): Unknown token: " <<
853 void BufferParams::writeFile(ostream & os) const
855 // The top of the file is written by the buffer.
856 // Prints out the buffer info into the .lyx file given by file
859 os << "\\textclass " << baseClass()->name() << '\n';
862 if (!preamble.empty()) {
863 // remove '\n' from the end of preamble
864 string const tmppreamble = rtrim(preamble, "\n");
865 os << "\\begin_preamble\n"
867 << "\n\\end_preamble\n";
871 if (!options.empty()) {
872 os << "\\options " << options << '\n';
875 // use the class options defined in the layout?
876 os << "\\use_default_options "
877 << convert<string>(use_default_options) << "\n";
879 // the master document
880 if (!master.empty()) {
881 os << "\\master " << master << '\n';
885 if (!removedModules_.empty()) {
886 os << "\\begin_removed_modules" << '\n';
887 list<string>::const_iterator it = removedModules_.begin();
888 list<string>::const_iterator en = removedModules_.end();
889 for (; it != en; it++)
891 os << "\\end_removed_modules" << '\n';
895 if (!layoutModules_.empty()) {
896 os << "\\begin_modules" << '\n';
897 LayoutModuleList::const_iterator it = layoutModules_.begin();
898 LayoutModuleList::const_iterator en = layoutModules_.end();
899 for (; it != en; it++)
901 os << "\\end_modules" << '\n';
905 if (!includedChildren_.empty()) {
906 os << "\\begin_includeonly" << '\n';
907 list<string>::const_iterator it = includedChildren_.begin();
908 list<string>::const_iterator en = includedChildren_.end();
909 for (; it != en; it++)
911 os << "\\end_includeonly" << '\n';
913 os << "\\maintain_unincluded_children "
914 << convert<string>(maintain_unincluded_children) << '\n';
916 // local layout information
917 if (!local_layout.empty()) {
918 // remove '\n' from the end
919 string const tmplocal = rtrim(local_layout, "\n");
920 os << "\\begin_local_layout\n"
922 << "\n\\end_local_layout\n";
925 // then the text parameters
926 if (language != ignore_language)
927 os << "\\language " << language->lang() << '\n';
928 os << "\\inputencoding " << inputenc
929 << "\n\\fontencoding " << fontenc
930 << "\n\\font_roman " << fontsRoman
931 << "\n\\font_sans " << fontsSans
932 << "\n\\font_typewriter " << fontsTypewriter
933 << "\n\\font_default_family " << fontsDefaultFamily
934 << "\n\\use_xetex " << convert<string>(useXetex)
935 << "\n\\font_sc " << convert<string>(fontsSC)
936 << "\n\\font_osf " << convert<string>(fontsOSF)
937 << "\n\\font_sf_scale " << fontsSansScale
938 << "\n\\font_tt_scale " << fontsTypewriterScale
940 if (!fontsCJK.empty()) {
941 os << "\\font_cjk " << fontsCJK << '\n';
943 os << "\n\\graphics " << graphicsDriver << '\n';
944 os << "\\default_output_format " << defaultOutputFormat << '\n';
945 os << "\\output_sync " << output_sync << '\n';
946 if (!output_sync_macro.empty())
947 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
948 os << "\\bibtex_command " << bibtex_command << '\n';
949 os << "\\index_command " << index_command << '\n';
951 if (!float_placement.empty()) {
952 os << "\\float_placement " << float_placement << '\n';
954 os << "\\paperfontsize " << fontsize << '\n';
956 spacing().writeFile(os);
957 pdfoptions().writeFile(os);
959 os << "\\papersize " << string_papersize[papersize]
960 << "\n\\use_geometry " << convert<string>(use_geometry)
961 << "\n\\use_amsmath " << use_amsmath
962 << "\n\\use_esint " << use_esint
963 << "\n\\use_mhchem " << use_mhchem
964 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
965 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
966 << "\n\\use_indices " << convert<string>(use_indices)
967 << "\n\\paperorientation " << string_orientation[orientation]
968 << "\n\\suppress_date " << convert<string>(suppress_date)
970 if (isbackgroundcolor == true)
971 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
972 if (isfontcolor == true)
973 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
974 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
975 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
976 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
977 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
979 BranchList::const_iterator it = branchlist().begin();
980 BranchList::const_iterator end = branchlist().end();
981 for (; it != end; ++it) {
982 os << "\\branch " << to_utf8(it->branch())
983 << "\n\\selected " << it->isSelected()
984 << "\n\\filename_suffix " << it->hasFileNameSuffix()
985 << "\n\\color " << lyx::X11hexname(it->color())
990 IndicesList::const_iterator iit = indiceslist().begin();
991 IndicesList::const_iterator iend = indiceslist().end();
992 for (; iit != iend; ++iit) {
993 os << "\\index " << to_utf8(iit->index())
994 << "\n\\shortcut " << to_utf8(iit->shortcut())
995 << "\n\\color " << lyx::X11hexname(iit->color())
1000 if (!paperwidth.empty())
1001 os << "\\paperwidth "
1002 << VSpace(paperwidth).asLyXCommand() << '\n';
1003 if (!paperheight.empty())
1004 os << "\\paperheight "
1005 << VSpace(paperheight).asLyXCommand() << '\n';
1006 if (!leftmargin.empty())
1007 os << "\\leftmargin "
1008 << VSpace(leftmargin).asLyXCommand() << '\n';
1009 if (!topmargin.empty())
1010 os << "\\topmargin "
1011 << VSpace(topmargin).asLyXCommand() << '\n';
1012 if (!rightmargin.empty())
1013 os << "\\rightmargin "
1014 << VSpace(rightmargin).asLyXCommand() << '\n';
1015 if (!bottommargin.empty())
1016 os << "\\bottommargin "
1017 << VSpace(bottommargin).asLyXCommand() << '\n';
1018 if (!headheight.empty())
1019 os << "\\headheight "
1020 << VSpace(headheight).asLyXCommand() << '\n';
1021 if (!headsep.empty())
1023 << VSpace(headsep).asLyXCommand() << '\n';
1024 if (!footskip.empty())
1026 << VSpace(footskip).asLyXCommand() << '\n';
1027 if (!columnsep.empty())
1028 os << "\\columnsep "
1029 << VSpace(columnsep).asLyXCommand() << '\n';
1030 os << "\\secnumdepth " << secnumdepth
1031 << "\n\\tocdepth " << tocdepth
1032 << "\n\\paragraph_separation "
1033 << string_paragraph_separation[paragraph_separation];
1034 if (!paragraph_separation)
1035 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1037 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1038 os << "\n\\quotes_language "
1039 << string_quotes_language[quotes_language]
1040 << "\n\\papercolumns " << columns
1041 << "\n\\papersides " << sides
1042 << "\n\\paperpagestyle " << pagestyle << '\n';
1043 if (!listings_params.empty())
1044 os << "\\listings_params \"" <<
1045 InsetListingsParams(listings_params).encodedString() << "\"\n";
1046 for (int i = 0; i < 4; ++i) {
1047 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1048 if (user_defined_bullet(i).getFont() != -1) {
1049 os << "\\bullet " << i << " "
1050 << user_defined_bullet(i).getFont() << " "
1051 << user_defined_bullet(i).getCharacter() << " "
1052 << user_defined_bullet(i).getSize() << "\n";
1056 os << "\\bulletLaTeX " << i << " \""
1057 << lyx::to_ascii(user_defined_bullet(i).getText())
1063 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1064 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1065 << "\\html_math_output " << html_math_output << '\n'
1066 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1068 if (html_math_img_scale != 1.0)
1069 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1070 if (!html_latex_start.empty())
1071 os << "\\html_latex_start " << html_latex_start << '\n';
1072 if (!html_latex_end.empty())
1073 os << "\\html_latex_end " << html_latex_end << '\n';
1075 os << pimpl_->authorlist;
1079 void BufferParams::validate(LaTeXFeatures & features) const
1081 features.require(documentClass().requires());
1083 if (outputChanges) {
1084 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1085 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1086 LaTeXFeatures::isAvailable("xcolor");
1088 switch (features.runparams().flavor) {
1089 case OutputParams::LATEX:
1091 features.require("ct-dvipost");
1092 features.require("dvipost");
1093 } else if (xcolorulem) {
1094 features.require("ct-xcolor-ulem");
1095 features.require("ulem");
1096 features.require("xcolor");
1098 features.require("ct-none");
1101 case OutputParams::PDFLATEX:
1102 case OutputParams::XETEX:
1104 features.require("ct-xcolor-ulem");
1105 features.require("ulem");
1106 features.require("xcolor");
1107 // improves color handling in PDF output
1108 features.require("pdfcolmk");
1110 features.require("ct-none");
1118 // Floats with 'Here definitely' as default setting.
1119 if (float_placement.find('H') != string::npos)
1120 features.require("float");
1122 // AMS Style is at document level
1123 if (use_amsmath == package_on
1124 || documentClass().provides("amsmath"))
1125 features.require("amsmath");
1126 if (use_esint == package_on)
1127 features.require("esint");
1128 if (use_mhchem == package_on)
1129 features.require("mhchem");
1131 // Document-level line spacing
1132 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1133 features.require("setspace");
1135 // the bullet shapes are buffer level not paragraph level
1136 // so they are tested here
1137 for (int i = 0; i < 4; ++i) {
1138 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1140 int const font = user_defined_bullet(i).getFont();
1142 int const c = user_defined_bullet(i).getCharacter();
1148 features.require("latexsym");
1150 } else if (font == 1) {
1151 features.require("amssymb");
1152 } else if (font >= 2 && font <= 5) {
1153 features.require("pifont");
1157 if (pdfoptions().use_hyperref) {
1158 features.require("hyperref");
1159 // due to interferences with babel and hyperref, the color package has to
1160 // be loaded after hyperref when hyperref is used with the colorlinks
1161 // option, see http://www.lyx.org/trac/ticket/5291
1162 if (pdfoptions().colorlinks)
1163 features.require("color");
1167 features.require("xetex");
1169 if (language->lang() == "vietnamese")
1170 features.require("vietnamese");
1171 else if (language->lang() == "japanese")
1172 features.require("japanese");
1176 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1177 TexRow & texrow, FileName const & filepath) const
1179 os << "\\documentclass";
1181 DocumentClass const & tclass = documentClass();
1183 ostringstream clsoptions; // the document class options.
1185 if (tokenPos(tclass.opt_fontsize(),
1186 '|', fontsize) >= 0) {
1187 // only write if existing in list (and not default)
1188 clsoptions << fontsize << "pt,";
1191 // all paper sizes except of A4, A5, B5 and the US sizes need the
1193 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1194 && papersize != PAPER_USLETTER
1195 && papersize != PAPER_USLEGAL
1196 && papersize != PAPER_USEXECUTIVE
1197 && papersize != PAPER_A4
1198 && papersize != PAPER_A5
1199 && papersize != PAPER_B5;
1201 if (!use_geometry) {
1202 switch (papersize) {
1204 clsoptions << "a4paper,";
1206 case PAPER_USLETTER:
1207 clsoptions << "letterpaper,";
1210 clsoptions << "a5paper,";
1213 clsoptions << "b5paper,";
1215 case PAPER_USEXECUTIVE:
1216 clsoptions << "executivepaper,";
1219 clsoptions << "legalpaper,";
1246 if (sides != tclass.sides()) {
1249 clsoptions << "oneside,";
1252 clsoptions << "twoside,";
1258 if (columns != tclass.columns()) {
1260 clsoptions << "twocolumn,";
1262 clsoptions << "onecolumn,";
1266 && orientation == ORIENTATION_LANDSCAPE)
1267 clsoptions << "landscape,";
1269 // language should be a parameter to \documentclass
1270 if (language->babel() == "hebrew"
1271 && default_language->babel() != "hebrew")
1272 // This seems necessary
1273 features.useLanguage(default_language);
1275 ostringstream language_options;
1276 bool const use_babel = features.useBabel();
1278 language_options << features.getLanguages();
1279 if (!language->babel().empty()) {
1280 if (!language_options.str().empty())
1281 language_options << ',';
1282 language_options << language->babel();
1284 // if Vietnamese is used, babel must directly be loaded
1285 // with language options, not in the class options, see
1286 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1287 size_t viet = language_options.str().find("vietnam");
1288 // viet = string::npos when not found
1289 // the same is for all other languages that are not directly supported by
1290 // babel, but where LaTeX-packages add babel support.
1291 // this is currently the case for Latvian, Lithuanian, Mongolian
1293 size_t latvian = language_options.str().find("latvian");
1294 size_t lithu = language_options.str().find("lithuanian");
1295 size_t mongo = language_options.str().find("mongolian");
1296 size_t turkmen = language_options.str().find("turkmen");
1297 // if Japanese is used, babel must directly be loaded
1298 // with language options, not in the class options, see
1299 // http://www.lyx.org/trac/ticket/4597#c4
1300 size_t japan = language_options.str().find("japanese");
1301 if (lyxrc.language_global_options && !language_options.str().empty()
1302 && viet == string::npos && japan == string::npos
1303 && latvian == string::npos && lithu == string::npos
1304 && mongo == string::npos && turkmen == string::npos)
1305 clsoptions << language_options.str() << ',';
1308 // the predefined options from the layout
1309 if (use_default_options && !tclass.options().empty())
1310 clsoptions << tclass.options() << ',';
1312 // the user-defined options
1313 if (!options.empty()) {
1314 clsoptions << options << ',';
1317 string strOptions(clsoptions.str());
1318 if (!strOptions.empty()) {
1319 strOptions = rtrim(strOptions, ",");
1321 os << '[' << from_utf8(strOptions) << ']';
1324 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1326 // end of \documentclass defs
1329 os << "\\usepackage{fontspec}\n";
1333 // font selection must be done before loading fontenc.sty
1334 string const fonts =
1335 loadFonts(fontsRoman, fontsSans,
1336 fontsTypewriter, fontsSC, fontsOSF,
1337 fontsSansScale, fontsTypewriterScale, useXetex);
1338 if (!fonts.empty()) {
1339 os << from_ascii(fonts);
1342 if (fontsDefaultFamily != "default")
1343 os << "\\renewcommand{\\familydefault}{\\"
1344 << from_ascii(fontsDefaultFamily) << "}\n";
1346 // set font encoding
1347 // for arabic_arabi and farsi we also need to load the LAE and
1349 // XeTeX works without fontenc
1350 if (font_encoding() != "default" && language->lang() != "japanese"
1351 && !useXetex && !tclass.provides("fontenc")) {
1352 size_t fars = language_options.str().find("farsi");
1353 size_t arab = language_options.str().find("arabic");
1354 if (language->lang() == "arabic_arabi"
1355 || language->lang() == "farsi" || fars != string::npos
1356 || arab != string::npos) {
1357 os << "\\usepackage[" << from_ascii(font_encoding())
1358 << ",LFE,LAE]{fontenc}\n";
1361 os << "\\usepackage[" << from_ascii(font_encoding())
1367 // handle inputenc etc.
1368 writeEncodingPreamble(os, features, texrow);
1371 if (!features.runparams().includeall && !includedChildren_.empty()) {
1372 os << "\\includeonly{";
1373 list<string>::const_iterator it = includedChildren_.begin();
1375 for (; it != includedChildren_.end() ; ++it) {
1376 string incfile = *it;
1377 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1378 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1380 if (!features.runparams().nice)
1382 // \includeonly doesn't want an extension
1383 incfile = changeExtension(incfile, string());
1384 incfile = support::latex_path(incfile);
1385 if (!incfile.empty()) {
1388 os << from_utf8(incfile);
1395 if (!listings_params.empty() || features.isRequired("listings")) {
1396 os << "\\usepackage{listings}\n";
1399 if (!listings_params.empty()) {
1401 // do not test validity because listings_params is
1402 // supposed to be valid
1404 InsetListingsParams(listings_params).separatedParams(true);
1405 // we can't support all packages, but we should load the color package
1406 if (par.find("\\color", 0) != string::npos)
1407 features.require("color");
1408 os << from_utf8(par);
1409 // count the number of newlines
1410 for (size_t i = 0; i < par.size(); ++i)
1416 if (!tclass.provides("geometry")
1417 && (use_geometry || nonstandard_papersize)) {
1418 odocstringstream ods;
1419 if (!getGraphicsDriver("geometry").empty())
1420 ods << getGraphicsDriver("geometry");
1421 if (orientation == ORIENTATION_LANDSCAPE)
1422 ods << ",landscape";
1423 switch (papersize) {
1425 if (!paperwidth.empty())
1426 ods << ",paperwidth="
1427 << from_ascii(paperwidth);
1428 if (!paperheight.empty())
1429 ods << ",paperheight="
1430 << from_ascii(paperheight);
1432 case PAPER_USLETTER:
1433 ods << ",letterpaper";
1436 ods << ",legalpaper";
1438 case PAPER_USEXECUTIVE:
1439 ods << ",executivepaper";
1505 // default papersize ie PAPER_DEFAULT
1506 switch (lyxrc.default_papersize) {
1507 case PAPER_DEFAULT: // keep compiler happy
1508 case PAPER_USLETTER:
1509 ods << ",letterpaper";
1512 ods << ",legalpaper";
1514 case PAPER_USEXECUTIVE:
1515 ods << ",executivepaper";
1550 docstring const g_options = trim(ods.str(), ",");
1551 os << "\\usepackage";
1552 if (!g_options.empty())
1553 os << '[' << g_options << ']';
1554 os << "{geometry}\n";
1556 // output this only if use_geometry is true
1558 os << "\\geometry{verbose";
1559 if (!topmargin.empty())
1560 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1561 if (!bottommargin.empty())
1562 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1563 if (!leftmargin.empty())
1564 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1565 if (!rightmargin.empty())
1566 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1567 if (!headheight.empty())
1568 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1569 if (!headsep.empty())
1570 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1571 if (!footskip.empty())
1572 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1573 if (!columnsep.empty())
1574 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1578 } else if (orientation == ORIENTATION_LANDSCAPE
1579 || papersize != PAPER_DEFAULT) {
1580 features.require("papersize");
1583 if (tokenPos(tclass.opt_pagestyle(),
1584 '|', pagestyle) >= 0) {
1585 if (pagestyle == "fancy") {
1586 os << "\\usepackage{fancyhdr}\n";
1589 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1593 // only output when the background color is not default
1594 if (isbackgroundcolor == true) {
1595 // only require color here, the background color will be defined
1596 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1598 features.require("color");
1599 features.require("pagecolor");
1602 // only output when the font color is not default
1603 if (isfontcolor == true) {
1604 // only require color here, the font color will be defined
1605 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1607 features.require("color");
1608 features.require("fontcolor");
1611 // Only if class has a ToC hierarchy
1612 if (tclass.hasTocLevels()) {
1613 if (secnumdepth != tclass.secnumdepth()) {
1614 os << "\\setcounter{secnumdepth}{"
1619 if (tocdepth != tclass.tocdepth()) {
1620 os << "\\setcounter{tocdepth}{"
1627 if (paragraph_separation) {
1628 // when skip separation
1629 switch (getDefSkip().kind()) {
1630 case VSpace::SMALLSKIP:
1631 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1633 case VSpace::MEDSKIP:
1634 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1636 case VSpace::BIGSKIP:
1637 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1639 case VSpace::LENGTH:
1640 os << "\\setlength{\\parskip}{"
1641 << from_utf8(getDefSkip().length().asLatexString())
1644 default: // should never happen // Then delete it.
1645 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1649 os << "\\setlength{\\parindent}{0pt}\n";
1652 // when separation by indentation
1653 // only output something when a width is given
1654 if (getIndentation().asLyXCommand() != "default") {
1655 os << "\\setlength{\\parindent}{"
1656 << from_utf8(getIndentation().asLatexCommand())
1662 // Now insert the LyX specific LaTeX commands...
1663 docstring lyxpreamble;
1666 if (!output_sync_macro.empty())
1667 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1668 else if (features.runparams().flavor == OutputParams::LATEX)
1669 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1670 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1671 lyxpreamble += "\\synctex=-1\n";
1674 // due to interferences with babel and hyperref, the color package has to
1675 // be loaded (when it is not already loaded) before babel when hyperref
1676 // is used with the colorlinks option, see
1677 // http://www.lyx.org/trac/ticket/5291
1678 // we decided therefore to load color always before babel, see
1679 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1680 lyxpreamble += from_ascii(features.getColorOptions());
1682 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1684 && (features.isRequired("jurabib")
1685 || features.isRequired("hyperref")
1686 || features.isRequired("vietnamese")
1687 || features.isRequired("japanese") ) ) {
1689 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1690 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1693 // The optional packages;
1694 lyxpreamble += from_ascii(features.getPackages());
1696 // Additional Indices
1697 if (features.isRequired("splitidx")) {
1698 IndicesList::const_iterator iit = indiceslist().begin();
1699 IndicesList::const_iterator iend = indiceslist().end();
1700 for (; iit != iend; ++iit) {
1701 lyxpreamble += "\\newindex[";
1702 lyxpreamble += iit->index();
1703 lyxpreamble += "]{";
1704 lyxpreamble += iit->shortcut();
1705 lyxpreamble += "}\n";
1710 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1713 // * Hyperref manual: "Make sure it comes last of your loaded
1714 // packages, to give it a fighting chance of not being over-written,
1715 // since its job is to redefine many LaTeX commands."
1716 // * Email from Heiko Oberdiek: "It is usually better to load babel
1717 // before hyperref. Then hyperref has a chance to detect babel.
1718 // * Has to be loaded before the "LyX specific LaTeX commands" to
1719 // avoid errors with algorithm floats.
1720 // use hyperref explicitly if it is required
1721 if (features.isRequired("hyperref")) {
1722 // pass what we have to stream here, since we need
1723 // to access the stream itself in PDFOptions.
1727 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1729 OutputParams tmp_params = features.runparams();
1730 lines += pdfoptions().writeLaTeX(tmp_params, os,
1731 documentClass().provides("hyperref"));
1732 texrow.newlines(lines);
1733 // set back for the rest
1734 lyxpreamble.clear();
1737 // Will be surrounded by \makeatletter and \makeatother when not empty
1738 docstring atlyxpreamble;
1740 // Some macros LyX will need
1741 docstring tmppreamble(features.getMacros());
1743 if (!tmppreamble.empty())
1744 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1745 "LyX specific LaTeX commands.\n"
1746 + tmppreamble + '\n';
1748 // the text class specific preamble
1749 tmppreamble = features.getTClassPreamble();
1750 if (!tmppreamble.empty())
1751 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1752 "Textclass specific LaTeX commands.\n"
1753 + tmppreamble + '\n';
1755 // suppress date if selected
1756 // use \@ifundefined because we cannot be sure that every document class
1757 // has a \date command
1759 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1761 /* the user-defined preamble */
1762 if (!containsOnly(preamble, " \n\t"))
1764 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1765 "User specified LaTeX commands.\n"
1766 + from_utf8(preamble) + '\n';
1768 // subfig loads internally the LaTeX package "caption". As
1769 // caption is a very popular package, users will load it in
1770 // the preamble. Therefore we must load subfig behind the
1771 // user-defined preamble and check if the caption package was
1772 // loaded or not. For the case that caption is loaded before
1773 // subfig, there is the subfig option "caption=false". This
1774 // option also works when a koma-script class is used and
1775 // koma's own caption commands are used instead of caption. We
1776 // use \PassOptionsToPackage here because the user could have
1777 // already loaded subfig in the preamble.
1778 if (features.isRequired("subfig")) {
1779 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1780 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1781 "\\usepackage{subfig}\n";
1784 // Itemize bullet settings need to be last in case the user
1785 // defines their own bullets that use a package included
1786 // in the user-defined preamble -- ARRae
1787 // Actually it has to be done much later than that
1788 // since some packages like frenchb make modifications
1789 // at \begin{document} time -- JMarc
1790 docstring bullets_def;
1791 for (int i = 0; i < 4; ++i) {
1792 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1793 if (bullets_def.empty())
1794 bullets_def += "\\AtBeginDocument{\n";
1795 bullets_def += " \\def\\labelitemi";
1797 // `i' is one less than the item to modify
1804 bullets_def += "ii";
1810 bullets_def += '{' +
1811 user_defined_bullet(i).getText()
1816 if (!bullets_def.empty())
1817 atlyxpreamble += bullets_def + "}\n\n";
1819 if (!atlyxpreamble.empty())
1820 lyxpreamble += "\n\\makeatletter\n"
1821 + atlyxpreamble + "\\makeatother\n\n";
1823 // We try to load babel late, in case it interferes with other packages.
1824 // Jurabib and Hyperref have to be called after babel, though.
1825 if (use_babel && !features.isRequired("jurabib")
1826 && !features.isRequired("hyperref")
1827 && !features.isRequired("vietnamese")
1828 && !features.isRequired("japanese")) {
1830 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1831 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1834 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1835 if (!i18npreamble.empty())
1836 lyxpreamble += i18npreamble + '\n';
1839 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1840 texrow.newlines(nlines);
1844 // these packages (xunicode, for that matter) need to be loaded at least
1845 // after amsmath, amssymb, esint and the other packages that provide
1848 os << "\\usepackage{xunicode}\n";
1850 os << "\\usepackage{xltxtra}\n";
1857 void BufferParams::useClassDefaults()
1859 DocumentClass const & tclass = documentClass();
1861 sides = tclass.sides();
1862 columns = tclass.columns();
1863 pagestyle = tclass.pagestyle();
1864 use_default_options = true;
1865 // Only if class has a ToC hierarchy
1866 if (tclass.hasTocLevels()) {
1867 secnumdepth = tclass.secnumdepth();
1868 tocdepth = tclass.tocdepth();
1873 bool BufferParams::hasClassDefaults() const
1875 DocumentClass const & tclass = documentClass();
1877 return sides == tclass.sides()
1878 && columns == tclass.columns()
1879 && pagestyle == tclass.pagestyle()
1880 && use_default_options
1881 && secnumdepth == tclass.secnumdepth()
1882 && tocdepth == tclass.tocdepth();
1886 DocumentClass const & BufferParams::documentClass() const
1892 DocumentClass const * BufferParams::documentClassPtr() const {
1897 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1898 // evil, but this function is evil
1899 doc_class_ = const_cast<DocumentClass *>(tc);
1903 bool BufferParams::setBaseClass(string const & classname)
1905 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1906 LayoutFileList & bcl = LayoutFileList::get();
1907 if (!bcl.haveClass(classname)) {
1909 bformat(_("The layout file:\n"
1911 "could not be found. A default textclass with default\n"
1912 "layouts will be used. LyX will not be able to produce\n"
1914 from_utf8(classname));
1915 frontend::Alert::error(_("Document class not found"), s);
1916 bcl.addEmptyClass(classname);
1919 bool const success = bcl[classname].load();
1922 bformat(_("Due to some error in it, the layout file:\n"
1924 "could not be loaded. A default textclass with default\n"
1925 "layouts will be used. LyX will not be able to produce\n"
1927 from_utf8(classname));
1928 frontend::Alert::error(_("Could not load class"), s);
1929 bcl.addEmptyClass(classname);
1932 pimpl_->baseClass_ = classname;
1933 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1938 LayoutFile const * BufferParams::baseClass() const
1940 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1941 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1947 LayoutFileIndex const & BufferParams::baseClassID() const
1949 return pimpl_->baseClass_;
1953 void BufferParams::makeDocumentClass()
1958 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1960 if (!local_layout.empty()) {
1961 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1962 docstring const msg = _("Error reading internal layout information");
1963 frontend::Alert::warning(_("Read Error"), msg);
1969 bool BufferParams::moduleCanBeAdded(string const & modName) const
1971 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1975 bool BufferParams::addLayoutModule(string const & modName)
1977 LayoutModuleList::const_iterator it = layoutModules_.begin();
1978 LayoutModuleList::const_iterator end = layoutModules_.end();
1979 for (; it != end; it++)
1982 layoutModules_.push_back(modName);
1987 Font const BufferParams::getFont() const
1989 FontInfo f = documentClass().defaultfont();
1990 if (fontsDefaultFamily == "rmdefault")
1991 f.setFamily(ROMAN_FAMILY);
1992 else if (fontsDefaultFamily == "sfdefault")
1993 f.setFamily(SANS_FAMILY);
1994 else if (fontsDefaultFamily == "ttdefault")
1995 f.setFamily(TYPEWRITER_FAMILY);
1996 return Font(f, language);
2000 void BufferParams::readPreamble(Lexer & lex)
2002 if (lex.getString() != "\\begin_preamble")
2003 lyxerr << "Error (BufferParams::readPreamble):"
2004 "consistency check failed." << endl;
2006 preamble = lex.getLongString("\\end_preamble");
2010 void BufferParams::readLocalLayout(Lexer & lex)
2012 if (lex.getString() != "\\begin_local_layout")
2013 lyxerr << "Error (BufferParams::readLocalLayout):"
2014 "consistency check failed." << endl;
2016 local_layout = lex.getLongString("\\end_local_layout");
2020 void BufferParams::readLanguage(Lexer & lex)
2022 if (!lex.next()) return;
2024 string const tmptok = lex.getString();
2026 // check if tmptok is part of tex_babel in tex-defs.h
2027 language = languages.getLanguage(tmptok);
2029 // Language tmptok was not found
2030 language = default_language;
2031 lyxerr << "Warning: Setting language `"
2032 << tmptok << "' to `" << language->lang()
2038 void BufferParams::readGraphicsDriver(Lexer & lex)
2043 string const tmptok = lex.getString();
2044 // check if tmptok is part of tex_graphics in tex_defs.h
2047 string const test = tex_graphics[n++];
2049 if (test == tmptok) {
2050 graphicsDriver = tmptok;
2055 "Warning: graphics driver `$$Token' not recognized!\n"
2056 " Setting graphics driver to `default'.\n");
2057 graphicsDriver = "default";
2064 void BufferParams::readBullets(Lexer & lex)
2069 int const index = lex.getInteger();
2071 int temp_int = lex.getInteger();
2072 user_defined_bullet(index).setFont(temp_int);
2073 temp_bullet(index).setFont(temp_int);
2075 user_defined_bullet(index).setCharacter(temp_int);
2076 temp_bullet(index).setCharacter(temp_int);
2078 user_defined_bullet(index).setSize(temp_int);
2079 temp_bullet(index).setSize(temp_int);
2083 void BufferParams::readBulletsLaTeX(Lexer & lex)
2085 // The bullet class should be able to read this.
2088 int const index = lex.getInteger();
2090 docstring const temp_str = lex.getDocString();
2092 user_defined_bullet(index).setText(temp_str);
2093 temp_bullet(index).setText(temp_str);
2097 void BufferParams::readModules(Lexer & lex)
2099 if (!lex.eatLine()) {
2100 lyxerr << "Error (BufferParams::readModules):"
2101 "Unexpected end of input." << endl;
2105 string mod = lex.getString();
2106 if (mod == "\\end_modules")
2108 addLayoutModule(mod);
2114 void BufferParams::readRemovedModules(Lexer & lex)
2116 if (!lex.eatLine()) {
2117 lyxerr << "Error (BufferParams::readRemovedModules):"
2118 "Unexpected end of input." << endl;
2122 string mod = lex.getString();
2123 if (mod == "\\end_removed_modules")
2125 removedModules_.push_back(mod);
2128 // now we want to remove any removed modules that were previously
2129 // added. normally, that will be because default modules were added in
2130 // setBaseClass(), which gets called when \textclass is read at the
2131 // start of the read.
2132 list<string>::const_iterator rit = removedModules_.begin();
2133 list<string>::const_iterator const ren = removedModules_.end();
2134 for (; rit != ren; rit++) {
2135 LayoutModuleList::iterator const mit = layoutModules_.begin();
2136 LayoutModuleList::iterator const men = layoutModules_.end();
2137 LayoutModuleList::iterator found = find(mit, men, *rit);
2140 layoutModules_.erase(found);
2145 void BufferParams::readIncludeonly(Lexer & lex)
2147 if (!lex.eatLine()) {
2148 lyxerr << "Error (BufferParams::readIncludeonly):"
2149 "Unexpected end of input." << endl;
2153 string child = lex.getString();
2154 if (child == "\\end_includeonly")
2156 includedChildren_.push_back(child);
2162 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2164 char real_papersize = papersize;
2165 if (real_papersize == PAPER_DEFAULT)
2166 real_papersize = lyxrc.default_papersize;
2168 switch (real_papersize) {
2170 // could be anything, so don't guess
2172 case PAPER_CUSTOM: {
2173 if (purpose == XDVI && !paperwidth.empty() &&
2174 !paperheight.empty()) {
2175 // heightxwidth<unit>
2176 string first = paperwidth;
2177 string second = paperheight;
2178 if (orientation == ORIENTATION_LANDSCAPE)
2181 return first.erase(first.length() - 2)
2187 // dvips and dvipdfm do not know this
2188 if (purpose == DVIPS || purpose == DVIPDFM)
2192 if (purpose == DVIPS || purpose == DVIPDFM)
2196 if (purpose == DVIPS || purpose == DVIPDFM)
2206 if (purpose == DVIPS || purpose == DVIPDFM)
2210 if (purpose == DVIPS || purpose == DVIPDFM)
2214 if (purpose == DVIPS || purpose == DVIPDFM)
2218 if (purpose == DVIPS || purpose == DVIPDFM)
2222 if (purpose == DVIPS || purpose == DVIPDFM)
2226 // dvipdfm does not know this
2227 if (purpose == DVIPDFM)
2231 if (purpose == DVIPDFM)
2235 if (purpose == DVIPS || purpose == DVIPDFM)
2239 if (purpose == DVIPS || purpose == DVIPDFM)
2243 if (purpose == DVIPS || purpose == DVIPDFM)
2247 if (purpose == DVIPS || purpose == DVIPDFM)
2251 if (purpose == DVIPS || purpose == DVIPDFM)
2255 if (purpose == DVIPS || purpose == DVIPDFM)
2259 if (purpose == DVIPS || purpose == DVIPDFM)
2263 if (purpose == DVIPS || purpose == DVIPDFM)
2266 case PAPER_USEXECUTIVE:
2267 // dvipdfm does not know this
2268 if (purpose == DVIPDFM)
2273 case PAPER_USLETTER:
2275 if (purpose == XDVI)
2282 string const BufferParams::dvips_options() const
2287 && papersize == PAPER_CUSTOM
2288 && !lyxrc.print_paper_dimension_flag.empty()
2289 && !paperwidth.empty()
2290 && !paperheight.empty()) {
2291 // using a custom papersize
2292 result = lyxrc.print_paper_dimension_flag;
2293 result += ' ' + paperwidth;
2294 result += ',' + paperheight;
2296 string const paper_option = paperSizeName(DVIPS);
2297 if (!paper_option.empty() && (paper_option != "letter" ||
2298 orientation != ORIENTATION_LANDSCAPE)) {
2299 // dvips won't accept -t letter -t landscape.
2300 // In all other cases, include the paper size
2302 result = lyxrc.print_paper_flag;
2303 result += ' ' + paper_option;
2306 if (orientation == ORIENTATION_LANDSCAPE &&
2307 papersize != PAPER_CUSTOM)
2308 result += ' ' + lyxrc.print_landscape_flag;
2313 string const BufferParams::font_encoding() const
2315 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2319 string BufferParams::babelCall(string const & lang_opts) const
2321 string lang_pack = lyxrc.language_package;
2322 if (lang_pack != "\\usepackage{babel}")
2324 // suppress the babel call when there is no babel language defined
2325 // for the document language in the lib/languages file and if no
2326 // other languages are used (lang_opts is then empty)
2327 if (lang_opts.empty())
2329 // If Vietnamese is used, babel must directly be loaded with the
2330 // language options, see
2331 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2332 size_t viet = lang_opts.find("vietnam");
2333 // viet = string::npos when not found
2334 // the same is for all other languages that are not directly supported by
2335 // babel, but where LaTeX-packages add babel support.
2336 // this is currently the case for Latvian, Lithuanian, Mongolian
2338 size_t latvian = lang_opts.find("latvian");
2339 size_t lithu = lang_opts.find("lithuanian");
2340 size_t mongo = lang_opts.find("mongolian");
2341 size_t turkmen = lang_opts.find("turkmen");
2342 // If Japanese is used, babel must directly be loaded with the
2343 // language options, see
2344 // http://www.lyx.org/trac/ticket/4597#c4
2345 size_t japan = lang_opts.find("japanese");
2346 if (!lyxrc.language_global_options || viet != string::npos
2347 || japan != string::npos || latvian != string::npos
2348 || lithu != string::npos || mongo != string::npos
2349 || turkmen != string::npos)
2350 return "\\usepackage[" + lang_opts + "]{babel}";
2355 docstring BufferParams::getGraphicsDriver(string const & package) const
2359 if (package == "geometry") {
2360 if (graphicsDriver == "dvips"
2361 || graphicsDriver == "dvipdfm"
2362 || graphicsDriver == "pdftex"
2363 || graphicsDriver == "vtex")
2364 result = from_ascii(graphicsDriver);
2365 else if (graphicsDriver == "dvipdfmx")
2366 result = from_ascii("dvipdfm");
2373 void BufferParams::writeEncodingPreamble(odocstream & os,
2374 LaTeXFeatures & features, TexRow & texrow) const
2378 if (inputenc == "auto") {
2379 string const doc_encoding =
2380 language->encoding()->latexName();
2381 Encoding::Package const package =
2382 language->encoding()->package();
2384 // Create a list with all the input encodings used
2386 set<string> encodings =
2387 features.getEncodingSet(doc_encoding);
2389 // If the "japanese" package (i.e. pLaTeX) is used,
2390 // inputenc must be omitted.
2391 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2392 if (package == Encoding::japanese)
2393 features.require("japanese");
2395 if ((!encodings.empty() || package == Encoding::inputenc)
2396 && !features.isRequired("japanese")) {
2397 os << "\\usepackage[";
2398 set<string>::const_iterator it = encodings.begin();
2399 set<string>::const_iterator const end = encodings.end();
2401 os << from_ascii(*it);
2404 for (; it != end; ++it)
2405 os << ',' << from_ascii(*it);
2406 if (package == Encoding::inputenc) {
2407 if (!encodings.empty())
2409 os << from_ascii(doc_encoding);
2411 os << "]{inputenc}\n";
2414 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2415 if (language->encoding()->name() == "utf8-cjk"
2416 && LaTeXFeatures::isAvailable("CJKutf8"))
2417 os << "\\usepackage{CJKutf8}\n";
2419 os << "\\usepackage{CJK}\n";
2422 } else if (inputenc != "default") {
2423 switch (encoding().package()) {
2424 case Encoding::none:
2425 case Encoding::japanese:
2427 case Encoding::inputenc:
2428 // do not load inputenc if japanese is used
2429 if (features.isRequired("japanese"))
2431 os << "\\usepackage[" << from_ascii(inputenc)
2436 if (encoding().name() == "utf8-cjk"
2437 && LaTeXFeatures::isAvailable("CJKutf8"))
2438 os << "\\usepackage{CJKutf8}\n";
2440 os << "\\usepackage{CJK}\n";
2446 // The encoding "armscii8" (for Armenian) is only available when
2447 // the package "armtex" is loaded.
2448 if (language->encoding()->latexName() == "armscii8"
2449 || inputenc == "armscii8") {
2450 os << "\\usepackage{armtex}\n";
2456 string const BufferParams::parseFontName(string const & name) const
2458 string mangled = name;
2459 size_t const idx = mangled.find('[');
2460 if (idx == string::npos || idx == 0)
2463 return mangled.substr(0, idx - 1);
2467 string const BufferParams::loadFonts(string const & rm,
2468 string const & sf, string const & tt,
2469 bool const & sc, bool const & osf,
2470 int const & sfscale, int const & ttscale,
2471 bool const & xetex) const
2473 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2474 several packages have been replaced by others, that might not
2475 be installed on every system. We have to take care for that
2476 (see psnfss.pdf). We try to support all psnfss fonts as well
2477 as the fonts that have become de facto standard in the LaTeX
2478 world (e.g. Latin Modern). We do not support obsolete fonts
2479 (like PSLatex). In general, it should be possible to mix any
2480 rm font with any sf or tt font, respectively. (JSpitzm)
2482 -- separate math fonts.
2485 if (rm == "default" && sf == "default" && tt == "default")
2492 if (rm != "default")
2493 os << "\\setmainfont[Mapping=tex-text]{"
2494 << parseFontName(rm) << "}\n";
2495 if (sf != "default") {
2496 string const sans = parseFontName(sf);
2498 os << "\\setsansfont[Scale="
2499 << float(sfscale) / 100
2500 << ",Mapping=tex-text]{"
2503 os << "\\setsansfont[Mapping=tex-text]{"
2506 if (tt != "default") {
2507 string const mono = parseFontName(tt);
2509 os << "\\setmonofont[Scale="
2510 << float(sfscale) / 100
2514 os << "\\setmonofont[Mapping=tex-text]{"
2518 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2523 // Computer Modern (must be explicitly selectable -- there might be classes
2524 // that define a different default font!
2526 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2527 // osf for Computer Modern needs eco.sty
2529 os << "\\usepackage{eco}\n";
2531 // Latin Modern Roman
2532 else if (rm == "lmodern")
2533 os << "\\usepackage{lmodern}\n";
2535 else if (rm == "ae") {
2536 // not needed when using OT1 font encoding.
2537 if (font_encoding() != "default")
2538 os << "\\usepackage{ae,aecompl}\n";
2541 else if (rm == "times") {
2542 // try to load the best available package
2543 if (LaTeXFeatures::isAvailable("mathptmx"))
2544 os << "\\usepackage{mathptmx}\n";
2545 else if (LaTeXFeatures::isAvailable("mathptm"))
2546 os << "\\usepackage{mathptm}\n";
2548 os << "\\usepackage{times}\n";
2551 else if (rm == "palatino") {
2552 // try to load the best available package
2553 if (LaTeXFeatures::isAvailable("mathpazo")) {
2554 os << "\\usepackage";
2560 // "osf" includes "sc"!
2564 os << "{mathpazo}\n";
2566 else if (LaTeXFeatures::isAvailable("mathpple"))
2567 os << "\\usepackage{mathpple}\n";
2569 os << "\\usepackage{palatino}\n";
2572 else if (rm == "utopia") {
2573 // fourier supersedes utopia.sty, but does
2574 // not work with OT1 encoding.
2575 if (LaTeXFeatures::isAvailable("fourier")
2576 && font_encoding() != "default") {
2577 os << "\\usepackage";
2588 os << "{fourier}\n";
2591 os << "\\usepackage{utopia}\n";
2593 // Bera (complete fontset)
2594 else if (rm == "bera" && sf == "default" && tt == "default")
2595 os << "\\usepackage{bera}\n";
2597 else if (rm != "default")
2598 os << "\\usepackage" << "{" << rm << "}\n";
2601 // Helvetica, Bera Sans
2602 if (sf == "helvet" || sf == "berasans") {
2604 os << "\\usepackage[scaled=" << float(sfscale) / 100
2605 << "]{" << sf << "}\n";
2607 os << "\\usepackage{" << sf << "}\n";
2610 else if (sf == "avant")
2611 os << "\\usepackage{" << sf << "}\n";
2612 // Computer Modern, Latin Modern, CM Bright
2613 else if (sf != "default")
2614 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2616 // monospaced/typewriter
2617 // Courier, LuxiMono
2618 if (tt == "luximono" || tt == "beramono") {
2620 os << "\\usepackage[scaled=" << float(ttscale) / 100
2621 << "]{" << tt << "}\n";
2623 os << "\\usepackage{" << tt << "}\n";
2626 else if (tt == "courier" )
2627 os << "\\usepackage{" << tt << "}\n";
2628 // Computer Modern, Latin Modern, CM Bright
2629 else if (tt != "default")
2630 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2636 Encoding const & BufferParams::encoding() const
2639 return *(encodings.fromLaTeXName("utf8-plain"));
2640 if (inputenc == "auto" || inputenc == "default")
2641 return *language->encoding();
2642 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2645 LYXERR0("Unknown inputenc value `" << inputenc
2646 << "'. Using `auto' instead.");
2647 return *language->encoding();
2651 CiteEngine BufferParams::citeEngine() const
2653 // FIXME the class should provide the numerical/
2654 // authoryear choice
2655 if (documentClass().provides("natbib")
2656 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2657 return ENGINE_NATBIB_AUTHORYEAR;
2658 return cite_engine_;
2662 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2664 cite_engine_ = cite_engine;