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 boxbgcolor = lyx::rgbFromHexName("#ff0000");
379 compressed = lyxrc.save_compressed;
380 for (int iter = 0; iter < 4; ++iter) {
381 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
382 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
385 indiceslist().addDefault(B_("Index"));
386 html_be_strict = true;
387 html_math_output = MathML;
391 docstring BufferParams::B_(string const & l10n) const
393 LASSERT(language, /**/);
394 return getMessages(language->code()).get(l10n);
398 AuthorList & BufferParams::authors()
400 return pimpl_->authorlist;
404 AuthorList const & BufferParams::authors() const
406 return pimpl_->authorlist;
410 BranchList & BufferParams::branchlist()
412 return pimpl_->branchlist;
416 BranchList const & BufferParams::branchlist() const
418 return pimpl_->branchlist;
422 IndicesList & BufferParams::indiceslist()
424 return pimpl_->indiceslist;
428 IndicesList const & BufferParams::indiceslist() const
430 return pimpl_->indiceslist;
434 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
436 LASSERT(index < 4, /**/);
437 return pimpl_->temp_bullets[index];
441 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
443 LASSERT(index < 4, /**/);
444 return pimpl_->temp_bullets[index];
448 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
450 LASSERT(index < 4, /**/);
451 return pimpl_->user_defined_bullets[index];
455 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
457 LASSERT(index < 4, /**/);
458 return pimpl_->user_defined_bullets[index];
462 Spacing & BufferParams::spacing()
464 return pimpl_->spacing;
468 Spacing const & BufferParams::spacing() const
470 return pimpl_->spacing;
474 PDFOptions & BufferParams::pdfoptions()
476 return pimpl_->pdfoptions;
480 PDFOptions const & BufferParams::pdfoptions() const
482 return pimpl_->pdfoptions;
486 HSpace const & BufferParams::getIndentation() const
488 return pimpl_->indentation;
492 void BufferParams::setIndentation(HSpace const & indent)
494 pimpl_->indentation = indent;
498 VSpace const & BufferParams::getDefSkip() const
500 return pimpl_->defskip;
504 void BufferParams::setDefSkip(VSpace const & vs)
506 pimpl_->defskip = vs;
510 string BufferParams::readToken(Lexer & lex, string const & token,
511 FileName const & filepath)
513 if (token == "\\textclass") {
515 string const classname = lex.getString();
516 // if there exists a local layout file, ignore the system one
517 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
519 LayoutFileList & bcl = LayoutFileList::get();
520 if (tcp.empty() && !filepath.empty())
521 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
525 setBaseClass(classname);
526 // We assume that a tex class exists for local or unknown layouts so this warning
527 // will only be given for system layouts.
528 if (!baseClass()->isTeXClassAvailable()) {
530 translateIfPossible(from_utf8(baseClass()->description()));
531 docstring const msg =
532 bformat(_("The document class requested\n"
534 "requires external files that are not available.\n"
535 "The document class can still be used, but LyX\n"
536 "will not be able to produce output until the\n"
537 "following prerequisites are installed:\n"
539 "See section 3.1.2.2 of the User's Guide for\n"
540 "more information."),
541 desc, from_utf8(baseClass()->prerequisites()));
542 frontend::Alert::warning(_("Document class not available"),
545 } else if (token == "\\begin_preamble") {
547 } else if (token == "\\begin_local_layout") {
548 readLocalLayout(lex);
549 } else if (token == "\\begin_modules") {
551 } else if (token == "\\begin_removed_modules") {
552 readRemovedModules(lex);
553 } else if (token == "\\begin_includeonly") {
554 readIncludeonly(lex);
555 } else if (token == "\\maintain_unincluded_children") {
556 lex >> maintain_unincluded_children;
557 } else if (token == "\\options") {
559 options = lex.getString();
560 } else if (token == "\\use_default_options") {
561 lex >> use_default_options;
562 } else if (token == "\\master") {
564 master = lex.getString();
565 } else if (token == "\\suppress_date") {
566 lex >> suppress_date;
567 } else if (token == "\\language") {
569 } else if (token == "\\inputencoding") {
571 } else if (token == "\\graphics") {
572 readGraphicsDriver(lex);
573 } else if (token == "\\default_output_format") {
574 lex >> defaultOutputFormat;
575 } else if (token == "\\bibtex_command") {
577 bibtex_command = lex.getString();
578 } else if (token == "\\index_command") {
580 index_command = lex.getString();
581 } else if (token == "\\fontencoding") {
583 fontenc = lex.getString();
584 } else if (token == "\\font_roman") {
586 fontsRoman = lex.getString();
587 } else if (token == "\\font_sans") {
589 fontsSans = lex.getString();
590 } else if (token == "\\font_typewriter") {
592 fontsTypewriter = lex.getString();
593 } else if (token == "\\font_default_family") {
594 lex >> fontsDefaultFamily;
595 } else if (token == "\\use_xetex") {
597 } else if (token == "\\font_sc") {
599 } else if (token == "\\font_osf") {
601 } else if (token == "\\font_sf_scale") {
602 lex >> fontsSansScale;
603 } else if (token == "\\font_tt_scale") {
604 lex >> fontsTypewriterScale;
605 } else if (token == "\\font_cjk") {
607 } else if (token == "\\paragraph_separation") {
610 paragraph_separation = parseptranslator().find(parsep);
611 } else if (token == "\\paragraph_indentation") {
613 string indentation = lex.getString();
614 pimpl_->indentation = HSpace(indentation);
615 } else if (token == "\\defskip") {
617 string defskip = lex.getString();
618 if (defskip == "defskip")
621 pimpl_->defskip = VSpace(defskip);
622 } else if (token == "\\quotes_language") {
625 quotes_language = quoteslangtranslator().find(quotes_lang);
626 } else if (token == "\\papersize") {
629 papersize = papersizetranslator().find(ppsize);
630 } else if (token == "\\use_geometry") {
632 } else if (token == "\\use_amsmath") {
635 use_amsmath = packagetranslator().find(use_ams);
636 } else if (token == "\\use_esint") {
639 use_esint = packagetranslator().find(useesint);
640 } else if (token == "\\use_mhchem") {
643 use_mhchem = packagetranslator().find(usemhchem);
644 } else if (token == "\\cite_engine") {
647 cite_engine_ = citeenginetranslator().find(engine);
648 } else if (token == "\\use_bibtopic") {
650 } else if (token == "\\use_indices") {
652 } else if (token == "\\tracking_changes") {
654 } else if (token == "\\output_changes") {
655 lex >> outputChanges;
656 } else if (token == "\\branch") {
658 docstring branch = lex.getDocString();
659 branchlist().add(branch);
662 string const tok = lex.getString();
663 if (tok == "\\end_branch")
665 Branch * branch_ptr = branchlist().find(branch);
666 if (tok == "\\selected") {
669 branch_ptr->setSelected(lex.getInteger());
671 if (tok == "\\filename_suffix") {
674 branch_ptr->setFilenameSuffix(lex.getInteger());
676 if (tok == "\\color") {
678 string color = lex.getString();
680 branch_ptr->setColor(color);
681 // Update also the Color table:
683 color = lcolor.getX11Name(Color_background);
685 lcolor.setColor(to_utf8(branch), color);
688 } else if (token == "\\index") {
690 docstring index = lex.getDocString();
692 indiceslist().add(index);
695 string const tok = lex.getString();
696 if (tok == "\\end_index")
698 Index * index_ptr = indiceslist().find(index);
699 if (tok == "\\shortcut") {
701 shortcut = lex.getDocString();
703 index_ptr->setShortcut(shortcut);
705 if (tok == "\\color") {
707 string color = lex.getString();
709 index_ptr->setColor(color);
710 // Update also the Color table:
712 color = lcolor.getX11Name(Color_background);
714 if (!shortcut.empty())
715 lcolor.setColor(to_utf8(shortcut), color);
718 } else if (token == "\\author") {
720 istringstream ss(lex.getString());
723 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
724 } else if (token == "\\paperorientation") {
727 orientation = paperorientationtranslator().find(orient);
728 } else if (token == "\\backgroundcolor") {
730 backgroundcolor = lyx::rgbFromHexName(lex.getString());
731 isbackgroundcolor = true;
732 } else if (token == "\\fontcolor") {
734 fontcolor = lyx::rgbFromHexName(lex.getString());
736 } else if (token == "\\notefontcolor") {
738 string color = lex.getString();
739 notefontcolor = lyx::rgbFromHexName(color);
740 } else if (token == "\\boxbgcolor") {
742 string color = lex.getString();
743 boxbgcolor = lyx::rgbFromHexName(color);
744 } else if (token == "\\paperwidth") {
746 } else if (token == "\\paperheight") {
748 } else if (token == "\\leftmargin") {
750 } else if (token == "\\topmargin") {
752 } else if (token == "\\rightmargin") {
754 } else if (token == "\\bottommargin") {
756 } else if (token == "\\headheight") {
758 } else if (token == "\\headsep") {
760 } else if (token == "\\footskip") {
762 } else if (token == "\\columnsep") {
764 } else if (token == "\\paperfontsize") {
766 } else if (token == "\\papercolumns") {
768 } else if (token == "\\listings_params") {
771 listings_params = InsetListingsParams(par).params();
772 } else if (token == "\\papersides") {
775 sides = sidestranslator().find(psides);
776 } else if (token == "\\paperpagestyle") {
778 } else if (token == "\\bullet") {
780 } else if (token == "\\bulletLaTeX") {
781 readBulletsLaTeX(lex);
782 } else if (token == "\\secnumdepth") {
784 } else if (token == "\\tocdepth") {
786 } else if (token == "\\spacing") {
790 if (nspacing == "other") {
793 spacing().set(spacetranslator().find(nspacing), tmp_val);
794 } else if (token == "\\float_placement") {
795 lex >> float_placement;
797 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
798 string toktmp = pdfoptions().readToken(lex, token);
799 if (!toktmp.empty()) {
800 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
804 } else if (token == "\\html_math_output") {
807 html_math_output = static_cast<MathOutput>(temp);
808 } else if (token == "\\html_be_strict") {
809 lex >> html_be_strict;
811 lyxerr << "BufferParams::readToken(): Unknown token: " <<
820 void BufferParams::writeFile(ostream & os) const
822 // The top of the file is written by the buffer.
823 // Prints out the buffer info into the .lyx file given by file
826 os << "\\textclass " << baseClass()->name() << '\n';
829 if (!preamble.empty()) {
830 // remove '\n' from the end of preamble
831 string const tmppreamble = rtrim(preamble, "\n");
832 os << "\\begin_preamble\n"
834 << "\n\\end_preamble\n";
838 if (!options.empty()) {
839 os << "\\options " << options << '\n';
842 // use the class options defined in the layout?
843 os << "\\use_default_options "
844 << convert<string>(use_default_options) << "\n";
846 // the master document
847 if (!master.empty()) {
848 os << "\\master " << master << '\n';
852 if (!removedModules_.empty()) {
853 os << "\\begin_removed_modules" << '\n';
854 list<string>::const_iterator it = removedModules_.begin();
855 list<string>::const_iterator en = removedModules_.end();
856 for (; it != en; it++)
858 os << "\\end_removed_modules" << '\n';
862 if (!layoutModules_.empty()) {
863 os << "\\begin_modules" << '\n';
864 LayoutModuleList::const_iterator it = layoutModules_.begin();
865 LayoutModuleList::const_iterator en = layoutModules_.end();
866 for (; it != en; it++)
868 os << "\\end_modules" << '\n';
872 if (!includedChildren_.empty()) {
873 os << "\\begin_includeonly" << '\n';
874 list<string>::const_iterator it = includedChildren_.begin();
875 list<string>::const_iterator en = includedChildren_.end();
876 for (; it != en; it++)
878 os << "\\end_includeonly" << '\n';
880 os << "\\maintain_unincluded_children "
881 << convert<string>(maintain_unincluded_children) << '\n';
883 // local layout information
884 if (!local_layout.empty()) {
885 // remove '\n' from the end
886 string const tmplocal = rtrim(local_layout, "\n");
887 os << "\\begin_local_layout\n"
889 << "\n\\end_local_layout\n";
892 // then the text parameters
893 if (language != ignore_language)
894 os << "\\language " << language->lang() << '\n';
895 os << "\\inputencoding " << inputenc
896 << "\n\\fontencoding " << fontenc
897 << "\n\\font_roman " << fontsRoman
898 << "\n\\font_sans " << fontsSans
899 << "\n\\font_typewriter " << fontsTypewriter
900 << "\n\\font_default_family " << fontsDefaultFamily
901 << "\n\\use_xetex " << convert<string>(useXetex)
902 << "\n\\font_sc " << convert<string>(fontsSC)
903 << "\n\\font_osf " << convert<string>(fontsOSF)
904 << "\n\\font_sf_scale " << fontsSansScale
905 << "\n\\font_tt_scale " << fontsTypewriterScale
907 if (!fontsCJK.empty()) {
908 os << "\\font_cjk " << fontsCJK << '\n';
910 os << "\n\\graphics " << graphicsDriver << '\n';
911 os << "\\default_output_format " << defaultOutputFormat << '\n';
912 os << "\\bibtex_command " << bibtex_command << '\n';
913 os << "\\index_command " << index_command << '\n';
915 if (!float_placement.empty()) {
916 os << "\\float_placement " << float_placement << '\n';
918 os << "\\paperfontsize " << fontsize << '\n';
920 spacing().writeFile(os);
921 pdfoptions().writeFile(os);
923 os << "\\papersize " << string_papersize[papersize]
924 << "\n\\use_geometry " << convert<string>(use_geometry)
925 << "\n\\use_amsmath " << use_amsmath
926 << "\n\\use_esint " << use_esint
927 << "\n\\use_mhchem " << use_mhchem
928 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
929 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
930 << "\n\\use_indices " << convert<string>(use_indices)
931 << "\n\\paperorientation " << string_orientation[orientation]
932 << "\n\\suppress_date " << convert<string>(suppress_date)
934 if (isbackgroundcolor == true)
935 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
936 if (isfontcolor == true)
937 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
938 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
939 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
940 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
941 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
943 BranchList::const_iterator it = branchlist().begin();
944 BranchList::const_iterator end = branchlist().end();
945 for (; it != end; ++it) {
946 os << "\\branch " << to_utf8(it->branch())
947 << "\n\\selected " << it->isSelected()
948 << "\n\\filename_suffix " << it->hasFilenameSuffix()
949 << "\n\\color " << lyx::X11hexname(it->color())
954 IndicesList::const_iterator iit = indiceslist().begin();
955 IndicesList::const_iterator iend = indiceslist().end();
956 for (; iit != iend; ++iit) {
957 os << "\\index " << to_utf8(iit->index())
958 << "\n\\shortcut " << to_utf8(iit->shortcut())
959 << "\n\\color " << lyx::X11hexname(iit->color())
964 if (!paperwidth.empty())
965 os << "\\paperwidth "
966 << VSpace(paperwidth).asLyXCommand() << '\n';
967 if (!paperheight.empty())
968 os << "\\paperheight "
969 << VSpace(paperheight).asLyXCommand() << '\n';
970 if (!leftmargin.empty())
971 os << "\\leftmargin "
972 << VSpace(leftmargin).asLyXCommand() << '\n';
973 if (!topmargin.empty())
975 << VSpace(topmargin).asLyXCommand() << '\n';
976 if (!rightmargin.empty())
977 os << "\\rightmargin "
978 << VSpace(rightmargin).asLyXCommand() << '\n';
979 if (!bottommargin.empty())
980 os << "\\bottommargin "
981 << VSpace(bottommargin).asLyXCommand() << '\n';
982 if (!headheight.empty())
983 os << "\\headheight "
984 << VSpace(headheight).asLyXCommand() << '\n';
985 if (!headsep.empty())
987 << VSpace(headsep).asLyXCommand() << '\n';
988 if (!footskip.empty())
990 << VSpace(footskip).asLyXCommand() << '\n';
991 if (!columnsep.empty())
993 << VSpace(columnsep).asLyXCommand() << '\n';
994 os << "\\secnumdepth " << secnumdepth
995 << "\n\\tocdepth " << tocdepth
996 << "\n\\paragraph_separation "
997 << string_paragraph_separation[paragraph_separation];
998 if (!paragraph_separation)
999 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1001 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1002 os << "\n\\quotes_language "
1003 << string_quotes_language[quotes_language]
1004 << "\n\\papercolumns " << columns
1005 << "\n\\papersides " << sides
1006 << "\n\\paperpagestyle " << pagestyle << '\n';
1007 if (!listings_params.empty())
1008 os << "\\listings_params \"" <<
1009 InsetListingsParams(listings_params).encodedString() << "\"\n";
1010 for (int i = 0; i < 4; ++i) {
1011 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1012 if (user_defined_bullet(i).getFont() != -1) {
1013 os << "\\bullet " << i << " "
1014 << user_defined_bullet(i).getFont() << " "
1015 << user_defined_bullet(i).getCharacter() << " "
1016 << user_defined_bullet(i).getSize() << "\n";
1020 os << "\\bulletLaTeX " << i << " \""
1021 << lyx::to_ascii(user_defined_bullet(i).getText())
1027 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n"
1028 << "\\output_changes " << convert<string>(outputChanges) << "\n"
1029 << "\\html_math_output " << html_math_output << "\n"
1030 << "\\html_be_strict " << convert<string>(html_be_strict) << "\n";
1032 os << pimpl_->authorlist;
1036 void BufferParams::validate(LaTeXFeatures & features) const
1038 features.require(documentClass().requires());
1040 if (outputChanges) {
1041 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1042 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1043 LaTeXFeatures::isAvailable("xcolor");
1045 switch (features.runparams().flavor) {
1046 case OutputParams::LATEX:
1048 features.require("ct-dvipost");
1049 features.require("dvipost");
1050 } else if (xcolorulem) {
1051 features.require("ct-xcolor-ulem");
1052 features.require("ulem");
1053 features.require("xcolor");
1055 features.require("ct-none");
1058 case OutputParams::PDFLATEX:
1059 case OutputParams::XETEX:
1061 features.require("ct-xcolor-ulem");
1062 features.require("ulem");
1063 features.require("xcolor");
1064 // improves color handling in PDF output
1065 features.require("pdfcolmk");
1067 features.require("ct-none");
1075 // Floats with 'Here definitely' as default setting.
1076 if (float_placement.find('H') != string::npos)
1077 features.require("float");
1079 // AMS Style is at document level
1080 if (use_amsmath == package_on
1081 || documentClass().provides("amsmath"))
1082 features.require("amsmath");
1083 if (use_esint == package_on)
1084 features.require("esint");
1085 if (use_mhchem == package_on)
1086 features.require("mhchem");
1088 // Document-level line spacing
1089 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1090 features.require("setspace");
1092 // the bullet shapes are buffer level not paragraph level
1093 // so they are tested here
1094 for (int i = 0; i < 4; ++i) {
1095 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1097 int const font = user_defined_bullet(i).getFont();
1099 int const c = user_defined_bullet(i).getCharacter();
1105 features.require("latexsym");
1107 } else if (font == 1) {
1108 features.require("amssymb");
1109 } else if (font >= 2 && font <= 5) {
1110 features.require("pifont");
1114 if (pdfoptions().use_hyperref) {
1115 features.require("hyperref");
1116 // due to interferences with babel and hyperref, the color package has to
1117 // be loaded after hyperref when hyperref is used with the colorlinks
1118 // option, see http://www.lyx.org/trac/ticket/5291
1119 if (pdfoptions().colorlinks)
1120 features.require("color");
1124 features.require("xetex");
1126 if (language->lang() == "vietnamese")
1127 features.require("vietnamese");
1128 else if (language->lang() == "japanese")
1129 features.require("japanese");
1133 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1134 TexRow & texrow, FileName const & filepath) const
1136 os << "\\documentclass";
1138 DocumentClass const & tclass = documentClass();
1140 ostringstream clsoptions; // the document class options.
1142 if (tokenPos(tclass.opt_fontsize(),
1143 '|', fontsize) >= 0) {
1144 // only write if existing in list (and not default)
1145 clsoptions << fontsize << "pt,";
1148 // custom, A3, B3 and B4 paper sizes need geometry
1149 bool nonstandard_papersize = papersize == PAPER_B3
1150 || papersize == PAPER_B4
1151 || papersize == PAPER_A3
1152 || papersize == PAPER_CUSTOM;
1154 if (!use_geometry) {
1155 switch (papersize) {
1157 clsoptions << "a4paper,";
1159 case PAPER_USLETTER:
1160 clsoptions << "letterpaper,";
1163 clsoptions << "a5paper,";
1166 clsoptions << "b5paper,";
1168 case PAPER_USEXECUTIVE:
1169 clsoptions << "executivepaper,";
1172 clsoptions << "legalpaper,";
1184 if (sides != tclass.sides()) {
1187 clsoptions << "oneside,";
1190 clsoptions << "twoside,";
1196 if (columns != tclass.columns()) {
1198 clsoptions << "twocolumn,";
1200 clsoptions << "onecolumn,";
1204 && orientation == ORIENTATION_LANDSCAPE)
1205 clsoptions << "landscape,";
1207 // language should be a parameter to \documentclass
1208 if (language->babel() == "hebrew"
1209 && default_language->babel() != "hebrew")
1210 // This seems necessary
1211 features.useLanguage(default_language);
1213 ostringstream language_options;
1214 bool const use_babel = features.useBabel();
1216 language_options << features.getLanguages();
1217 if (!language->babel().empty()) {
1218 if (!language_options.str().empty())
1219 language_options << ',';
1220 language_options << language->babel();
1222 // if Vietnamese is used, babel must directly be loaded
1223 // with language options, not in the class options, see
1224 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1225 size_t viet = language_options.str().find("vietnam");
1226 // viet = string::npos when not found
1227 // the same is for all other languages that are not directly supported by
1228 // babel, but where LaTeX-packages add babel support.
1229 // this is currently the case for Latvian, Lithuanian, Mongolian
1231 size_t latvian = language_options.str().find("latvian");
1232 size_t lithu = language_options.str().find("lithuanian");
1233 size_t mongo = language_options.str().find("mongolian");
1234 size_t turkmen = language_options.str().find("turkmen");
1235 // if Japanese is used, babel must directly be loaded
1236 // with language options, not in the class options, see
1237 // http://www.lyx.org/trac/ticket/4597#c4
1238 size_t japan = language_options.str().find("japanese");
1239 if (lyxrc.language_global_options && !language_options.str().empty()
1240 && viet == string::npos && japan == string::npos
1241 && latvian == string::npos && lithu == string::npos
1242 && mongo == string::npos && turkmen == string::npos)
1243 clsoptions << language_options.str() << ',';
1246 // the predefined options from the layout
1247 if (use_default_options && !tclass.options().empty())
1248 clsoptions << tclass.options() << ',';
1250 // the user-defined options
1251 if (!options.empty()) {
1252 clsoptions << options << ',';
1255 string strOptions(clsoptions.str());
1256 if (!strOptions.empty()) {
1257 strOptions = rtrim(strOptions, ",");
1259 os << '[' << from_utf8(strOptions) << ']';
1262 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1264 // end of \documentclass defs
1267 os << "\\usepackage{fontspec}\n";
1271 // font selection must be done before loading fontenc.sty
1272 string const fonts =
1273 loadFonts(fontsRoman, fontsSans,
1274 fontsTypewriter, fontsSC, fontsOSF,
1275 fontsSansScale, fontsTypewriterScale, useXetex);
1276 if (!fonts.empty()) {
1277 os << from_ascii(fonts);
1280 if (fontsDefaultFamily != "default")
1281 os << "\\renewcommand{\\familydefault}{\\"
1282 << from_ascii(fontsDefaultFamily) << "}\n";
1284 // set font encoding
1285 // for arabic_arabi and farsi we also need to load the LAE and
1287 // XeTeX works without fontenc
1288 if (font_encoding() != "default" && language->lang() != "japanese"
1290 if (language->lang() == "arabic_arabi"
1291 || language->lang() == "farsi") {
1292 os << "\\usepackage[" << from_ascii(font_encoding())
1293 << ",LFE,LAE]{fontenc}\n";
1296 os << "\\usepackage[" << from_ascii(font_encoding())
1302 // handle inputenc etc.
1303 writeEncodingPreamble(os, features, texrow);
1306 if (!features.runparams().includeall && !includedChildren_.empty()) {
1307 os << "\\includeonly{";
1308 list<string>::const_iterator it = includedChildren_.begin();
1310 for (; it != includedChildren_.end() ; ++it) {
1311 string incfile = *it;
1312 FileName inc = makeAbsPath(incfile, filepath.absFilename());
1313 string mangled = DocFileName(changeExtension(inc.absFilename(), ".tex")).
1315 if (!features.runparams().nice)
1317 // \includeonly doesn't want an extension
1318 incfile = changeExtension(incfile, string());
1319 incfile = support::latex_path(incfile);
1320 if (!incfile.empty()) {
1323 os << from_utf8(incfile);
1330 if (!listings_params.empty() || features.isRequired("listings")) {
1331 os << "\\usepackage{listings}\n";
1334 if (!listings_params.empty()) {
1336 // do not test validity because listings_params is
1337 // supposed to be valid
1339 InsetListingsParams(listings_params).separatedParams(true);
1340 // we can't support all packages, but we should load the color package
1341 if (par.find("\\color", 0) != string::npos)
1342 features.require("color");
1343 os << from_utf8(par);
1344 // count the number of newlines
1345 for (size_t i = 0; i < par.size(); ++i)
1351 if (!tclass.provides("geometry")
1352 && (use_geometry || nonstandard_papersize)) {
1353 odocstringstream ods;
1354 if (!getGraphicsDriver("geometry").empty())
1355 ods << getGraphicsDriver("geometry");
1356 if (orientation == ORIENTATION_LANDSCAPE)
1357 ods << ",landscape";
1358 switch (papersize) {
1360 if (!paperwidth.empty())
1361 ods << ",paperwidth="
1362 << from_ascii(paperwidth);
1363 if (!paperheight.empty())
1364 ods << ",paperheight="
1365 << from_ascii(paperheight);
1367 case PAPER_USLETTER:
1368 ods << ",letterpaper";
1371 ods << ",legalpaper";
1373 case PAPER_USEXECUTIVE:
1374 ods << ",executivepaper";
1395 // default papersize ie PAPER_DEFAULT
1396 switch (lyxrc.default_papersize) {
1397 case PAPER_DEFAULT: // keep compiler happy
1398 case PAPER_USLETTER:
1399 ods << ",letterpaper";
1402 ods << ",legalpaper";
1404 case PAPER_USEXECUTIVE:
1405 ods << ",executivepaper";
1425 docstring const g_options = trim(ods.str(), ",");
1426 os << "\\usepackage";
1427 if (!g_options.empty())
1428 os << '[' << g_options << ']';
1429 os << "{geometry}\n";
1431 os << "\\geometry{verbose";
1432 if (!topmargin.empty())
1433 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1434 if (!bottommargin.empty())
1435 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1436 if (!leftmargin.empty())
1437 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1438 if (!rightmargin.empty())
1439 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1440 if (!headheight.empty())
1441 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1442 if (!headsep.empty())
1443 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1444 if (!footskip.empty())
1445 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1446 if (!columnsep.empty())
1447 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1450 } else if (orientation == ORIENTATION_LANDSCAPE) {
1451 features.require("papersize");
1454 if (tokenPos(tclass.opt_pagestyle(),
1455 '|', pagestyle) >= 0) {
1456 if (pagestyle == "fancy") {
1457 os << "\\usepackage{fancyhdr}\n";
1460 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1464 // only output when the background color is not default
1465 if (isbackgroundcolor == true) {
1466 // only require color here, the background color will be defined
1467 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1469 features.require("color");
1470 features.require("pagecolor");
1473 // only output when the font color is not default
1474 if (isfontcolor == true) {
1475 // only require color here, the font color will be defined
1476 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1478 features.require("color");
1479 features.require("fontcolor");
1482 // Only if class has a ToC hierarchy
1483 if (tclass.hasTocLevels()) {
1484 if (secnumdepth != tclass.secnumdepth()) {
1485 os << "\\setcounter{secnumdepth}{"
1490 if (tocdepth != tclass.tocdepth()) {
1491 os << "\\setcounter{tocdepth}{"
1498 if (paragraph_separation) {
1499 // when skip separation
1500 switch (getDefSkip().kind()) {
1501 case VSpace::SMALLSKIP:
1502 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1504 case VSpace::MEDSKIP:
1505 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1507 case VSpace::BIGSKIP:
1508 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1510 case VSpace::LENGTH:
1511 os << "\\setlength{\\parskip}{"
1512 << from_utf8(getDefSkip().length().asLatexString())
1515 default: // should never happen // Then delete it.
1516 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1520 os << "\\setlength{\\parindent}{0pt}\n";
1523 // when separation by indentation
1524 // only output something when a width is given
1525 if (getIndentation().asLyXCommand() != "default") {
1526 os << "\\setlength{\\parindent}{"
1527 << from_utf8(getIndentation().asLatexCommand())
1533 // Now insert the LyX specific LaTeX commands...
1534 docstring lyxpreamble;
1536 // due to interferences with babel and hyperref, the color package has to
1537 // be loaded (when it is not already loaded) before babel when hyperref
1538 // is used with the colorlinks option, see
1539 // http://www.lyx.org/trac/ticket/5291
1540 // we decided therefore to load color always before babel, see
1541 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1542 lyxpreamble += from_ascii(features.getColorOptions());
1544 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1546 && (features.isRequired("jurabib")
1547 || features.isRequired("hyperref")
1548 || features.isRequired("vietnamese")
1549 || features.isRequired("japanese") ) ) {
1551 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1552 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1555 // The optional packages;
1556 lyxpreamble += from_ascii(features.getPackages());
1558 // Additional Indices
1559 if (features.isRequired("splitidx")) {
1560 IndicesList::const_iterator iit = indiceslist().begin();
1561 IndicesList::const_iterator iend = indiceslist().end();
1562 for (; iit != iend; ++iit) {
1563 lyxpreamble += "\\newindex[";
1564 lyxpreamble += iit->index();
1565 lyxpreamble += "]{";
1566 lyxpreamble += iit->shortcut();
1567 lyxpreamble += "}\n";
1572 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1575 // * Hyperref manual: "Make sure it comes last of your loaded
1576 // packages, to give it a fighting chance of not being over-written,
1577 // since its job is to redefine many LaTeX commands."
1578 // * Email from Heiko Oberdiek: "It is usually better to load babel
1579 // before hyperref. Then hyperref has a chance to detect babel.
1580 // * Has to be loaded before the "LyX specific LaTeX commands" to
1581 // avoid errors with algorithm floats.
1582 // use hyperref explicitly if it is required
1583 if (features.isRequired("hyperref")) {
1584 // pass what we have to stream here, since we need
1585 // to access the stream itself in PDFOptions.
1589 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1591 OutputParams tmp_params = features.runparams();
1592 lines += pdfoptions().writeLaTeX(tmp_params, os,
1593 documentClass().provides("hyperref"));
1594 texrow.newlines(lines);
1595 // set back for the rest
1596 lyxpreamble.clear();
1599 // Will be surrounded by \makeatletter and \makeatother when not empty
1600 docstring atlyxpreamble;
1602 // Some macros LyX will need
1603 docstring tmppreamble(features.getMacros());
1605 if (!tmppreamble.empty())
1606 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1607 "LyX specific LaTeX commands.\n"
1608 + tmppreamble + '\n';
1610 // the text class specific preamble
1611 tmppreamble = features.getTClassPreamble();
1612 if (!tmppreamble.empty())
1613 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1614 "Textclass specific LaTeX commands.\n"
1615 + tmppreamble + '\n';
1617 // suppress date if selected
1618 // use \@ifundefined because we cannot be sure that every document class
1619 // has a \date command
1621 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1623 /* the user-defined preamble */
1624 if (!containsOnly(preamble, " \n\t"))
1626 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1627 "User specified LaTeX commands.\n"
1628 + from_utf8(preamble) + '\n';
1630 // subfig loads internally the LaTeX package "caption". As
1631 // caption is a very popular package, users will load it in
1632 // the preamble. Therefore we must load subfig behind the
1633 // user-defined preamble and check if the caption package was
1634 // loaded or not. For the case that caption is loaded before
1635 // subfig, there is the subfig option "caption=false". This
1636 // option also works when a koma-script class is used and
1637 // koma's own caption commands are used instead of caption. We
1638 // use \PassOptionsToPackage here because the user could have
1639 // already loaded subfig in the preamble.
1640 if (features.isRequired("subfig")) {
1641 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1642 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1643 "\\usepackage{subfig}\n";
1646 // Itemize bullet settings need to be last in case the user
1647 // defines their own bullets that use a package included
1648 // in the user-defined preamble -- ARRae
1649 // Actually it has to be done much later than that
1650 // since some packages like frenchb make modifications
1651 // at \begin{document} time -- JMarc
1652 docstring bullets_def;
1653 for (int i = 0; i < 4; ++i) {
1654 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1655 if (bullets_def.empty())
1656 bullets_def += "\\AtBeginDocument{\n";
1657 bullets_def += " \\def\\labelitemi";
1659 // `i' is one less than the item to modify
1666 bullets_def += "ii";
1672 bullets_def += '{' +
1673 user_defined_bullet(i).getText()
1678 if (!bullets_def.empty())
1679 atlyxpreamble += bullets_def + "}\n\n";
1681 if (!atlyxpreamble.empty())
1682 lyxpreamble += "\n\\makeatletter\n"
1683 + atlyxpreamble + "\\makeatother\n\n";
1685 // We try to load babel late, in case it interferes with other packages.
1686 // Jurabib and Hyperref have to be called after babel, though.
1687 if (use_babel && !features.isRequired("jurabib")
1688 && !features.isRequired("hyperref")
1689 && !features.isRequired("vietnamese")
1690 && !features.isRequired("japanese")) {
1692 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1693 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1696 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1697 if (!i18npreamble.empty())
1698 lyxpreamble += i18npreamble + '\n';
1701 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1702 texrow.newlines(nlines);
1706 // these packages (xunicode, for that matter) need to be loaded at least
1707 // after amsmath, amssymb, esint and the other packages that provide
1710 os << "\\usepackage{xunicode}\n";
1712 os << "\\usepackage{xltxtra}\n";
1719 void BufferParams::useClassDefaults()
1721 DocumentClass const & tclass = documentClass();
1723 sides = tclass.sides();
1724 columns = tclass.columns();
1725 pagestyle = tclass.pagestyle();
1726 use_default_options = true;
1727 // Only if class has a ToC hierarchy
1728 if (tclass.hasTocLevels()) {
1729 secnumdepth = tclass.secnumdepth();
1730 tocdepth = tclass.tocdepth();
1735 bool BufferParams::hasClassDefaults() const
1737 DocumentClass const & tclass = documentClass();
1739 return sides == tclass.sides()
1740 && columns == tclass.columns()
1741 && pagestyle == tclass.pagestyle()
1742 && use_default_options
1743 && secnumdepth == tclass.secnumdepth()
1744 && tocdepth == tclass.tocdepth();
1748 DocumentClass const & BufferParams::documentClass() const
1754 DocumentClass const * BufferParams::documentClassPtr() const {
1759 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1760 // evil, but this function is evil
1761 doc_class_ = const_cast<DocumentClass *>(tc);
1765 bool BufferParams::setBaseClass(string const & classname)
1767 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1768 LayoutFileList & bcl = LayoutFileList::get();
1769 if (!bcl.haveClass(classname)) {
1771 bformat(_("The layout file:\n"
1773 "could not be found. A default textclass with default\n"
1774 "layouts will be used. LyX will not be able to produce\n"
1776 from_utf8(classname));
1777 frontend::Alert::error(_("Document class not found"), s);
1778 bcl.addEmptyClass(classname);
1781 bool const success = bcl[classname].load();
1784 bformat(_("Due to some error in it, the layout file:\n"
1786 "could not be loaded. A default textclass with default\n"
1787 "layouts will be used. LyX will not be able to produce\n"
1789 from_utf8(classname));
1790 frontend::Alert::error(_("Could not load class"), s);
1791 bcl.addEmptyClass(classname);
1794 pimpl_->baseClass_ = classname;
1795 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1800 LayoutFile const * BufferParams::baseClass() const
1802 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1803 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1809 LayoutFileIndex const & BufferParams::baseClassID() const
1811 return pimpl_->baseClass_;
1815 void BufferParams::makeDocumentClass()
1820 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1822 if (!local_layout.empty()) {
1823 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1824 docstring const msg = _("Error reading internal layout information");
1825 frontend::Alert::warning(_("Read Error"), msg);
1831 bool BufferParams::moduleCanBeAdded(string const & modName) const
1833 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1837 bool BufferParams::addLayoutModule(string const & modName)
1839 LayoutModuleList::const_iterator it = layoutModules_.begin();
1840 LayoutModuleList::const_iterator end = layoutModules_.end();
1841 for (; it != end; it++)
1844 layoutModules_.push_back(modName);
1849 Font const BufferParams::getFont() const
1851 FontInfo f = documentClass().defaultfont();
1852 if (fontsDefaultFamily == "rmdefault")
1853 f.setFamily(ROMAN_FAMILY);
1854 else if (fontsDefaultFamily == "sfdefault")
1855 f.setFamily(SANS_FAMILY);
1856 else if (fontsDefaultFamily == "ttdefault")
1857 f.setFamily(TYPEWRITER_FAMILY);
1858 return Font(f, language);
1862 void BufferParams::readPreamble(Lexer & lex)
1864 if (lex.getString() != "\\begin_preamble")
1865 lyxerr << "Error (BufferParams::readPreamble):"
1866 "consistency check failed." << endl;
1868 preamble = lex.getLongString("\\end_preamble");
1872 void BufferParams::readLocalLayout(Lexer & lex)
1874 if (lex.getString() != "\\begin_local_layout")
1875 lyxerr << "Error (BufferParams::readLocalLayout):"
1876 "consistency check failed." << endl;
1878 local_layout = lex.getLongString("\\end_local_layout");
1882 void BufferParams::readLanguage(Lexer & lex)
1884 if (!lex.next()) return;
1886 string const tmptok = lex.getString();
1888 // check if tmptok is part of tex_babel in tex-defs.h
1889 language = languages.getLanguage(tmptok);
1891 // Language tmptok was not found
1892 language = default_language;
1893 lyxerr << "Warning: Setting language `"
1894 << tmptok << "' to `" << language->lang()
1900 void BufferParams::readGraphicsDriver(Lexer & lex)
1905 string const tmptok = lex.getString();
1906 // check if tmptok is part of tex_graphics in tex_defs.h
1909 string const test = tex_graphics[n++];
1911 if (test == tmptok) {
1912 graphicsDriver = tmptok;
1917 "Warning: graphics driver `$$Token' not recognized!\n"
1918 " Setting graphics driver to `default'.\n");
1919 graphicsDriver = "default";
1926 void BufferParams::readBullets(Lexer & lex)
1931 int const index = lex.getInteger();
1933 int temp_int = lex.getInteger();
1934 user_defined_bullet(index).setFont(temp_int);
1935 temp_bullet(index).setFont(temp_int);
1937 user_defined_bullet(index).setCharacter(temp_int);
1938 temp_bullet(index).setCharacter(temp_int);
1940 user_defined_bullet(index).setSize(temp_int);
1941 temp_bullet(index).setSize(temp_int);
1945 void BufferParams::readBulletsLaTeX(Lexer & lex)
1947 // The bullet class should be able to read this.
1950 int const index = lex.getInteger();
1952 docstring const temp_str = lex.getDocString();
1954 user_defined_bullet(index).setText(temp_str);
1955 temp_bullet(index).setText(temp_str);
1959 void BufferParams::readModules(Lexer & lex)
1961 if (!lex.eatLine()) {
1962 lyxerr << "Error (BufferParams::readModules):"
1963 "Unexpected end of input." << endl;
1967 string mod = lex.getString();
1968 if (mod == "\\end_modules")
1970 addLayoutModule(mod);
1976 void BufferParams::readRemovedModules(Lexer & lex)
1978 if (!lex.eatLine()) {
1979 lyxerr << "Error (BufferParams::readRemovedModules):"
1980 "Unexpected end of input." << endl;
1984 string mod = lex.getString();
1985 if (mod == "\\end_removed_modules")
1987 removedModules_.push_back(mod);
1990 // now we want to remove any removed modules that were previously
1991 // added. normally, that will be because default modules were added in
1992 // setBaseClass(), which gets called when \textclass is read at the
1993 // start of the read.
1994 list<string>::const_iterator rit = removedModules_.begin();
1995 list<string>::const_iterator const ren = removedModules_.end();
1996 for (; rit != ren; rit++) {
1997 LayoutModuleList::iterator const mit = layoutModules_.begin();
1998 LayoutModuleList::iterator const men = layoutModules_.end();
1999 LayoutModuleList::iterator found = find(mit, men, *rit);
2002 layoutModules_.erase(found);
2007 void BufferParams::readIncludeonly(Lexer & lex)
2009 if (!lex.eatLine()) {
2010 lyxerr << "Error (BufferParams::readIncludeonly):"
2011 "Unexpected end of input." << endl;
2015 string child = lex.getString();
2016 if (child == "\\end_includeonly")
2018 includedChildren_.push_back(child);
2024 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2026 char real_papersize = papersize;
2027 if (real_papersize == PAPER_DEFAULT)
2028 real_papersize = lyxrc.default_papersize;
2030 switch (real_papersize) {
2032 // could be anything, so don't guess
2034 case PAPER_CUSTOM: {
2035 if (purpose == XDVI && !paperwidth.empty() &&
2036 !paperheight.empty()) {
2037 // heightxwidth<unit>
2038 string first = paperwidth;
2039 string second = paperheight;
2040 if (orientation == ORIENTATION_LANDSCAPE)
2043 return first.erase(first.length() - 2)
2055 // dvips and dvipdfm do not know this
2056 if (purpose == DVIPS || purpose == DVIPDFM)
2060 // dvipdfm does not know this
2061 if (purpose == DVIPDFM)
2065 // dvipdfm does not know this
2066 if (purpose == DVIPDFM)
2069 case PAPER_USEXECUTIVE:
2070 // dvipdfm does not know this
2071 if (purpose == DVIPDFM)
2076 case PAPER_USLETTER:
2078 if (purpose == XDVI)
2085 string const BufferParams::dvips_options() const
2090 && papersize == PAPER_CUSTOM
2091 && !lyxrc.print_paper_dimension_flag.empty()
2092 && !paperwidth.empty()
2093 && !paperheight.empty()) {
2094 // using a custom papersize
2095 result = lyxrc.print_paper_dimension_flag;
2096 result += ' ' + paperwidth;
2097 result += ',' + paperheight;
2099 string const paper_option = paperSizeName(DVIPS);
2100 if (!paper_option.empty() && (paper_option != "letter" ||
2101 orientation != ORIENTATION_LANDSCAPE)) {
2102 // dvips won't accept -t letter -t landscape.
2103 // In all other cases, include the paper size
2105 result = lyxrc.print_paper_flag;
2106 result += ' ' + paper_option;
2109 if (orientation == ORIENTATION_LANDSCAPE &&
2110 papersize != PAPER_CUSTOM)
2111 result += ' ' + lyxrc.print_landscape_flag;
2116 string const BufferParams::font_encoding() const
2118 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2122 string BufferParams::babelCall(string const & lang_opts) const
2124 string lang_pack = lyxrc.language_package;
2125 if (lang_pack != "\\usepackage{babel}")
2127 // suppress the babel call when there is no babel language defined
2128 // for the document language in the lib/languages file and if no
2129 // other languages are used (lang_opts is then empty)
2130 if (lang_opts.empty())
2132 // If Vietnamese is used, babel must directly be loaded with the
2133 // language options, see
2134 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2135 size_t viet = lang_opts.find("vietnam");
2136 // viet = string::npos when not found
2137 // the same is for all other languages that are not directly supported by
2138 // babel, but where LaTeX-packages add babel support.
2139 // this is currently the case for Latvian, Lithuanian, Mongolian
2141 size_t latvian = lang_opts.find("latvian");
2142 size_t lithu = lang_opts.find("lithuanian");
2143 size_t mongo = lang_opts.find("mongolian");
2144 size_t turkmen = lang_opts.find("turkmen");
2145 // If Japanese is used, babel must directly be loaded with the
2146 // language options, see
2147 // http://www.lyx.org/trac/ticket/4597#c4
2148 size_t japan = lang_opts.find("japanese");
2149 if (!lyxrc.language_global_options || viet != string::npos
2150 || japan != string::npos || latvian != string::npos
2151 || lithu != string::npos || mongo != string::npos
2152 || turkmen != string::npos)
2153 return "\\usepackage[" + lang_opts + "]{babel}";
2158 docstring BufferParams::getGraphicsDriver(string const & package) const
2162 if (package == "geometry") {
2163 if (graphicsDriver == "dvips"
2164 || graphicsDriver == "dvipdfm"
2165 || graphicsDriver == "pdftex"
2166 || graphicsDriver == "vtex")
2167 result = from_ascii(graphicsDriver);
2168 else if (graphicsDriver == "dvipdfmx")
2169 result = from_ascii("dvipdfm");
2176 void BufferParams::writeEncodingPreamble(odocstream & os,
2177 LaTeXFeatures & features, TexRow & texrow) const
2181 if (inputenc == "auto") {
2182 string const doc_encoding =
2183 language->encoding()->latexName();
2184 Encoding::Package const package =
2185 language->encoding()->package();
2187 // Create a list with all the input encodings used
2189 set<string> encodings =
2190 features.getEncodingSet(doc_encoding);
2192 // If the "japanese" package (i.e. pLaTeX) is used,
2193 // inputenc must be omitted.
2194 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2195 if (package == Encoding::japanese)
2196 features.require("japanese");
2198 if ((!encodings.empty() || package == Encoding::inputenc)
2199 && !features.isRequired("japanese")) {
2200 os << "\\usepackage[";
2201 set<string>::const_iterator it = encodings.begin();
2202 set<string>::const_iterator const end = encodings.end();
2204 os << from_ascii(*it);
2207 for (; it != end; ++it)
2208 os << ',' << from_ascii(*it);
2209 if (package == Encoding::inputenc) {
2210 if (!encodings.empty())
2212 os << from_ascii(doc_encoding);
2214 os << "]{inputenc}\n";
2217 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2218 if (language->encoding()->name() == "utf8-cjk"
2219 && LaTeXFeatures::isAvailable("CJKutf8"))
2220 os << "\\usepackage{CJKutf8}\n";
2222 os << "\\usepackage{CJK}\n";
2225 } else if (inputenc != "default") {
2226 switch (encoding().package()) {
2227 case Encoding::none:
2228 case Encoding::japanese:
2230 case Encoding::inputenc:
2231 // do not load inputenc if japanese is used
2232 if (features.isRequired("japanese"))
2234 os << "\\usepackage[" << from_ascii(inputenc)
2239 if (encoding().name() == "utf8-cjk"
2240 && LaTeXFeatures::isAvailable("CJKutf8"))
2241 os << "\\usepackage{CJKutf8}\n";
2243 os << "\\usepackage{CJK}\n";
2249 // The encoding "armscii8" (for Armenian) is only available when
2250 // the package "armtex" is loaded.
2251 if (language->encoding()->latexName() == "armscii8"
2252 || inputenc == "armscii8") {
2253 os << "\\usepackage{armtex}\n";
2259 string const BufferParams::parseFontName(string const & name) const
2261 string mangled = name;
2262 size_t const idx = mangled.find('[');
2263 if (idx == string::npos || idx == 0)
2266 return mangled.substr(0, idx - 1);
2270 string const BufferParams::loadFonts(string const & rm,
2271 string const & sf, string const & tt,
2272 bool const & sc, bool const & osf,
2273 int const & sfscale, int const & ttscale,
2274 bool const & xetex) const
2276 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2277 several packages have been replaced by others, that might not
2278 be installed on every system. We have to take care for that
2279 (see psnfss.pdf). We try to support all psnfss fonts as well
2280 as the fonts that have become de facto standard in the LaTeX
2281 world (e.g. Latin Modern). We do not support obsolete fonts
2282 (like PSLatex). In general, it should be possible to mix any
2283 rm font with any sf or tt font, respectively. (JSpitzm)
2285 -- separate math fonts.
2288 if (rm == "default" && sf == "default" && tt == "default")
2295 if (rm != "default")
2296 os << "\\setmainfont[Mapping=tex-text]{"
2297 << parseFontName(rm) << "}\n";
2298 if (sf != "default") {
2299 string const sans = parseFontName(sf);
2301 os << "\\setsansfont[Scale="
2302 << float(sfscale) / 100
2303 << ",Mapping=tex-text]{"
2306 os << "\\setsansfont[Mapping=tex-text]{"
2309 if (tt != "default") {
2310 string const mono = parseFontName(tt);
2312 os << "\\setmonofont[Scale="
2313 << float(sfscale) / 100
2317 os << "\\setmonofont[Mapping=tex-text]{"
2321 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2326 // Computer Modern (must be explicitly selectable -- there might be classes
2327 // that define a different default font!
2329 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2330 // osf for Computer Modern needs eco.sty
2332 os << "\\usepackage{eco}\n";
2334 // Latin Modern Roman
2335 else if (rm == "lmodern")
2336 os << "\\usepackage{lmodern}\n";
2338 else if (rm == "ae") {
2339 // not needed when using OT1 font encoding.
2340 if (font_encoding() != "default")
2341 os << "\\usepackage{ae,aecompl}\n";
2344 else if (rm == "times") {
2345 // try to load the best available package
2346 if (LaTeXFeatures::isAvailable("mathptmx"))
2347 os << "\\usepackage{mathptmx}\n";
2348 else if (LaTeXFeatures::isAvailable("mathptm"))
2349 os << "\\usepackage{mathptm}\n";
2351 os << "\\usepackage{times}\n";
2354 else if (rm == "palatino") {
2355 // try to load the best available package
2356 if (LaTeXFeatures::isAvailable("mathpazo")) {
2357 os << "\\usepackage";
2363 // "osf" includes "sc"!
2367 os << "{mathpazo}\n";
2369 else if (LaTeXFeatures::isAvailable("mathpple"))
2370 os << "\\usepackage{mathpple}\n";
2372 os << "\\usepackage{palatino}\n";
2375 else if (rm == "utopia") {
2376 // fourier supersedes utopia.sty, but does
2377 // not work with OT1 encoding.
2378 if (LaTeXFeatures::isAvailable("fourier")
2379 && font_encoding() != "default") {
2380 os << "\\usepackage";
2391 os << "{fourier}\n";
2394 os << "\\usepackage{utopia}\n";
2396 // Bera (complete fontset)
2397 else if (rm == "bera" && sf == "default" && tt == "default")
2398 os << "\\usepackage{bera}\n";
2400 else if (rm != "default")
2401 os << "\\usepackage" << "{" << rm << "}\n";
2404 // Helvetica, Bera Sans
2405 if (sf == "helvet" || sf == "berasans") {
2407 os << "\\usepackage[scaled=" << float(sfscale) / 100
2408 << "]{" << sf << "}\n";
2410 os << "\\usepackage{" << sf << "}\n";
2413 else if (sf == "avant")
2414 os << "\\usepackage{" << sf << "}\n";
2415 // Computer Modern, Latin Modern, CM Bright
2416 else if (sf != "default")
2417 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2419 // monospaced/typewriter
2420 // Courier, LuxiMono
2421 if (tt == "luximono" || tt == "beramono") {
2423 os << "\\usepackage[scaled=" << float(ttscale) / 100
2424 << "]{" << tt << "}\n";
2426 os << "\\usepackage{" << tt << "}\n";
2429 else if (tt == "courier" )
2430 os << "\\usepackage{" << tt << "}\n";
2431 // Computer Modern, Latin Modern, CM Bright
2432 else if (tt != "default")
2433 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2439 Encoding const & BufferParams::encoding() const
2442 return *(encodings.fromLaTeXName("utf8-plain"));
2443 if (inputenc == "auto" || inputenc == "default")
2444 return *language->encoding();
2445 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2448 LYXERR0("Unknown inputenc value `" << inputenc
2449 << "'. Using `auto' instead.");
2450 return *language->encoding();
2454 CiteEngine BufferParams::citeEngine() const
2456 // FIXME the class should provide the numerical/
2457 // authoryear choice
2458 if (documentClass().provides("natbib")
2459 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2460 return ENGINE_NATBIB_AUTHORYEAR;
2461 return cite_engine_;
2465 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2467 cite_engine_ = cite_engine;