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 // set the font color within LyX
741 lcolor.setColor(Color_greyedouttext, color);
742 } else if (token == "\\boxbgcolor") {
744 string color = lex.getString();
745 boxbgcolor = lyx::rgbFromHexName(color);
746 // set the font color within LyX
747 lcolor.setColor(Color_shadedbg, color);
748 } else if (token == "\\paperwidth") {
750 } else if (token == "\\paperheight") {
752 } else if (token == "\\leftmargin") {
754 } else if (token == "\\topmargin") {
756 } else if (token == "\\rightmargin") {
758 } else if (token == "\\bottommargin") {
760 } else if (token == "\\headheight") {
762 } else if (token == "\\headsep") {
764 } else if (token == "\\footskip") {
766 } else if (token == "\\columnsep") {
768 } else if (token == "\\paperfontsize") {
770 } else if (token == "\\papercolumns") {
772 } else if (token == "\\listings_params") {
775 listings_params = InsetListingsParams(par).params();
776 } else if (token == "\\papersides") {
779 sides = sidestranslator().find(psides);
780 } else if (token == "\\paperpagestyle") {
782 } else if (token == "\\bullet") {
784 } else if (token == "\\bulletLaTeX") {
785 readBulletsLaTeX(lex);
786 } else if (token == "\\secnumdepth") {
788 } else if (token == "\\tocdepth") {
790 } else if (token == "\\spacing") {
794 if (nspacing == "other") {
797 spacing().set(spacetranslator().find(nspacing), tmp_val);
798 } else if (token == "\\float_placement") {
799 lex >> float_placement;
801 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
802 string toktmp = pdfoptions().readToken(lex, token);
803 if (!toktmp.empty()) {
804 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
808 } else if (token == "\\html_math_output") {
811 html_math_output = static_cast<MathOutput>(temp);
812 } else if (token == "\\html_be_strict") {
813 lex >> html_be_strict;
815 lyxerr << "BufferParams::readToken(): Unknown token: " <<
824 void BufferParams::writeFile(ostream & os) const
826 // The top of the file is written by the buffer.
827 // Prints out the buffer info into the .lyx file given by file
830 os << "\\textclass " << baseClass()->name() << '\n';
833 if (!preamble.empty()) {
834 // remove '\n' from the end of preamble
835 string const tmppreamble = rtrim(preamble, "\n");
836 os << "\\begin_preamble\n"
838 << "\n\\end_preamble\n";
842 if (!options.empty()) {
843 os << "\\options " << options << '\n';
846 // use the class options defined in the layout?
847 os << "\\use_default_options "
848 << convert<string>(use_default_options) << "\n";
850 // the master document
851 if (!master.empty()) {
852 os << "\\master " << master << '\n';
856 if (!removedModules_.empty()) {
857 os << "\\begin_removed_modules" << '\n';
858 list<string>::const_iterator it = removedModules_.begin();
859 list<string>::const_iterator en = removedModules_.end();
860 for (; it != en; it++)
862 os << "\\end_removed_modules" << '\n';
866 if (!layoutModules_.empty()) {
867 os << "\\begin_modules" << '\n';
868 LayoutModuleList::const_iterator it = layoutModules_.begin();
869 LayoutModuleList::const_iterator en = layoutModules_.end();
870 for (; it != en; it++)
872 os << "\\end_modules" << '\n';
876 if (!includedChildren_.empty()) {
877 os << "\\begin_includeonly" << '\n';
878 list<string>::const_iterator it = includedChildren_.begin();
879 list<string>::const_iterator en = includedChildren_.end();
880 for (; it != en; it++)
882 os << "\\end_includeonly" << '\n';
884 os << "\\maintain_unincluded_children "
885 << convert<string>(maintain_unincluded_children) << '\n';
887 // local layout information
888 if (!local_layout.empty()) {
889 // remove '\n' from the end
890 string const tmplocal = rtrim(local_layout, "\n");
891 os << "\\begin_local_layout\n"
893 << "\n\\end_local_layout\n";
896 // then the text parameters
897 if (language != ignore_language)
898 os << "\\language " << language->lang() << '\n';
899 os << "\\inputencoding " << inputenc
900 << "\n\\fontencoding " << fontenc
901 << "\n\\font_roman " << fontsRoman
902 << "\n\\font_sans " << fontsSans
903 << "\n\\font_typewriter " << fontsTypewriter
904 << "\n\\font_default_family " << fontsDefaultFamily
905 << "\n\\use_xetex " << convert<string>(useXetex)
906 << "\n\\font_sc " << convert<string>(fontsSC)
907 << "\n\\font_osf " << convert<string>(fontsOSF)
908 << "\n\\font_sf_scale " << fontsSansScale
909 << "\n\\font_tt_scale " << fontsTypewriterScale
911 if (!fontsCJK.empty()) {
912 os << "\\font_cjk " << fontsCJK << '\n';
914 os << "\n\\graphics " << graphicsDriver << '\n';
915 os << "\\default_output_format " << defaultOutputFormat << '\n';
916 os << "\\bibtex_command " << bibtex_command << '\n';
917 os << "\\index_command " << index_command << '\n';
919 if (!float_placement.empty()) {
920 os << "\\float_placement " << float_placement << '\n';
922 os << "\\paperfontsize " << fontsize << '\n';
924 spacing().writeFile(os);
925 pdfoptions().writeFile(os);
927 os << "\\papersize " << string_papersize[papersize]
928 << "\n\\use_geometry " << convert<string>(use_geometry)
929 << "\n\\use_amsmath " << use_amsmath
930 << "\n\\use_esint " << use_esint
931 << "\n\\use_mhchem " << use_mhchem
932 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
933 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
934 << "\n\\use_indices " << convert<string>(use_indices)
935 << "\n\\paperorientation " << string_orientation[orientation]
936 << "\n\\suppress_date " << convert<string>(suppress_date)
938 if (isbackgroundcolor == true)
939 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
940 if (isfontcolor == true)
941 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
942 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
943 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
944 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
945 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
947 BranchList::const_iterator it = branchlist().begin();
948 BranchList::const_iterator end = branchlist().end();
949 for (; it != end; ++it) {
950 os << "\\branch " << to_utf8(it->branch())
951 << "\n\\selected " << it->isSelected()
952 << "\n\\filename_suffix " << it->hasFilenameSuffix()
953 << "\n\\color " << lyx::X11hexname(it->color())
958 IndicesList::const_iterator iit = indiceslist().begin();
959 IndicesList::const_iterator iend = indiceslist().end();
960 for (; iit != iend; ++iit) {
961 os << "\\index " << to_utf8(iit->index())
962 << "\n\\shortcut " << to_utf8(iit->shortcut())
963 << "\n\\color " << lyx::X11hexname(iit->color())
968 if (!paperwidth.empty())
969 os << "\\paperwidth "
970 << VSpace(paperwidth).asLyXCommand() << '\n';
971 if (!paperheight.empty())
972 os << "\\paperheight "
973 << VSpace(paperheight).asLyXCommand() << '\n';
974 if (!leftmargin.empty())
975 os << "\\leftmargin "
976 << VSpace(leftmargin).asLyXCommand() << '\n';
977 if (!topmargin.empty())
979 << VSpace(topmargin).asLyXCommand() << '\n';
980 if (!rightmargin.empty())
981 os << "\\rightmargin "
982 << VSpace(rightmargin).asLyXCommand() << '\n';
983 if (!bottommargin.empty())
984 os << "\\bottommargin "
985 << VSpace(bottommargin).asLyXCommand() << '\n';
986 if (!headheight.empty())
987 os << "\\headheight "
988 << VSpace(headheight).asLyXCommand() << '\n';
989 if (!headsep.empty())
991 << VSpace(headsep).asLyXCommand() << '\n';
992 if (!footskip.empty())
994 << VSpace(footskip).asLyXCommand() << '\n';
995 if (!columnsep.empty())
997 << VSpace(columnsep).asLyXCommand() << '\n';
998 os << "\\secnumdepth " << secnumdepth
999 << "\n\\tocdepth " << tocdepth
1000 << "\n\\paragraph_separation "
1001 << string_paragraph_separation[paragraph_separation];
1002 if (!paragraph_separation)
1003 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1005 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1006 os << "\n\\quotes_language "
1007 << string_quotes_language[quotes_language]
1008 << "\n\\papercolumns " << columns
1009 << "\n\\papersides " << sides
1010 << "\n\\paperpagestyle " << pagestyle << '\n';
1011 if (!listings_params.empty())
1012 os << "\\listings_params \"" <<
1013 InsetListingsParams(listings_params).encodedString() << "\"\n";
1014 for (int i = 0; i < 4; ++i) {
1015 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1016 if (user_defined_bullet(i).getFont() != -1) {
1017 os << "\\bullet " << i << " "
1018 << user_defined_bullet(i).getFont() << " "
1019 << user_defined_bullet(i).getCharacter() << " "
1020 << user_defined_bullet(i).getSize() << "\n";
1024 os << "\\bulletLaTeX " << i << " \""
1025 << lyx::to_ascii(user_defined_bullet(i).getText())
1031 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n"
1032 << "\\output_changes " << convert<string>(outputChanges) << "\n"
1033 << "\\html_math_output " << html_math_output << "\n"
1034 << "\\html_be_strict " << convert<string>(html_be_strict) << "\n";
1036 os << pimpl_->authorlist;
1040 void BufferParams::validate(LaTeXFeatures & features) const
1042 features.require(documentClass().requires());
1044 if (outputChanges) {
1045 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1046 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1047 LaTeXFeatures::isAvailable("xcolor");
1049 switch (features.runparams().flavor) {
1050 case OutputParams::LATEX:
1052 features.require("ct-dvipost");
1053 features.require("dvipost");
1054 } else if (xcolorulem) {
1055 features.require("ct-xcolor-ulem");
1056 features.require("ulem");
1057 features.require("xcolor");
1059 features.require("ct-none");
1062 case OutputParams::PDFLATEX:
1063 case OutputParams::XETEX:
1065 features.require("ct-xcolor-ulem");
1066 features.require("ulem");
1067 features.require("xcolor");
1068 // improves color handling in PDF output
1069 features.require("pdfcolmk");
1071 features.require("ct-none");
1079 // Floats with 'Here definitely' as default setting.
1080 if (float_placement.find('H') != string::npos)
1081 features.require("float");
1083 // AMS Style is at document level
1084 if (use_amsmath == package_on
1085 || documentClass().provides("amsmath"))
1086 features.require("amsmath");
1087 if (use_esint == package_on)
1088 features.require("esint");
1089 if (use_mhchem == package_on)
1090 features.require("mhchem");
1092 // Document-level line spacing
1093 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1094 features.require("setspace");
1096 // the bullet shapes are buffer level not paragraph level
1097 // so they are tested here
1098 for (int i = 0; i < 4; ++i) {
1099 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1101 int const font = user_defined_bullet(i).getFont();
1103 int const c = user_defined_bullet(i).getCharacter();
1109 features.require("latexsym");
1111 } else if (font == 1) {
1112 features.require("amssymb");
1113 } else if (font >= 2 && font <= 5) {
1114 features.require("pifont");
1118 if (pdfoptions().use_hyperref) {
1119 features.require("hyperref");
1120 // due to interferences with babel and hyperref, the color package has to
1121 // be loaded after hyperref when hyperref is used with the colorlinks
1122 // option, see http://www.lyx.org/trac/ticket/5291
1123 if (pdfoptions().colorlinks)
1124 features.require("color");
1128 features.require("xetex");
1130 if (language->lang() == "vietnamese")
1131 features.require("vietnamese");
1132 else if (language->lang() == "japanese")
1133 features.require("japanese");
1137 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1138 TexRow & texrow, FileName const & filepath) const
1140 os << "\\documentclass";
1142 DocumentClass const & tclass = documentClass();
1144 ostringstream clsoptions; // the document class options.
1146 if (tokenPos(tclass.opt_fontsize(),
1147 '|', fontsize) >= 0) {
1148 // only write if existing in list (and not default)
1149 clsoptions << fontsize << "pt,";
1152 // custom, A3, B3 and B4 paper sizes need geometry
1153 bool nonstandard_papersize = papersize == PAPER_B3
1154 || papersize == PAPER_B4
1155 || papersize == PAPER_A3
1156 || papersize == PAPER_CUSTOM;
1158 if (!use_geometry) {
1159 switch (papersize) {
1161 clsoptions << "a4paper,";
1163 case PAPER_USLETTER:
1164 clsoptions << "letterpaper,";
1167 clsoptions << "a5paper,";
1170 clsoptions << "b5paper,";
1172 case PAPER_USEXECUTIVE:
1173 clsoptions << "executivepaper,";
1176 clsoptions << "legalpaper,";
1188 if (sides != tclass.sides()) {
1191 clsoptions << "oneside,";
1194 clsoptions << "twoside,";
1200 if (columns != tclass.columns()) {
1202 clsoptions << "twocolumn,";
1204 clsoptions << "onecolumn,";
1208 && orientation == ORIENTATION_LANDSCAPE)
1209 clsoptions << "landscape,";
1211 // language should be a parameter to \documentclass
1212 if (language->babel() == "hebrew"
1213 && default_language->babel() != "hebrew")
1214 // This seems necessary
1215 features.useLanguage(default_language);
1217 ostringstream language_options;
1218 bool const use_babel = features.useBabel();
1220 language_options << features.getLanguages();
1221 if (!language->babel().empty()) {
1222 if (!language_options.str().empty())
1223 language_options << ',';
1224 language_options << language->babel();
1226 // if Vietnamese is used, babel must directly be loaded
1227 // with language options, not in the class options, see
1228 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1229 size_t viet = language_options.str().find("vietnam");
1230 // viet = string::npos when not found
1231 // the same is for all other languages that are not directly supported by
1232 // babel, but where LaTeX-packages add babel support.
1233 // this is currently the case for Latvian, Lithuanian, Mongolian
1235 size_t latvian = language_options.str().find("latvian");
1236 size_t lithu = language_options.str().find("lithuanian");
1237 size_t mongo = language_options.str().find("mongolian");
1238 size_t turkmen = language_options.str().find("turkmen");
1239 // if Japanese is used, babel must directly be loaded
1240 // with language options, not in the class options, see
1241 // http://www.lyx.org/trac/ticket/4597#c4
1242 size_t japan = language_options.str().find("japanese");
1243 if (lyxrc.language_global_options && !language_options.str().empty()
1244 && viet == string::npos && japan == string::npos
1245 && latvian == string::npos && lithu == string::npos
1246 && mongo == string::npos && turkmen == string::npos)
1247 clsoptions << language_options.str() << ',';
1250 // the predefined options from the layout
1251 if (use_default_options && !tclass.options().empty())
1252 clsoptions << tclass.options() << ',';
1254 // the user-defined options
1255 if (!options.empty()) {
1256 clsoptions << options << ',';
1259 string strOptions(clsoptions.str());
1260 if (!strOptions.empty()) {
1261 strOptions = rtrim(strOptions, ",");
1263 os << '[' << from_utf8(strOptions) << ']';
1266 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1268 // end of \documentclass defs
1271 os << "\\usepackage{fontspec}\n";
1275 // font selection must be done before loading fontenc.sty
1276 string const fonts =
1277 loadFonts(fontsRoman, fontsSans,
1278 fontsTypewriter, fontsSC, fontsOSF,
1279 fontsSansScale, fontsTypewriterScale, useXetex);
1280 if (!fonts.empty()) {
1281 os << from_ascii(fonts);
1284 if (fontsDefaultFamily != "default")
1285 os << "\\renewcommand{\\familydefault}{\\"
1286 << from_ascii(fontsDefaultFamily) << "}\n";
1288 // set font encoding
1289 // for arabic_arabi and farsi we also need to load the LAE and
1291 // XeTeX works without fontenc
1292 if (font_encoding() != "default" && language->lang() != "japanese"
1294 if (language->lang() == "arabic_arabi"
1295 || language->lang() == "farsi") {
1296 os << "\\usepackage[" << from_ascii(font_encoding())
1297 << ",LFE,LAE]{fontenc}\n";
1300 os << "\\usepackage[" << from_ascii(font_encoding())
1306 // handle inputenc etc.
1307 writeEncodingPreamble(os, features, texrow);
1310 if (!features.runparams().includeall && !includedChildren_.empty()) {
1311 os << "\\includeonly{";
1312 list<string>::const_iterator it = includedChildren_.begin();
1314 for (; it != includedChildren_.end() ; ++it) {
1315 string incfile = *it;
1316 FileName inc = makeAbsPath(incfile, filepath.absFilename());
1317 string mangled = DocFileName(changeExtension(inc.absFilename(), ".tex")).
1319 if (!features.runparams().nice)
1321 // \includeonly doesn't want an extension
1322 incfile = changeExtension(incfile, string());
1323 incfile = support::latex_path(incfile);
1324 if (!incfile.empty()) {
1327 os << from_utf8(incfile);
1334 if (!listings_params.empty() || features.isRequired("listings")) {
1335 os << "\\usepackage{listings}\n";
1338 if (!listings_params.empty()) {
1340 // do not test validity because listings_params is
1341 // supposed to be valid
1343 InsetListingsParams(listings_params).separatedParams(true);
1344 // we can't support all packages, but we should load the color package
1345 if (par.find("\\color", 0) != string::npos)
1346 features.require("color");
1347 os << from_utf8(par);
1348 // count the number of newlines
1349 for (size_t i = 0; i < par.size(); ++i)
1355 if (!tclass.provides("geometry")
1356 && (use_geometry || nonstandard_papersize)) {
1357 odocstringstream ods;
1358 if (!getGraphicsDriver("geometry").empty())
1359 ods << getGraphicsDriver("geometry");
1360 if (orientation == ORIENTATION_LANDSCAPE)
1361 ods << ",landscape";
1362 switch (papersize) {
1364 if (!paperwidth.empty())
1365 ods << ",paperwidth="
1366 << from_ascii(paperwidth);
1367 if (!paperheight.empty())
1368 ods << ",paperheight="
1369 << from_ascii(paperheight);
1371 case PAPER_USLETTER:
1372 ods << ",letterpaper";
1375 ods << ",legalpaper";
1377 case PAPER_USEXECUTIVE:
1378 ods << ",executivepaper";
1399 // default papersize ie PAPER_DEFAULT
1400 switch (lyxrc.default_papersize) {
1401 case PAPER_DEFAULT: // keep compiler happy
1402 case PAPER_USLETTER:
1403 ods << ",letterpaper";
1406 ods << ",legalpaper";
1408 case PAPER_USEXECUTIVE:
1409 ods << ",executivepaper";
1429 docstring const g_options = trim(ods.str(), ",");
1430 os << "\\usepackage";
1431 if (!g_options.empty())
1432 os << '[' << g_options << ']';
1433 os << "{geometry}\n";
1435 os << "\\geometry{verbose";
1436 if (!topmargin.empty())
1437 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1438 if (!bottommargin.empty())
1439 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1440 if (!leftmargin.empty())
1441 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1442 if (!rightmargin.empty())
1443 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1444 if (!headheight.empty())
1445 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1446 if (!headsep.empty())
1447 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1448 if (!footskip.empty())
1449 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1450 if (!columnsep.empty())
1451 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1454 } else if (orientation == ORIENTATION_LANDSCAPE) {
1455 features.require("papersize");
1458 if (tokenPos(tclass.opt_pagestyle(),
1459 '|', pagestyle) >= 0) {
1460 if (pagestyle == "fancy") {
1461 os << "\\usepackage{fancyhdr}\n";
1464 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1468 // only output when the background color is not default
1469 if (isbackgroundcolor == true) {
1470 // only require color here, the background color will be defined
1471 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1473 features.require("color");
1474 features.require("pagecolor");
1477 // only output when the font color is not default
1478 if (isfontcolor == true) {
1479 // only require color here, the font color will be defined
1480 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1482 features.require("color");
1483 features.require("fontcolor");
1486 // Only if class has a ToC hierarchy
1487 if (tclass.hasTocLevels()) {
1488 if (secnumdepth != tclass.secnumdepth()) {
1489 os << "\\setcounter{secnumdepth}{"
1494 if (tocdepth != tclass.tocdepth()) {
1495 os << "\\setcounter{tocdepth}{"
1502 if (paragraph_separation) {
1503 // when skip separation
1504 switch (getDefSkip().kind()) {
1505 case VSpace::SMALLSKIP:
1506 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1508 case VSpace::MEDSKIP:
1509 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1511 case VSpace::BIGSKIP:
1512 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1514 case VSpace::LENGTH:
1515 os << "\\setlength{\\parskip}{"
1516 << from_utf8(getDefSkip().length().asLatexString())
1519 default: // should never happen // Then delete it.
1520 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1524 os << "\\setlength{\\parindent}{0pt}\n";
1527 // when separation by indentation
1528 // only output something when a width is given
1529 if (getIndentation().asLyXCommand() != "default") {
1530 os << "\\setlength{\\parindent}{"
1531 << from_utf8(getIndentation().asLatexCommand())
1537 // Now insert the LyX specific LaTeX commands...
1538 docstring lyxpreamble;
1540 // due to interferences with babel and hyperref, the color package has to
1541 // be loaded (when it is not already loaded) before babel when hyperref
1542 // is used with the colorlinks option, see
1543 // http://www.lyx.org/trac/ticket/5291
1544 // we decided therefore to load color always before babel, see
1545 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1546 lyxpreamble += from_ascii(features.getColorOptions());
1548 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1550 && (features.isRequired("jurabib")
1551 || features.isRequired("hyperref")
1552 || features.isRequired("vietnamese")
1553 || features.isRequired("japanese") ) ) {
1555 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1556 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1559 // The optional packages;
1560 lyxpreamble += from_ascii(features.getPackages());
1562 // Additional Indices
1563 if (features.isRequired("splitidx")) {
1564 IndicesList::const_iterator iit = indiceslist().begin();
1565 IndicesList::const_iterator iend = indiceslist().end();
1566 for (; iit != iend; ++iit) {
1567 lyxpreamble += "\\newindex[";
1568 lyxpreamble += iit->index();
1569 lyxpreamble += "]{";
1570 lyxpreamble += iit->shortcut();
1571 lyxpreamble += "}\n";
1576 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1579 // * Hyperref manual: "Make sure it comes last of your loaded
1580 // packages, to give it a fighting chance of not being over-written,
1581 // since its job is to redefine many LaTeX commands."
1582 // * Email from Heiko Oberdiek: "It is usually better to load babel
1583 // before hyperref. Then hyperref has a chance to detect babel.
1584 // * Has to be loaded before the "LyX specific LaTeX commands" to
1585 // avoid errors with algorithm floats.
1586 // use hyperref explicitly if it is required
1587 if (features.isRequired("hyperref")) {
1588 // pass what we have to stream here, since we need
1589 // to access the stream itself in PDFOptions.
1593 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1595 OutputParams tmp_params = features.runparams();
1596 lines += pdfoptions().writeLaTeX(tmp_params, os,
1597 documentClass().provides("hyperref"));
1598 texrow.newlines(lines);
1599 // set back for the rest
1600 lyxpreamble.clear();
1603 // Will be surrounded by \makeatletter and \makeatother when not empty
1604 docstring atlyxpreamble;
1606 // Some macros LyX will need
1607 docstring tmppreamble(features.getMacros());
1609 if (!tmppreamble.empty())
1610 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1611 "LyX specific LaTeX commands.\n"
1612 + tmppreamble + '\n';
1614 // the text class specific preamble
1615 tmppreamble = features.getTClassPreamble();
1616 if (!tmppreamble.empty())
1617 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1618 "Textclass specific LaTeX commands.\n"
1619 + tmppreamble + '\n';
1621 // suppress date if selected
1622 // use \@ifundefined because we cannot be sure that every document class
1623 // has a \date command
1625 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1627 /* the user-defined preamble */
1628 if (!containsOnly(preamble, " \n\t"))
1630 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1631 "User specified LaTeX commands.\n"
1632 + from_utf8(preamble) + '\n';
1634 // subfig loads internally the LaTeX package "caption". As
1635 // caption is a very popular package, users will load it in
1636 // the preamble. Therefore we must load subfig behind the
1637 // user-defined preamble and check if the caption package was
1638 // loaded or not. For the case that caption is loaded before
1639 // subfig, there is the subfig option "caption=false". This
1640 // option also works when a koma-script class is used and
1641 // koma's own caption commands are used instead of caption. We
1642 // use \PassOptionsToPackage here because the user could have
1643 // already loaded subfig in the preamble.
1644 if (features.isRequired("subfig")) {
1645 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1646 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1647 "\\usepackage{subfig}\n";
1650 // Itemize bullet settings need to be last in case the user
1651 // defines their own bullets that use a package included
1652 // in the user-defined preamble -- ARRae
1653 // Actually it has to be done much later than that
1654 // since some packages like frenchb make modifications
1655 // at \begin{document} time -- JMarc
1656 docstring bullets_def;
1657 for (int i = 0; i < 4; ++i) {
1658 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1659 if (bullets_def.empty())
1660 bullets_def += "\\AtBeginDocument{\n";
1661 bullets_def += " \\def\\labelitemi";
1663 // `i' is one less than the item to modify
1670 bullets_def += "ii";
1676 bullets_def += '{' +
1677 user_defined_bullet(i).getText()
1682 if (!bullets_def.empty())
1683 atlyxpreamble += bullets_def + "}\n\n";
1685 if (!atlyxpreamble.empty())
1686 lyxpreamble += "\n\\makeatletter\n"
1687 + atlyxpreamble + "\\makeatother\n\n";
1689 // We try to load babel late, in case it interferes with other packages.
1690 // Jurabib and Hyperref have to be called after babel, though.
1691 if (use_babel && !features.isRequired("jurabib")
1692 && !features.isRequired("hyperref")
1693 && !features.isRequired("vietnamese")
1694 && !features.isRequired("japanese")) {
1696 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1697 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1700 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1701 if (!i18npreamble.empty())
1702 lyxpreamble += i18npreamble + '\n';
1705 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1706 texrow.newlines(nlines);
1710 // these packages (xunicode, for that matter) need to be loaded at least
1711 // after amsmath, amssymb, esint and the other packages that provide
1714 os << "\\usepackage{xunicode}\n";
1716 os << "\\usepackage{xltxtra}\n";
1723 void BufferParams::useClassDefaults()
1725 DocumentClass const & tclass = documentClass();
1727 sides = tclass.sides();
1728 columns = tclass.columns();
1729 pagestyle = tclass.pagestyle();
1730 use_default_options = true;
1731 // Only if class has a ToC hierarchy
1732 if (tclass.hasTocLevels()) {
1733 secnumdepth = tclass.secnumdepth();
1734 tocdepth = tclass.tocdepth();
1739 bool BufferParams::hasClassDefaults() const
1741 DocumentClass const & tclass = documentClass();
1743 return sides == tclass.sides()
1744 && columns == tclass.columns()
1745 && pagestyle == tclass.pagestyle()
1746 && use_default_options
1747 && secnumdepth == tclass.secnumdepth()
1748 && tocdepth == tclass.tocdepth();
1752 DocumentClass const & BufferParams::documentClass() const
1758 DocumentClass const * BufferParams::documentClassPtr() const {
1763 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1764 // evil, but this function is evil
1765 doc_class_ = const_cast<DocumentClass *>(tc);
1769 bool BufferParams::setBaseClass(string const & classname)
1771 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1772 LayoutFileList & bcl = LayoutFileList::get();
1773 if (!bcl.haveClass(classname)) {
1775 bformat(_("The layout file:\n"
1777 "could not be found. A default textclass with default\n"
1778 "layouts will be used. LyX will not be able to produce\n"
1780 from_utf8(classname));
1781 frontend::Alert::error(_("Document class not found"), s);
1782 bcl.addEmptyClass(classname);
1785 bool const success = bcl[classname].load();
1788 bformat(_("Due to some error in it, the layout file:\n"
1790 "could not be loaded. A default textclass with default\n"
1791 "layouts will be used. LyX will not be able to produce\n"
1793 from_utf8(classname));
1794 frontend::Alert::error(_("Could not load class"), s);
1795 bcl.addEmptyClass(classname);
1798 pimpl_->baseClass_ = classname;
1799 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1804 LayoutFile const * BufferParams::baseClass() const
1806 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1807 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1813 LayoutFileIndex const & BufferParams::baseClassID() const
1815 return pimpl_->baseClass_;
1819 void BufferParams::makeDocumentClass()
1824 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1826 if (!local_layout.empty()) {
1827 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1828 docstring const msg = _("Error reading internal layout information");
1829 frontend::Alert::warning(_("Read Error"), msg);
1835 bool BufferParams::moduleCanBeAdded(string const & modName) const
1837 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1841 bool BufferParams::addLayoutModule(string const & modName)
1843 LayoutModuleList::const_iterator it = layoutModules_.begin();
1844 LayoutModuleList::const_iterator end = layoutModules_.end();
1845 for (; it != end; it++)
1848 layoutModules_.push_back(modName);
1853 Font const BufferParams::getFont() const
1855 FontInfo f = documentClass().defaultfont();
1856 if (fontsDefaultFamily == "rmdefault")
1857 f.setFamily(ROMAN_FAMILY);
1858 else if (fontsDefaultFamily == "sfdefault")
1859 f.setFamily(SANS_FAMILY);
1860 else if (fontsDefaultFamily == "ttdefault")
1861 f.setFamily(TYPEWRITER_FAMILY);
1862 return Font(f, language);
1866 void BufferParams::readPreamble(Lexer & lex)
1868 if (lex.getString() != "\\begin_preamble")
1869 lyxerr << "Error (BufferParams::readPreamble):"
1870 "consistency check failed." << endl;
1872 preamble = lex.getLongString("\\end_preamble");
1876 void BufferParams::readLocalLayout(Lexer & lex)
1878 if (lex.getString() != "\\begin_local_layout")
1879 lyxerr << "Error (BufferParams::readLocalLayout):"
1880 "consistency check failed." << endl;
1882 local_layout = lex.getLongString("\\end_local_layout");
1886 void BufferParams::readLanguage(Lexer & lex)
1888 if (!lex.next()) return;
1890 string const tmptok = lex.getString();
1892 // check if tmptok is part of tex_babel in tex-defs.h
1893 language = languages.getLanguage(tmptok);
1895 // Language tmptok was not found
1896 language = default_language;
1897 lyxerr << "Warning: Setting language `"
1898 << tmptok << "' to `" << language->lang()
1904 void BufferParams::readGraphicsDriver(Lexer & lex)
1909 string const tmptok = lex.getString();
1910 // check if tmptok is part of tex_graphics in tex_defs.h
1913 string const test = tex_graphics[n++];
1915 if (test == tmptok) {
1916 graphicsDriver = tmptok;
1921 "Warning: graphics driver `$$Token' not recognized!\n"
1922 " Setting graphics driver to `default'.\n");
1923 graphicsDriver = "default";
1930 void BufferParams::readBullets(Lexer & lex)
1935 int const index = lex.getInteger();
1937 int temp_int = lex.getInteger();
1938 user_defined_bullet(index).setFont(temp_int);
1939 temp_bullet(index).setFont(temp_int);
1941 user_defined_bullet(index).setCharacter(temp_int);
1942 temp_bullet(index).setCharacter(temp_int);
1944 user_defined_bullet(index).setSize(temp_int);
1945 temp_bullet(index).setSize(temp_int);
1949 void BufferParams::readBulletsLaTeX(Lexer & lex)
1951 // The bullet class should be able to read this.
1954 int const index = lex.getInteger();
1956 docstring const temp_str = lex.getDocString();
1958 user_defined_bullet(index).setText(temp_str);
1959 temp_bullet(index).setText(temp_str);
1963 void BufferParams::readModules(Lexer & lex)
1965 if (!lex.eatLine()) {
1966 lyxerr << "Error (BufferParams::readModules):"
1967 "Unexpected end of input." << endl;
1971 string mod = lex.getString();
1972 if (mod == "\\end_modules")
1974 addLayoutModule(mod);
1980 void BufferParams::readRemovedModules(Lexer & lex)
1982 if (!lex.eatLine()) {
1983 lyxerr << "Error (BufferParams::readRemovedModules):"
1984 "Unexpected end of input." << endl;
1988 string mod = lex.getString();
1989 if (mod == "\\end_removed_modules")
1991 removedModules_.push_back(mod);
1994 // now we want to remove any removed modules that were previously
1995 // added. normally, that will be because default modules were added in
1996 // setBaseClass(), which gets called when \textclass is read at the
1997 // start of the read.
1998 list<string>::const_iterator rit = removedModules_.begin();
1999 list<string>::const_iterator const ren = removedModules_.end();
2000 for (; rit != ren; rit++) {
2001 LayoutModuleList::iterator const mit = layoutModules_.begin();
2002 LayoutModuleList::iterator const men = layoutModules_.end();
2003 LayoutModuleList::iterator found = find(mit, men, *rit);
2006 layoutModules_.erase(found);
2011 void BufferParams::readIncludeonly(Lexer & lex)
2013 if (!lex.eatLine()) {
2014 lyxerr << "Error (BufferParams::readIncludeonly):"
2015 "Unexpected end of input." << endl;
2019 string child = lex.getString();
2020 if (child == "\\end_includeonly")
2022 includedChildren_.push_back(child);
2028 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2030 char real_papersize = papersize;
2031 if (real_papersize == PAPER_DEFAULT)
2032 real_papersize = lyxrc.default_papersize;
2034 switch (real_papersize) {
2036 // could be anything, so don't guess
2038 case PAPER_CUSTOM: {
2039 if (purpose == XDVI && !paperwidth.empty() &&
2040 !paperheight.empty()) {
2041 // heightxwidth<unit>
2042 string first = paperwidth;
2043 string second = paperheight;
2044 if (orientation == ORIENTATION_LANDSCAPE)
2047 return first.erase(first.length() - 2)
2059 // dvips and dvipdfm do not know this
2060 if (purpose == DVIPS || purpose == DVIPDFM)
2064 // dvipdfm does not know this
2065 if (purpose == DVIPDFM)
2069 // dvipdfm does not know this
2070 if (purpose == DVIPDFM)
2073 case PAPER_USEXECUTIVE:
2074 // dvipdfm does not know this
2075 if (purpose == DVIPDFM)
2080 case PAPER_USLETTER:
2082 if (purpose == XDVI)
2089 string const BufferParams::dvips_options() const
2094 && papersize == PAPER_CUSTOM
2095 && !lyxrc.print_paper_dimension_flag.empty()
2096 && !paperwidth.empty()
2097 && !paperheight.empty()) {
2098 // using a custom papersize
2099 result = lyxrc.print_paper_dimension_flag;
2100 result += ' ' + paperwidth;
2101 result += ',' + paperheight;
2103 string const paper_option = paperSizeName(DVIPS);
2104 if (!paper_option.empty() && (paper_option != "letter" ||
2105 orientation != ORIENTATION_LANDSCAPE)) {
2106 // dvips won't accept -t letter -t landscape.
2107 // In all other cases, include the paper size
2109 result = lyxrc.print_paper_flag;
2110 result += ' ' + paper_option;
2113 if (orientation == ORIENTATION_LANDSCAPE &&
2114 papersize != PAPER_CUSTOM)
2115 result += ' ' + lyxrc.print_landscape_flag;
2120 string const BufferParams::font_encoding() const
2122 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2126 string BufferParams::babelCall(string const & lang_opts) const
2128 string lang_pack = lyxrc.language_package;
2129 if (lang_pack != "\\usepackage{babel}")
2131 // suppress the babel call when there is no babel language defined
2132 // for the document language in the lib/languages file and if no
2133 // other languages are used (lang_opts is then empty)
2134 if (lang_opts.empty())
2136 // If Vietnamese is used, babel must directly be loaded with the
2137 // language options, see
2138 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2139 size_t viet = lang_opts.find("vietnam");
2140 // viet = string::npos when not found
2141 // the same is for all other languages that are not directly supported by
2142 // babel, but where LaTeX-packages add babel support.
2143 // this is currently the case for Latvian, Lithuanian, Mongolian
2145 size_t latvian = lang_opts.find("latvian");
2146 size_t lithu = lang_opts.find("lithuanian");
2147 size_t mongo = lang_opts.find("mongolian");
2148 size_t turkmen = lang_opts.find("turkmen");
2149 // If Japanese is used, babel must directly be loaded with the
2150 // language options, see
2151 // http://www.lyx.org/trac/ticket/4597#c4
2152 size_t japan = lang_opts.find("japanese");
2153 if (!lyxrc.language_global_options || viet != string::npos
2154 || japan != string::npos || latvian != string::npos
2155 || lithu != string::npos || mongo != string::npos
2156 || turkmen != string::npos)
2157 return "\\usepackage[" + lang_opts + "]{babel}";
2162 docstring BufferParams::getGraphicsDriver(string const & package) const
2166 if (package == "geometry") {
2167 if (graphicsDriver == "dvips"
2168 || graphicsDriver == "dvipdfm"
2169 || graphicsDriver == "pdftex"
2170 || graphicsDriver == "vtex")
2171 result = from_ascii(graphicsDriver);
2172 else if (graphicsDriver == "dvipdfmx")
2173 result = from_ascii("dvipdfm");
2180 void BufferParams::writeEncodingPreamble(odocstream & os,
2181 LaTeXFeatures & features, TexRow & texrow) const
2185 if (inputenc == "auto") {
2186 string const doc_encoding =
2187 language->encoding()->latexName();
2188 Encoding::Package const package =
2189 language->encoding()->package();
2191 // Create a list with all the input encodings used
2193 set<string> encodings =
2194 features.getEncodingSet(doc_encoding);
2196 // If the "japanese" package (i.e. pLaTeX) is used,
2197 // inputenc must be omitted.
2198 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2199 if (package == Encoding::japanese)
2200 features.require("japanese");
2202 if ((!encodings.empty() || package == Encoding::inputenc)
2203 && !features.isRequired("japanese")) {
2204 os << "\\usepackage[";
2205 set<string>::const_iterator it = encodings.begin();
2206 set<string>::const_iterator const end = encodings.end();
2208 os << from_ascii(*it);
2211 for (; it != end; ++it)
2212 os << ',' << from_ascii(*it);
2213 if (package == Encoding::inputenc) {
2214 if (!encodings.empty())
2216 os << from_ascii(doc_encoding);
2218 os << "]{inputenc}\n";
2221 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2222 if (language->encoding()->name() == "utf8-cjk"
2223 && LaTeXFeatures::isAvailable("CJKutf8"))
2224 os << "\\usepackage{CJKutf8}\n";
2226 os << "\\usepackage{CJK}\n";
2229 } else if (inputenc != "default") {
2230 switch (encoding().package()) {
2231 case Encoding::none:
2232 case Encoding::japanese:
2234 case Encoding::inputenc:
2235 // do not load inputenc if japanese is used
2236 if (features.isRequired("japanese"))
2238 os << "\\usepackage[" << from_ascii(inputenc)
2243 if (encoding().name() == "utf8-cjk"
2244 && LaTeXFeatures::isAvailable("CJKutf8"))
2245 os << "\\usepackage{CJKutf8}\n";
2247 os << "\\usepackage{CJK}\n";
2253 // The encoding "armscii8" (for Armenian) is only available when
2254 // the package "armtex" is loaded.
2255 if (language->encoding()->latexName() == "armscii8"
2256 || inputenc == "armscii8") {
2257 os << "\\usepackage{armtex}\n";
2263 string const BufferParams::parseFontName(string const & name) const
2265 string mangled = name;
2266 size_t const idx = mangled.find('[');
2267 if (idx == string::npos || idx == 0)
2270 return mangled.substr(0, idx - 1);
2274 string const BufferParams::loadFonts(string const & rm,
2275 string const & sf, string const & tt,
2276 bool const & sc, bool const & osf,
2277 int const & sfscale, int const & ttscale,
2278 bool const & xetex) const
2280 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2281 several packages have been replaced by others, that might not
2282 be installed on every system. We have to take care for that
2283 (see psnfss.pdf). We try to support all psnfss fonts as well
2284 as the fonts that have become de facto standard in the LaTeX
2285 world (e.g. Latin Modern). We do not support obsolete fonts
2286 (like PSLatex). In general, it should be possible to mix any
2287 rm font with any sf or tt font, respectively. (JSpitzm)
2289 -- separate math fonts.
2292 if (rm == "default" && sf == "default" && tt == "default")
2299 if (rm != "default")
2300 os << "\\setmainfont[Mapping=tex-text]{"
2301 << parseFontName(rm) << "}\n";
2302 if (sf != "default") {
2303 string const sans = parseFontName(sf);
2305 os << "\\setsansfont[Scale="
2306 << float(sfscale) / 100
2307 << ",Mapping=tex-text]{"
2310 os << "\\setsansfont[Mapping=tex-text]{"
2313 if (tt != "default") {
2314 string const mono = parseFontName(tt);
2316 os << "\\setmonofont[Scale="
2317 << float(sfscale) / 100
2321 os << "\\setmonofont[Mapping=tex-text]{"
2325 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2330 // Computer Modern (must be explicitly selectable -- there might be classes
2331 // that define a different default font!
2333 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2334 // osf for Computer Modern needs eco.sty
2336 os << "\\usepackage{eco}\n";
2338 // Latin Modern Roman
2339 else if (rm == "lmodern")
2340 os << "\\usepackage{lmodern}\n";
2342 else if (rm == "ae") {
2343 // not needed when using OT1 font encoding.
2344 if (font_encoding() != "default")
2345 os << "\\usepackage{ae,aecompl}\n";
2348 else if (rm == "times") {
2349 // try to load the best available package
2350 if (LaTeXFeatures::isAvailable("mathptmx"))
2351 os << "\\usepackage{mathptmx}\n";
2352 else if (LaTeXFeatures::isAvailable("mathptm"))
2353 os << "\\usepackage{mathptm}\n";
2355 os << "\\usepackage{times}\n";
2358 else if (rm == "palatino") {
2359 // try to load the best available package
2360 if (LaTeXFeatures::isAvailable("mathpazo")) {
2361 os << "\\usepackage";
2367 // "osf" includes "sc"!
2371 os << "{mathpazo}\n";
2373 else if (LaTeXFeatures::isAvailable("mathpple"))
2374 os << "\\usepackage{mathpple}\n";
2376 os << "\\usepackage{palatino}\n";
2379 else if (rm == "utopia") {
2380 // fourier supersedes utopia.sty, but does
2381 // not work with OT1 encoding.
2382 if (LaTeXFeatures::isAvailable("fourier")
2383 && font_encoding() != "default") {
2384 os << "\\usepackage";
2395 os << "{fourier}\n";
2398 os << "\\usepackage{utopia}\n";
2400 // Bera (complete fontset)
2401 else if (rm == "bera" && sf == "default" && tt == "default")
2402 os << "\\usepackage{bera}\n";
2404 else if (rm != "default")
2405 os << "\\usepackage" << "{" << rm << "}\n";
2408 // Helvetica, Bera Sans
2409 if (sf == "helvet" || sf == "berasans") {
2411 os << "\\usepackage[scaled=" << float(sfscale) / 100
2412 << "]{" << sf << "}\n";
2414 os << "\\usepackage{" << sf << "}\n";
2417 else if (sf == "avant")
2418 os << "\\usepackage{" << sf << "}\n";
2419 // Computer Modern, Latin Modern, CM Bright
2420 else if (sf != "default")
2421 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2423 // monospaced/typewriter
2424 // Courier, LuxiMono
2425 if (tt == "luximono" || tt == "beramono") {
2427 os << "\\usepackage[scaled=" << float(ttscale) / 100
2428 << "]{" << tt << "}\n";
2430 os << "\\usepackage{" << tt << "}\n";
2433 else if (tt == "courier" )
2434 os << "\\usepackage{" << tt << "}\n";
2435 // Computer Modern, Latin Modern, CM Bright
2436 else if (tt != "default")
2437 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2443 Encoding const & BufferParams::encoding() const
2446 return *(encodings.fromLaTeXName("utf8-plain"));
2447 if (inputenc == "auto" || inputenc == "default")
2448 return *language->encoding();
2449 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2452 LYXERR0("Unknown inputenc value `" << inputenc
2453 << "'. Using `auto' instead.");
2454 return *language->encoding();
2458 CiteEngine BufferParams::citeEngine() const
2460 // FIXME the class should provide the numerical/
2461 // authoryear choice
2462 if (documentClass().provides("natbib")
2463 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2464 return ENGINE_NATBIB_AUTHORYEAR;
2465 return cite_engine_;
2469 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2471 cite_engine_ = cite_engine;