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 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
79 static char const * const string_orientation[] = {
80 "portrait", "landscape", ""
84 static char const * const string_footnotekinds[] = {
85 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
89 static char const * const tex_graphics[] = {
90 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
91 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
92 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
93 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
104 // Paragraph separation
105 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
108 ParSepTranslator const init_parseptranslator()
110 ParSepTranslator translator
111 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
112 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
117 ParSepTranslator const & parseptranslator()
119 static ParSepTranslator translator = init_parseptranslator();
125 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
128 QuotesLangTranslator const init_quoteslangtranslator()
130 QuotesLangTranslator translator
131 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
132 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
133 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
134 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
135 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
136 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
141 QuotesLangTranslator const & quoteslangtranslator()
143 static QuotesLangTranslator translator = init_quoteslangtranslator();
149 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
152 static PaperSizeTranslator initPaperSizeTranslator()
154 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
155 translator.addPair(string_papersize[1], PAPER_CUSTOM);
156 translator.addPair(string_papersize[2], PAPER_USLETTER);
157 translator.addPair(string_papersize[3], PAPER_USLEGAL);
158 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
159 translator.addPair(string_papersize[5], PAPER_A3);
160 translator.addPair(string_papersize[6], PAPER_A4);
161 translator.addPair(string_papersize[7], PAPER_A5);
162 translator.addPair(string_papersize[8], PAPER_B3);
163 translator.addPair(string_papersize[9], PAPER_B4);
164 translator.addPair(string_papersize[10], PAPER_B5);
169 PaperSizeTranslator const & papersizetranslator()
171 static PaperSizeTranslator translator = initPaperSizeTranslator();
177 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
180 PaperOrientationTranslator const init_paperorientationtranslator()
182 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
183 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
188 PaperOrientationTranslator const & paperorientationtranslator()
190 static PaperOrientationTranslator translator = init_paperorientationtranslator();
196 typedef Translator<int, PageSides> SidesTranslator;
199 SidesTranslator const init_sidestranslator()
201 SidesTranslator translator(1, OneSide);
202 translator.addPair(2, TwoSides);
207 SidesTranslator const & sidestranslator()
209 static SidesTranslator translator = init_sidestranslator();
215 typedef Translator<int, BufferParams::Package> PackageTranslator;
218 PackageTranslator const init_packagetranslator()
220 PackageTranslator translator(0, BufferParams::package_off);
221 translator.addPair(1, BufferParams::package_auto);
222 translator.addPair(2, BufferParams::package_on);
227 PackageTranslator const & packagetranslator()
229 static PackageTranslator translator = init_packagetranslator();
235 typedef Translator<string, CiteEngine> CiteEngineTranslator;
238 CiteEngineTranslator const init_citeenginetranslator()
240 CiteEngineTranslator translator("basic", ENGINE_BASIC);
241 translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
242 translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
243 translator.addPair("jurabib", ENGINE_JURABIB);
248 CiteEngineTranslator const & citeenginetranslator()
250 static CiteEngineTranslator translator = init_citeenginetranslator();
256 typedef Translator<string, Spacing::Space> SpaceTranslator;
259 SpaceTranslator const init_spacetranslator()
261 SpaceTranslator translator("default", Spacing::Default);
262 translator.addPair("single", Spacing::Single);
263 translator.addPair("onehalf", Spacing::Onehalf);
264 translator.addPair("double", Spacing::Double);
265 translator.addPair("other", Spacing::Other);
270 SpaceTranslator const & spacetranslator()
272 static SpaceTranslator translator = init_spacetranslator();
279 class BufferParams::Impl
284 AuthorList authorlist;
285 BranchList branchlist;
286 Bullet temp_bullets[4];
287 Bullet user_defined_bullets[4];
288 IndicesList indiceslist;
290 /** This is the amount of space used for paragraph_separation "skip",
291 * and for detached paragraphs in "indented" documents.
295 PDFOptions pdfoptions;
296 LayoutFileIndex baseClass_;
300 BufferParams::Impl::Impl()
301 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
303 // set initial author
305 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
310 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
314 return new BufferParams::Impl(*ptr);
318 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
324 BufferParams::BufferParams()
327 setBaseClass(defaultBaseclass());
329 paragraph_separation = ParagraphIndentSeparation;
330 quotes_language = InsetQuotes::EnglishQuotes;
331 fontsize = "default";
334 papersize = PAPER_DEFAULT;
335 orientation = ORIENTATION_PORTRAIT;
336 use_geometry = false;
337 use_amsmath = package_auto;
338 use_esint = package_auto;
339 use_mhchem = package_auto;
340 cite_engine_ = ENGINE_BASIC;
341 use_bibtopic = false;
343 trackChanges = false;
344 outputChanges = false;
345 use_default_options = true;
346 maintain_unincluded_children = false;
349 language = default_language;
351 fontsRoman = "default";
352 fontsSans = "default";
353 fontsTypewriter = "default";
354 fontsDefaultFamily = "default";
358 fontsSansScale = 100;
359 fontsTypewriterScale = 100;
361 graphicsDriver = "default";
362 defaultOutputFormat = "default";
363 bibtex_command = "default";
364 index_command = "default";
367 listings_params = string();
368 pagestyle = "default";
369 suppress_date = false;
370 // white is equal to no background color
371 backgroundcolor = lyx::rgbFromHexName("#ffffff");
372 // no color is the default (black)
373 fontcolor = lyx::rgbFromHexName("#000000");
375 // light gray is the default font color for greyed-out notes
376 notefontcolor = lyx::rgbFromHexName("#cccccc");
377 compressed = lyxrc.save_compressed;
378 for (int iter = 0; iter < 4; ++iter) {
379 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
380 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
383 indiceslist().addDefault(B_("Index"));
384 html_be_strict = true;
385 html_math_output = MathML;
389 docstring BufferParams::B_(string const & l10n) const
391 LASSERT(language, /**/);
392 return getMessages(language->code()).get(l10n);
396 AuthorList & BufferParams::authors()
398 return pimpl_->authorlist;
402 AuthorList const & BufferParams::authors() const
404 return pimpl_->authorlist;
408 BranchList & BufferParams::branchlist()
410 return pimpl_->branchlist;
414 BranchList const & BufferParams::branchlist() const
416 return pimpl_->branchlist;
420 IndicesList & BufferParams::indiceslist()
422 return pimpl_->indiceslist;
426 IndicesList const & BufferParams::indiceslist() const
428 return pimpl_->indiceslist;
432 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
434 LASSERT(index < 4, /**/);
435 return pimpl_->temp_bullets[index];
439 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
441 LASSERT(index < 4, /**/);
442 return pimpl_->temp_bullets[index];
446 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
448 LASSERT(index < 4, /**/);
449 return pimpl_->user_defined_bullets[index];
453 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
455 LASSERT(index < 4, /**/);
456 return pimpl_->user_defined_bullets[index];
460 Spacing & BufferParams::spacing()
462 return pimpl_->spacing;
466 Spacing const & BufferParams::spacing() const
468 return pimpl_->spacing;
472 PDFOptions & BufferParams::pdfoptions()
474 return pimpl_->pdfoptions;
478 PDFOptions const & BufferParams::pdfoptions() const
480 return pimpl_->pdfoptions;
484 HSpace const & BufferParams::getIndentation() const
486 return pimpl_->indentation;
490 void BufferParams::setIndentation(HSpace const & indent)
492 pimpl_->indentation = indent;
496 VSpace const & BufferParams::getDefSkip() const
498 return pimpl_->defskip;
502 void BufferParams::setDefSkip(VSpace const & vs)
504 pimpl_->defskip = vs;
508 string BufferParams::readToken(Lexer & lex, string const & token,
509 FileName const & filepath)
511 if (token == "\\textclass") {
513 string const classname = lex.getString();
514 // if there exists a local layout file, ignore the system one
515 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
517 LayoutFileList & bcl = LayoutFileList::get();
518 if (tcp.empty() && !filepath.empty())
519 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
523 setBaseClass(classname);
524 // We assume that a tex class exists for local or unknown layouts so this warning
525 // will only be given for system layouts.
526 if (!baseClass()->isTeXClassAvailable()) {
528 translateIfPossible(from_utf8(baseClass()->description()));
529 docstring const msg =
530 bformat(_("The document class requested\n"
532 "requires external files that are not available.\n"
533 "The document class can still be used, but LyX\n"
534 "will not be able to produce output until the\n"
535 "following prerequisites are installed:\n"
537 "See section 3.1.2.2 of the User's Guide for\n"
538 "more information."),
539 desc, from_utf8(baseClass()->prerequisites()));
540 frontend::Alert::warning(_("Document class not available"),
543 } else if (token == "\\begin_preamble") {
545 } else if (token == "\\begin_local_layout") {
546 readLocalLayout(lex);
547 } else if (token == "\\begin_modules") {
549 } else if (token == "\\begin_removed_modules") {
550 readRemovedModules(lex);
551 } else if (token == "\\begin_includeonly") {
552 readIncludeonly(lex);
553 } else if (token == "\\maintain_unincluded_children") {
554 lex >> maintain_unincluded_children;
555 } else if (token == "\\options") {
557 options = lex.getString();
558 } else if (token == "\\use_default_options") {
559 lex >> use_default_options;
560 } else if (token == "\\master") {
562 master = lex.getString();
563 } else if (token == "\\suppress_date") {
564 lex >> suppress_date;
565 } else if (token == "\\language") {
567 } else if (token == "\\inputencoding") {
569 } else if (token == "\\graphics") {
570 readGraphicsDriver(lex);
571 } else if (token == "\\default_output_format") {
572 lex >> defaultOutputFormat;
573 } else if (token == "\\bibtex_command") {
575 bibtex_command = lex.getString();
576 } else if (token == "\\index_command") {
578 index_command = lex.getString();
579 } else if (token == "\\fontencoding") {
581 fontenc = lex.getString();
582 } else if (token == "\\font_roman") {
584 fontsRoman = lex.getString();
585 } else if (token == "\\font_sans") {
587 fontsSans = lex.getString();
588 } else if (token == "\\font_typewriter") {
590 fontsTypewriter = lex.getString();
591 } else if (token == "\\font_default_family") {
592 lex >> fontsDefaultFamily;
593 } else if (token == "\\use_xetex") {
595 } else if (token == "\\font_sc") {
597 } else if (token == "\\font_osf") {
599 } else if (token == "\\font_sf_scale") {
600 lex >> fontsSansScale;
601 } else if (token == "\\font_tt_scale") {
602 lex >> fontsTypewriterScale;
603 } else if (token == "\\font_cjk") {
605 } else if (token == "\\paragraph_separation") {
608 paragraph_separation = parseptranslator().find(parsep);
609 } else if (token == "\\paragraph_indentation") {
611 string indentation = lex.getString();
612 pimpl_->indentation = HSpace(indentation);
613 } else if (token == "\\defskip") {
615 string defskip = lex.getString();
616 if (defskip == "defskip")
619 pimpl_->defskip = VSpace(defskip);
620 } else if (token == "\\quotes_language") {
623 quotes_language = quoteslangtranslator().find(quotes_lang);
624 } else if (token == "\\papersize") {
627 papersize = papersizetranslator().find(ppsize);
628 } else if (token == "\\use_geometry") {
630 } else if (token == "\\use_amsmath") {
633 use_amsmath = packagetranslator().find(use_ams);
634 } else if (token == "\\use_esint") {
637 use_esint = packagetranslator().find(useesint);
638 } else if (token == "\\use_mhchem") {
641 use_mhchem = packagetranslator().find(usemhchem);
642 } else if (token == "\\cite_engine") {
645 cite_engine_ = citeenginetranslator().find(engine);
646 } else if (token == "\\use_bibtopic") {
648 } else if (token == "\\use_indices") {
650 } else if (token == "\\tracking_changes") {
652 } else if (token == "\\output_changes") {
653 lex >> outputChanges;
654 } else if (token == "\\branch") {
656 docstring branch = lex.getDocString();
657 branchlist().add(branch);
660 string const tok = lex.getString();
661 if (tok == "\\end_branch")
663 Branch * branch_ptr = branchlist().find(branch);
664 if (tok == "\\selected") {
667 branch_ptr->setSelected(lex.getInteger());
669 if (tok == "\\filename_suffix") {
672 branch_ptr->setFilenameSuffix(lex.getInteger());
674 if (tok == "\\color") {
676 string color = lex.getString();
678 branch_ptr->setColor(color);
679 // Update also the Color table:
681 color = lcolor.getX11Name(Color_background);
683 lcolor.setColor(to_utf8(branch), color);
686 } else if (token == "\\index") {
688 docstring index = lex.getDocString();
690 indiceslist().add(index);
693 string const tok = lex.getString();
694 if (tok == "\\end_index")
696 Index * index_ptr = indiceslist().find(index);
697 if (tok == "\\shortcut") {
699 shortcut = lex.getDocString();
701 index_ptr->setShortcut(shortcut);
703 if (tok == "\\color") {
705 string color = lex.getString();
707 index_ptr->setColor(color);
708 // Update also the Color table:
710 color = lcolor.getX11Name(Color_background);
712 if (!shortcut.empty())
713 lcolor.setColor(to_utf8(shortcut), color);
716 } else if (token == "\\author") {
718 istringstream ss(lex.getString());
721 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
722 } else if (token == "\\paperorientation") {
725 orientation = paperorientationtranslator().find(orient);
726 } else if (token == "\\backgroundcolor") {
728 backgroundcolor = lyx::rgbFromHexName(lex.getString());
729 } else if (token == "\\fontcolor") {
731 fontcolor = lyx::rgbFromHexName(lex.getString());
733 } else if (token == "\\notefontcolor") {
735 string color = lex.getString();
736 notefontcolor = lyx::rgbFromHexName(color);
737 // set the font color within LyX
738 lcolor.setColor(Color_greyedouttext, color);
739 } else if (token == "\\paperwidth") {
741 } else if (token == "\\paperheight") {
743 } else if (token == "\\leftmargin") {
745 } else if (token == "\\topmargin") {
747 } else if (token == "\\rightmargin") {
749 } else if (token == "\\bottommargin") {
751 } else if (token == "\\headheight") {
753 } else if (token == "\\headsep") {
755 } else if (token == "\\footskip") {
757 } else if (token == "\\columnsep") {
759 } else if (token == "\\paperfontsize") {
761 } else if (token == "\\papercolumns") {
763 } else if (token == "\\listings_params") {
766 listings_params = InsetListingsParams(par).params();
767 } else if (token == "\\papersides") {
770 sides = sidestranslator().find(psides);
771 } else if (token == "\\paperpagestyle") {
773 } else if (token == "\\bullet") {
775 } else if (token == "\\bulletLaTeX") {
776 readBulletsLaTeX(lex);
777 } else if (token == "\\secnumdepth") {
779 } else if (token == "\\tocdepth") {
781 } else if (token == "\\spacing") {
785 if (nspacing == "other") {
788 spacing().set(spacetranslator().find(nspacing), tmp_val);
789 } else if (token == "\\float_placement") {
790 lex >> float_placement;
792 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
793 string toktmp = pdfoptions().readToken(lex, token);
794 if (!toktmp.empty()) {
795 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
799 } else if (token == "\\html_math_output") {
802 html_math_output = static_cast<MathOutput>(temp);
803 } else if (token == "\\html_be_strict") {
804 lex >> html_be_strict;
806 lyxerr << "BufferParams::readToken(): Unknown token: " <<
815 void BufferParams::writeFile(ostream & os) const
817 // The top of the file is written by the buffer.
818 // Prints out the buffer info into the .lyx file given by file
821 os << "\\textclass " << baseClass()->name() << '\n';
824 if (!preamble.empty()) {
825 // remove '\n' from the end of preamble
826 string const tmppreamble = rtrim(preamble, "\n");
827 os << "\\begin_preamble\n"
829 << "\n\\end_preamble\n";
833 if (!options.empty()) {
834 os << "\\options " << options << '\n';
837 // use the class options defined in the layout?
838 os << "\\use_default_options "
839 << convert<string>(use_default_options) << "\n";
841 // the master document
842 if (!master.empty()) {
843 os << "\\master " << master << '\n';
847 if (!removedModules_.empty()) {
848 os << "\\begin_removed_modules" << '\n';
849 list<string>::const_iterator it = removedModules_.begin();
850 list<string>::const_iterator en = removedModules_.end();
851 for (; it != en; it++)
853 os << "\\end_removed_modules" << '\n';
857 if (!layoutModules_.empty()) {
858 os << "\\begin_modules" << '\n';
859 LayoutModuleList::const_iterator it = layoutModules_.begin();
860 LayoutModuleList::const_iterator en = layoutModules_.end();
861 for (; it != en; it++)
863 os << "\\end_modules" << '\n';
867 if (!includedChildren_.empty()) {
868 os << "\\begin_includeonly" << '\n';
869 list<string>::const_iterator it = includedChildren_.begin();
870 list<string>::const_iterator en = includedChildren_.end();
871 for (; it != en; it++)
873 os << "\\end_includeonly" << '\n';
875 os << "\\maintain_unincluded_children "
876 << convert<string>(maintain_unincluded_children) << '\n';
878 // local layout information
879 if (!local_layout.empty()) {
880 // remove '\n' from the end
881 string const tmplocal = rtrim(local_layout, "\n");
882 os << "\\begin_local_layout\n"
884 << "\n\\end_local_layout\n";
887 // then the text parameters
888 if (language != ignore_language)
889 os << "\\language " << language->lang() << '\n';
890 os << "\\inputencoding " << inputenc
891 << "\n\\fontencoding " << fontenc
892 << "\n\\font_roman " << fontsRoman
893 << "\n\\font_sans " << fontsSans
894 << "\n\\font_typewriter " << fontsTypewriter
895 << "\n\\font_default_family " << fontsDefaultFamily
896 << "\n\\use_xetex " << convert<string>(useXetex)
897 << "\n\\font_sc " << convert<string>(fontsSC)
898 << "\n\\font_osf " << convert<string>(fontsOSF)
899 << "\n\\font_sf_scale " << fontsSansScale
900 << "\n\\font_tt_scale " << fontsTypewriterScale
902 if (!fontsCJK.empty()) {
903 os << "\\font_cjk " << fontsCJK << '\n';
905 os << "\n\\graphics " << graphicsDriver << '\n';
906 os << "\\default_output_format " << defaultOutputFormat << '\n';
907 os << "\\bibtex_command " << bibtex_command << '\n';
908 os << "\\index_command " << index_command << '\n';
910 if (!float_placement.empty()) {
911 os << "\\float_placement " << float_placement << '\n';
913 os << "\\paperfontsize " << fontsize << '\n';
915 spacing().writeFile(os);
916 pdfoptions().writeFile(os);
918 os << "\\papersize " << string_papersize[papersize]
919 << "\n\\use_geometry " << convert<string>(use_geometry)
920 << "\n\\use_amsmath " << use_amsmath
921 << "\n\\use_esint " << use_esint
922 << "\n\\use_mhchem " << use_mhchem
923 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
924 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
925 << "\n\\use_indices " << convert<string>(use_indices)
926 << "\n\\paperorientation " << string_orientation[orientation]
927 << "\n\\suppress_date " << convert<string>(suppress_date)
929 if (backgroundcolor != lyx::rgbFromHexName("#ffffff"))
930 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
931 if (isfontcolor == true)
932 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
933 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
934 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
936 BranchList::const_iterator it = branchlist().begin();
937 BranchList::const_iterator end = branchlist().end();
938 for (; it != end; ++it) {
939 os << "\\branch " << to_utf8(it->branch())
940 << "\n\\selected " << it->isSelected()
941 << "\n\\filename_suffix " << it->hasFilenameSuffix()
942 << "\n\\color " << lyx::X11hexname(it->color())
947 IndicesList::const_iterator iit = indiceslist().begin();
948 IndicesList::const_iterator iend = indiceslist().end();
949 for (; iit != iend; ++iit) {
950 os << "\\index " << to_utf8(iit->index())
951 << "\n\\shortcut " << to_utf8(iit->shortcut())
952 << "\n\\color " << lyx::X11hexname(iit->color())
957 if (!paperwidth.empty())
958 os << "\\paperwidth "
959 << VSpace(paperwidth).asLyXCommand() << '\n';
960 if (!paperheight.empty())
961 os << "\\paperheight "
962 << VSpace(paperheight).asLyXCommand() << '\n';
963 if (!leftmargin.empty())
964 os << "\\leftmargin "
965 << VSpace(leftmargin).asLyXCommand() << '\n';
966 if (!topmargin.empty())
968 << VSpace(topmargin).asLyXCommand() << '\n';
969 if (!rightmargin.empty())
970 os << "\\rightmargin "
971 << VSpace(rightmargin).asLyXCommand() << '\n';
972 if (!bottommargin.empty())
973 os << "\\bottommargin "
974 << VSpace(bottommargin).asLyXCommand() << '\n';
975 if (!headheight.empty())
976 os << "\\headheight "
977 << VSpace(headheight).asLyXCommand() << '\n';
978 if (!headsep.empty())
980 << VSpace(headsep).asLyXCommand() << '\n';
981 if (!footskip.empty())
983 << VSpace(footskip).asLyXCommand() << '\n';
984 if (!columnsep.empty())
986 << VSpace(columnsep).asLyXCommand() << '\n';
987 os << "\\secnumdepth " << secnumdepth
988 << "\n\\tocdepth " << tocdepth
989 << "\n\\paragraph_separation "
990 << string_paragraph_separation[paragraph_separation];
991 if (!paragraph_separation)
992 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
994 os << "\n\\defskip " << getDefSkip().asLyXCommand();
995 os << "\n\\quotes_language "
996 << string_quotes_language[quotes_language]
997 << "\n\\papercolumns " << columns
998 << "\n\\papersides " << sides
999 << "\n\\paperpagestyle " << pagestyle << '\n';
1000 if (!listings_params.empty())
1001 os << "\\listings_params \"" <<
1002 InsetListingsParams(listings_params).encodedString() << "\"\n";
1003 for (int i = 0; i < 4; ++i) {
1004 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1005 if (user_defined_bullet(i).getFont() != -1) {
1006 os << "\\bullet " << i << " "
1007 << user_defined_bullet(i).getFont() << " "
1008 << user_defined_bullet(i).getCharacter() << " "
1009 << user_defined_bullet(i).getSize() << "\n";
1013 os << "\\bulletLaTeX " << i << " \""
1014 << lyx::to_ascii(user_defined_bullet(i).getText())
1020 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n"
1021 << "\\output_changes " << convert<string>(outputChanges) << "\n"
1022 << "\\html_math_output " << html_math_output << "\n"
1023 << "\\html_be_strict " << convert<string>(html_be_strict) << "\n";
1025 os << pimpl_->authorlist;
1029 void BufferParams::validate(LaTeXFeatures & features) const
1031 features.require(documentClass().requires());
1033 if (outputChanges) {
1034 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1035 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1036 LaTeXFeatures::isAvailable("xcolor");
1038 switch (features.runparams().flavor) {
1039 case OutputParams::LATEX:
1041 features.require("ct-dvipost");
1042 features.require("dvipost");
1043 } else if (xcolorulem) {
1044 features.require("ct-xcolor-ulem");
1045 features.require("ulem");
1046 features.require("xcolor");
1048 features.require("ct-none");
1051 case OutputParams::PDFLATEX:
1052 case OutputParams::XETEX:
1054 features.require("ct-xcolor-ulem");
1055 features.require("ulem");
1056 features.require("xcolor");
1057 // improves color handling in PDF output
1058 features.require("pdfcolmk");
1060 features.require("ct-none");
1068 // Floats with 'Here definitely' as default setting.
1069 if (float_placement.find('H') != string::npos)
1070 features.require("float");
1072 // AMS Style is at document level
1073 if (use_amsmath == package_on
1074 || documentClass().provides("amsmath"))
1075 features.require("amsmath");
1076 if (use_esint == package_on)
1077 features.require("esint");
1078 if (use_mhchem == package_on)
1079 features.require("mhchem");
1081 // Document-level line spacing
1082 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1083 features.require("setspace");
1085 // the bullet shapes are buffer level not paragraph level
1086 // so they are tested here
1087 for (int i = 0; i < 4; ++i) {
1088 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1090 int const font = user_defined_bullet(i).getFont();
1092 int const c = user_defined_bullet(i).getCharacter();
1098 features.require("latexsym");
1100 } else if (font == 1) {
1101 features.require("amssymb");
1102 } else if (font >= 2 && font <= 5) {
1103 features.require("pifont");
1107 if (pdfoptions().use_hyperref) {
1108 features.require("hyperref");
1109 // due to interferences with babel and hyperref, the color package has to
1110 // be loaded after hyperref when hyperref is used with the colorlinks
1111 // option, see http://www.lyx.org/trac/ticket/5291
1112 if (pdfoptions().colorlinks)
1113 features.require("color");
1117 features.require("xetex");
1119 if (language->lang() == "vietnamese")
1120 features.require("vietnamese");
1121 else if (language->lang() == "japanese")
1122 features.require("japanese");
1126 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1127 TexRow & texrow, FileName const & filepath) const
1129 os << "\\documentclass";
1131 DocumentClass const & tclass = documentClass();
1133 ostringstream clsoptions; // the document class options.
1135 if (tokenPos(tclass.opt_fontsize(),
1136 '|', fontsize) >= 0) {
1137 // only write if existing in list (and not default)
1138 clsoptions << fontsize << "pt,";
1141 // custom, A3, B3 and B4 paper sizes need geometry
1142 bool nonstandard_papersize = papersize == PAPER_B3
1143 || papersize == PAPER_B4
1144 || papersize == PAPER_A3
1145 || papersize == PAPER_CUSTOM;
1147 if (!use_geometry) {
1148 switch (papersize) {
1150 clsoptions << "a4paper,";
1152 case PAPER_USLETTER:
1153 clsoptions << "letterpaper,";
1156 clsoptions << "a5paper,";
1159 clsoptions << "b5paper,";
1161 case PAPER_USEXECUTIVE:
1162 clsoptions << "executivepaper,";
1165 clsoptions << "legalpaper,";
1177 if (sides != tclass.sides()) {
1180 clsoptions << "oneside,";
1183 clsoptions << "twoside,";
1189 if (columns != tclass.columns()) {
1191 clsoptions << "twocolumn,";
1193 clsoptions << "onecolumn,";
1197 && orientation == ORIENTATION_LANDSCAPE)
1198 clsoptions << "landscape,";
1200 // language should be a parameter to \documentclass
1201 if (language->babel() == "hebrew"
1202 && default_language->babel() != "hebrew")
1203 // This seems necessary
1204 features.useLanguage(default_language);
1206 ostringstream language_options;
1207 bool const use_babel = features.useBabel();
1209 language_options << features.getLanguages();
1210 if (!language->babel().empty()) {
1211 if (!language_options.str().empty())
1212 language_options << ',';
1213 language_options << language->babel();
1215 // if Vietnamese is used, babel must directly be loaded
1216 // with language options, not in the class options, see
1217 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1218 size_t viet = language_options.str().find("vietnam");
1219 // viet = string::npos when not found
1220 // the same is for all other languages that are not directly supported by
1221 // babel, but where LaTeX-packages add babel support.
1222 // this is currently the case for Latvian, Lithuanian, Mongolian
1224 size_t latvian = language_options.str().find("latvian");
1225 size_t lithu = language_options.str().find("lithuanian");
1226 size_t mongo = language_options.str().find("mongolian");
1227 size_t turkmen = language_options.str().find("turkmen");
1228 // if Japanese is used, babel must directly be loaded
1229 // with language options, not in the class options, see
1230 // http://www.lyx.org/trac/ticket/4597#c4
1231 size_t japan = language_options.str().find("japanese");
1232 if (lyxrc.language_global_options && !language_options.str().empty()
1233 && viet == string::npos && japan == string::npos
1234 && latvian == string::npos && lithu == string::npos
1235 && mongo == string::npos && turkmen == string::npos)
1236 clsoptions << language_options.str() << ',';
1239 // the predefined options from the layout
1240 if (use_default_options && !tclass.options().empty())
1241 clsoptions << tclass.options() << ',';
1243 // the user-defined options
1244 if (!options.empty()) {
1245 clsoptions << options << ',';
1248 string strOptions(clsoptions.str());
1249 if (!strOptions.empty()) {
1250 strOptions = rtrim(strOptions, ",");
1252 os << '[' << from_utf8(strOptions) << ']';
1255 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1257 // end of \documentclass defs
1260 os << "\\usepackage{fontspec}\n";
1264 // font selection must be done before loading fontenc.sty
1265 string const fonts =
1266 loadFonts(fontsRoman, fontsSans,
1267 fontsTypewriter, fontsSC, fontsOSF,
1268 fontsSansScale, fontsTypewriterScale, useXetex);
1269 if (!fonts.empty()) {
1270 os << from_ascii(fonts);
1273 if (fontsDefaultFamily != "default")
1274 os << "\\renewcommand{\\familydefault}{\\"
1275 << from_ascii(fontsDefaultFamily) << "}\n";
1277 // set font encoding
1278 // for arabic_arabi and farsi we also need to load the LAE and
1280 // XeTeX works without fontenc
1281 if (font_encoding() != "default" && language->lang() != "japanese"
1283 if (language->lang() == "arabic_arabi"
1284 || language->lang() == "farsi") {
1285 os << "\\usepackage[" << from_ascii(font_encoding())
1286 << ",LFE,LAE]{fontenc}\n";
1289 os << "\\usepackage[" << from_ascii(font_encoding())
1295 // handle inputenc etc.
1296 writeEncodingPreamble(os, features, texrow);
1299 if (!features.runparams().includeall && !includedChildren_.empty()) {
1300 os << "\\includeonly{";
1301 list<string>::const_iterator it = includedChildren_.begin();
1303 for (; it != includedChildren_.end() ; ++it) {
1304 string incfile = *it;
1305 FileName inc = makeAbsPath(incfile, filepath.absFilename());
1306 string mangled = DocFileName(changeExtension(inc.absFilename(), ".tex")).
1308 if (!features.runparams().nice)
1310 // \includeonly doesn't want an extension
1311 incfile = changeExtension(incfile, string());
1312 incfile = support::latex_path(incfile);
1313 if (!incfile.empty()) {
1316 os << from_utf8(incfile);
1323 if (!listings_params.empty() || features.isRequired("listings")) {
1324 os << "\\usepackage{listings}\n";
1327 if (!listings_params.empty()) {
1329 // do not test validity because listings_params is
1330 // supposed to be valid
1332 InsetListingsParams(listings_params).separatedParams(true);
1333 // we can't support all packages, but we should load the color package
1334 if (par.find("\\color", 0) != string::npos)
1335 features.require("color");
1336 os << from_utf8(par);
1337 // count the number of newlines
1338 for (size_t i = 0; i < par.size(); ++i)
1344 if (!tclass.provides("geometry")
1345 && (use_geometry || nonstandard_papersize)) {
1346 odocstringstream ods;
1347 if (!getGraphicsDriver("geometry").empty())
1348 ods << getGraphicsDriver("geometry");
1349 if (orientation == ORIENTATION_LANDSCAPE)
1350 ods << ",landscape";
1351 switch (papersize) {
1353 if (!paperwidth.empty())
1354 ods << ",paperwidth="
1355 << from_ascii(paperwidth);
1356 if (!paperheight.empty())
1357 ods << ",paperheight="
1358 << from_ascii(paperheight);
1360 case PAPER_USLETTER:
1361 ods << ",letterpaper";
1364 ods << ",legalpaper";
1366 case PAPER_USEXECUTIVE:
1367 ods << ",executivepaper";
1388 // default papersize ie PAPER_DEFAULT
1389 switch (lyxrc.default_papersize) {
1390 case PAPER_DEFAULT: // keep compiler happy
1391 case PAPER_USLETTER:
1392 ods << ",letterpaper";
1395 ods << ",legalpaper";
1397 case PAPER_USEXECUTIVE:
1398 ods << ",executivepaper";
1418 docstring const g_options = trim(ods.str(), ",");
1419 os << "\\usepackage";
1420 if (!g_options.empty())
1421 os << '[' << g_options << ']';
1422 os << "{geometry}\n";
1424 os << "\\geometry{verbose";
1425 if (!topmargin.empty())
1426 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1427 if (!bottommargin.empty())
1428 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1429 if (!leftmargin.empty())
1430 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1431 if (!rightmargin.empty())
1432 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1433 if (!headheight.empty())
1434 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1435 if (!headsep.empty())
1436 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1437 if (!footskip.empty())
1438 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1439 if (!columnsep.empty())
1440 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1443 } else if (orientation == ORIENTATION_LANDSCAPE) {
1444 features.require("papersize");
1447 if (tokenPos(tclass.opt_pagestyle(),
1448 '|', pagestyle) >= 0) {
1449 if (pagestyle == "fancy") {
1450 os << "\\usepackage{fancyhdr}\n";
1453 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1457 // only output when the background color is not white
1458 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1459 // only require color here, the background color will be defined
1460 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1462 features.require("color");
1463 features.require("pagecolor");
1466 // only output when the font color is not black
1467 if (isfontcolor == true) {
1468 // only require color here, the font color will be defined
1469 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1471 features.require("color");
1472 features.require("fontcolor");
1475 // Only if class has a ToC hierarchy
1476 if (tclass.hasTocLevels()) {
1477 if (secnumdepth != tclass.secnumdepth()) {
1478 os << "\\setcounter{secnumdepth}{"
1483 if (tocdepth != tclass.tocdepth()) {
1484 os << "\\setcounter{tocdepth}{"
1491 if (paragraph_separation) {
1492 // when skip separation
1493 switch (getDefSkip().kind()) {
1494 case VSpace::SMALLSKIP:
1495 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1497 case VSpace::MEDSKIP:
1498 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1500 case VSpace::BIGSKIP:
1501 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1503 case VSpace::LENGTH:
1504 os << "\\setlength{\\parskip}{"
1505 << from_utf8(getDefSkip().length().asLatexString())
1508 default: // should never happen // Then delete it.
1509 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1513 os << "\\setlength{\\parindent}{0pt}\n";
1516 // when separation by indentation
1517 // only output something when a width is given
1518 if (getIndentation().asLyXCommand() != "default") {
1519 os << "\\setlength{\\parindent}{"
1520 << from_utf8(getIndentation().asLatexCommand())
1526 // Now insert the LyX specific LaTeX commands...
1527 docstring lyxpreamble;
1529 // due to interferences with babel and hyperref, the color package has to
1530 // be loaded (when it is not already loaded) before babel when hyperref
1531 // is used with the colorlinks option, see
1532 // http://www.lyx.org/trac/ticket/5291
1533 // we decided therefore to load color always before babel, see
1534 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1535 lyxpreamble += from_ascii(features.getColorOptions());
1537 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1539 && (features.isRequired("jurabib")
1540 || features.isRequired("hyperref")
1541 || features.isRequired("vietnamese")
1542 || features.isRequired("japanese") ) ) {
1544 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1545 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1548 // The optional packages;
1549 lyxpreamble += from_ascii(features.getPackages());
1551 // Additional Indices
1552 if (features.isRequired("splitidx")) {
1553 IndicesList::const_iterator iit = indiceslist().begin();
1554 IndicesList::const_iterator iend = indiceslist().end();
1555 for (; iit != iend; ++iit) {
1556 lyxpreamble += "\\newindex[";
1557 lyxpreamble += iit->index();
1558 lyxpreamble += "]{";
1559 lyxpreamble += iit->shortcut();
1560 lyxpreamble += "}\n";
1565 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1568 // * Hyperref manual: "Make sure it comes last of your loaded
1569 // packages, to give it a fighting chance of not being over-written,
1570 // since its job is to redefine many LaTeX commands."
1571 // * Email from Heiko Oberdiek: "It is usually better to load babel
1572 // before hyperref. Then hyperref has a chance to detect babel.
1573 // * Has to be loaded before the "LyX specific LaTeX commands" to
1574 // avoid errors with algorithm floats.
1575 // use hyperref explicitly if it is required
1576 if (features.isRequired("hyperref")) {
1577 // pass what we have to stream here, since we need
1578 // to access the stream itself in PDFOptions.
1582 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1584 OutputParams tmp_params = features.runparams();
1585 lines += pdfoptions().writeLaTeX(tmp_params, os,
1586 documentClass().provides("hyperref"));
1587 texrow.newlines(lines);
1588 // set back for the rest
1589 lyxpreamble.clear();
1592 // Will be surrounded by \makeatletter and \makeatother when not empty
1593 docstring atlyxpreamble;
1595 // Some macros LyX will need
1596 docstring tmppreamble(features.getMacros());
1598 if (!tmppreamble.empty())
1599 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1600 "LyX specific LaTeX commands.\n"
1601 + tmppreamble + '\n';
1603 // the text class specific preamble
1604 tmppreamble = features.getTClassPreamble();
1605 if (!tmppreamble.empty())
1606 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1607 "Textclass specific LaTeX commands.\n"
1608 + tmppreamble + '\n';
1610 // suppress date if selected
1611 // use \@ifundefined because we cannot be sure that every document class
1612 // has a \date command
1614 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1616 /* the user-defined preamble */
1617 if (!containsOnly(preamble, " \n\t"))
1619 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1620 "User specified LaTeX commands.\n"
1621 + from_utf8(preamble) + '\n';
1623 // subfig loads internally the LaTeX package "caption". As
1624 // caption is a very popular package, users will load it in
1625 // the preamble. Therefore we must load subfig behind the
1626 // user-defined preamble and check if the caption package was
1627 // loaded or not. For the case that caption is loaded before
1628 // subfig, there is the subfig option "caption=false". This
1629 // option also works when a koma-script class is used and
1630 // koma's own caption commands are used instead of caption. We
1631 // use \PassOptionsToPackage here because the user could have
1632 // already loaded subfig in the preamble.
1633 if (features.isRequired("subfig")) {
1634 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1635 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1636 "\\usepackage{subfig}\n";
1639 // Itemize bullet settings need to be last in case the user
1640 // defines their own bullets that use a package included
1641 // in the user-defined preamble -- ARRae
1642 // Actually it has to be done much later than that
1643 // since some packages like frenchb make modifications
1644 // at \begin{document} time -- JMarc
1645 docstring bullets_def;
1646 for (int i = 0; i < 4; ++i) {
1647 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1648 if (bullets_def.empty())
1649 bullets_def += "\\AtBeginDocument{\n";
1650 bullets_def += " \\def\\labelitemi";
1652 // `i' is one less than the item to modify
1659 bullets_def += "ii";
1665 bullets_def += '{' +
1666 user_defined_bullet(i).getText()
1671 if (!bullets_def.empty())
1672 atlyxpreamble += bullets_def + "}\n\n";
1674 if (!atlyxpreamble.empty())
1675 lyxpreamble += "\n\\makeatletter\n"
1676 + atlyxpreamble + "\\makeatother\n\n";
1678 // We try to load babel late, in case it interferes with other packages.
1679 // Jurabib and Hyperref have to be called after babel, though.
1680 if (use_babel && !features.isRequired("jurabib")
1681 && !features.isRequired("hyperref")
1682 && !features.isRequired("vietnamese")
1683 && !features.isRequired("japanese")) {
1685 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1686 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1689 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1690 if (!i18npreamble.empty())
1691 lyxpreamble += i18npreamble + '\n';
1694 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1695 texrow.newlines(nlines);
1699 // these packages (xunicode, for that matter) need to be loaded at least
1700 // after amsmath, amssymb, esint and the other packages that provide
1703 os << "\\usepackage{xunicode}\n";
1705 os << "\\usepackage{xltxtra}\n";
1712 void BufferParams::useClassDefaults()
1714 DocumentClass const & tclass = documentClass();
1716 sides = tclass.sides();
1717 columns = tclass.columns();
1718 pagestyle = tclass.pagestyle();
1719 use_default_options = true;
1720 // Only if class has a ToC hierarchy
1721 if (tclass.hasTocLevels()) {
1722 secnumdepth = tclass.secnumdepth();
1723 tocdepth = tclass.tocdepth();
1728 bool BufferParams::hasClassDefaults() const
1730 DocumentClass const & tclass = documentClass();
1732 return sides == tclass.sides()
1733 && columns == tclass.columns()
1734 && pagestyle == tclass.pagestyle()
1735 && use_default_options
1736 && secnumdepth == tclass.secnumdepth()
1737 && tocdepth == tclass.tocdepth();
1741 DocumentClass const & BufferParams::documentClass() const
1747 DocumentClass const * BufferParams::documentClassPtr() const {
1752 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1753 // evil, but this function is evil
1754 doc_class_ = const_cast<DocumentClass *>(tc);
1758 bool BufferParams::setBaseClass(string const & classname)
1760 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1761 LayoutFileList & bcl = LayoutFileList::get();
1762 if (!bcl.haveClass(classname)) {
1764 bformat(_("The document class %1$s could not be found. "
1765 "A default textclass with default layouts will be used. "
1766 "LyX might not be able to produce output unless a correct "
1767 "textclass is selected from the document settings dialog."),
1768 from_utf8(classname));
1769 frontend::Alert::error(_("Document class not found"), s);
1770 bcl.addEmptyClass(classname);
1773 bool const success = bcl[classname].load();
1776 bformat(_("The document class %1$s could not be loaded."),
1777 from_utf8(classname));
1778 frontend::Alert::error(_("Could not load class"), s);
1782 pimpl_->baseClass_ = classname;
1783 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1788 LayoutFile const * BufferParams::baseClass() const
1790 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1791 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1797 LayoutFileIndex const & BufferParams::baseClassID() const
1799 return pimpl_->baseClass_;
1803 void BufferParams::makeDocumentClass()
1808 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1810 if (!local_layout.empty()) {
1811 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1812 docstring const msg = _("Error reading internal layout information");
1813 frontend::Alert::warning(_("Read Error"), msg);
1818 bool BufferParams::moduleCanBeAdded(string const & modName) const
1820 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1824 bool BufferParams::addLayoutModule(string const & modName)
1826 LayoutModuleList::const_iterator it = layoutModules_.begin();
1827 LayoutModuleList::const_iterator end = layoutModules_.end();
1828 for (; it != end; it++)
1831 layoutModules_.push_back(modName);
1836 Font const BufferParams::getFont() const
1838 FontInfo f = documentClass().defaultfont();
1839 if (fontsDefaultFamily == "rmdefault")
1840 f.setFamily(ROMAN_FAMILY);
1841 else if (fontsDefaultFamily == "sfdefault")
1842 f.setFamily(SANS_FAMILY);
1843 else if (fontsDefaultFamily == "ttdefault")
1844 f.setFamily(TYPEWRITER_FAMILY);
1845 return Font(f, language);
1849 void BufferParams::readPreamble(Lexer & lex)
1851 if (lex.getString() != "\\begin_preamble")
1852 lyxerr << "Error (BufferParams::readPreamble):"
1853 "consistency check failed." << endl;
1855 preamble = lex.getLongString("\\end_preamble");
1859 void BufferParams::readLocalLayout(Lexer & lex)
1861 if (lex.getString() != "\\begin_local_layout")
1862 lyxerr << "Error (BufferParams::readLocalLayout):"
1863 "consistency check failed." << endl;
1865 local_layout = lex.getLongString("\\end_local_layout");
1869 void BufferParams::readLanguage(Lexer & lex)
1871 if (!lex.next()) return;
1873 string const tmptok = lex.getString();
1875 // check if tmptok is part of tex_babel in tex-defs.h
1876 language = languages.getLanguage(tmptok);
1878 // Language tmptok was not found
1879 language = default_language;
1880 lyxerr << "Warning: Setting language `"
1881 << tmptok << "' to `" << language->lang()
1887 void BufferParams::readGraphicsDriver(Lexer & lex)
1892 string const tmptok = lex.getString();
1893 // check if tmptok is part of tex_graphics in tex_defs.h
1896 string const test = tex_graphics[n++];
1898 if (test == tmptok) {
1899 graphicsDriver = tmptok;
1904 "Warning: graphics driver `$$Token' not recognized!\n"
1905 " Setting graphics driver to `default'.\n");
1906 graphicsDriver = "default";
1913 void BufferParams::readBullets(Lexer & lex)
1918 int const index = lex.getInteger();
1920 int temp_int = lex.getInteger();
1921 user_defined_bullet(index).setFont(temp_int);
1922 temp_bullet(index).setFont(temp_int);
1924 user_defined_bullet(index).setCharacter(temp_int);
1925 temp_bullet(index).setCharacter(temp_int);
1927 user_defined_bullet(index).setSize(temp_int);
1928 temp_bullet(index).setSize(temp_int);
1932 void BufferParams::readBulletsLaTeX(Lexer & lex)
1934 // The bullet class should be able to read this.
1937 int const index = lex.getInteger();
1939 docstring const temp_str = lex.getDocString();
1941 user_defined_bullet(index).setText(temp_str);
1942 temp_bullet(index).setText(temp_str);
1946 void BufferParams::readModules(Lexer & lex)
1948 if (!lex.eatLine()) {
1949 lyxerr << "Error (BufferParams::readModules):"
1950 "Unexpected end of input." << endl;
1954 string mod = lex.getString();
1955 if (mod == "\\end_modules")
1957 addLayoutModule(mod);
1963 void BufferParams::readRemovedModules(Lexer & lex)
1965 if (!lex.eatLine()) {
1966 lyxerr << "Error (BufferParams::readRemovedModules):"
1967 "Unexpected end of input." << endl;
1971 string mod = lex.getString();
1972 if (mod == "\\end_removed_modules")
1974 removedModules_.push_back(mod);
1977 // now we want to remove any removed modules that were previously
1978 // added. normally, that will be because default modules were added in
1979 // setBaseClass(), which gets called when \textclass is read at the
1980 // start of the read.
1981 list<string>::const_iterator rit = removedModules_.begin();
1982 list<string>::const_iterator const ren = removedModules_.end();
1983 for (; rit != ren; rit++) {
1984 LayoutModuleList::iterator const mit = layoutModules_.begin();
1985 LayoutModuleList::iterator const men = layoutModules_.end();
1986 LayoutModuleList::iterator found = find(mit, men, *rit);
1989 layoutModules_.erase(found);
1994 void BufferParams::readIncludeonly(Lexer & lex)
1996 if (!lex.eatLine()) {
1997 lyxerr << "Error (BufferParams::readIncludeonly):"
1998 "Unexpected end of input." << endl;
2002 string child = lex.getString();
2003 if (child == "\\end_includeonly")
2005 includedChildren_.push_back(child);
2011 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2013 char real_papersize = papersize;
2014 if (real_papersize == PAPER_DEFAULT)
2015 real_papersize = lyxrc.default_papersize;
2017 switch (real_papersize) {
2019 // could be anything, so don't guess
2021 case PAPER_CUSTOM: {
2022 if (purpose == XDVI && !paperwidth.empty() &&
2023 !paperheight.empty()) {
2024 // heightxwidth<unit>
2025 string first = paperwidth;
2026 string second = paperheight;
2027 if (orientation == ORIENTATION_LANDSCAPE)
2030 return first.erase(first.length() - 2)
2042 // dvips and dvipdfm do not know this
2043 if (purpose == DVIPS || purpose == DVIPDFM)
2047 // dvipdfm does not know this
2048 if (purpose == DVIPDFM)
2052 // dvipdfm does not know this
2053 if (purpose == DVIPDFM)
2056 case PAPER_USEXECUTIVE:
2057 // dvipdfm does not know this
2058 if (purpose == DVIPDFM)
2063 case PAPER_USLETTER:
2065 if (purpose == XDVI)
2072 string const BufferParams::dvips_options() const
2077 && papersize == PAPER_CUSTOM
2078 && !lyxrc.print_paper_dimension_flag.empty()
2079 && !paperwidth.empty()
2080 && !paperheight.empty()) {
2081 // using a custom papersize
2082 result = lyxrc.print_paper_dimension_flag;
2083 result += ' ' + paperwidth;
2084 result += ',' + paperheight;
2086 string const paper_option = paperSizeName(DVIPS);
2087 if (!paper_option.empty() && (paper_option != "letter" ||
2088 orientation != ORIENTATION_LANDSCAPE)) {
2089 // dvips won't accept -t letter -t landscape.
2090 // In all other cases, include the paper size
2092 result = lyxrc.print_paper_flag;
2093 result += ' ' + paper_option;
2096 if (orientation == ORIENTATION_LANDSCAPE &&
2097 papersize != PAPER_CUSTOM)
2098 result += ' ' + lyxrc.print_landscape_flag;
2103 string const BufferParams::font_encoding() const
2105 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2109 string BufferParams::babelCall(string const & lang_opts) const
2111 string lang_pack = lyxrc.language_package;
2112 if (lang_pack != "\\usepackage{babel}")
2114 // suppress the babel call when there is no babel language defined
2115 // for the document language in the lib/languages file and if no
2116 // other languages are used (lang_opts is then empty)
2117 if (lang_opts.empty())
2119 // If Vietnamese is used, babel must directly be loaded with the
2120 // language options, see
2121 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2122 size_t viet = lang_opts.find("vietnam");
2123 // viet = string::npos when not found
2124 // the same is for all other languages that are not directly supported by
2125 // babel, but where LaTeX-packages add babel support.
2126 // this is currently the case for Latvian, Lithuanian, Mongolian
2128 size_t latvian = lang_opts.find("latvian");
2129 size_t lithu = lang_opts.find("lithuanian");
2130 size_t mongo = lang_opts.find("mongolian");
2131 size_t turkmen = lang_opts.find("turkmen");
2132 // If Japanese is used, babel must directly be loaded with the
2133 // language options, see
2134 // http://www.lyx.org/trac/ticket/4597#c4
2135 size_t japan = lang_opts.find("japanese");
2136 if (!lyxrc.language_global_options || viet != string::npos
2137 || japan != string::npos || latvian != string::npos
2138 || lithu != string::npos || mongo != string::npos
2139 || turkmen != string::npos)
2140 return "\\usepackage[" + lang_opts + "]{babel}";
2145 docstring BufferParams::getGraphicsDriver(string const & package) const
2149 if (package == "geometry") {
2150 if (graphicsDriver == "dvips"
2151 || graphicsDriver == "dvipdfm"
2152 || graphicsDriver == "pdftex"
2153 || graphicsDriver == "vtex")
2154 result = from_ascii(graphicsDriver);
2155 else if (graphicsDriver == "dvipdfmx")
2156 result = from_ascii("dvipdfm");
2163 void BufferParams::writeEncodingPreamble(odocstream & os,
2164 LaTeXFeatures & features, TexRow & texrow) const
2168 if (inputenc == "auto") {
2169 string const doc_encoding =
2170 language->encoding()->latexName();
2171 Encoding::Package const package =
2172 language->encoding()->package();
2174 // Create a list with all the input encodings used
2176 set<string> encodings =
2177 features.getEncodingSet(doc_encoding);
2179 // If the "japanese" package (i.e. pLaTeX) is used,
2180 // inputenc must be omitted.
2181 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2182 if (package == Encoding::japanese)
2183 features.require("japanese");
2185 if ((!encodings.empty() || package == Encoding::inputenc)
2186 && !features.isRequired("japanese")) {
2187 os << "\\usepackage[";
2188 set<string>::const_iterator it = encodings.begin();
2189 set<string>::const_iterator const end = encodings.end();
2191 os << from_ascii(*it);
2194 for (; it != end; ++it)
2195 os << ',' << from_ascii(*it);
2196 if (package == Encoding::inputenc) {
2197 if (!encodings.empty())
2199 os << from_ascii(doc_encoding);
2201 os << "]{inputenc}\n";
2204 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2205 if (language->encoding()->name() == "utf8-cjk"
2206 && LaTeXFeatures::isAvailable("CJKutf8"))
2207 os << "\\usepackage{CJKutf8}\n";
2209 os << "\\usepackage{CJK}\n";
2212 } else if (inputenc != "default") {
2213 switch (encoding().package()) {
2214 case Encoding::none:
2215 case Encoding::japanese:
2217 case Encoding::inputenc:
2218 // do not load inputenc if japanese is used
2219 if (features.isRequired("japanese"))
2221 os << "\\usepackage[" << from_ascii(inputenc)
2226 if (encoding().name() == "utf8-cjk"
2227 && LaTeXFeatures::isAvailable("CJKutf8"))
2228 os << "\\usepackage{CJKutf8}\n";
2230 os << "\\usepackage{CJK}\n";
2236 // The encoding "armscii8" (for Armenian) is only available when
2237 // the package "armtex" is loaded.
2238 if (language->encoding()->latexName() == "armscii8"
2239 || inputenc == "armscii8") {
2240 os << "\\usepackage{armtex}\n";
2246 string const BufferParams::parseFontName(string const & name) const
2248 string mangled = name;
2249 size_t const idx = mangled.find('[');
2250 if (idx == string::npos || idx == 0)
2253 return mangled.substr(0, idx - 1);
2257 string const BufferParams::loadFonts(string const & rm,
2258 string const & sf, string const & tt,
2259 bool const & sc, bool const & osf,
2260 int const & sfscale, int const & ttscale,
2261 bool const & xetex) const
2263 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2264 several packages have been replaced by others, that might not
2265 be installed on every system. We have to take care for that
2266 (see psnfss.pdf). We try to support all psnfss fonts as well
2267 as the fonts that have become de facto standard in the LaTeX
2268 world (e.g. Latin Modern). We do not support obsolete fonts
2269 (like PSLatex). In general, it should be possible to mix any
2270 rm font with any sf or tt font, respectively. (JSpitzm)
2272 -- separate math fonts.
2275 if (rm == "default" && sf == "default" && tt == "default")
2282 if (rm != "default")
2283 os << "\\setmainfont[Mapping=tex-text]{"
2284 << parseFontName(rm) << "}\n";
2285 if (sf != "default") {
2286 string const sans = parseFontName(sf);
2288 os << "\\setsansfont[Scale="
2289 << float(sfscale) / 100
2290 << ",Mapping=tex-text]{"
2293 os << "\\setsansfont[Mapping=tex-text]{"
2296 if (tt != "default") {
2297 string const mono = parseFontName(tt);
2299 os << "\\setmonofont[Scale="
2300 << float(sfscale) / 100
2304 os << "\\setmonofont[Mapping=tex-text]{"
2308 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2313 // Computer Modern (must be explicitly selectable -- there might be classes
2314 // that define a different default font!
2316 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2317 // osf for Computer Modern needs eco.sty
2319 os << "\\usepackage{eco}\n";
2321 // Latin Modern Roman
2322 else if (rm == "lmodern")
2323 os << "\\usepackage{lmodern}\n";
2325 else if (rm == "ae") {
2326 // not needed when using OT1 font encoding.
2327 if (font_encoding() != "default")
2328 os << "\\usepackage{ae,aecompl}\n";
2331 else if (rm == "times") {
2332 // try to load the best available package
2333 if (LaTeXFeatures::isAvailable("mathptmx"))
2334 os << "\\usepackage{mathptmx}\n";
2335 else if (LaTeXFeatures::isAvailable("mathptm"))
2336 os << "\\usepackage{mathptm}\n";
2338 os << "\\usepackage{times}\n";
2341 else if (rm == "palatino") {
2342 // try to load the best available package
2343 if (LaTeXFeatures::isAvailable("mathpazo")) {
2344 os << "\\usepackage";
2350 // "osf" includes "sc"!
2354 os << "{mathpazo}\n";
2356 else if (LaTeXFeatures::isAvailable("mathpple"))
2357 os << "\\usepackage{mathpple}\n";
2359 os << "\\usepackage{palatino}\n";
2362 else if (rm == "utopia") {
2363 // fourier supersedes utopia.sty, but does
2364 // not work with OT1 encoding.
2365 if (LaTeXFeatures::isAvailable("fourier")
2366 && font_encoding() != "default") {
2367 os << "\\usepackage";
2378 os << "{fourier}\n";
2381 os << "\\usepackage{utopia}\n";
2383 // Bera (complete fontset)
2384 else if (rm == "bera" && sf == "default" && tt == "default")
2385 os << "\\usepackage{bera}\n";
2387 else if (rm != "default")
2388 os << "\\usepackage" << "{" << rm << "}\n";
2391 // Helvetica, Bera Sans
2392 if (sf == "helvet" || sf == "berasans") {
2394 os << "\\usepackage[scaled=" << float(sfscale) / 100
2395 << "]{" << sf << "}\n";
2397 os << "\\usepackage{" << sf << "}\n";
2400 else if (sf == "avant")
2401 os << "\\usepackage{" << sf << "}\n";
2402 // Computer Modern, Latin Modern, CM Bright
2403 else if (sf != "default")
2404 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2406 // monospaced/typewriter
2407 // Courier, LuxiMono
2408 if (tt == "luximono" || tt == "beramono") {
2410 os << "\\usepackage[scaled=" << float(ttscale) / 100
2411 << "]{" << tt << "}\n";
2413 os << "\\usepackage{" << tt << "}\n";
2416 else if (tt == "courier" )
2417 os << "\\usepackage{" << tt << "}\n";
2418 // Computer Modern, Latin Modern, CM Bright
2419 else if (tt != "default")
2420 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2426 Encoding const & BufferParams::encoding() const
2429 return *(encodings.fromLaTeXName("utf8-plain"));
2430 if (inputenc == "auto" || inputenc == "default")
2431 return *language->encoding();
2432 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2435 LYXERR0("Unknown inputenc value `" << inputenc
2436 << "'. Using `auto' instead.");
2437 return *language->encoding();
2441 CiteEngine BufferParams::citeEngine() const
2443 // FIXME the class should provide the numerical/
2444 // authoryear choice
2445 if (documentClass().provides("natbib")
2446 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2447 return ENGINE_NATBIB_AUTHORYEAR;
2448 return cite_engine_;
2452 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2454 cite_engine_ = cite_engine;