2 * \file BufferParams.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Alfredo Braunstein
7 * \author Lars Gullik Bjønnes
8 * \author Jean-Marc Lasgouttes
10 * \author André Pönitz
11 * \author Martin Vermeer
13 * Full author contact details are available in file CREDITS.
18 #include "BufferParams.h"
21 #include "LayoutFile.h"
22 #include "BranchList.h"
23 #include "buffer_funcs.h"
29 #include "IndicesList.h"
31 #include "LaTeXFeatures.h"
32 #include "ModuleList.h"
36 #include "OutputParams.h"
40 #include "PDFOptions.h"
42 #include "frontends/alert.h"
44 #include "insets/InsetListingsParams.h"
46 #include "support/convert.h"
47 #include "support/debug.h"
48 #include "support/docstream.h"
49 #include "support/FileName.h"
50 #include "support/filetools.h"
51 #include "support/gettext.h"
52 #include "support/Messages.h"
53 #include "support/Translator.h"
54 #include "support/lstrings.h"
60 using namespace lyx::support;
63 static char const * const string_paragraph_separation[] = {
68 static char const * const string_quotes_language[] = {
69 "english", "swedish", "german", "polish", "french", "danish", ""
73 static char const * const string_papersize[] = {
74 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
75 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
79 static char const * const string_orientation[] = {
80 "portrait", "landscape", ""
84 static char const * const string_footnotekinds[] = {
85 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
89 static char const * const tex_graphics[] = {
90 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
91 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
92 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
93 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
104 // Paragraph separation
105 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
108 ParSepTranslator const init_parseptranslator()
110 ParSepTranslator translator
111 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
112 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
117 ParSepTranslator const & parseptranslator()
119 static ParSepTranslator translator = init_parseptranslator();
125 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
128 QuotesLangTranslator const init_quoteslangtranslator()
130 QuotesLangTranslator translator
131 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
132 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
133 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
134 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
135 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
136 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
141 QuotesLangTranslator const & quoteslangtranslator()
143 static QuotesLangTranslator translator = init_quoteslangtranslator();
149 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
152 static PaperSizeTranslator initPaperSizeTranslator()
154 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
155 translator.addPair(string_papersize[1], PAPER_CUSTOM);
156 translator.addPair(string_papersize[2], PAPER_USLETTER);
157 translator.addPair(string_papersize[3], PAPER_USLEGAL);
158 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
159 translator.addPair(string_papersize[5], PAPER_A3);
160 translator.addPair(string_papersize[6], PAPER_A4);
161 translator.addPair(string_papersize[7], PAPER_A5);
162 translator.addPair(string_papersize[8], PAPER_B3);
163 translator.addPair(string_papersize[9], PAPER_B4);
164 translator.addPair(string_papersize[10], PAPER_B5);
169 PaperSizeTranslator const & papersizetranslator()
171 static PaperSizeTranslator translator = initPaperSizeTranslator();
177 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
180 PaperOrientationTranslator const init_paperorientationtranslator()
182 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
183 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
188 PaperOrientationTranslator const & paperorientationtranslator()
190 static PaperOrientationTranslator translator = init_paperorientationtranslator();
196 typedef Translator<int, PageSides> SidesTranslator;
199 SidesTranslator const init_sidestranslator()
201 SidesTranslator translator(1, OneSide);
202 translator.addPair(2, TwoSides);
207 SidesTranslator const & sidestranslator()
209 static SidesTranslator translator = init_sidestranslator();
215 typedef Translator<int, BufferParams::Package> PackageTranslator;
218 PackageTranslator const init_packagetranslator()
220 PackageTranslator translator(0, BufferParams::package_off);
221 translator.addPair(1, BufferParams::package_auto);
222 translator.addPair(2, BufferParams::package_on);
227 PackageTranslator const & packagetranslator()
229 static PackageTranslator translator = init_packagetranslator();
235 typedef Translator<string, CiteEngine> CiteEngineTranslator;
238 CiteEngineTranslator const init_citeenginetranslator()
240 CiteEngineTranslator translator("basic", ENGINE_BASIC);
241 translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
242 translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
243 translator.addPair("jurabib", ENGINE_JURABIB);
248 CiteEngineTranslator const & citeenginetranslator()
250 static CiteEngineTranslator translator = init_citeenginetranslator();
256 typedef Translator<string, Spacing::Space> SpaceTranslator;
259 SpaceTranslator const init_spacetranslator()
261 SpaceTranslator translator("default", Spacing::Default);
262 translator.addPair("single", Spacing::Single);
263 translator.addPair("onehalf", Spacing::Onehalf);
264 translator.addPair("double", Spacing::Double);
265 translator.addPair("other", Spacing::Other);
270 SpaceTranslator const & spacetranslator()
272 static SpaceTranslator translator = init_spacetranslator();
279 class BufferParams::Impl
284 AuthorList authorlist;
285 BranchList branchlist;
286 Bullet temp_bullets[4];
287 Bullet user_defined_bullets[4];
288 IndicesList indiceslist;
290 /** This is the amount of space used for paragraph_separation "skip",
291 * and for detached paragraphs in "indented" documents.
295 PDFOptions pdfoptions;
296 LayoutFileIndex baseClass_;
300 BufferParams::Impl::Impl()
301 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
303 // set initial author
305 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
310 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
314 return new BufferParams::Impl(*ptr);
318 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
324 BufferParams::BufferParams()
327 setBaseClass(defaultBaseclass());
329 paragraph_separation = ParagraphIndentSeparation;
330 quotes_language = InsetQuotes::EnglishQuotes;
331 fontsize = "default";
334 papersize = PAPER_DEFAULT;
335 orientation = ORIENTATION_PORTRAIT;
336 use_geometry = false;
337 use_amsmath = package_auto;
338 use_esint = package_auto;
339 use_mhchem = package_auto;
340 cite_engine_ = ENGINE_BASIC;
341 use_bibtopic = false;
343 trackChanges = false;
344 outputChanges = false;
345 use_default_options = true;
346 maintain_unincluded_children = false;
349 language = default_language;
351 fontsRoman = "default";
352 fontsSans = "default";
353 fontsTypewriter = "default";
354 fontsDefaultFamily = "default";
358 fontsSansScale = 100;
359 fontsTypewriterScale = 100;
361 graphicsDriver = "default";
362 defaultOutputFormat = "default";
363 bibtex_command = "default";
364 index_command = "default";
367 listings_params = string();
368 pagestyle = "default";
369 suppress_date = false;
370 // white is equal to no background color
371 backgroundcolor = lyx::rgbFromHexName("#ffffff");
372 // light gray is the default font color for greyed-out notes
373 notefontcolor = lyx::rgbFromHexName("#cccccc");
374 compressed = lyxrc.save_compressed;
375 for (int iter = 0; iter < 4; ++iter) {
376 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
377 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
380 indiceslist().addDefault(B_("Index"));
381 html_be_strict = true;
382 html_math_output = MathML;
386 docstring BufferParams::B_(string const & l10n) const
388 LASSERT(language, /**/);
389 return getMessages(language->code()).get(l10n);
393 AuthorList & BufferParams::authors()
395 return pimpl_->authorlist;
399 AuthorList const & BufferParams::authors() const
401 return pimpl_->authorlist;
405 BranchList & BufferParams::branchlist()
407 return pimpl_->branchlist;
411 BranchList const & BufferParams::branchlist() const
413 return pimpl_->branchlist;
417 IndicesList & BufferParams::indiceslist()
419 return pimpl_->indiceslist;
423 IndicesList const & BufferParams::indiceslist() const
425 return pimpl_->indiceslist;
429 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
431 LASSERT(index < 4, /**/);
432 return pimpl_->temp_bullets[index];
436 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
438 LASSERT(index < 4, /**/);
439 return pimpl_->temp_bullets[index];
443 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
445 LASSERT(index < 4, /**/);
446 return pimpl_->user_defined_bullets[index];
450 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
452 LASSERT(index < 4, /**/);
453 return pimpl_->user_defined_bullets[index];
457 Spacing & BufferParams::spacing()
459 return pimpl_->spacing;
463 Spacing const & BufferParams::spacing() const
465 return pimpl_->spacing;
469 PDFOptions & BufferParams::pdfoptions()
471 return pimpl_->pdfoptions;
475 PDFOptions const & BufferParams::pdfoptions() const
477 return pimpl_->pdfoptions;
481 HSpace const & BufferParams::getIndentation() const
483 return pimpl_->indentation;
487 void BufferParams::setIndentation(HSpace const & indent)
489 pimpl_->indentation = indent;
493 VSpace const & BufferParams::getDefSkip() const
495 return pimpl_->defskip;
499 void BufferParams::setDefSkip(VSpace const & vs)
501 pimpl_->defskip = vs;
505 string BufferParams::readToken(Lexer & lex, string const & token,
506 FileName const & filepath)
508 if (token == "\\textclass") {
510 string const classname = lex.getString();
511 // if there exists a local layout file, ignore the system one
512 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
514 LayoutFileList & bcl = LayoutFileList::get();
515 if (tcp.empty() && !filepath.empty())
516 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
520 setBaseClass(classname);
521 // We assume that a tex class exists for local or unknown layouts so this warning
522 // will only be given for system layouts.
523 if (!baseClass()->isTeXClassAvailable()) {
525 translateIfPossible(from_utf8(baseClass()->description()));
526 docstring const msg =
527 bformat(_("The document class requested\n"
529 "requires external files that are not available.\n"
530 "The document class can still be used, but LyX\n"
531 "will not be able to produce output until the\n"
532 "following prerequisites are installed:\n"
534 "See section 3.1.2.2 of the User's Guide for\n"
535 "more information."),
536 desc, from_utf8(baseClass()->prerequisites()));
537 frontend::Alert::warning(_("Document class not available"),
540 } else if (token == "\\begin_preamble") {
542 } else if (token == "\\begin_local_layout") {
543 readLocalLayout(lex);
544 } else if (token == "\\begin_modules") {
546 } else if (token == "\\begin_removed_modules") {
547 readRemovedModules(lex);
548 } else if (token == "\\begin_includeonly") {
549 readIncludeonly(lex);
550 } else if (token == "\\maintain_unincluded_children") {
551 lex >> maintain_unincluded_children;
552 } else if (token == "\\options") {
554 options = lex.getString();
555 } else if (token == "\\use_default_options") {
556 lex >> use_default_options;
557 } else if (token == "\\master") {
559 master = lex.getString();
560 } else if (token == "\\suppress_date") {
561 lex >> suppress_date;
562 } else if (token == "\\language") {
564 } else if (token == "\\inputencoding") {
566 } else if (token == "\\graphics") {
567 readGraphicsDriver(lex);
568 } else if (token == "\\default_output_format") {
569 lex >> defaultOutputFormat;
570 } else if (token == "\\bibtex_command") {
572 bibtex_command = lex.getString();
573 } else if (token == "\\index_command") {
575 index_command = lex.getString();
576 } else if (token == "\\fontencoding") {
578 fontenc = lex.getString();
579 } else if (token == "\\font_roman") {
581 fontsRoman = lex.getString();
582 } else if (token == "\\font_sans") {
584 fontsSans = lex.getString();
585 } else if (token == "\\font_typewriter") {
587 fontsTypewriter = lex.getString();
588 } else if (token == "\\font_default_family") {
589 lex >> fontsDefaultFamily;
590 } else if (token == "\\use_xetex") {
592 } else if (token == "\\font_sc") {
594 } else if (token == "\\font_osf") {
596 } else if (token == "\\font_sf_scale") {
597 lex >> fontsSansScale;
598 } else if (token == "\\font_tt_scale") {
599 lex >> fontsTypewriterScale;
600 } else if (token == "\\font_cjk") {
602 } else if (token == "\\paragraph_separation") {
605 paragraph_separation = parseptranslator().find(parsep);
606 } else if (token == "\\paragraph_indentation") {
608 string indentation = lex.getString();
609 pimpl_->indentation = HSpace(indentation);
610 } else if (token == "\\defskip") {
612 string defskip = lex.getString();
613 if (defskip == "defskip")
616 pimpl_->defskip = VSpace(defskip);
617 } else if (token == "\\quotes_language") {
620 quotes_language = quoteslangtranslator().find(quotes_lang);
621 } else if (token == "\\papersize") {
624 papersize = papersizetranslator().find(ppsize);
625 } else if (token == "\\use_geometry") {
627 } else if (token == "\\use_amsmath") {
630 use_amsmath = packagetranslator().find(use_ams);
631 } else if (token == "\\use_esint") {
634 use_esint = packagetranslator().find(useesint);
635 } else if (token == "\\use_mhchem") {
638 use_mhchem = packagetranslator().find(usemhchem);
639 } else if (token == "\\cite_engine") {
642 cite_engine_ = citeenginetranslator().find(engine);
643 } else if (token == "\\use_bibtopic") {
645 } else if (token == "\\use_indices") {
647 } else if (token == "\\tracking_changes") {
649 } else if (token == "\\output_changes") {
650 lex >> outputChanges;
651 } else if (token == "\\branch") {
653 docstring branch = lex.getDocString();
654 branchlist().add(branch);
657 string const tok = lex.getString();
658 if (tok == "\\end_branch")
660 Branch * branch_ptr = branchlist().find(branch);
661 if (tok == "\\selected") {
664 branch_ptr->setSelected(lex.getInteger());
666 if (tok == "\\filename_suffix") {
669 branch_ptr->setFilenameSuffix(lex.getInteger());
671 if (tok == "\\color") {
673 string color = lex.getString();
675 branch_ptr->setColor(color);
676 // Update also the Color table:
678 color = lcolor.getX11Name(Color_background);
680 lcolor.setColor(to_utf8(branch), color);
683 } else if (token == "\\index") {
685 docstring index = lex.getDocString();
687 indiceslist().add(index);
690 string const tok = lex.getString();
691 if (tok == "\\end_index")
693 Index * index_ptr = indiceslist().find(index);
694 if (tok == "\\shortcut") {
696 shortcut = lex.getDocString();
698 index_ptr->setShortcut(shortcut);
700 if (tok == "\\color") {
702 string color = lex.getString();
704 index_ptr->setColor(color);
705 // Update also the Color table:
707 color = lcolor.getX11Name(Color_background);
709 if (!shortcut.empty())
710 lcolor.setColor(to_utf8(shortcut), color);
713 } else if (token == "\\author") {
715 istringstream ss(lex.getString());
718 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
719 } else if (token == "\\paperorientation") {
722 orientation = paperorientationtranslator().find(orient);
723 } else if (token == "\\backgroundcolor") {
725 backgroundcolor = lyx::rgbFromHexName(lex.getString());
726 } else if (token == "\\notefontcolor") {
728 string color = lex.getString();
729 notefontcolor = lyx::rgbFromHexName(color);
730 // set the font color within LyX
731 lcolor.setColor(Color_greyedouttext, color);
732 } else if (token == "\\paperwidth") {
734 } else if (token == "\\paperheight") {
736 } else if (token == "\\leftmargin") {
738 } else if (token == "\\topmargin") {
740 } else if (token == "\\rightmargin") {
742 } else if (token == "\\bottommargin") {
744 } else if (token == "\\headheight") {
746 } else if (token == "\\headsep") {
748 } else if (token == "\\footskip") {
750 } else if (token == "\\columnsep") {
752 } else if (token == "\\paperfontsize") {
754 } else if (token == "\\papercolumns") {
756 } else if (token == "\\listings_params") {
759 listings_params = InsetListingsParams(par).params();
760 } else if (token == "\\papersides") {
763 sides = sidestranslator().find(psides);
764 } else if (token == "\\paperpagestyle") {
766 } else if (token == "\\bullet") {
768 } else if (token == "\\bulletLaTeX") {
769 readBulletsLaTeX(lex);
770 } else if (token == "\\secnumdepth") {
772 } else if (token == "\\tocdepth") {
774 } else if (token == "\\spacing") {
778 if (nspacing == "other") {
781 spacing().set(spacetranslator().find(nspacing), tmp_val);
782 } else if (token == "\\float_placement") {
783 lex >> float_placement;
785 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
786 string toktmp = pdfoptions().readToken(lex, token);
787 if (!toktmp.empty()) {
788 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
792 } else if (token == "\\html_math_output") {
795 html_math_output = static_cast<MathOutput>(temp);
796 } else if (token == "\\html_be_strict") {
797 lex >> html_be_strict;
799 lyxerr << "BufferParams::readToken(): Unknown token: " <<
808 void BufferParams::writeFile(ostream & os) const
810 // The top of the file is written by the buffer.
811 // Prints out the buffer info into the .lyx file given by file
814 os << "\\textclass " << baseClass()->name() << '\n';
817 if (!preamble.empty()) {
818 // remove '\n' from the end of preamble
819 string const tmppreamble = rtrim(preamble, "\n");
820 os << "\\begin_preamble\n"
822 << "\n\\end_preamble\n";
826 if (!options.empty()) {
827 os << "\\options " << options << '\n';
830 // use the class options defined in the layout?
831 os << "\\use_default_options "
832 << convert<string>(use_default_options) << "\n";
834 // the master document
835 if (!master.empty()) {
836 os << "\\master " << master << '\n';
840 if (!removedModules_.empty()) {
841 os << "\\begin_removed_modules" << '\n';
842 list<string>::const_iterator it = removedModules_.begin();
843 list<string>::const_iterator en = removedModules_.end();
844 for (; it != en; it++)
846 os << "\\end_removed_modules" << '\n';
850 if (!layoutModules_.empty()) {
851 os << "\\begin_modules" << '\n';
852 LayoutModuleList::const_iterator it = layoutModules_.begin();
853 LayoutModuleList::const_iterator en = layoutModules_.end();
854 for (; it != en; it++)
856 os << "\\end_modules" << '\n';
860 if (!includedChildren_.empty()) {
861 os << "\\begin_includeonly" << '\n';
862 list<string>::const_iterator it = includedChildren_.begin();
863 list<string>::const_iterator en = includedChildren_.end();
864 for (; it != en; it++)
866 os << "\\end_includeonly" << '\n';
868 os << "\\maintain_unincluded_children "
869 << convert<string>(maintain_unincluded_children) << '\n';
871 // local layout information
872 if (!local_layout.empty()) {
873 // remove '\n' from the end
874 string const tmplocal = rtrim(local_layout, "\n");
875 os << "\\begin_local_layout\n"
877 << "\n\\end_local_layout\n";
880 // then the text parameters
881 if (language != ignore_language)
882 os << "\\language " << language->lang() << '\n';
883 os << "\\inputencoding " << inputenc
884 << "\n\\fontencoding " << fontenc
885 << "\n\\font_roman " << fontsRoman
886 << "\n\\font_sans " << fontsSans
887 << "\n\\font_typewriter " << fontsTypewriter
888 << "\n\\font_default_family " << fontsDefaultFamily
889 << "\n\\use_xetex " << convert<string>(useXetex)
890 << "\n\\font_sc " << convert<string>(fontsSC)
891 << "\n\\font_osf " << convert<string>(fontsOSF)
892 << "\n\\font_sf_scale " << fontsSansScale
893 << "\n\\font_tt_scale " << fontsTypewriterScale
895 if (!fontsCJK.empty()) {
896 os << "\\font_cjk " << fontsCJK << '\n';
898 os << "\n\\graphics " << graphicsDriver << '\n';
899 os << "\\default_output_format " << defaultOutputFormat << '\n';
900 os << "\\bibtex_command " << bibtex_command << '\n';
901 os << "\\index_command " << index_command << '\n';
903 if (!float_placement.empty()) {
904 os << "\\float_placement " << float_placement << '\n';
906 os << "\\paperfontsize " << fontsize << '\n';
908 spacing().writeFile(os);
909 pdfoptions().writeFile(os);
911 os << "\\papersize " << string_papersize[papersize]
912 << "\n\\use_geometry " << convert<string>(use_geometry)
913 << "\n\\use_amsmath " << use_amsmath
914 << "\n\\use_esint " << use_esint
915 << "\n\\use_mhchem " << use_mhchem
916 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
917 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
918 << "\n\\use_indices " << convert<string>(use_indices)
919 << "\n\\paperorientation " << string_orientation[orientation]
920 << "\n\\suppress_date " << convert<string>(suppress_date)
922 if (backgroundcolor != lyx::rgbFromHexName("#ffffff"))
923 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
924 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
925 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
927 BranchList::const_iterator it = branchlist().begin();
928 BranchList::const_iterator end = branchlist().end();
929 for (; it != end; ++it) {
930 os << "\\branch " << to_utf8(it->branch())
931 << "\n\\selected " << it->isSelected()
932 << "\n\\filename_suffix " << it->hasFilenameSuffix()
933 << "\n\\color " << lyx::X11hexname(it->color())
938 IndicesList::const_iterator iit = indiceslist().begin();
939 IndicesList::const_iterator iend = indiceslist().end();
940 for (; iit != iend; ++iit) {
941 os << "\\index " << to_utf8(iit->index())
942 << "\n\\shortcut " << to_utf8(iit->shortcut())
943 << "\n\\color " << lyx::X11hexname(iit->color())
948 if (!paperwidth.empty())
949 os << "\\paperwidth "
950 << VSpace(paperwidth).asLyXCommand() << '\n';
951 if (!paperheight.empty())
952 os << "\\paperheight "
953 << VSpace(paperheight).asLyXCommand() << '\n';
954 if (!leftmargin.empty())
955 os << "\\leftmargin "
956 << VSpace(leftmargin).asLyXCommand() << '\n';
957 if (!topmargin.empty())
959 << VSpace(topmargin).asLyXCommand() << '\n';
960 if (!rightmargin.empty())
961 os << "\\rightmargin "
962 << VSpace(rightmargin).asLyXCommand() << '\n';
963 if (!bottommargin.empty())
964 os << "\\bottommargin "
965 << VSpace(bottommargin).asLyXCommand() << '\n';
966 if (!headheight.empty())
967 os << "\\headheight "
968 << VSpace(headheight).asLyXCommand() << '\n';
969 if (!headsep.empty())
971 << VSpace(headsep).asLyXCommand() << '\n';
972 if (!footskip.empty())
974 << VSpace(footskip).asLyXCommand() << '\n';
975 if (!columnsep.empty())
977 << VSpace(columnsep).asLyXCommand() << '\n';
978 os << "\\secnumdepth " << secnumdepth
979 << "\n\\tocdepth " << tocdepth
980 << "\n\\paragraph_separation "
981 << string_paragraph_separation[paragraph_separation];
982 if (!paragraph_separation)
983 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
985 os << "\n\\defskip " << getDefSkip().asLyXCommand();
986 os << "\n\\quotes_language "
987 << string_quotes_language[quotes_language]
988 << "\n\\papercolumns " << columns
989 << "\n\\papersides " << sides
990 << "\n\\paperpagestyle " << pagestyle << '\n';
991 if (!listings_params.empty())
992 os << "\\listings_params \"" <<
993 InsetListingsParams(listings_params).encodedString() << "\"\n";
994 for (int i = 0; i < 4; ++i) {
995 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
996 if (user_defined_bullet(i).getFont() != -1) {
997 os << "\\bullet " << i << " "
998 << user_defined_bullet(i).getFont() << " "
999 << user_defined_bullet(i).getCharacter() << " "
1000 << user_defined_bullet(i).getSize() << "\n";
1004 os << "\\bulletLaTeX " << i << " \""
1005 << lyx::to_ascii(user_defined_bullet(i).getText())
1011 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n"
1012 << "\\output_changes " << convert<string>(outputChanges) << "\n"
1013 << "\\html_math_output " << html_math_output << "\n"
1014 << "\\html_be_strict " << convert<string>(html_be_strict) << "\n";
1016 os << pimpl_->authorlist;
1020 void BufferParams::validate(LaTeXFeatures & features) const
1022 features.require(documentClass().requires());
1024 if (outputChanges) {
1025 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1026 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1027 LaTeXFeatures::isAvailable("xcolor");
1029 switch (features.runparams().flavor) {
1030 case OutputParams::LATEX:
1032 features.require("ct-dvipost");
1033 features.require("dvipost");
1034 } else if (xcolorulem) {
1035 features.require("ct-xcolor-ulem");
1036 features.require("ulem");
1037 features.require("xcolor");
1039 features.require("ct-none");
1042 case OutputParams::PDFLATEX:
1043 case OutputParams::XETEX:
1045 features.require("ct-xcolor-ulem");
1046 features.require("ulem");
1047 features.require("xcolor");
1048 // improves color handling in PDF output
1049 features.require("pdfcolmk");
1051 features.require("ct-none");
1059 // Floats with 'Here definitely' as default setting.
1060 if (float_placement.find('H') != string::npos)
1061 features.require("float");
1063 // AMS Style is at document level
1064 if (use_amsmath == package_on
1065 || documentClass().provides("amsmath"))
1066 features.require("amsmath");
1067 if (use_esint == package_on)
1068 features.require("esint");
1069 if (use_mhchem == package_on)
1070 features.require("mhchem");
1072 // Document-level line spacing
1073 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1074 features.require("setspace");
1076 // the bullet shapes are buffer level not paragraph level
1077 // so they are tested here
1078 for (int i = 0; i < 4; ++i) {
1079 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1081 int const font = user_defined_bullet(i).getFont();
1083 int const c = user_defined_bullet(i).getCharacter();
1089 features.require("latexsym");
1091 } else if (font == 1) {
1092 features.require("amssymb");
1093 } else if (font >= 2 && font <= 5) {
1094 features.require("pifont");
1098 if (pdfoptions().use_hyperref) {
1099 features.require("hyperref");
1100 // due to interferences with babel and hyperref, the color package has to
1101 // be loaded after hyperref when hyperref is used with the colorlinks
1102 // option, see http://www.lyx.org/trac/ticket/5291
1103 if (pdfoptions().colorlinks)
1104 features.require("color");
1108 features.require("xetex");
1110 if (language->lang() == "vietnamese")
1111 features.require("vietnamese");
1112 else if (language->lang() == "japanese")
1113 features.require("japanese");
1117 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1118 TexRow & texrow, FileName const & filepath) const
1120 os << "\\documentclass";
1122 DocumentClass const & tclass = documentClass();
1124 ostringstream clsoptions; // the document class options.
1126 if (tokenPos(tclass.opt_fontsize(),
1127 '|', fontsize) >= 0) {
1128 // only write if existing in list (and not default)
1129 clsoptions << fontsize << "pt,";
1132 // custom, A3, B3 and B4 paper sizes need geometry
1133 bool nonstandard_papersize = papersize == PAPER_B3
1134 || papersize == PAPER_B4
1135 || papersize == PAPER_A3
1136 || papersize == PAPER_CUSTOM;
1138 if (!use_geometry) {
1139 switch (papersize) {
1141 clsoptions << "a4paper,";
1143 case PAPER_USLETTER:
1144 clsoptions << "letterpaper,";
1147 clsoptions << "a5paper,";
1150 clsoptions << "b5paper,";
1152 case PAPER_USEXECUTIVE:
1153 clsoptions << "executivepaper,";
1156 clsoptions << "legalpaper,";
1168 if (sides != tclass.sides()) {
1171 clsoptions << "oneside,";
1174 clsoptions << "twoside,";
1180 if (columns != tclass.columns()) {
1182 clsoptions << "twocolumn,";
1184 clsoptions << "onecolumn,";
1188 && orientation == ORIENTATION_LANDSCAPE)
1189 clsoptions << "landscape,";
1191 // language should be a parameter to \documentclass
1192 if (language->babel() == "hebrew"
1193 && default_language->babel() != "hebrew")
1194 // This seems necessary
1195 features.useLanguage(default_language);
1197 ostringstream language_options;
1198 bool const use_babel = features.useBabel();
1200 language_options << features.getLanguages();
1201 if (!language->babel().empty()) {
1202 if (!language_options.str().empty())
1203 language_options << ',';
1204 language_options << language->babel();
1206 // if Vietnamese is used, babel must directly be loaded
1207 // with language options, not in the class options, see
1208 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1209 size_t viet = language_options.str().find("vietnam");
1210 // viet = string::npos when not found
1211 // the same is for all other languages that are not directly supported by
1212 // babel, but where LaTeX-packages add babel support.
1213 // this is currently the case for Latvian, Lithuanian, Mongolian
1215 size_t latvian = language_options.str().find("latvian");
1216 size_t lithu = language_options.str().find("lithuanian");
1217 size_t mongo = language_options.str().find("mongolian");
1218 size_t turkmen = language_options.str().find("turkmen");
1219 // if Japanese is used, babel must directly be loaded
1220 // with language options, not in the class options, see
1221 // http://www.lyx.org/trac/ticket/4597#c4
1222 size_t japan = language_options.str().find("japanese");
1223 if (lyxrc.language_global_options && !language_options.str().empty()
1224 && viet == string::npos && japan == string::npos
1225 && latvian == string::npos && lithu == string::npos
1226 && mongo == string::npos && turkmen == string::npos)
1227 clsoptions << language_options.str() << ',';
1230 // the predefined options from the layout
1231 if (use_default_options && !tclass.options().empty())
1232 clsoptions << tclass.options() << ',';
1234 // the user-defined options
1235 if (!options.empty()) {
1236 clsoptions << options << ',';
1239 string strOptions(clsoptions.str());
1240 if (!strOptions.empty()) {
1241 strOptions = rtrim(strOptions, ",");
1243 os << '[' << from_utf8(strOptions) << ']';
1246 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1248 // end of \documentclass defs
1251 os << "\\usepackage{fontspec}\n";
1255 // font selection must be done before loading fontenc.sty
1256 string const fonts =
1257 loadFonts(fontsRoman, fontsSans,
1258 fontsTypewriter, fontsSC, fontsOSF,
1259 fontsSansScale, fontsTypewriterScale, useXetex);
1260 if (!fonts.empty()) {
1261 os << from_ascii(fonts);
1264 if (fontsDefaultFamily != "default")
1265 os << "\\renewcommand{\\familydefault}{\\"
1266 << from_ascii(fontsDefaultFamily) << "}\n";
1268 // set font encoding
1269 // for arabic_arabi and farsi we also need to load the LAE and
1271 // XeTeX works without fontenc
1272 if (font_encoding() != "default" && language->lang() != "japanese"
1274 if (language->lang() == "arabic_arabi"
1275 || language->lang() == "farsi") {
1276 os << "\\usepackage[" << from_ascii(font_encoding())
1277 << ",LFE,LAE]{fontenc}\n";
1280 os << "\\usepackage[" << from_ascii(font_encoding())
1286 // handle inputenc etc.
1287 writeEncodingPreamble(os, features, texrow);
1290 if (!features.runparams().includeall && !includedChildren_.empty()) {
1291 os << "\\includeonly{";
1292 list<string>::const_iterator it = includedChildren_.begin();
1294 for (; it != includedChildren_.end() ; ++it) {
1295 string incfile = *it;
1296 FileName inc = makeAbsPath(incfile, filepath.absFilename());
1297 string mangled = DocFileName(changeExtension(inc.absFilename(), ".tex")).
1299 if (!features.runparams().nice)
1301 // \includeonly doesn't want an extension
1302 incfile = changeExtension(incfile, string());
1303 incfile = support::latex_path(incfile);
1304 if (!incfile.empty()) {
1307 os << from_utf8(incfile);
1314 if (!listings_params.empty() || features.isRequired("listings")) {
1315 os << "\\usepackage{listings}\n";
1318 if (!listings_params.empty()) {
1320 // do not test validity because listings_params is
1321 // supposed to be valid
1323 InsetListingsParams(listings_params).separatedParams(true);
1324 // we can't support all packages, but we should load the color package
1325 if (par.find("\\color", 0) != string::npos)
1326 features.require("color");
1327 os << from_utf8(par);
1328 // count the number of newlines
1329 for (size_t i = 0; i < par.size(); ++i)
1335 if (!tclass.provides("geometry")
1336 && (use_geometry || nonstandard_papersize)) {
1337 odocstringstream ods;
1338 if (!getGraphicsDriver("geometry").empty())
1339 ods << getGraphicsDriver("geometry");
1340 if (orientation == ORIENTATION_LANDSCAPE)
1341 ods << ",landscape";
1342 switch (papersize) {
1344 if (!paperwidth.empty())
1345 ods << ",paperwidth="
1346 << from_ascii(paperwidth);
1347 if (!paperheight.empty())
1348 ods << ",paperheight="
1349 << from_ascii(paperheight);
1351 case PAPER_USLETTER:
1352 ods << ",letterpaper";
1355 ods << ",legalpaper";
1357 case PAPER_USEXECUTIVE:
1358 ods << ",executivepaper";
1379 // default papersize ie PAPER_DEFAULT
1380 switch (lyxrc.default_papersize) {
1381 case PAPER_DEFAULT: // keep compiler happy
1382 case PAPER_USLETTER:
1383 ods << ",letterpaper";
1386 ods << ",legalpaper";
1388 case PAPER_USEXECUTIVE:
1389 ods << ",executivepaper";
1409 docstring const g_options = trim(ods.str(), ",");
1410 os << "\\usepackage";
1411 if (!g_options.empty())
1412 os << '[' << g_options << ']';
1413 os << "{geometry}\n";
1415 os << "\\geometry{verbose";
1416 if (!topmargin.empty())
1417 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1418 if (!bottommargin.empty())
1419 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1420 if (!leftmargin.empty())
1421 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1422 if (!rightmargin.empty())
1423 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1424 if (!headheight.empty())
1425 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1426 if (!headsep.empty())
1427 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1428 if (!footskip.empty())
1429 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1430 if (!columnsep.empty())
1431 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1434 } else if (orientation == ORIENTATION_LANDSCAPE) {
1435 features.require("papersize");
1438 if (tokenPos(tclass.opt_pagestyle(),
1439 '|', pagestyle) >= 0) {
1440 if (pagestyle == "fancy") {
1441 os << "\\usepackage{fancyhdr}\n";
1444 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1448 // only output when the background color is not white
1449 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1450 // only require color here, the background color will be defined
1451 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1453 features.require("color");
1454 features.require("pagecolor");
1457 // Only if class has a ToC hierarchy
1458 if (tclass.hasTocLevels()) {
1459 if (secnumdepth != tclass.secnumdepth()) {
1460 os << "\\setcounter{secnumdepth}{"
1465 if (tocdepth != tclass.tocdepth()) {
1466 os << "\\setcounter{tocdepth}{"
1473 if (paragraph_separation) {
1474 // when skip separation
1475 switch (getDefSkip().kind()) {
1476 case VSpace::SMALLSKIP:
1477 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1479 case VSpace::MEDSKIP:
1480 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1482 case VSpace::BIGSKIP:
1483 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1485 case VSpace::LENGTH:
1486 os << "\\setlength{\\parskip}{"
1487 << from_utf8(getDefSkip().length().asLatexString())
1490 default: // should never happen // Then delete it.
1491 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1495 os << "\\setlength{\\parindent}{0pt}\n";
1498 // when separation by indentation
1499 // only output something when a width is given
1500 if (getIndentation().asLyXCommand() != "default") {
1501 os << "\\setlength{\\parindent}{"
1502 << from_utf8(getIndentation().asLatexCommand())
1508 // Now insert the LyX specific LaTeX commands...
1509 docstring lyxpreamble;
1511 // due to interferences with babel and hyperref, the color package has to
1512 // be loaded (when it is not already loaded) before babel when hyperref
1513 // is used with the colorlinks option, see
1514 // http://www.lyx.org/trac/ticket/5291
1515 // we decided therefore to load color always before babel, see
1516 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1517 lyxpreamble += from_ascii(features.getColorOptions());
1519 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1521 && (features.isRequired("jurabib")
1522 || features.isRequired("hyperref")
1523 || features.isRequired("vietnamese")
1524 || features.isRequired("japanese") ) ) {
1526 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1527 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1530 // The optional packages;
1531 lyxpreamble += from_ascii(features.getPackages());
1533 // Additional Indices
1534 if (features.isRequired("splitidx")) {
1535 IndicesList::const_iterator iit = indiceslist().begin();
1536 IndicesList::const_iterator iend = indiceslist().end();
1537 for (; iit != iend; ++iit) {
1538 lyxpreamble += "\\newindex[";
1539 lyxpreamble += iit->index();
1540 lyxpreamble += "]{";
1541 lyxpreamble += iit->shortcut();
1542 lyxpreamble += "}\n";
1547 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1550 // * Hyperref manual: "Make sure it comes last of your loaded
1551 // packages, to give it a fighting chance of not being over-written,
1552 // since its job is to redefine many LaTeX commands."
1553 // * Email from Heiko Oberdiek: "It is usually better to load babel
1554 // before hyperref. Then hyperref has a chance to detect babel.
1555 // * Has to be loaded before the "LyX specific LaTeX commands" to
1556 // avoid errors with algorithm floats.
1557 // use hyperref explicitly if it is required
1558 if (features.isRequired("hyperref")) {
1559 // pass what we have to stream here, since we need
1560 // to access the stream itself in PDFOptions.
1564 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1566 OutputParams tmp_params = features.runparams();
1567 lines += pdfoptions().writeLaTeX(tmp_params, os,
1568 documentClass().provides("hyperref"));
1569 texrow.newlines(lines);
1570 // set back for the rest
1571 lyxpreamble.clear();
1574 // Will be surrounded by \makeatletter and \makeatother when not empty
1575 docstring atlyxpreamble;
1577 // Some macros LyX will need
1578 docstring tmppreamble(features.getMacros());
1580 if (!tmppreamble.empty())
1581 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1582 "LyX specific LaTeX commands.\n"
1583 + tmppreamble + '\n';
1585 // the text class specific preamble
1586 tmppreamble = features.getTClassPreamble();
1587 if (!tmppreamble.empty())
1588 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1589 "Textclass specific LaTeX commands.\n"
1590 + tmppreamble + '\n';
1592 // suppress date if selected
1593 // use \@ifundefined because we cannot be sure that every document class
1594 // has a \date command
1596 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1598 /* the user-defined preamble */
1599 if (!containsOnly(preamble, " \n\t"))
1601 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1602 "User specified LaTeX commands.\n"
1603 + from_utf8(preamble) + '\n';
1605 // subfig loads internally the LaTeX package "caption". As
1606 // caption is a very popular package, users will load it in
1607 // the preamble. Therefore we must load subfig behind the
1608 // user-defined preamble and check if the caption package was
1609 // loaded or not. For the case that caption is loaded before
1610 // subfig, there is the subfig option "caption=false". This
1611 // option also works when a koma-script class is used and
1612 // koma's own caption commands are used instead of caption. We
1613 // use \PassOptionsToPackage here because the user could have
1614 // already loaded subfig in the preamble.
1615 if (features.isRequired("subfig")) {
1616 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1617 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1618 "\\usepackage{subfig}\n";
1621 // Itemize bullet settings need to be last in case the user
1622 // defines their own bullets that use a package included
1623 // in the user-defined preamble -- ARRae
1624 // Actually it has to be done much later than that
1625 // since some packages like frenchb make modifications
1626 // at \begin{document} time -- JMarc
1627 docstring bullets_def;
1628 for (int i = 0; i < 4; ++i) {
1629 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1630 if (bullets_def.empty())
1631 bullets_def += "\\AtBeginDocument{\n";
1632 bullets_def += " \\def\\labelitemi";
1634 // `i' is one less than the item to modify
1641 bullets_def += "ii";
1647 bullets_def += '{' +
1648 user_defined_bullet(i).getText()
1653 if (!bullets_def.empty())
1654 atlyxpreamble += bullets_def + "}\n\n";
1656 if (!atlyxpreamble.empty())
1657 lyxpreamble += "\n\\makeatletter\n"
1658 + atlyxpreamble + "\\makeatother\n\n";
1660 // We try to load babel late, in case it interferes with other packages.
1661 // Jurabib and Hyperref have to be called after babel, though.
1662 if (use_babel && !features.isRequired("jurabib")
1663 && !features.isRequired("hyperref")
1664 && !features.isRequired("vietnamese")
1665 && !features.isRequired("japanese")) {
1667 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1668 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1671 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1672 if (!i18npreamble.empty())
1673 lyxpreamble += i18npreamble + '\n';
1676 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1677 texrow.newlines(nlines);
1681 // these packages (xunicode, for that matter) need to be loaded at least
1682 // after amsmath, amssymb, esint and the other packages that provide
1685 os << "\\usepackage{xunicode}\n";
1687 os << "\\usepackage{xltxtra}\n";
1694 void BufferParams::useClassDefaults()
1696 DocumentClass const & tclass = documentClass();
1698 sides = tclass.sides();
1699 columns = tclass.columns();
1700 pagestyle = tclass.pagestyle();
1701 use_default_options = true;
1702 // Only if class has a ToC hierarchy
1703 if (tclass.hasTocLevels()) {
1704 secnumdepth = tclass.secnumdepth();
1705 tocdepth = tclass.tocdepth();
1710 bool BufferParams::hasClassDefaults() const
1712 DocumentClass const & tclass = documentClass();
1714 return sides == tclass.sides()
1715 && columns == tclass.columns()
1716 && pagestyle == tclass.pagestyle()
1717 && use_default_options
1718 && secnumdepth == tclass.secnumdepth()
1719 && tocdepth == tclass.tocdepth();
1723 DocumentClass const & BufferParams::documentClass() const
1729 DocumentClass const * BufferParams::documentClassPtr() const {
1734 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1735 // evil, but this function is evil
1736 doc_class_ = const_cast<DocumentClass *>(tc);
1740 bool BufferParams::setBaseClass(string const & classname)
1742 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1743 LayoutFileList & bcl = LayoutFileList::get();
1744 if (!bcl.haveClass(classname)) {
1746 bformat(_("The document class %1$s could not be found. "
1747 "A default textclass with default layouts will be used. "
1748 "LyX might not be able to produce output unless a correct "
1749 "textclass is selected from the document settings dialog."),
1750 from_utf8(classname));
1751 frontend::Alert::error(_("Document class not found"), s);
1752 bcl.addEmptyClass(classname);
1755 bool const success = bcl[classname].load();
1758 bformat(_("The document class %1$s could not be loaded."),
1759 from_utf8(classname));
1760 frontend::Alert::error(_("Could not load class"), s);
1764 pimpl_->baseClass_ = classname;
1765 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1770 LayoutFile const * BufferParams::baseClass() const
1772 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1773 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1779 LayoutFileIndex const & BufferParams::baseClassID() const
1781 return pimpl_->baseClass_;
1785 void BufferParams::makeDocumentClass()
1790 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1792 if (!local_layout.empty()) {
1793 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1794 docstring const msg = _("Error reading internal layout information");
1795 frontend::Alert::warning(_("Read Error"), msg);
1800 bool BufferParams::moduleCanBeAdded(string const & modName) const
1802 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1806 bool BufferParams::addLayoutModule(string const & modName)
1808 LayoutModuleList::const_iterator it = layoutModules_.begin();
1809 LayoutModuleList::const_iterator end = layoutModules_.end();
1810 for (; it != end; it++)
1813 layoutModules_.push_back(modName);
1818 Font const BufferParams::getFont() const
1820 FontInfo f = documentClass().defaultfont();
1821 if (fontsDefaultFamily == "rmdefault")
1822 f.setFamily(ROMAN_FAMILY);
1823 else if (fontsDefaultFamily == "sfdefault")
1824 f.setFamily(SANS_FAMILY);
1825 else if (fontsDefaultFamily == "ttdefault")
1826 f.setFamily(TYPEWRITER_FAMILY);
1827 return Font(f, language);
1831 void BufferParams::readPreamble(Lexer & lex)
1833 if (lex.getString() != "\\begin_preamble")
1834 lyxerr << "Error (BufferParams::readPreamble):"
1835 "consistency check failed." << endl;
1837 preamble = lex.getLongString("\\end_preamble");
1841 void BufferParams::readLocalLayout(Lexer & lex)
1843 if (lex.getString() != "\\begin_local_layout")
1844 lyxerr << "Error (BufferParams::readLocalLayout):"
1845 "consistency check failed." << endl;
1847 local_layout = lex.getLongString("\\end_local_layout");
1851 void BufferParams::readLanguage(Lexer & lex)
1853 if (!lex.next()) return;
1855 string const tmptok = lex.getString();
1857 // check if tmptok is part of tex_babel in tex-defs.h
1858 language = languages.getLanguage(tmptok);
1860 // Language tmptok was not found
1861 language = default_language;
1862 lyxerr << "Warning: Setting language `"
1863 << tmptok << "' to `" << language->lang()
1869 void BufferParams::readGraphicsDriver(Lexer & lex)
1874 string const tmptok = lex.getString();
1875 // check if tmptok is part of tex_graphics in tex_defs.h
1878 string const test = tex_graphics[n++];
1880 if (test == tmptok) {
1881 graphicsDriver = tmptok;
1886 "Warning: graphics driver `$$Token' not recognized!\n"
1887 " Setting graphics driver to `default'.\n");
1888 graphicsDriver = "default";
1895 void BufferParams::readBullets(Lexer & lex)
1900 int const index = lex.getInteger();
1902 int temp_int = lex.getInteger();
1903 user_defined_bullet(index).setFont(temp_int);
1904 temp_bullet(index).setFont(temp_int);
1906 user_defined_bullet(index).setCharacter(temp_int);
1907 temp_bullet(index).setCharacter(temp_int);
1909 user_defined_bullet(index).setSize(temp_int);
1910 temp_bullet(index).setSize(temp_int);
1914 void BufferParams::readBulletsLaTeX(Lexer & lex)
1916 // The bullet class should be able to read this.
1919 int const index = lex.getInteger();
1921 docstring const temp_str = lex.getDocString();
1923 user_defined_bullet(index).setText(temp_str);
1924 temp_bullet(index).setText(temp_str);
1928 void BufferParams::readModules(Lexer & lex)
1930 if (!lex.eatLine()) {
1931 lyxerr << "Error (BufferParams::readModules):"
1932 "Unexpected end of input." << endl;
1936 string mod = lex.getString();
1937 if (mod == "\\end_modules")
1939 addLayoutModule(mod);
1945 void BufferParams::readRemovedModules(Lexer & lex)
1947 if (!lex.eatLine()) {
1948 lyxerr << "Error (BufferParams::readRemovedModules):"
1949 "Unexpected end of input." << endl;
1953 string mod = lex.getString();
1954 if (mod == "\\end_removed_modules")
1956 removedModules_.push_back(mod);
1959 // now we want to remove any removed modules that were previously
1960 // added. normally, that will be because default modules were added in
1961 // setBaseClass(), which gets called when \textclass is read at the
1962 // start of the read.
1963 list<string>::const_iterator rit = removedModules_.begin();
1964 list<string>::const_iterator const ren = removedModules_.end();
1965 for (; rit != ren; rit++) {
1966 LayoutModuleList::iterator const mit = layoutModules_.begin();
1967 LayoutModuleList::iterator const men = layoutModules_.end();
1968 LayoutModuleList::iterator found = find(mit, men, *rit);
1971 layoutModules_.erase(found);
1976 void BufferParams::readIncludeonly(Lexer & lex)
1978 if (!lex.eatLine()) {
1979 lyxerr << "Error (BufferParams::readIncludeonly):"
1980 "Unexpected end of input." << endl;
1984 string child = lex.getString();
1985 if (child == "\\end_includeonly")
1987 includedChildren_.push_back(child);
1993 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1995 char real_papersize = papersize;
1996 if (real_papersize == PAPER_DEFAULT)
1997 real_papersize = lyxrc.default_papersize;
1999 switch (real_papersize) {
2001 // could be anything, so don't guess
2003 case PAPER_CUSTOM: {
2004 if (purpose == XDVI && !paperwidth.empty() &&
2005 !paperheight.empty()) {
2006 // heightxwidth<unit>
2007 string first = paperwidth;
2008 string second = paperheight;
2009 if (orientation == ORIENTATION_LANDSCAPE)
2012 return first.erase(first.length() - 2)
2024 // dvips and dvipdfm do not know this
2025 if (purpose == DVIPS || purpose == DVIPDFM)
2029 // dvipdfm does not know this
2030 if (purpose == DVIPDFM)
2034 // dvipdfm does not know this
2035 if (purpose == DVIPDFM)
2038 case PAPER_USEXECUTIVE:
2039 // dvipdfm does not know this
2040 if (purpose == DVIPDFM)
2045 case PAPER_USLETTER:
2047 if (purpose == XDVI)
2054 string const BufferParams::dvips_options() const
2059 && papersize == PAPER_CUSTOM
2060 && !lyxrc.print_paper_dimension_flag.empty()
2061 && !paperwidth.empty()
2062 && !paperheight.empty()) {
2063 // using a custom papersize
2064 result = lyxrc.print_paper_dimension_flag;
2065 result += ' ' + paperwidth;
2066 result += ',' + paperheight;
2068 string const paper_option = paperSizeName(DVIPS);
2069 if (!paper_option.empty() && (paper_option != "letter" ||
2070 orientation != ORIENTATION_LANDSCAPE)) {
2071 // dvips won't accept -t letter -t landscape.
2072 // In all other cases, include the paper size
2074 result = lyxrc.print_paper_flag;
2075 result += ' ' + paper_option;
2078 if (orientation == ORIENTATION_LANDSCAPE &&
2079 papersize != PAPER_CUSTOM)
2080 result += ' ' + lyxrc.print_landscape_flag;
2085 string const BufferParams::font_encoding() const
2087 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2091 string BufferParams::babelCall(string const & lang_opts) const
2093 string lang_pack = lyxrc.language_package;
2094 if (lang_pack != "\\usepackage{babel}")
2096 // suppress the babel call when there is no babel language defined
2097 // for the document language in the lib/languages file and if no
2098 // other languages are used (lang_opts is then empty)
2099 if (lang_opts.empty())
2101 // If Vietnamese is used, babel must directly be loaded with the
2102 // language options, see
2103 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2104 size_t viet = lang_opts.find("vietnam");
2105 // viet = string::npos when not found
2106 // the same is for all other languages that are not directly supported by
2107 // babel, but where LaTeX-packages add babel support.
2108 // this is currently the case for Latvian, Lithuanian, Mongolian
2110 size_t latvian = lang_opts.find("latvian");
2111 size_t lithu = lang_opts.find("lithuanian");
2112 size_t mongo = lang_opts.find("mongolian");
2113 size_t turkmen = lang_opts.find("turkmen");
2114 // If Japanese is used, babel must directly be loaded with the
2115 // language options, see
2116 // http://www.lyx.org/trac/ticket/4597#c4
2117 size_t japan = lang_opts.find("japanese");
2118 if (!lyxrc.language_global_options || viet != string::npos
2119 || japan != string::npos || latvian != string::npos
2120 || lithu != string::npos || mongo != string::npos
2121 || turkmen != string::npos)
2122 return "\\usepackage[" + lang_opts + "]{babel}";
2127 docstring BufferParams::getGraphicsDriver(string const & package) const
2131 if (package == "geometry") {
2132 if (graphicsDriver == "dvips"
2133 || graphicsDriver == "dvipdfm"
2134 || graphicsDriver == "pdftex"
2135 || graphicsDriver == "vtex")
2136 result = from_ascii(graphicsDriver);
2137 else if (graphicsDriver == "dvipdfmx")
2138 result = from_ascii("dvipdfm");
2145 void BufferParams::writeEncodingPreamble(odocstream & os,
2146 LaTeXFeatures & features, TexRow & texrow) const
2150 if (inputenc == "auto") {
2151 string const doc_encoding =
2152 language->encoding()->latexName();
2153 Encoding::Package const package =
2154 language->encoding()->package();
2156 // Create a list with all the input encodings used
2158 set<string> encodings =
2159 features.getEncodingSet(doc_encoding);
2161 // If the "japanese" package (i.e. pLaTeX) is used,
2162 // inputenc must be omitted.
2163 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2164 if (package == Encoding::japanese)
2165 features.require("japanese");
2167 if ((!encodings.empty() || package == Encoding::inputenc)
2168 && !features.isRequired("japanese")) {
2169 os << "\\usepackage[";
2170 set<string>::const_iterator it = encodings.begin();
2171 set<string>::const_iterator const end = encodings.end();
2173 os << from_ascii(*it);
2176 for (; it != end; ++it)
2177 os << ',' << from_ascii(*it);
2178 if (package == Encoding::inputenc) {
2179 if (!encodings.empty())
2181 os << from_ascii(doc_encoding);
2183 os << "]{inputenc}\n";
2186 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2187 if (language->encoding()->name() == "utf8-cjk"
2188 && LaTeXFeatures::isAvailable("CJKutf8"))
2189 os << "\\usepackage{CJKutf8}\n";
2191 os << "\\usepackage{CJK}\n";
2194 } else if (inputenc != "default") {
2195 switch (encoding().package()) {
2196 case Encoding::none:
2197 case Encoding::japanese:
2199 case Encoding::inputenc:
2200 // do not load inputenc if japanese is used
2201 if (features.isRequired("japanese"))
2203 os << "\\usepackage[" << from_ascii(inputenc)
2208 if (encoding().name() == "utf8-cjk"
2209 && LaTeXFeatures::isAvailable("CJKutf8"))
2210 os << "\\usepackage{CJKutf8}\n";
2212 os << "\\usepackage{CJK}\n";
2218 // The encoding "armscii8" (for Armenian) is only available when
2219 // the package "armtex" is loaded.
2220 if (language->encoding()->latexName() == "armscii8"
2221 || inputenc == "armscii8") {
2222 os << "\\usepackage{armtex}\n";
2228 string const BufferParams::parseFontName(string const & name) const
2230 string mangled = name;
2231 size_t const idx = mangled.find('[');
2232 if (idx == string::npos || idx == 0)
2235 return mangled.substr(0, idx - 1);
2239 string const BufferParams::loadFonts(string const & rm,
2240 string const & sf, string const & tt,
2241 bool const & sc, bool const & osf,
2242 int const & sfscale, int const & ttscale,
2243 bool const & xetex) const
2245 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2246 several packages have been replaced by others, that might not
2247 be installed on every system. We have to take care for that
2248 (see psnfss.pdf). We try to support all psnfss fonts as well
2249 as the fonts that have become de facto standard in the LaTeX
2250 world (e.g. Latin Modern). We do not support obsolete fonts
2251 (like PSLatex). In general, it should be possible to mix any
2252 rm font with any sf or tt font, respectively. (JSpitzm)
2254 -- separate math fonts.
2257 if (rm == "default" && sf == "default" && tt == "default")
2264 if (rm != "default")
2265 os << "\\setmainfont[Mapping=tex-text]{"
2266 << parseFontName(rm) << "}\n";
2267 if (sf != "default") {
2268 string const sans = parseFontName(sf);
2270 os << "\\setsansfont[Scale="
2271 << float(sfscale) / 100
2272 << ",Mapping=tex-text]{"
2275 os << "\\setsansfont[Mapping=tex-text]{"
2278 if (tt != "default") {
2279 string const mono = parseFontName(tt);
2281 os << "\\setmonofont[Scale="
2282 << float(sfscale) / 100
2286 os << "\\setmonofont[Mapping=tex-text]{"
2290 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2295 // Computer Modern (must be explicitly selectable -- there might be classes
2296 // that define a different default font!
2298 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2299 // osf for Computer Modern needs eco.sty
2301 os << "\\usepackage{eco}\n";
2303 // Latin Modern Roman
2304 else if (rm == "lmodern")
2305 os << "\\usepackage{lmodern}\n";
2307 else if (rm == "ae") {
2308 // not needed when using OT1 font encoding.
2309 if (font_encoding() != "default")
2310 os << "\\usepackage{ae,aecompl}\n";
2313 else if (rm == "times") {
2314 // try to load the best available package
2315 if (LaTeXFeatures::isAvailable("mathptmx"))
2316 os << "\\usepackage{mathptmx}\n";
2317 else if (LaTeXFeatures::isAvailable("mathptm"))
2318 os << "\\usepackage{mathptm}\n";
2320 os << "\\usepackage{times}\n";
2323 else if (rm == "palatino") {
2324 // try to load the best available package
2325 if (LaTeXFeatures::isAvailable("mathpazo")) {
2326 os << "\\usepackage";
2332 // "osf" includes "sc"!
2336 os << "{mathpazo}\n";
2338 else if (LaTeXFeatures::isAvailable("mathpple"))
2339 os << "\\usepackage{mathpple}\n";
2341 os << "\\usepackage{palatino}\n";
2344 else if (rm == "utopia") {
2345 // fourier supersedes utopia.sty, but does
2346 // not work with OT1 encoding.
2347 if (LaTeXFeatures::isAvailable("fourier")
2348 && font_encoding() != "default") {
2349 os << "\\usepackage";
2360 os << "{fourier}\n";
2363 os << "\\usepackage{utopia}\n";
2365 // Bera (complete fontset)
2366 else if (rm == "bera" && sf == "default" && tt == "default")
2367 os << "\\usepackage{bera}\n";
2369 else if (rm != "default")
2370 os << "\\usepackage" << "{" << rm << "}\n";
2373 // Helvetica, Bera Sans
2374 if (sf == "helvet" || sf == "berasans") {
2376 os << "\\usepackage[scaled=" << float(sfscale) / 100
2377 << "]{" << sf << "}\n";
2379 os << "\\usepackage{" << sf << "}\n";
2382 else if (sf == "avant")
2383 os << "\\usepackage{" << sf << "}\n";
2384 // Computer Modern, Latin Modern, CM Bright
2385 else if (sf != "default")
2386 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2388 // monospaced/typewriter
2389 // Courier, LuxiMono
2390 if (tt == "luximono" || tt == "beramono") {
2392 os << "\\usepackage[scaled=" << float(ttscale) / 100
2393 << "]{" << tt << "}\n";
2395 os << "\\usepackage{" << tt << "}\n";
2398 else if (tt == "courier" )
2399 os << "\\usepackage{" << tt << "}\n";
2400 // Computer Modern, Latin Modern, CM Bright
2401 else if (tt != "default")
2402 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2408 Encoding const & BufferParams::encoding() const
2411 return *(encodings.fromLaTeXName("utf8-plain"));
2412 if (inputenc == "auto" || inputenc == "default")
2413 return *language->encoding();
2414 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2417 LYXERR0("Unknown inputenc value `" << inputenc
2418 << "'. Using `auto' instead.");
2419 return *language->encoding();
2423 CiteEngine BufferParams::citeEngine() const
2425 // FIXME the class should provide the numerical/
2426 // authoryear choice
2427 if (documentClass().provides("natbib")
2428 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2429 return ENGINE_NATBIB_AUTHORYEAR;
2430 return cite_engine_;
2434 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2436 cite_engine_ = cite_engine;