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 // no color is the default (white)
371 backgroundcolor = lyx::rgbFromHexName("#ffffff");
372 isbackgroundcolor = false;
373 // no color is the default (black)
374 fontcolor = lyx::rgbFromHexName("#000000");
376 // light gray is the default font color for greyed-out notes
377 notefontcolor = lyx::rgbFromHexName("#cccccc");
378 compressed = lyxrc.save_compressed;
379 for (int iter = 0; iter < 4; ++iter) {
380 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
381 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
384 indiceslist().addDefault(B_("Index"));
385 html_be_strict = true;
386 html_math_output = MathML;
390 docstring BufferParams::B_(string const & l10n) const
392 LASSERT(language, /**/);
393 return getMessages(language->code()).get(l10n);
397 AuthorList & BufferParams::authors()
399 return pimpl_->authorlist;
403 AuthorList const & BufferParams::authors() const
405 return pimpl_->authorlist;
409 BranchList & BufferParams::branchlist()
411 return pimpl_->branchlist;
415 BranchList const & BufferParams::branchlist() const
417 return pimpl_->branchlist;
421 IndicesList & BufferParams::indiceslist()
423 return pimpl_->indiceslist;
427 IndicesList const & BufferParams::indiceslist() const
429 return pimpl_->indiceslist;
433 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
435 LASSERT(index < 4, /**/);
436 return pimpl_->temp_bullets[index];
440 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
442 LASSERT(index < 4, /**/);
443 return pimpl_->temp_bullets[index];
447 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
449 LASSERT(index < 4, /**/);
450 return pimpl_->user_defined_bullets[index];
454 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
456 LASSERT(index < 4, /**/);
457 return pimpl_->user_defined_bullets[index];
461 Spacing & BufferParams::spacing()
463 return pimpl_->spacing;
467 Spacing const & BufferParams::spacing() const
469 return pimpl_->spacing;
473 PDFOptions & BufferParams::pdfoptions()
475 return pimpl_->pdfoptions;
479 PDFOptions const & BufferParams::pdfoptions() const
481 return pimpl_->pdfoptions;
485 HSpace const & BufferParams::getIndentation() const
487 return pimpl_->indentation;
491 void BufferParams::setIndentation(HSpace const & indent)
493 pimpl_->indentation = indent;
497 VSpace const & BufferParams::getDefSkip() const
499 return pimpl_->defskip;
503 void BufferParams::setDefSkip(VSpace const & vs)
505 pimpl_->defskip = vs;
509 string BufferParams::readToken(Lexer & lex, string const & token,
510 FileName const & filepath)
512 if (token == "\\textclass") {
514 string const classname = lex.getString();
515 // if there exists a local layout file, ignore the system one
516 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
518 LayoutFileList & bcl = LayoutFileList::get();
519 if (tcp.empty() && !filepath.empty())
520 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
524 setBaseClass(classname);
525 // We assume that a tex class exists for local or unknown layouts so this warning
526 // will only be given for system layouts.
527 if (!baseClass()->isTeXClassAvailable()) {
529 translateIfPossible(from_utf8(baseClass()->description()));
530 docstring const msg =
531 bformat(_("The document class requested\n"
533 "requires external files that are not available.\n"
534 "The document class can still be used, but LyX\n"
535 "will not be able to produce output until the\n"
536 "following prerequisites are installed:\n"
538 "See section 3.1.2.2 of the User's Guide for\n"
539 "more information."),
540 desc, from_utf8(baseClass()->prerequisites()));
541 frontend::Alert::warning(_("Document class not available"),
544 } else if (token == "\\begin_preamble") {
546 } else if (token == "\\begin_local_layout") {
547 readLocalLayout(lex);
548 } else if (token == "\\begin_modules") {
550 } else if (token == "\\begin_removed_modules") {
551 readRemovedModules(lex);
552 } else if (token == "\\begin_includeonly") {
553 readIncludeonly(lex);
554 } else if (token == "\\maintain_unincluded_children") {
555 lex >> maintain_unincluded_children;
556 } else if (token == "\\options") {
558 options = lex.getString();
559 } else if (token == "\\use_default_options") {
560 lex >> use_default_options;
561 } else if (token == "\\master") {
563 master = lex.getString();
564 } else if (token == "\\suppress_date") {
565 lex >> suppress_date;
566 } else if (token == "\\language") {
568 } else if (token == "\\inputencoding") {
570 } else if (token == "\\graphics") {
571 readGraphicsDriver(lex);
572 } else if (token == "\\default_output_format") {
573 lex >> defaultOutputFormat;
574 } else if (token == "\\bibtex_command") {
576 bibtex_command = lex.getString();
577 } else if (token == "\\index_command") {
579 index_command = lex.getString();
580 } else if (token == "\\fontencoding") {
582 fontenc = lex.getString();
583 } else if (token == "\\font_roman") {
585 fontsRoman = lex.getString();
586 } else if (token == "\\font_sans") {
588 fontsSans = lex.getString();
589 } else if (token == "\\font_typewriter") {
591 fontsTypewriter = lex.getString();
592 } else if (token == "\\font_default_family") {
593 lex >> fontsDefaultFamily;
594 } else if (token == "\\use_xetex") {
596 } else if (token == "\\font_sc") {
598 } else if (token == "\\font_osf") {
600 } else if (token == "\\font_sf_scale") {
601 lex >> fontsSansScale;
602 } else if (token == "\\font_tt_scale") {
603 lex >> fontsTypewriterScale;
604 } else if (token == "\\font_cjk") {
606 } else if (token == "\\paragraph_separation") {
609 paragraph_separation = parseptranslator().find(parsep);
610 } else if (token == "\\paragraph_indentation") {
612 string indentation = lex.getString();
613 pimpl_->indentation = HSpace(indentation);
614 } else if (token == "\\defskip") {
616 string defskip = lex.getString();
617 if (defskip == "defskip")
620 pimpl_->defskip = VSpace(defskip);
621 } else if (token == "\\quotes_language") {
624 quotes_language = quoteslangtranslator().find(quotes_lang);
625 } else if (token == "\\papersize") {
628 papersize = papersizetranslator().find(ppsize);
629 } else if (token == "\\use_geometry") {
631 } else if (token == "\\use_amsmath") {
634 use_amsmath = packagetranslator().find(use_ams);
635 } else if (token == "\\use_esint") {
638 use_esint = packagetranslator().find(useesint);
639 } else if (token == "\\use_mhchem") {
642 use_mhchem = packagetranslator().find(usemhchem);
643 } else if (token == "\\cite_engine") {
646 cite_engine_ = citeenginetranslator().find(engine);
647 } else if (token == "\\use_bibtopic") {
649 } else if (token == "\\use_indices") {
651 } else if (token == "\\tracking_changes") {
653 } else if (token == "\\output_changes") {
654 lex >> outputChanges;
655 } else if (token == "\\branch") {
657 docstring branch = lex.getDocString();
658 branchlist().add(branch);
661 string const tok = lex.getString();
662 if (tok == "\\end_branch")
664 Branch * branch_ptr = branchlist().find(branch);
665 if (tok == "\\selected") {
668 branch_ptr->setSelected(lex.getInteger());
670 if (tok == "\\filename_suffix") {
673 branch_ptr->setFilenameSuffix(lex.getInteger());
675 if (tok == "\\color") {
677 string color = lex.getString();
679 branch_ptr->setColor(color);
680 // Update also the Color table:
682 color = lcolor.getX11Name(Color_background);
684 lcolor.setColor(to_utf8(branch), color);
687 } else if (token == "\\index") {
689 docstring index = lex.getDocString();
691 indiceslist().add(index);
694 string const tok = lex.getString();
695 if (tok == "\\end_index")
697 Index * index_ptr = indiceslist().find(index);
698 if (tok == "\\shortcut") {
700 shortcut = lex.getDocString();
702 index_ptr->setShortcut(shortcut);
704 if (tok == "\\color") {
706 string color = lex.getString();
708 index_ptr->setColor(color);
709 // Update also the Color table:
711 color = lcolor.getX11Name(Color_background);
713 if (!shortcut.empty())
714 lcolor.setColor(to_utf8(shortcut), color);
717 } else if (token == "\\author") {
719 istringstream ss(lex.getString());
722 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
723 } else if (token == "\\paperorientation") {
726 orientation = paperorientationtranslator().find(orient);
727 } else if (token == "\\backgroundcolor") {
729 backgroundcolor = lyx::rgbFromHexName(lex.getString());
730 isbackgroundcolor = true;
731 } else if (token == "\\fontcolor") {
733 fontcolor = lyx::rgbFromHexName(lex.getString());
735 } else if (token == "\\notefontcolor") {
737 string color = lex.getString();
738 notefontcolor = lyx::rgbFromHexName(color);
739 // set the font color within LyX
740 // FIXME: the color is correctly set but later overwritten by the default
741 lcolor.setColor(Color_greyedouttext, color);
742 } else if (token == "\\paperwidth") {
744 } else if (token == "\\paperheight") {
746 } else if (token == "\\leftmargin") {
748 } else if (token == "\\topmargin") {
750 } else if (token == "\\rightmargin") {
752 } else if (token == "\\bottommargin") {
754 } else if (token == "\\headheight") {
756 } else if (token == "\\headsep") {
758 } else if (token == "\\footskip") {
760 } else if (token == "\\columnsep") {
762 } else if (token == "\\paperfontsize") {
764 } else if (token == "\\papercolumns") {
766 } else if (token == "\\listings_params") {
769 listings_params = InsetListingsParams(par).params();
770 } else if (token == "\\papersides") {
773 sides = sidestranslator().find(psides);
774 } else if (token == "\\paperpagestyle") {
776 } else if (token == "\\bullet") {
778 } else if (token == "\\bulletLaTeX") {
779 readBulletsLaTeX(lex);
780 } else if (token == "\\secnumdepth") {
782 } else if (token == "\\tocdepth") {
784 } else if (token == "\\spacing") {
788 if (nspacing == "other") {
791 spacing().set(spacetranslator().find(nspacing), tmp_val);
792 } else if (token == "\\float_placement") {
793 lex >> float_placement;
795 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
796 string toktmp = pdfoptions().readToken(lex, token);
797 if (!toktmp.empty()) {
798 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
802 } else if (token == "\\html_math_output") {
805 html_math_output = static_cast<MathOutput>(temp);
806 } else if (token == "\\html_be_strict") {
807 lex >> html_be_strict;
809 lyxerr << "BufferParams::readToken(): Unknown token: " <<
818 void BufferParams::writeFile(ostream & os) const
820 // The top of the file is written by the buffer.
821 // Prints out the buffer info into the .lyx file given by file
824 os << "\\textclass " << baseClass()->name() << '\n';
827 if (!preamble.empty()) {
828 // remove '\n' from the end of preamble
829 string const tmppreamble = rtrim(preamble, "\n");
830 os << "\\begin_preamble\n"
832 << "\n\\end_preamble\n";
836 if (!options.empty()) {
837 os << "\\options " << options << '\n';
840 // use the class options defined in the layout?
841 os << "\\use_default_options "
842 << convert<string>(use_default_options) << "\n";
844 // the master document
845 if (!master.empty()) {
846 os << "\\master " << master << '\n';
850 if (!removedModules_.empty()) {
851 os << "\\begin_removed_modules" << '\n';
852 list<string>::const_iterator it = removedModules_.begin();
853 list<string>::const_iterator en = removedModules_.end();
854 for (; it != en; it++)
856 os << "\\end_removed_modules" << '\n';
860 if (!layoutModules_.empty()) {
861 os << "\\begin_modules" << '\n';
862 LayoutModuleList::const_iterator it = layoutModules_.begin();
863 LayoutModuleList::const_iterator en = layoutModules_.end();
864 for (; it != en; it++)
866 os << "\\end_modules" << '\n';
870 if (!includedChildren_.empty()) {
871 os << "\\begin_includeonly" << '\n';
872 list<string>::const_iterator it = includedChildren_.begin();
873 list<string>::const_iterator en = includedChildren_.end();
874 for (; it != en; it++)
876 os << "\\end_includeonly" << '\n';
878 os << "\\maintain_unincluded_children "
879 << convert<string>(maintain_unincluded_children) << '\n';
881 // local layout information
882 if (!local_layout.empty()) {
883 // remove '\n' from the end
884 string const tmplocal = rtrim(local_layout, "\n");
885 os << "\\begin_local_layout\n"
887 << "\n\\end_local_layout\n";
890 // then the text parameters
891 if (language != ignore_language)
892 os << "\\language " << language->lang() << '\n';
893 os << "\\inputencoding " << inputenc
894 << "\n\\fontencoding " << fontenc
895 << "\n\\font_roman " << fontsRoman
896 << "\n\\font_sans " << fontsSans
897 << "\n\\font_typewriter " << fontsTypewriter
898 << "\n\\font_default_family " << fontsDefaultFamily
899 << "\n\\use_xetex " << convert<string>(useXetex)
900 << "\n\\font_sc " << convert<string>(fontsSC)
901 << "\n\\font_osf " << convert<string>(fontsOSF)
902 << "\n\\font_sf_scale " << fontsSansScale
903 << "\n\\font_tt_scale " << fontsTypewriterScale
905 if (!fontsCJK.empty()) {
906 os << "\\font_cjk " << fontsCJK << '\n';
908 os << "\n\\graphics " << graphicsDriver << '\n';
909 os << "\\default_output_format " << defaultOutputFormat << '\n';
910 os << "\\bibtex_command " << bibtex_command << '\n';
911 os << "\\index_command " << index_command << '\n';
913 if (!float_placement.empty()) {
914 os << "\\float_placement " << float_placement << '\n';
916 os << "\\paperfontsize " << fontsize << '\n';
918 spacing().writeFile(os);
919 pdfoptions().writeFile(os);
921 os << "\\papersize " << string_papersize[papersize]
922 << "\n\\use_geometry " << convert<string>(use_geometry)
923 << "\n\\use_amsmath " << use_amsmath
924 << "\n\\use_esint " << use_esint
925 << "\n\\use_mhchem " << use_mhchem
926 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
927 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
928 << "\n\\use_indices " << convert<string>(use_indices)
929 << "\n\\paperorientation " << string_orientation[orientation]
930 << "\n\\suppress_date " << convert<string>(suppress_date)
932 if (isbackgroundcolor == true)
933 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
934 if (isfontcolor == true)
935 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
936 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
937 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
939 BranchList::const_iterator it = branchlist().begin();
940 BranchList::const_iterator end = branchlist().end();
941 for (; it != end; ++it) {
942 os << "\\branch " << to_utf8(it->branch())
943 << "\n\\selected " << it->isSelected()
944 << "\n\\filename_suffix " << it->hasFilenameSuffix()
945 << "\n\\color " << lyx::X11hexname(it->color())
950 IndicesList::const_iterator iit = indiceslist().begin();
951 IndicesList::const_iterator iend = indiceslist().end();
952 for (; iit != iend; ++iit) {
953 os << "\\index " << to_utf8(iit->index())
954 << "\n\\shortcut " << to_utf8(iit->shortcut())
955 << "\n\\color " << lyx::X11hexname(iit->color())
960 if (!paperwidth.empty())
961 os << "\\paperwidth "
962 << VSpace(paperwidth).asLyXCommand() << '\n';
963 if (!paperheight.empty())
964 os << "\\paperheight "
965 << VSpace(paperheight).asLyXCommand() << '\n';
966 if (!leftmargin.empty())
967 os << "\\leftmargin "
968 << VSpace(leftmargin).asLyXCommand() << '\n';
969 if (!topmargin.empty())
971 << VSpace(topmargin).asLyXCommand() << '\n';
972 if (!rightmargin.empty())
973 os << "\\rightmargin "
974 << VSpace(rightmargin).asLyXCommand() << '\n';
975 if (!bottommargin.empty())
976 os << "\\bottommargin "
977 << VSpace(bottommargin).asLyXCommand() << '\n';
978 if (!headheight.empty())
979 os << "\\headheight "
980 << VSpace(headheight).asLyXCommand() << '\n';
981 if (!headsep.empty())
983 << VSpace(headsep).asLyXCommand() << '\n';
984 if (!footskip.empty())
986 << VSpace(footskip).asLyXCommand() << '\n';
987 if (!columnsep.empty())
989 << VSpace(columnsep).asLyXCommand() << '\n';
990 os << "\\secnumdepth " << secnumdepth
991 << "\n\\tocdepth " << tocdepth
992 << "\n\\paragraph_separation "
993 << string_paragraph_separation[paragraph_separation];
994 if (!paragraph_separation)
995 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
997 os << "\n\\defskip " << getDefSkip().asLyXCommand();
998 os << "\n\\quotes_language "
999 << string_quotes_language[quotes_language]
1000 << "\n\\papercolumns " << columns
1001 << "\n\\papersides " << sides
1002 << "\n\\paperpagestyle " << pagestyle << '\n';
1003 if (!listings_params.empty())
1004 os << "\\listings_params \"" <<
1005 InsetListingsParams(listings_params).encodedString() << "\"\n";
1006 for (int i = 0; i < 4; ++i) {
1007 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1008 if (user_defined_bullet(i).getFont() != -1) {
1009 os << "\\bullet " << i << " "
1010 << user_defined_bullet(i).getFont() << " "
1011 << user_defined_bullet(i).getCharacter() << " "
1012 << user_defined_bullet(i).getSize() << "\n";
1016 os << "\\bulletLaTeX " << i << " \""
1017 << lyx::to_ascii(user_defined_bullet(i).getText())
1023 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n"
1024 << "\\output_changes " << convert<string>(outputChanges) << "\n"
1025 << "\\html_math_output " << html_math_output << "\n"
1026 << "\\html_be_strict " << convert<string>(html_be_strict) << "\n";
1028 os << pimpl_->authorlist;
1032 void BufferParams::validate(LaTeXFeatures & features) const
1034 features.require(documentClass().requires());
1036 if (outputChanges) {
1037 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1038 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1039 LaTeXFeatures::isAvailable("xcolor");
1041 switch (features.runparams().flavor) {
1042 case OutputParams::LATEX:
1044 features.require("ct-dvipost");
1045 features.require("dvipost");
1046 } else if (xcolorulem) {
1047 features.require("ct-xcolor-ulem");
1048 features.require("ulem");
1049 features.require("xcolor");
1051 features.require("ct-none");
1054 case OutputParams::PDFLATEX:
1055 case OutputParams::XETEX:
1057 features.require("ct-xcolor-ulem");
1058 features.require("ulem");
1059 features.require("xcolor");
1060 // improves color handling in PDF output
1061 features.require("pdfcolmk");
1063 features.require("ct-none");
1071 // Floats with 'Here definitely' as default setting.
1072 if (float_placement.find('H') != string::npos)
1073 features.require("float");
1075 // AMS Style is at document level
1076 if (use_amsmath == package_on
1077 || documentClass().provides("amsmath"))
1078 features.require("amsmath");
1079 if (use_esint == package_on)
1080 features.require("esint");
1081 if (use_mhchem == package_on)
1082 features.require("mhchem");
1084 // Document-level line spacing
1085 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1086 features.require("setspace");
1088 // the bullet shapes are buffer level not paragraph level
1089 // so they are tested here
1090 for (int i = 0; i < 4; ++i) {
1091 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1093 int const font = user_defined_bullet(i).getFont();
1095 int const c = user_defined_bullet(i).getCharacter();
1101 features.require("latexsym");
1103 } else if (font == 1) {
1104 features.require("amssymb");
1105 } else if (font >= 2 && font <= 5) {
1106 features.require("pifont");
1110 if (pdfoptions().use_hyperref) {
1111 features.require("hyperref");
1112 // due to interferences with babel and hyperref, the color package has to
1113 // be loaded after hyperref when hyperref is used with the colorlinks
1114 // option, see http://www.lyx.org/trac/ticket/5291
1115 if (pdfoptions().colorlinks)
1116 features.require("color");
1120 features.require("xetex");
1122 if (language->lang() == "vietnamese")
1123 features.require("vietnamese");
1124 else if (language->lang() == "japanese")
1125 features.require("japanese");
1129 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1130 TexRow & texrow, FileName const & filepath) const
1132 os << "\\documentclass";
1134 DocumentClass const & tclass = documentClass();
1136 ostringstream clsoptions; // the document class options.
1138 if (tokenPos(tclass.opt_fontsize(),
1139 '|', fontsize) >= 0) {
1140 // only write if existing in list (and not default)
1141 clsoptions << fontsize << "pt,";
1144 // custom, A3, B3 and B4 paper sizes need geometry
1145 bool nonstandard_papersize = papersize == PAPER_B3
1146 || papersize == PAPER_B4
1147 || papersize == PAPER_A3
1148 || papersize == PAPER_CUSTOM;
1150 if (!use_geometry) {
1151 switch (papersize) {
1153 clsoptions << "a4paper,";
1155 case PAPER_USLETTER:
1156 clsoptions << "letterpaper,";
1159 clsoptions << "a5paper,";
1162 clsoptions << "b5paper,";
1164 case PAPER_USEXECUTIVE:
1165 clsoptions << "executivepaper,";
1168 clsoptions << "legalpaper,";
1180 if (sides != tclass.sides()) {
1183 clsoptions << "oneside,";
1186 clsoptions << "twoside,";
1192 if (columns != tclass.columns()) {
1194 clsoptions << "twocolumn,";
1196 clsoptions << "onecolumn,";
1200 && orientation == ORIENTATION_LANDSCAPE)
1201 clsoptions << "landscape,";
1203 // language should be a parameter to \documentclass
1204 if (language->babel() == "hebrew"
1205 && default_language->babel() != "hebrew")
1206 // This seems necessary
1207 features.useLanguage(default_language);
1209 ostringstream language_options;
1210 bool const use_babel = features.useBabel();
1212 language_options << features.getLanguages();
1213 if (!language->babel().empty()) {
1214 if (!language_options.str().empty())
1215 language_options << ',';
1216 language_options << language->babel();
1218 // if Vietnamese is used, babel must directly be loaded
1219 // with language options, not in the class options, see
1220 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1221 size_t viet = language_options.str().find("vietnam");
1222 // viet = string::npos when not found
1223 // the same is for all other languages that are not directly supported by
1224 // babel, but where LaTeX-packages add babel support.
1225 // this is currently the case for Latvian, Lithuanian, Mongolian
1227 size_t latvian = language_options.str().find("latvian");
1228 size_t lithu = language_options.str().find("lithuanian");
1229 size_t mongo = language_options.str().find("mongolian");
1230 size_t turkmen = language_options.str().find("turkmen");
1231 // if Japanese is used, babel must directly be loaded
1232 // with language options, not in the class options, see
1233 // http://www.lyx.org/trac/ticket/4597#c4
1234 size_t japan = language_options.str().find("japanese");
1235 if (lyxrc.language_global_options && !language_options.str().empty()
1236 && viet == string::npos && japan == string::npos
1237 && latvian == string::npos && lithu == string::npos
1238 && mongo == string::npos && turkmen == string::npos)
1239 clsoptions << language_options.str() << ',';
1242 // the predefined options from the layout
1243 if (use_default_options && !tclass.options().empty())
1244 clsoptions << tclass.options() << ',';
1246 // the user-defined options
1247 if (!options.empty()) {
1248 clsoptions << options << ',';
1251 string strOptions(clsoptions.str());
1252 if (!strOptions.empty()) {
1253 strOptions = rtrim(strOptions, ",");
1255 os << '[' << from_utf8(strOptions) << ']';
1258 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1260 // end of \documentclass defs
1263 os << "\\usepackage{fontspec}\n";
1267 // font selection must be done before loading fontenc.sty
1268 string const fonts =
1269 loadFonts(fontsRoman, fontsSans,
1270 fontsTypewriter, fontsSC, fontsOSF,
1271 fontsSansScale, fontsTypewriterScale, useXetex);
1272 if (!fonts.empty()) {
1273 os << from_ascii(fonts);
1276 if (fontsDefaultFamily != "default")
1277 os << "\\renewcommand{\\familydefault}{\\"
1278 << from_ascii(fontsDefaultFamily) << "}\n";
1280 // set font encoding
1281 // for arabic_arabi and farsi we also need to load the LAE and
1283 // XeTeX works without fontenc
1284 if (font_encoding() != "default" && language->lang() != "japanese"
1286 if (language->lang() == "arabic_arabi"
1287 || language->lang() == "farsi") {
1288 os << "\\usepackage[" << from_ascii(font_encoding())
1289 << ",LFE,LAE]{fontenc}\n";
1292 os << "\\usepackage[" << from_ascii(font_encoding())
1298 // handle inputenc etc.
1299 writeEncodingPreamble(os, features, texrow);
1302 if (!features.runparams().includeall && !includedChildren_.empty()) {
1303 os << "\\includeonly{";
1304 list<string>::const_iterator it = includedChildren_.begin();
1306 for (; it != includedChildren_.end() ; ++it) {
1307 string incfile = *it;
1308 FileName inc = makeAbsPath(incfile, filepath.absFilename());
1309 string mangled = DocFileName(changeExtension(inc.absFilename(), ".tex")).
1311 if (!features.runparams().nice)
1313 // \includeonly doesn't want an extension
1314 incfile = changeExtension(incfile, string());
1315 incfile = support::latex_path(incfile);
1316 if (!incfile.empty()) {
1319 os << from_utf8(incfile);
1326 if (!listings_params.empty() || features.isRequired("listings")) {
1327 os << "\\usepackage{listings}\n";
1330 if (!listings_params.empty()) {
1332 // do not test validity because listings_params is
1333 // supposed to be valid
1335 InsetListingsParams(listings_params).separatedParams(true);
1336 // we can't support all packages, but we should load the color package
1337 if (par.find("\\color", 0) != string::npos)
1338 features.require("color");
1339 os << from_utf8(par);
1340 // count the number of newlines
1341 for (size_t i = 0; i < par.size(); ++i)
1347 if (!tclass.provides("geometry")
1348 && (use_geometry || nonstandard_papersize)) {
1349 odocstringstream ods;
1350 if (!getGraphicsDriver("geometry").empty())
1351 ods << getGraphicsDriver("geometry");
1352 if (orientation == ORIENTATION_LANDSCAPE)
1353 ods << ",landscape";
1354 switch (papersize) {
1356 if (!paperwidth.empty())
1357 ods << ",paperwidth="
1358 << from_ascii(paperwidth);
1359 if (!paperheight.empty())
1360 ods << ",paperheight="
1361 << from_ascii(paperheight);
1363 case PAPER_USLETTER:
1364 ods << ",letterpaper";
1367 ods << ",legalpaper";
1369 case PAPER_USEXECUTIVE:
1370 ods << ",executivepaper";
1391 // default papersize ie PAPER_DEFAULT
1392 switch (lyxrc.default_papersize) {
1393 case PAPER_DEFAULT: // keep compiler happy
1394 case PAPER_USLETTER:
1395 ods << ",letterpaper";
1398 ods << ",legalpaper";
1400 case PAPER_USEXECUTIVE:
1401 ods << ",executivepaper";
1421 docstring const g_options = trim(ods.str(), ",");
1422 os << "\\usepackage";
1423 if (!g_options.empty())
1424 os << '[' << g_options << ']';
1425 os << "{geometry}\n";
1427 os << "\\geometry{verbose";
1428 if (!topmargin.empty())
1429 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1430 if (!bottommargin.empty())
1431 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1432 if (!leftmargin.empty())
1433 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1434 if (!rightmargin.empty())
1435 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1436 if (!headheight.empty())
1437 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1438 if (!headsep.empty())
1439 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1440 if (!footskip.empty())
1441 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1442 if (!columnsep.empty())
1443 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1446 } else if (orientation == ORIENTATION_LANDSCAPE) {
1447 features.require("papersize");
1450 if (tokenPos(tclass.opt_pagestyle(),
1451 '|', pagestyle) >= 0) {
1452 if (pagestyle == "fancy") {
1453 os << "\\usepackage{fancyhdr}\n";
1456 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1460 // only output when the background color is not default
1461 if (isbackgroundcolor == true) {
1462 // only require color here, the background color will be defined
1463 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1465 features.require("color");
1466 features.require("pagecolor");
1469 // only output when the font color is not default
1470 if (isfontcolor == true) {
1471 // only require color here, the font color will be defined
1472 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1474 features.require("color");
1475 features.require("fontcolor");
1478 // Only if class has a ToC hierarchy
1479 if (tclass.hasTocLevels()) {
1480 if (secnumdepth != tclass.secnumdepth()) {
1481 os << "\\setcounter{secnumdepth}{"
1486 if (tocdepth != tclass.tocdepth()) {
1487 os << "\\setcounter{tocdepth}{"
1494 if (paragraph_separation) {
1495 // when skip separation
1496 switch (getDefSkip().kind()) {
1497 case VSpace::SMALLSKIP:
1498 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1500 case VSpace::MEDSKIP:
1501 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1503 case VSpace::BIGSKIP:
1504 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1506 case VSpace::LENGTH:
1507 os << "\\setlength{\\parskip}{"
1508 << from_utf8(getDefSkip().length().asLatexString())
1511 default: // should never happen // Then delete it.
1512 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1516 os << "\\setlength{\\parindent}{0pt}\n";
1519 // when separation by indentation
1520 // only output something when a width is given
1521 if (getIndentation().asLyXCommand() != "default") {
1522 os << "\\setlength{\\parindent}{"
1523 << from_utf8(getIndentation().asLatexCommand())
1529 // Now insert the LyX specific LaTeX commands...
1530 docstring lyxpreamble;
1532 // due to interferences with babel and hyperref, the color package has to
1533 // be loaded (when it is not already loaded) before babel when hyperref
1534 // is used with the colorlinks option, see
1535 // http://www.lyx.org/trac/ticket/5291
1536 // we decided therefore to load color always before babel, see
1537 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1538 lyxpreamble += from_ascii(features.getColorOptions());
1540 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1542 && (features.isRequired("jurabib")
1543 || features.isRequired("hyperref")
1544 || features.isRequired("vietnamese")
1545 || features.isRequired("japanese") ) ) {
1547 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1548 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1551 // The optional packages;
1552 lyxpreamble += from_ascii(features.getPackages());
1554 // Additional Indices
1555 if (features.isRequired("splitidx")) {
1556 IndicesList::const_iterator iit = indiceslist().begin();
1557 IndicesList::const_iterator iend = indiceslist().end();
1558 for (; iit != iend; ++iit) {
1559 lyxpreamble += "\\newindex[";
1560 lyxpreamble += iit->index();
1561 lyxpreamble += "]{";
1562 lyxpreamble += iit->shortcut();
1563 lyxpreamble += "}\n";
1568 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1571 // * Hyperref manual: "Make sure it comes last of your loaded
1572 // packages, to give it a fighting chance of not being over-written,
1573 // since its job is to redefine many LaTeX commands."
1574 // * Email from Heiko Oberdiek: "It is usually better to load babel
1575 // before hyperref. Then hyperref has a chance to detect babel.
1576 // * Has to be loaded before the "LyX specific LaTeX commands" to
1577 // avoid errors with algorithm floats.
1578 // use hyperref explicitly if it is required
1579 if (features.isRequired("hyperref")) {
1580 // pass what we have to stream here, since we need
1581 // to access the stream itself in PDFOptions.
1585 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1587 OutputParams tmp_params = features.runparams();
1588 lines += pdfoptions().writeLaTeX(tmp_params, os,
1589 documentClass().provides("hyperref"));
1590 texrow.newlines(lines);
1591 // set back for the rest
1592 lyxpreamble.clear();
1595 // Will be surrounded by \makeatletter and \makeatother when not empty
1596 docstring atlyxpreamble;
1598 // Some macros LyX will need
1599 docstring tmppreamble(features.getMacros());
1601 if (!tmppreamble.empty())
1602 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1603 "LyX specific LaTeX commands.\n"
1604 + tmppreamble + '\n';
1606 // the text class specific preamble
1607 tmppreamble = features.getTClassPreamble();
1608 if (!tmppreamble.empty())
1609 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1610 "Textclass specific LaTeX commands.\n"
1611 + tmppreamble + '\n';
1613 // suppress date if selected
1614 // use \@ifundefined because we cannot be sure that every document class
1615 // has a \date command
1617 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1619 /* the user-defined preamble */
1620 if (!containsOnly(preamble, " \n\t"))
1622 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1623 "User specified LaTeX commands.\n"
1624 + from_utf8(preamble) + '\n';
1626 // subfig loads internally the LaTeX package "caption". As
1627 // caption is a very popular package, users will load it in
1628 // the preamble. Therefore we must load subfig behind the
1629 // user-defined preamble and check if the caption package was
1630 // loaded or not. For the case that caption is loaded before
1631 // subfig, there is the subfig option "caption=false". This
1632 // option also works when a koma-script class is used and
1633 // koma's own caption commands are used instead of caption. We
1634 // use \PassOptionsToPackage here because the user could have
1635 // already loaded subfig in the preamble.
1636 if (features.isRequired("subfig")) {
1637 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1638 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1639 "\\usepackage{subfig}\n";
1642 // Itemize bullet settings need to be last in case the user
1643 // defines their own bullets that use a package included
1644 // in the user-defined preamble -- ARRae
1645 // Actually it has to be done much later than that
1646 // since some packages like frenchb make modifications
1647 // at \begin{document} time -- JMarc
1648 docstring bullets_def;
1649 for (int i = 0; i < 4; ++i) {
1650 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1651 if (bullets_def.empty())
1652 bullets_def += "\\AtBeginDocument{\n";
1653 bullets_def += " \\def\\labelitemi";
1655 // `i' is one less than the item to modify
1662 bullets_def += "ii";
1668 bullets_def += '{' +
1669 user_defined_bullet(i).getText()
1674 if (!bullets_def.empty())
1675 atlyxpreamble += bullets_def + "}\n\n";
1677 if (!atlyxpreamble.empty())
1678 lyxpreamble += "\n\\makeatletter\n"
1679 + atlyxpreamble + "\\makeatother\n\n";
1681 // We try to load babel late, in case it interferes with other packages.
1682 // Jurabib and Hyperref have to be called after babel, though.
1683 if (use_babel && !features.isRequired("jurabib")
1684 && !features.isRequired("hyperref")
1685 && !features.isRequired("vietnamese")
1686 && !features.isRequired("japanese")) {
1688 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1689 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1692 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1693 if (!i18npreamble.empty())
1694 lyxpreamble += i18npreamble + '\n';
1697 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1698 texrow.newlines(nlines);
1702 // these packages (xunicode, for that matter) need to be loaded at least
1703 // after amsmath, amssymb, esint and the other packages that provide
1706 os << "\\usepackage{xunicode}\n";
1708 os << "\\usepackage{xltxtra}\n";
1715 void BufferParams::useClassDefaults()
1717 DocumentClass const & tclass = documentClass();
1719 sides = tclass.sides();
1720 columns = tclass.columns();
1721 pagestyle = tclass.pagestyle();
1722 use_default_options = true;
1723 // Only if class has a ToC hierarchy
1724 if (tclass.hasTocLevels()) {
1725 secnumdepth = tclass.secnumdepth();
1726 tocdepth = tclass.tocdepth();
1731 bool BufferParams::hasClassDefaults() const
1733 DocumentClass const & tclass = documentClass();
1735 return sides == tclass.sides()
1736 && columns == tclass.columns()
1737 && pagestyle == tclass.pagestyle()
1738 && use_default_options
1739 && secnumdepth == tclass.secnumdepth()
1740 && tocdepth == tclass.tocdepth();
1744 DocumentClass const & BufferParams::documentClass() const
1750 DocumentClass const * BufferParams::documentClassPtr() const {
1755 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1756 // evil, but this function is evil
1757 doc_class_ = const_cast<DocumentClass *>(tc);
1761 bool BufferParams::setBaseClass(string const & classname)
1763 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1764 LayoutFileList & bcl = LayoutFileList::get();
1765 if (!bcl.haveClass(classname)) {
1767 bformat(_("The document class %1$s could not be found. "
1768 "A default textclass with default layouts will be used. "
1769 "LyX might not be able to produce output unless a correct "
1770 "textclass is selected from the document settings dialog."),
1771 from_utf8(classname));
1772 frontend::Alert::error(_("Document class not found"), s);
1773 bcl.addEmptyClass(classname);
1776 bool const success = bcl[classname].load();
1779 bformat(_("The document class %1$s could not be loaded."),
1780 from_utf8(classname));
1781 frontend::Alert::error(_("Could not load class"), s);
1785 pimpl_->baseClass_ = classname;
1786 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1791 LayoutFile const * BufferParams::baseClass() const
1793 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1794 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1800 LayoutFileIndex const & BufferParams::baseClassID() const
1802 return pimpl_->baseClass_;
1806 void BufferParams::makeDocumentClass()
1811 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1813 if (!local_layout.empty()) {
1814 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1815 docstring const msg = _("Error reading internal layout information");
1816 frontend::Alert::warning(_("Read Error"), msg);
1822 bool BufferParams::moduleCanBeAdded(string const & modName) const
1824 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1828 bool BufferParams::addLayoutModule(string const & modName)
1830 LayoutModuleList::const_iterator it = layoutModules_.begin();
1831 LayoutModuleList::const_iterator end = layoutModules_.end();
1832 for (; it != end; it++)
1835 layoutModules_.push_back(modName);
1840 Font const BufferParams::getFont() const
1842 FontInfo f = documentClass().defaultfont();
1843 if (fontsDefaultFamily == "rmdefault")
1844 f.setFamily(ROMAN_FAMILY);
1845 else if (fontsDefaultFamily == "sfdefault")
1846 f.setFamily(SANS_FAMILY);
1847 else if (fontsDefaultFamily == "ttdefault")
1848 f.setFamily(TYPEWRITER_FAMILY);
1849 return Font(f, language);
1853 void BufferParams::readPreamble(Lexer & lex)
1855 if (lex.getString() != "\\begin_preamble")
1856 lyxerr << "Error (BufferParams::readPreamble):"
1857 "consistency check failed." << endl;
1859 preamble = lex.getLongString("\\end_preamble");
1863 void BufferParams::readLocalLayout(Lexer & lex)
1865 if (lex.getString() != "\\begin_local_layout")
1866 lyxerr << "Error (BufferParams::readLocalLayout):"
1867 "consistency check failed." << endl;
1869 local_layout = lex.getLongString("\\end_local_layout");
1873 void BufferParams::readLanguage(Lexer & lex)
1875 if (!lex.next()) return;
1877 string const tmptok = lex.getString();
1879 // check if tmptok is part of tex_babel in tex-defs.h
1880 language = languages.getLanguage(tmptok);
1882 // Language tmptok was not found
1883 language = default_language;
1884 lyxerr << "Warning: Setting language `"
1885 << tmptok << "' to `" << language->lang()
1891 void BufferParams::readGraphicsDriver(Lexer & lex)
1896 string const tmptok = lex.getString();
1897 // check if tmptok is part of tex_graphics in tex_defs.h
1900 string const test = tex_graphics[n++];
1902 if (test == tmptok) {
1903 graphicsDriver = tmptok;
1908 "Warning: graphics driver `$$Token' not recognized!\n"
1909 " Setting graphics driver to `default'.\n");
1910 graphicsDriver = "default";
1917 void BufferParams::readBullets(Lexer & lex)
1922 int const index = lex.getInteger();
1924 int temp_int = lex.getInteger();
1925 user_defined_bullet(index).setFont(temp_int);
1926 temp_bullet(index).setFont(temp_int);
1928 user_defined_bullet(index).setCharacter(temp_int);
1929 temp_bullet(index).setCharacter(temp_int);
1931 user_defined_bullet(index).setSize(temp_int);
1932 temp_bullet(index).setSize(temp_int);
1936 void BufferParams::readBulletsLaTeX(Lexer & lex)
1938 // The bullet class should be able to read this.
1941 int const index = lex.getInteger();
1943 docstring const temp_str = lex.getDocString();
1945 user_defined_bullet(index).setText(temp_str);
1946 temp_bullet(index).setText(temp_str);
1950 void BufferParams::readModules(Lexer & lex)
1952 if (!lex.eatLine()) {
1953 lyxerr << "Error (BufferParams::readModules):"
1954 "Unexpected end of input." << endl;
1958 string mod = lex.getString();
1959 if (mod == "\\end_modules")
1961 addLayoutModule(mod);
1967 void BufferParams::readRemovedModules(Lexer & lex)
1969 if (!lex.eatLine()) {
1970 lyxerr << "Error (BufferParams::readRemovedModules):"
1971 "Unexpected end of input." << endl;
1975 string mod = lex.getString();
1976 if (mod == "\\end_removed_modules")
1978 removedModules_.push_back(mod);
1981 // now we want to remove any removed modules that were previously
1982 // added. normally, that will be because default modules were added in
1983 // setBaseClass(), which gets called when \textclass is read at the
1984 // start of the read.
1985 list<string>::const_iterator rit = removedModules_.begin();
1986 list<string>::const_iterator const ren = removedModules_.end();
1987 for (; rit != ren; rit++) {
1988 LayoutModuleList::iterator const mit = layoutModules_.begin();
1989 LayoutModuleList::iterator const men = layoutModules_.end();
1990 LayoutModuleList::iterator found = find(mit, men, *rit);
1993 layoutModules_.erase(found);
1998 void BufferParams::readIncludeonly(Lexer & lex)
2000 if (!lex.eatLine()) {
2001 lyxerr << "Error (BufferParams::readIncludeonly):"
2002 "Unexpected end of input." << endl;
2006 string child = lex.getString();
2007 if (child == "\\end_includeonly")
2009 includedChildren_.push_back(child);
2015 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2017 char real_papersize = papersize;
2018 if (real_papersize == PAPER_DEFAULT)
2019 real_papersize = lyxrc.default_papersize;
2021 switch (real_papersize) {
2023 // could be anything, so don't guess
2025 case PAPER_CUSTOM: {
2026 if (purpose == XDVI && !paperwidth.empty() &&
2027 !paperheight.empty()) {
2028 // heightxwidth<unit>
2029 string first = paperwidth;
2030 string second = paperheight;
2031 if (orientation == ORIENTATION_LANDSCAPE)
2034 return first.erase(first.length() - 2)
2046 // dvips and dvipdfm do not know this
2047 if (purpose == DVIPS || purpose == DVIPDFM)
2051 // dvipdfm does not know this
2052 if (purpose == DVIPDFM)
2056 // dvipdfm does not know this
2057 if (purpose == DVIPDFM)
2060 case PAPER_USEXECUTIVE:
2061 // dvipdfm does not know this
2062 if (purpose == DVIPDFM)
2067 case PAPER_USLETTER:
2069 if (purpose == XDVI)
2076 string const BufferParams::dvips_options() const
2081 && papersize == PAPER_CUSTOM
2082 && !lyxrc.print_paper_dimension_flag.empty()
2083 && !paperwidth.empty()
2084 && !paperheight.empty()) {
2085 // using a custom papersize
2086 result = lyxrc.print_paper_dimension_flag;
2087 result += ' ' + paperwidth;
2088 result += ',' + paperheight;
2090 string const paper_option = paperSizeName(DVIPS);
2091 if (!paper_option.empty() && (paper_option != "letter" ||
2092 orientation != ORIENTATION_LANDSCAPE)) {
2093 // dvips won't accept -t letter -t landscape.
2094 // In all other cases, include the paper size
2096 result = lyxrc.print_paper_flag;
2097 result += ' ' + paper_option;
2100 if (orientation == ORIENTATION_LANDSCAPE &&
2101 papersize != PAPER_CUSTOM)
2102 result += ' ' + lyxrc.print_landscape_flag;
2107 string const BufferParams::font_encoding() const
2109 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2113 string BufferParams::babelCall(string const & lang_opts) const
2115 string lang_pack = lyxrc.language_package;
2116 if (lang_pack != "\\usepackage{babel}")
2118 // suppress the babel call when there is no babel language defined
2119 // for the document language in the lib/languages file and if no
2120 // other languages are used (lang_opts is then empty)
2121 if (lang_opts.empty())
2123 // If Vietnamese is used, babel must directly be loaded with the
2124 // language options, see
2125 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2126 size_t viet = lang_opts.find("vietnam");
2127 // viet = string::npos when not found
2128 // the same is for all other languages that are not directly supported by
2129 // babel, but where LaTeX-packages add babel support.
2130 // this is currently the case for Latvian, Lithuanian, Mongolian
2132 size_t latvian = lang_opts.find("latvian");
2133 size_t lithu = lang_opts.find("lithuanian");
2134 size_t mongo = lang_opts.find("mongolian");
2135 size_t turkmen = lang_opts.find("turkmen");
2136 // If Japanese is used, babel must directly be loaded with the
2137 // language options, see
2138 // http://www.lyx.org/trac/ticket/4597#c4
2139 size_t japan = lang_opts.find("japanese");
2140 if (!lyxrc.language_global_options || viet != string::npos
2141 || japan != string::npos || latvian != string::npos
2142 || lithu != string::npos || mongo != string::npos
2143 || turkmen != string::npos)
2144 return "\\usepackage[" + lang_opts + "]{babel}";
2149 docstring BufferParams::getGraphicsDriver(string const & package) const
2153 if (package == "geometry") {
2154 if (graphicsDriver == "dvips"
2155 || graphicsDriver == "dvipdfm"
2156 || graphicsDriver == "pdftex"
2157 || graphicsDriver == "vtex")
2158 result = from_ascii(graphicsDriver);
2159 else if (graphicsDriver == "dvipdfmx")
2160 result = from_ascii("dvipdfm");
2167 void BufferParams::writeEncodingPreamble(odocstream & os,
2168 LaTeXFeatures & features, TexRow & texrow) const
2172 if (inputenc == "auto") {
2173 string const doc_encoding =
2174 language->encoding()->latexName();
2175 Encoding::Package const package =
2176 language->encoding()->package();
2178 // Create a list with all the input encodings used
2180 set<string> encodings =
2181 features.getEncodingSet(doc_encoding);
2183 // If the "japanese" package (i.e. pLaTeX) is used,
2184 // inputenc must be omitted.
2185 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2186 if (package == Encoding::japanese)
2187 features.require("japanese");
2189 if ((!encodings.empty() || package == Encoding::inputenc)
2190 && !features.isRequired("japanese")) {
2191 os << "\\usepackage[";
2192 set<string>::const_iterator it = encodings.begin();
2193 set<string>::const_iterator const end = encodings.end();
2195 os << from_ascii(*it);
2198 for (; it != end; ++it)
2199 os << ',' << from_ascii(*it);
2200 if (package == Encoding::inputenc) {
2201 if (!encodings.empty())
2203 os << from_ascii(doc_encoding);
2205 os << "]{inputenc}\n";
2208 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2209 if (language->encoding()->name() == "utf8-cjk"
2210 && LaTeXFeatures::isAvailable("CJKutf8"))
2211 os << "\\usepackage{CJKutf8}\n";
2213 os << "\\usepackage{CJK}\n";
2216 } else if (inputenc != "default") {
2217 switch (encoding().package()) {
2218 case Encoding::none:
2219 case Encoding::japanese:
2221 case Encoding::inputenc:
2222 // do not load inputenc if japanese is used
2223 if (features.isRequired("japanese"))
2225 os << "\\usepackage[" << from_ascii(inputenc)
2230 if (encoding().name() == "utf8-cjk"
2231 && LaTeXFeatures::isAvailable("CJKutf8"))
2232 os << "\\usepackage{CJKutf8}\n";
2234 os << "\\usepackage{CJK}\n";
2240 // The encoding "armscii8" (for Armenian) is only available when
2241 // the package "armtex" is loaded.
2242 if (language->encoding()->latexName() == "armscii8"
2243 || inputenc == "armscii8") {
2244 os << "\\usepackage{armtex}\n";
2250 string const BufferParams::parseFontName(string const & name) const
2252 string mangled = name;
2253 size_t const idx = mangled.find('[');
2254 if (idx == string::npos || idx == 0)
2257 return mangled.substr(0, idx - 1);
2261 string const BufferParams::loadFonts(string const & rm,
2262 string const & sf, string const & tt,
2263 bool const & sc, bool const & osf,
2264 int const & sfscale, int const & ttscale,
2265 bool const & xetex) const
2267 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2268 several packages have been replaced by others, that might not
2269 be installed on every system. We have to take care for that
2270 (see psnfss.pdf). We try to support all psnfss fonts as well
2271 as the fonts that have become de facto standard in the LaTeX
2272 world (e.g. Latin Modern). We do not support obsolete fonts
2273 (like PSLatex). In general, it should be possible to mix any
2274 rm font with any sf or tt font, respectively. (JSpitzm)
2276 -- separate math fonts.
2279 if (rm == "default" && sf == "default" && tt == "default")
2286 if (rm != "default")
2287 os << "\\setmainfont[Mapping=tex-text]{"
2288 << parseFontName(rm) << "}\n";
2289 if (sf != "default") {
2290 string const sans = parseFontName(sf);
2292 os << "\\setsansfont[Scale="
2293 << float(sfscale) / 100
2294 << ",Mapping=tex-text]{"
2297 os << "\\setsansfont[Mapping=tex-text]{"
2300 if (tt != "default") {
2301 string const mono = parseFontName(tt);
2303 os << "\\setmonofont[Scale="
2304 << float(sfscale) / 100
2308 os << "\\setmonofont[Mapping=tex-text]{"
2312 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2317 // Computer Modern (must be explicitly selectable -- there might be classes
2318 // that define a different default font!
2320 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2321 // osf for Computer Modern needs eco.sty
2323 os << "\\usepackage{eco}\n";
2325 // Latin Modern Roman
2326 else if (rm == "lmodern")
2327 os << "\\usepackage{lmodern}\n";
2329 else if (rm == "ae") {
2330 // not needed when using OT1 font encoding.
2331 if (font_encoding() != "default")
2332 os << "\\usepackage{ae,aecompl}\n";
2335 else if (rm == "times") {
2336 // try to load the best available package
2337 if (LaTeXFeatures::isAvailable("mathptmx"))
2338 os << "\\usepackage{mathptmx}\n";
2339 else if (LaTeXFeatures::isAvailable("mathptm"))
2340 os << "\\usepackage{mathptm}\n";
2342 os << "\\usepackage{times}\n";
2345 else if (rm == "palatino") {
2346 // try to load the best available package
2347 if (LaTeXFeatures::isAvailable("mathpazo")) {
2348 os << "\\usepackage";
2354 // "osf" includes "sc"!
2358 os << "{mathpazo}\n";
2360 else if (LaTeXFeatures::isAvailable("mathpple"))
2361 os << "\\usepackage{mathpple}\n";
2363 os << "\\usepackage{palatino}\n";
2366 else if (rm == "utopia") {
2367 // fourier supersedes utopia.sty, but does
2368 // not work with OT1 encoding.
2369 if (LaTeXFeatures::isAvailable("fourier")
2370 && font_encoding() != "default") {
2371 os << "\\usepackage";
2382 os << "{fourier}\n";
2385 os << "\\usepackage{utopia}\n";
2387 // Bera (complete fontset)
2388 else if (rm == "bera" && sf == "default" && tt == "default")
2389 os << "\\usepackage{bera}\n";
2391 else if (rm != "default")
2392 os << "\\usepackage" << "{" << rm << "}\n";
2395 // Helvetica, Bera Sans
2396 if (sf == "helvet" || sf == "berasans") {
2398 os << "\\usepackage[scaled=" << float(sfscale) / 100
2399 << "]{" << sf << "}\n";
2401 os << "\\usepackage{" << sf << "}\n";
2404 else if (sf == "avant")
2405 os << "\\usepackage{" << sf << "}\n";
2406 // Computer Modern, Latin Modern, CM Bright
2407 else if (sf != "default")
2408 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2410 // monospaced/typewriter
2411 // Courier, LuxiMono
2412 if (tt == "luximono" || tt == "beramono") {
2414 os << "\\usepackage[scaled=" << float(ttscale) / 100
2415 << "]{" << tt << "}\n";
2417 os << "\\usepackage{" << tt << "}\n";
2420 else if (tt == "courier" )
2421 os << "\\usepackage{" << tt << "}\n";
2422 // Computer Modern, Latin Modern, CM Bright
2423 else if (tt != "default")
2424 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2430 Encoding const & BufferParams::encoding() const
2433 return *(encodings.fromLaTeXName("utf8-plain"));
2434 if (inputenc == "auto" || inputenc == "default")
2435 return *language->encoding();
2436 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2439 LYXERR0("Unknown inputenc value `" << inputenc
2440 << "'. Using `auto' instead.");
2441 return *language->encoding();
2445 CiteEngine BufferParams::citeEngine() const
2447 // FIXME the class should provide the numerical/
2448 // authoryear choice
2449 if (documentClass().provides("natbib")
2450 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2451 return ENGINE_NATBIB_AUTHORYEAR;
2452 return cite_engine_;
2456 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2458 cite_engine_ = cite_engine;