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;
348 language = default_language;
349 fontsRoman = "default";
350 fontsSans = "default";
351 fontsTypewriter = "default";
352 fontsDefaultFamily = "default";
356 fontsSansScale = 100;
357 fontsTypewriterScale = 100;
359 graphicsDriver = "default";
360 defaultOutputFormat = "default";
361 bibtex_command = "default";
362 index_command = "default";
365 listings_params = string();
366 pagestyle = "default";
367 suppress_date = false;
368 // white is equal to no background color
369 backgroundcolor = lyx::rgbFromHexName("#ffffff");
371 for (int iter = 0; iter < 4; ++iter) {
372 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
373 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
376 indiceslist().addDefault(B_("Index"));
380 docstring BufferParams::B_(string const & l10n) const
382 LASSERT(language, /**/);
383 return getMessages(language->code()).get(l10n);
387 AuthorList & BufferParams::authors()
389 return pimpl_->authorlist;
393 AuthorList const & BufferParams::authors() const
395 return pimpl_->authorlist;
399 BranchList & BufferParams::branchlist()
401 return pimpl_->branchlist;
405 BranchList const & BufferParams::branchlist() const
407 return pimpl_->branchlist;
411 IndicesList & BufferParams::indiceslist()
413 return pimpl_->indiceslist;
417 IndicesList const & BufferParams::indiceslist() const
419 return pimpl_->indiceslist;
423 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
425 LASSERT(index < 4, /**/);
426 return pimpl_->temp_bullets[index];
430 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
432 LASSERT(index < 4, /**/);
433 return pimpl_->temp_bullets[index];
437 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
439 LASSERT(index < 4, /**/);
440 return pimpl_->user_defined_bullets[index];
444 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
446 LASSERT(index < 4, /**/);
447 return pimpl_->user_defined_bullets[index];
451 Spacing & BufferParams::spacing()
453 return pimpl_->spacing;
457 Spacing const & BufferParams::spacing() const
459 return pimpl_->spacing;
463 PDFOptions & BufferParams::pdfoptions()
465 return pimpl_->pdfoptions;
469 PDFOptions const & BufferParams::pdfoptions() const
471 return pimpl_->pdfoptions;
475 HSpace const & BufferParams::getIndentation() const
477 return pimpl_->indentation;
481 void BufferParams::setIndentation(HSpace const & indent)
483 pimpl_->indentation = indent;
487 VSpace const & BufferParams::getDefSkip() const
489 return pimpl_->defskip;
493 void BufferParams::setDefSkip(VSpace const & vs)
495 pimpl_->defskip = vs;
499 string BufferParams::readToken(Lexer & lex, string const & token,
500 FileName const & filepath)
502 if (token == "\\textclass") {
504 string const classname = lex.getString();
505 // if there exists a local layout file, ignore the system one
506 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
508 LayoutFileList & bcl = LayoutFileList::get();
509 if (tcp.empty() && !filepath.empty())
510 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
514 setBaseClass(classname);
515 // We assume that a tex class exists for local or unknown layouts so this warning
516 // will only be given for system layouts.
517 if (!baseClass()->isTeXClassAvailable()) {
518 docstring const msg =
519 bformat(_("The layout file requested by this document,\n"
521 "is not usable. This is probably because a LaTeX\n"
522 "class or style file required by it is not\n"
523 "available. See the Customization documentation\n"
524 "for more information.\n"), from_utf8(classname));
525 frontend::Alert::warning(_("Document class not available"),
526 msg + _("LyX will not be able to produce output."));
528 } else if (token == "\\begin_preamble") {
530 } else if (token == "\\begin_local_layout") {
531 readLocalLayout(lex);
532 } else if (token == "\\begin_modules") {
534 } else if (token == "\\begin_removed_modules") {
535 readRemovedModules(lex);
536 } else if (token == "\\options") {
538 options = lex.getString();
539 } else if (token == "\\use_default_options") {
540 lex >> use_default_options;
541 } else if (token == "\\master") {
543 master = lex.getString();
544 } else if (token == "\\suppress_date") {
545 lex >> suppress_date;
546 } else if (token == "\\language") {
548 } else if (token == "\\inputencoding") {
550 } else if (token == "\\graphics") {
551 readGraphicsDriver(lex);
552 } else if (token == "\\default_output_format") {
553 lex >> defaultOutputFormat;
554 } else if (token == "\\bibtex_command") {
556 bibtex_command = lex.getString();
557 } else if (token == "\\index_command") {
559 index_command = lex.getString();
560 } else if (token == "\\font_roman") {
562 fontsRoman = lex.getString();
563 } else if (token == "\\font_sans") {
565 fontsSans = lex.getString();
566 } else if (token == "\\font_typewriter") {
568 fontsTypewriter = lex.getString();
569 } else if (token == "\\font_default_family") {
570 lex >> fontsDefaultFamily;
571 } else if (token == "\\use_xetex") {
573 } else if (token == "\\font_sc") {
575 } else if (token == "\\font_osf") {
577 } else if (token == "\\font_sf_scale") {
578 lex >> fontsSansScale;
579 } else if (token == "\\font_tt_scale") {
580 lex >> fontsTypewriterScale;
581 } else if (token == "\\font_cjk") {
583 } else if (token == "\\paragraph_separation") {
586 paragraph_separation = parseptranslator().find(parsep);
587 } else if (token == "\\paragraph_indentation") {
589 string indentation = lex.getString();
590 pimpl_->indentation = HSpace(indentation);
591 } else if (token == "\\defskip") {
593 string defskip = lex.getString();
594 if (defskip == "defskip")
597 pimpl_->defskip = VSpace(defskip);
598 } else if (token == "\\quotes_language") {
601 quotes_language = quoteslangtranslator().find(quotes_lang);
602 } else if (token == "\\papersize") {
605 papersize = papersizetranslator().find(ppsize);
606 } else if (token == "\\use_geometry") {
608 } else if (token == "\\use_amsmath") {
611 use_amsmath = packagetranslator().find(use_ams);
612 } else if (token == "\\use_esint") {
615 use_esint = packagetranslator().find(useesint);
616 } else if (token == "\\use_mhchem") {
619 use_mhchem = packagetranslator().find(usemhchem);
620 } else if (token == "\\cite_engine") {
623 cite_engine_ = citeenginetranslator().find(engine);
624 } else if (token == "\\use_bibtopic") {
626 } else if (token == "\\use_indices") {
628 } else if (token == "\\tracking_changes") {
630 } else if (token == "\\output_changes") {
631 lex >> outputChanges;
632 } else if (token == "\\branch") {
634 docstring branch = lex.getDocString();
635 branchlist().add(branch);
638 string const tok = lex.getString();
639 if (tok == "\\end_branch")
641 Branch * branch_ptr = branchlist().find(branch);
642 if (tok == "\\selected") {
645 branch_ptr->setSelected(lex.getInteger());
647 if (tok == "\\filename_suffix") {
650 branch_ptr->setFilenameSuffix(lex.getInteger());
652 if (tok == "\\color") {
654 string color = lex.getString();
656 branch_ptr->setColor(color);
657 // Update also the Color table:
659 color = lcolor.getX11Name(Color_background);
661 lcolor.setColor(to_utf8(branch), color);
664 } else if (token == "\\index") {
666 docstring index = lex.getDocString();
668 indiceslist().add(index);
671 string const tok = lex.getString();
672 if (tok == "\\end_index")
674 Index * index_ptr = indiceslist().find(index);
675 if (tok == "\\shortcut") {
677 shortcut = lex.getDocString();
679 index_ptr->setShortcut(shortcut);
681 if (tok == "\\color") {
683 string color = lex.getString();
685 index_ptr->setColor(color);
686 // Update also the Color table:
688 color = lcolor.getX11Name(Color_background);
690 if (!shortcut.empty())
691 lcolor.setColor(to_utf8(shortcut), color);
694 } else if (token == "\\author") {
696 istringstream ss(lex.getString());
699 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
700 } else if (token == "\\paperorientation") {
703 orientation = paperorientationtranslator().find(orient);
704 } else if (token == "\\backgroundcolor") {
706 backgroundcolor = lyx::rgbFromHexName(lex.getString());
707 } else if (token == "\\paperwidth") {
709 } else if (token == "\\paperheight") {
711 } else if (token == "\\leftmargin") {
713 } else if (token == "\\topmargin") {
715 } else if (token == "\\rightmargin") {
717 } else if (token == "\\bottommargin") {
719 } else if (token == "\\headheight") {
721 } else if (token == "\\headsep") {
723 } else if (token == "\\footskip") {
725 } else if (token == "\\columnsep") {
727 } else if (token == "\\paperfontsize") {
729 } else if (token == "\\papercolumns") {
731 } else if (token == "\\listings_params") {
734 listings_params = InsetListingsParams(par).params();
735 } else if (token == "\\papersides") {
738 sides = sidestranslator().find(psides);
739 } else if (token == "\\paperpagestyle") {
741 } else if (token == "\\bullet") {
743 } else if (token == "\\bulletLaTeX") {
744 readBulletsLaTeX(lex);
745 } else if (token == "\\secnumdepth") {
747 } else if (token == "\\tocdepth") {
749 } else if (token == "\\spacing") {
753 if (nspacing == "other") {
756 spacing().set(spacetranslator().find(nspacing), tmp_val);
757 } else if (token == "\\float_placement") {
758 lex >> float_placement;
760 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
761 string toktmp = pdfoptions().readToken(lex, token);
762 if (!toktmp.empty()) {
763 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
768 lyxerr << "BufferParams::readToken(): Unknown token: " <<
777 void BufferParams::writeFile(ostream & os) const
779 // The top of the file is written by the buffer.
780 // Prints out the buffer info into the .lyx file given by file
783 os << "\\textclass " << baseClass()->name() << '\n';
786 if (!preamble.empty()) {
787 // remove '\n' from the end of preamble
788 string const tmppreamble = rtrim(preamble, "\n");
789 os << "\\begin_preamble\n"
791 << "\n\\end_preamble\n";
795 if (!options.empty()) {
796 os << "\\options " << options << '\n';
799 // use the class options defined in the layout?
800 os << "\\use_default_options "
801 << convert<string>(use_default_options) << "\n";
803 // the master document
804 if (!master.empty()) {
805 os << "\\master " << master << '\n';
809 if (!removedModules_.empty()) {
810 os << "\\begin_removed_modules" << '\n';
811 list<string>::const_iterator it = removedModules_.begin();
812 list<string>::const_iterator en = removedModules_.end();
813 for (; it != en; it++)
815 os << "\\end_removed_modules" << '\n';
819 if (!layoutModules_.empty()) {
820 os << "\\begin_modules" << '\n';
821 LayoutModuleList::const_iterator it = layoutModules_.begin();
822 LayoutModuleList::const_iterator en = layoutModules_.end();
823 for (; it != en; it++)
825 os << "\\end_modules" << '\n';
828 // local layout information
829 if (!local_layout.empty()) {
830 // remove '\n' from the end
831 string const tmplocal = rtrim(local_layout, "\n");
832 os << "\\begin_local_layout\n"
834 << "\n\\end_local_layout\n";
837 // then the text parameters
838 if (language != ignore_language)
839 os << "\\language " << language->lang() << '\n';
840 os << "\\inputencoding " << inputenc
841 << "\n\\font_roman " << fontsRoman
842 << "\n\\font_sans " << fontsSans
843 << "\n\\font_typewriter " << fontsTypewriter
844 << "\n\\font_default_family " << fontsDefaultFamily
845 << "\n\\use_xetex " << convert<string>(useXetex)
846 << "\n\\font_sc " << convert<string>(fontsSC)
847 << "\n\\font_osf " << convert<string>(fontsOSF)
848 << "\n\\font_sf_scale " << fontsSansScale
849 << "\n\\font_tt_scale " << fontsTypewriterScale
851 if (!fontsCJK.empty()) {
852 os << "\\font_cjk " << fontsCJK << '\n';
854 os << "\n\\graphics " << graphicsDriver << '\n';
855 os << "\\default_output_format " << defaultOutputFormat << '\n';
856 os << "\\bibtex_command " << bibtex_command << '\n';
857 os << "\\index_command " << index_command << '\n';
859 if (!float_placement.empty()) {
860 os << "\\float_placement " << float_placement << '\n';
862 os << "\\paperfontsize " << fontsize << '\n';
864 spacing().writeFile(os);
865 pdfoptions().writeFile(os);
867 os << "\\papersize " << string_papersize[papersize]
868 << "\n\\use_geometry " << convert<string>(use_geometry)
869 << "\n\\use_amsmath " << use_amsmath
870 << "\n\\use_esint " << use_esint
871 << "\n\\use_mhchem " << use_mhchem
872 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
873 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
874 << "\n\\use_indices " << convert<string>(use_indices)
875 << "\n\\paperorientation " << string_orientation[orientation]
876 << "\n\\suppress_date " << convert<string>(suppress_date)
878 if (backgroundcolor != lyx::rgbFromHexName("#ffffff"))
879 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
881 BranchList::const_iterator it = branchlist().begin();
882 BranchList::const_iterator end = branchlist().end();
883 for (; it != end; ++it) {
884 os << "\\branch " << to_utf8(it->branch())
885 << "\n\\selected " << it->isSelected()
886 << "\n\\filename_suffix " << it->hasFilenameSuffix()
887 << "\n\\color " << lyx::X11hexname(it->color())
892 IndicesList::const_iterator iit = indiceslist().begin();
893 IndicesList::const_iterator iend = indiceslist().end();
894 for (; iit != iend; ++iit) {
895 os << "\\index " << to_utf8(iit->index())
896 << "\n\\shortcut " << to_utf8(iit->shortcut())
897 << "\n\\color " << lyx::X11hexname(iit->color())
902 if (!paperwidth.empty())
903 os << "\\paperwidth "
904 << VSpace(paperwidth).asLyXCommand() << '\n';
905 if (!paperheight.empty())
906 os << "\\paperheight "
907 << VSpace(paperheight).asLyXCommand() << '\n';
908 if (!leftmargin.empty())
909 os << "\\leftmargin "
910 << VSpace(leftmargin).asLyXCommand() << '\n';
911 if (!topmargin.empty())
913 << VSpace(topmargin).asLyXCommand() << '\n';
914 if (!rightmargin.empty())
915 os << "\\rightmargin "
916 << VSpace(rightmargin).asLyXCommand() << '\n';
917 if (!bottommargin.empty())
918 os << "\\bottommargin "
919 << VSpace(bottommargin).asLyXCommand() << '\n';
920 if (!headheight.empty())
921 os << "\\headheight "
922 << VSpace(headheight).asLyXCommand() << '\n';
923 if (!headsep.empty())
925 << VSpace(headsep).asLyXCommand() << '\n';
926 if (!footskip.empty())
928 << VSpace(footskip).asLyXCommand() << '\n';
929 if (!columnsep.empty())
931 << VSpace(columnsep).asLyXCommand() << '\n';
932 os << "\\secnumdepth " << secnumdepth
933 << "\n\\tocdepth " << tocdepth
934 << "\n\\paragraph_separation "
935 << string_paragraph_separation[paragraph_separation];
936 if (!paragraph_separation)
937 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
939 os << "\n\\defskip " << getDefSkip().asLyXCommand();
940 os << "\n\\quotes_language "
941 << string_quotes_language[quotes_language]
942 << "\n\\papercolumns " << columns
943 << "\n\\papersides " << sides
944 << "\n\\paperpagestyle " << pagestyle << '\n';
945 if (!listings_params.empty())
946 os << "\\listings_params \"" <<
947 InsetListingsParams(listings_params).encodedString() << "\"\n";
948 for (int i = 0; i < 4; ++i) {
949 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
950 if (user_defined_bullet(i).getFont() != -1) {
951 os << "\\bullet " << i << " "
952 << user_defined_bullet(i).getFont() << " "
953 << user_defined_bullet(i).getCharacter() << " "
954 << user_defined_bullet(i).getSize() << "\n";
958 os << "\\bulletLaTeX " << i << " \""
959 << lyx::to_ascii(user_defined_bullet(i).getText())
965 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
966 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
968 os << pimpl_->authorlist;
972 void BufferParams::validate(LaTeXFeatures & features) const
974 features.require(documentClass().requires());
977 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
978 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
979 LaTeXFeatures::isAvailable("xcolor");
981 switch (features.runparams().flavor) {
982 case OutputParams::LATEX:
984 features.require("ct-dvipost");
985 features.require("dvipost");
986 } else if (xcolorulem) {
987 features.require("ct-xcolor-ulem");
988 features.require("ulem");
989 features.require("xcolor");
991 features.require("ct-none");
994 case OutputParams::PDFLATEX:
995 case OutputParams::XETEX:
997 features.require("ct-xcolor-ulem");
998 features.require("ulem");
999 features.require("xcolor");
1000 // improves color handling in PDF output
1001 features.require("pdfcolmk");
1003 features.require("ct-none");
1011 // Floats with 'Here definitely' as default setting.
1012 if (float_placement.find('H') != string::npos)
1013 features.require("float");
1015 // AMS Style is at document level
1016 if (use_amsmath == package_on
1017 || documentClass().provides("amsmath"))
1018 features.require("amsmath");
1019 if (use_esint == package_on)
1020 features.require("esint");
1021 if (use_mhchem == package_on)
1022 features.require("mhchem");
1024 // Document-level line spacing
1025 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1026 features.require("setspace");
1028 // the bullet shapes are buffer level not paragraph level
1029 // so they are tested here
1030 for (int i = 0; i < 4; ++i) {
1031 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1033 int const font = user_defined_bullet(i).getFont();
1035 int const c = user_defined_bullet(i).getCharacter();
1041 features.require("latexsym");
1043 } else if (font == 1) {
1044 features.require("amssymb");
1045 } else if (font >= 2 && font <= 5) {
1046 features.require("pifont");
1050 if (pdfoptions().use_hyperref) {
1051 features.require("hyperref");
1052 // due to interferences with babel and hyperref, the color package has to
1053 // be loaded after hyperref when hyperref is used with the colorlinks
1054 // option, see http://bugzilla.lyx.org/show_bug.cgi?id=5291
1055 if (pdfoptions().colorlinks)
1056 features.require("color");
1060 features.require("xetex");
1062 if (language->lang() == "vietnamese")
1063 features.require("vietnamese");
1064 else if (language->lang() == "japanese")
1065 features.require("japanese");
1069 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1070 TexRow & texrow) const
1072 os << "\\documentclass";
1074 DocumentClass const & tclass = documentClass();
1076 ostringstream clsoptions; // the document class options.
1078 if (tokenPos(tclass.opt_fontsize(),
1079 '|', fontsize) >= 0) {
1080 // only write if existing in list (and not default)
1081 clsoptions << fontsize << "pt,";
1084 // custom, A3, B3 and B4 paper sizes need geometry
1085 bool nonstandard_papersize = papersize == PAPER_B3
1086 || papersize == PAPER_B4
1087 || papersize == PAPER_A3
1088 || papersize == PAPER_CUSTOM;
1090 if (!use_geometry) {
1091 switch (papersize) {
1093 clsoptions << "a4paper,";
1095 case PAPER_USLETTER:
1096 clsoptions << "letterpaper,";
1099 clsoptions << "a5paper,";
1102 clsoptions << "b5paper,";
1104 case PAPER_USEXECUTIVE:
1105 clsoptions << "executivepaper,";
1108 clsoptions << "legalpaper,";
1120 if (sides != tclass.sides()) {
1123 clsoptions << "oneside,";
1126 clsoptions << "twoside,";
1132 if (columns != tclass.columns()) {
1134 clsoptions << "twocolumn,";
1136 clsoptions << "onecolumn,";
1140 && orientation == ORIENTATION_LANDSCAPE)
1141 clsoptions << "landscape,";
1143 // language should be a parameter to \documentclass
1144 if (language->babel() == "hebrew"
1145 && default_language->babel() != "hebrew")
1146 // This seems necessary
1147 features.useLanguage(default_language);
1149 ostringstream language_options;
1150 bool const use_babel = features.useBabel();
1152 language_options << features.getLanguages();
1153 if (!language->babel().empty()) {
1154 if (!language_options.str().empty())
1155 language_options << ',';
1156 language_options << language->babel();
1158 // if Vietnamese is used, babel must directly be loaded
1159 // with language options, not in the class options, see
1160 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1161 size_t viet = language_options.str().find("vietnam");
1162 // viet = string::npos when not found
1163 // the same is for all other languages that are not directly supported by
1164 // babel, but where LaTeX-packages add babel support.
1165 // this is currently the case for Latvian, Lithuanian, and Mongolian
1166 size_t latvian = language_options.str().find("latvian");
1167 size_t lithu = language_options.str().find("lithuanian");
1168 size_t mongo = language_options.str().find("mongolian");
1169 // if Japanese is used, babel must directly be loaded
1170 // with language options, not in the class options, see
1171 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1172 size_t japan = language_options.str().find("japanese");
1173 if (lyxrc.language_global_options && !language_options.str().empty()
1174 && viet == string::npos && japan == string::npos
1175 && latvian == string::npos && lithu == string::npos
1176 && mongo == string::npos)
1177 clsoptions << language_options.str() << ',';
1180 // the predefined options from the layout
1181 if (use_default_options && !tclass.options().empty())
1182 clsoptions << tclass.options() << ',';
1184 // the user-defined options
1185 if (!options.empty()) {
1186 clsoptions << options << ',';
1189 string strOptions(clsoptions.str());
1190 if (!strOptions.empty()) {
1191 strOptions = rtrim(strOptions, ",");
1193 os << '[' << from_utf8(strOptions) << ']';
1196 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1198 // end of \documentclass defs
1201 os << "\\usepackage{fontspec}\n";
1205 // font selection must be done before loading fontenc.sty
1206 string const fonts =
1207 loadFonts(fontsRoman, fontsSans,
1208 fontsTypewriter, fontsSC, fontsOSF,
1209 fontsSansScale, fontsTypewriterScale, useXetex);
1210 if (!fonts.empty()) {
1211 os << from_ascii(fonts);
1214 if (fontsDefaultFamily != "default")
1215 os << "\\renewcommand{\\familydefault}{\\"
1216 << from_ascii(fontsDefaultFamily) << "}\n";
1218 // set font encoding
1219 // this one is not per buffer
1220 // for arabic_arabi and farsi we also need to load the LAE and
1222 // XeTeX works without fontenc
1223 if (lyxrc.fontenc != "default" && language->lang() != "japanese"
1225 if (language->lang() == "arabic_arabi"
1226 || language->lang() == "farsi") {
1227 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1228 << ",LFE,LAE]{fontenc}\n";
1231 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1237 // handle inputenc etc.
1238 writeEncodingPreamble(os, features, texrow);
1240 if (!listings_params.empty() || features.isRequired("listings")) {
1241 os << "\\usepackage{listings}\n";
1244 if (!listings_params.empty()) {
1246 // do not test validity because listings_params is
1247 // supposed to be valid
1249 InsetListingsParams(listings_params).separatedParams(true);
1250 // we can't support all packages, but we should load the color package
1251 if (par.find("\\color", 0) != string::npos)
1252 features.require("color");
1253 os << from_utf8(par);
1254 // count the number of newlines
1255 for (size_t i = 0; i < par.size(); ++i)
1261 if (!tclass.provides("geometry")
1262 && (use_geometry || nonstandard_papersize)) {
1263 odocstringstream ods;
1264 if (!getGraphicsDriver("geometry").empty())
1265 ods << getGraphicsDriver("geometry");
1266 if (orientation == ORIENTATION_LANDSCAPE)
1267 ods << ",landscape";
1268 switch (papersize) {
1270 if (!paperwidth.empty())
1271 ods << ",paperwidth="
1272 << from_ascii(paperwidth);
1273 if (!paperheight.empty())
1274 ods << ",paperheight="
1275 << from_ascii(paperheight);
1277 case PAPER_USLETTER:
1278 ods << ",letterpaper";
1281 ods << ",legalpaper";
1283 case PAPER_USEXECUTIVE:
1284 ods << ",executivepaper";
1305 // default papersize ie PAPER_DEFAULT
1306 switch (lyxrc.default_papersize) {
1307 case PAPER_DEFAULT: // keep compiler happy
1308 case PAPER_USLETTER:
1309 ods << ",letterpaper";
1312 ods << ",legalpaper";
1314 case PAPER_USEXECUTIVE:
1315 ods << ",executivepaper";
1335 docstring const g_options = trim(ods.str(), ",");
1336 os << "\\usepackage";
1337 if (!g_options.empty())
1338 os << '[' << g_options << ']';
1339 os << "{geometry}\n";
1341 os << "\\geometry{verbose";
1342 if (!topmargin.empty())
1343 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1344 if (!bottommargin.empty())
1345 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1346 if (!leftmargin.empty())
1347 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1348 if (!rightmargin.empty())
1349 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1350 if (!headheight.empty())
1351 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1352 if (!headsep.empty())
1353 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1354 if (!footskip.empty())
1355 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1356 if (!columnsep.empty())
1357 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1360 } else if (orientation == ORIENTATION_LANDSCAPE) {
1361 features.require("papersize");
1364 if (tokenPos(tclass.opt_pagestyle(),
1365 '|', pagestyle) >= 0) {
1366 if (pagestyle == "fancy") {
1367 os << "\\usepackage{fancyhdr}\n";
1370 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1374 // only output when the background color is not white
1375 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1376 // only require color here, the background color will be defined
1377 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1379 features.require("color");
1380 features.require("pagecolor");
1383 // Only if class has a ToC hierarchy
1384 if (tclass.hasTocLevels()) {
1385 if (secnumdepth != tclass.secnumdepth()) {
1386 os << "\\setcounter{secnumdepth}{"
1391 if (tocdepth != tclass.tocdepth()) {
1392 os << "\\setcounter{tocdepth}{"
1399 if (paragraph_separation) {
1400 // when skip separation
1401 switch (getDefSkip().kind()) {
1402 case VSpace::SMALLSKIP:
1403 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1405 case VSpace::MEDSKIP:
1406 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1408 case VSpace::BIGSKIP:
1409 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1411 case VSpace::LENGTH:
1412 os << "\\setlength{\\parskip}{"
1413 << from_utf8(getDefSkip().length().asLatexString())
1416 default: // should never happen // Then delete it.
1417 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1421 os << "\\setlength{\\parindent}{0pt}\n";
1424 // when separation by indentation
1425 // only output something when a width is given
1426 if (getIndentation().asLyXCommand() != "default") {
1427 os << "\\setlength{\\parindent}{"
1428 << from_utf8(getIndentation().asLatexCommand())
1434 // Now insert the LyX specific LaTeX commands...
1435 docstring lyxpreamble;
1437 // due to interferences with babel and hyperref, the color package has to
1438 // be loaded (when it is not already loaded) before babel when hyperref
1439 // is used with the colorlinks option, see
1440 // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1441 // we decided therefore to load color always before babel, see
1442 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1443 lyxpreamble += from_ascii(features.getColorOptions());
1445 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1447 && (features.isRequired("jurabib")
1448 || features.isRequired("hyperref")
1449 || features.isRequired("vietnamese")
1450 || features.isRequired("japanese") ) ) {
1452 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1453 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1456 // The optional packages;
1457 lyxpreamble += from_ascii(features.getPackages());
1459 // Additional Indices
1460 if (features.isRequired("splitidx")) {
1461 IndicesList::const_iterator iit = indiceslist().begin();
1462 IndicesList::const_iterator iend = indiceslist().end();
1463 for (; iit != iend; ++iit) {
1464 lyxpreamble += "\\newindex[";
1465 lyxpreamble += iit->index();
1466 lyxpreamble += "]{";
1467 lyxpreamble += iit->shortcut();
1468 lyxpreamble += "}\n";
1473 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1476 // * Hyperref manual: "Make sure it comes last of your loaded
1477 // packages, to give it a fighting chance of not being over-written,
1478 // since its job is to redefine many LaTeX commands."
1479 // * Email from Heiko Oberdiek: "It is usually better to load babel
1480 // before hyperref. Then hyperref has a chance to detect babel.
1481 // * Has to be loaded before the "LyX specific LaTeX commands" to
1482 // avoid errors with algorithm floats.
1483 // use hyperref explicitely when it is required
1484 if (features.isRequired("hyperref")) {
1485 odocstringstream oss;
1486 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1487 lyxpreamble += oss.str();
1490 // Will be surrounded by \makeatletter and \makeatother when not empty
1491 docstring atlyxpreamble;
1493 // Some macros LyX will need
1494 docstring tmppreamble(features.getMacros());
1496 if (!tmppreamble.empty())
1497 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1498 "LyX specific LaTeX commands.\n"
1499 + tmppreamble + '\n';
1501 // the text class specific preamble
1502 tmppreamble = features.getTClassPreamble();
1503 if (!tmppreamble.empty())
1504 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1505 "Textclass specific LaTeX commands.\n"
1506 + tmppreamble + '\n';
1508 // suppress date if selected
1509 // use \@ifundefined because we cannot be sure that every document class
1510 // has a \date command
1512 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1514 /* the user-defined preamble */
1515 if (!containsOnly(preamble, " \n\t"))
1517 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1518 "User specified LaTeX commands.\n"
1519 + from_utf8(preamble) + '\n';
1521 // subfig loads internally the LaTeX package "caption". As
1522 // caption is a very popular package, users will load it in
1523 // the preamble. Therefore we must load subfig behind the
1524 // user-defined preamble and check if the caption package was
1525 // loaded or not. For the case that caption is loaded before
1526 // subfig, there is the subfig option "caption=false". This
1527 // option also works when a koma-script class is used and
1528 // koma's own caption commands are used instead of caption. We
1529 // use \PassOptionsToPackage here because the user could have
1530 // already loaded subfig in the preamble.
1531 if (features.isRequired("subfig")) {
1532 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1533 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1534 "\\usepackage{subfig}\n";
1537 // Itemize bullet settings need to be last in case the user
1538 // defines their own bullets that use a package included
1539 // in the user-defined preamble -- ARRae
1540 // Actually it has to be done much later than that
1541 // since some packages like frenchb make modifications
1542 // at \begin{document} time -- JMarc
1543 docstring bullets_def;
1544 for (int i = 0; i < 4; ++i) {
1545 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1546 if (bullets_def.empty())
1547 bullets_def += "\\AtBeginDocument{\n";
1548 bullets_def += " \\def\\labelitemi";
1550 // `i' is one less than the item to modify
1557 bullets_def += "ii";
1563 bullets_def += '{' +
1564 user_defined_bullet(i).getText()
1569 if (!bullets_def.empty())
1570 atlyxpreamble += bullets_def + "}\n\n";
1572 if (!atlyxpreamble.empty())
1573 lyxpreamble += "\n\\makeatletter\n"
1574 + atlyxpreamble + "\\makeatother\n\n";
1576 // We try to load babel late, in case it interferes with other packages.
1577 // Jurabib and Hyperref have to be called after babel, though.
1578 if (use_babel && !features.isRequired("jurabib")
1579 && !features.isRequired("hyperref")
1580 && !features.isRequired("vietnamese")
1581 && !features.isRequired("japanese")) {
1583 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1584 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1587 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1588 if (!i18npreamble.empty())
1589 lyxpreamble += i18npreamble + '\n';
1592 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1593 for (int j = 0; j != nlines; ++j) {
1599 // these packages (xunicode, for that matter) need to be loaded at least
1600 // after amsmath, amssymb, esint and the other packages that provide
1603 os << "\\usepackage{xunicode}\n";
1605 os << "\\usepackage{xltxtra}\n";
1612 void BufferParams::useClassDefaults()
1614 DocumentClass const & tclass = documentClass();
1616 sides = tclass.sides();
1617 columns = tclass.columns();
1618 pagestyle = tclass.pagestyle();
1619 use_default_options = true;
1620 // Only if class has a ToC hierarchy
1621 if (tclass.hasTocLevels()) {
1622 secnumdepth = tclass.secnumdepth();
1623 tocdepth = tclass.tocdepth();
1628 bool BufferParams::hasClassDefaults() const
1630 DocumentClass const & tclass = documentClass();
1632 return sides == tclass.sides()
1633 && columns == tclass.columns()
1634 && pagestyle == tclass.pagestyle()
1635 && use_default_options
1636 && secnumdepth == tclass.secnumdepth()
1637 && tocdepth == tclass.tocdepth();
1641 DocumentClass const & BufferParams::documentClass() const
1647 DocumentClass const * BufferParams::documentClassPtr() const {
1652 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1653 // evil, but this function is evil
1654 doc_class_ = const_cast<DocumentClass *>(tc);
1658 bool BufferParams::setBaseClass(string const & classname)
1660 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1661 LayoutFileList & bcl = LayoutFileList::get();
1662 if (!bcl.haveClass(classname)) {
1664 bformat(_("The document class %1$s could not be found. "
1665 "A default textclass with default layouts will be used. "
1666 "LyX might not be able to produce output unless a correct "
1667 "textclass is selected from the document settings dialog."),
1668 from_utf8(classname));
1669 frontend::Alert::error(_("Document class not found"), s);
1670 bcl.addEmptyClass(classname);
1673 bool const success = bcl[classname].load();
1676 bformat(_("The document class %1$s could not be loaded."),
1677 from_utf8(classname));
1678 frontend::Alert::error(_("Could not load class"), s);
1682 pimpl_->baseClass_ = classname;
1683 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1688 LayoutFile const * BufferParams::baseClass() const
1690 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1691 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1697 LayoutFileIndex const & BufferParams::baseClassID() const
1699 return pimpl_->baseClass_;
1703 void BufferParams::makeDocumentClass()
1708 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1710 if (!local_layout.empty()) {
1711 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1712 docstring const msg = _("Error reading internal layout information");
1713 frontend::Alert::warning(_("Read Error"), msg);
1718 bool BufferParams::moduleCanBeAdded(string const & modName) const
1720 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1724 bool BufferParams::addLayoutModule(string const & modName)
1726 LayoutModuleList::const_iterator it = layoutModules_.begin();
1727 LayoutModuleList::const_iterator end = layoutModules_.end();
1728 for (; it != end; it++)
1731 layoutModules_.push_back(modName);
1736 Font const BufferParams::getFont() const
1738 FontInfo f = documentClass().defaultfont();
1739 if (fontsDefaultFamily == "rmdefault")
1740 f.setFamily(ROMAN_FAMILY);
1741 else if (fontsDefaultFamily == "sfdefault")
1742 f.setFamily(SANS_FAMILY);
1743 else if (fontsDefaultFamily == "ttdefault")
1744 f.setFamily(TYPEWRITER_FAMILY);
1745 return Font(f, language);
1749 void BufferParams::readPreamble(Lexer & lex)
1751 if (lex.getString() != "\\begin_preamble")
1752 lyxerr << "Error (BufferParams::readPreamble):"
1753 "consistency check failed." << endl;
1755 preamble = lex.getLongString("\\end_preamble");
1759 void BufferParams::readLocalLayout(Lexer & lex)
1761 if (lex.getString() != "\\begin_local_layout")
1762 lyxerr << "Error (BufferParams::readLocalLayout):"
1763 "consistency check failed." << endl;
1765 local_layout = lex.getLongString("\\end_local_layout");
1769 void BufferParams::readLanguage(Lexer & lex)
1771 if (!lex.next()) return;
1773 string const tmptok = lex.getString();
1775 // check if tmptok is part of tex_babel in tex-defs.h
1776 language = languages.getLanguage(tmptok);
1778 // Language tmptok was not found
1779 language = default_language;
1780 lyxerr << "Warning: Setting language `"
1781 << tmptok << "' to `" << language->lang()
1787 void BufferParams::readGraphicsDriver(Lexer & lex)
1792 string const tmptok = lex.getString();
1793 // check if tmptok is part of tex_graphics in tex_defs.h
1796 string const test = tex_graphics[n++];
1798 if (test == tmptok) {
1799 graphicsDriver = tmptok;
1804 "Warning: graphics driver `$$Token' not recognized!\n"
1805 " Setting graphics driver to `default'.\n");
1806 graphicsDriver = "default";
1813 void BufferParams::readBullets(Lexer & lex)
1818 int const index = lex.getInteger();
1820 int temp_int = lex.getInteger();
1821 user_defined_bullet(index).setFont(temp_int);
1822 temp_bullet(index).setFont(temp_int);
1824 user_defined_bullet(index).setCharacter(temp_int);
1825 temp_bullet(index).setCharacter(temp_int);
1827 user_defined_bullet(index).setSize(temp_int);
1828 temp_bullet(index).setSize(temp_int);
1832 void BufferParams::readBulletsLaTeX(Lexer & lex)
1834 // The bullet class should be able to read this.
1837 int const index = lex.getInteger();
1839 docstring const temp_str = lex.getDocString();
1841 user_defined_bullet(index).setText(temp_str);
1842 temp_bullet(index).setText(temp_str);
1846 void BufferParams::readModules(Lexer & lex)
1848 if (!lex.eatLine()) {
1849 lyxerr << "Error (BufferParams::readModules):"
1850 "Unexpected end of input." << endl;
1854 string mod = lex.getString();
1855 if (mod == "\\end_modules")
1857 addLayoutModule(mod);
1863 void BufferParams::readRemovedModules(Lexer & lex)
1865 if (!lex.eatLine()) {
1866 lyxerr << "Error (BufferParams::readRemovedModules):"
1867 "Unexpected end of input." << endl;
1871 string mod = lex.getString();
1872 if (mod == "\\end_removed_modules")
1874 removedModules_.push_back(mod);
1877 // now we want to remove any removed modules that were previously
1878 // added. normally, that will be because default modules were added in
1879 // setBaseClass(), which gets called when \textclass is read at the
1880 // start of the read.
1881 list<string>::const_iterator rit = removedModules_.begin();
1882 list<string>::const_iterator const ren = removedModules_.end();
1883 for (; rit != ren; rit++) {
1884 LayoutModuleList::iterator const mit = layoutModules_.begin();
1885 LayoutModuleList::iterator const men = layoutModules_.end();
1886 LayoutModuleList::iterator found = find(mit, men, *rit);
1889 layoutModules_.erase(found);
1894 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1896 char real_papersize = papersize;
1897 if (real_papersize == PAPER_DEFAULT)
1898 real_papersize = lyxrc.default_papersize;
1900 switch (real_papersize) {
1902 // could be anything, so don't guess
1904 case PAPER_CUSTOM: {
1905 if (purpose == XDVI && !paperwidth.empty() &&
1906 !paperheight.empty()) {
1907 // heightxwidth<unit>
1908 string first = paperwidth;
1909 string second = paperheight;
1910 if (orientation == ORIENTATION_LANDSCAPE)
1913 return first.erase(first.length() - 2)
1925 // dvips and dvipdfm do not know this
1926 if (purpose == DVIPS || purpose == DVIPDFM)
1930 // dvipdfm does not know this
1931 if (purpose == DVIPDFM)
1935 // dvipdfm does not know this
1936 if (purpose == DVIPDFM)
1939 case PAPER_USEXECUTIVE:
1940 // dvipdfm does not know this
1941 if (purpose == DVIPDFM)
1946 case PAPER_USLETTER:
1948 if (purpose == XDVI)
1955 string const BufferParams::dvips_options() const
1960 && papersize == PAPER_CUSTOM
1961 && !lyxrc.print_paper_dimension_flag.empty()
1962 && !paperwidth.empty()
1963 && !paperheight.empty()) {
1964 // using a custom papersize
1965 result = lyxrc.print_paper_dimension_flag;
1966 result += ' ' + paperwidth;
1967 result += ',' + paperheight;
1969 string const paper_option = paperSizeName(DVIPS);
1970 if (!paper_option.empty() && (paper_option != "letter" ||
1971 orientation != ORIENTATION_LANDSCAPE)) {
1972 // dvips won't accept -t letter -t landscape.
1973 // In all other cases, include the paper size
1975 result = lyxrc.print_paper_flag;
1976 result += ' ' + paper_option;
1979 if (orientation == ORIENTATION_LANDSCAPE &&
1980 papersize != PAPER_CUSTOM)
1981 result += ' ' + lyxrc.print_landscape_flag;
1986 string BufferParams::babelCall(string const & lang_opts) const
1988 string lang_pack = lyxrc.language_package;
1989 if (lang_pack != "\\usepackage{babel}")
1991 // suppress the babel call when there is no babel language defined
1992 // for the document language in the lib/languages file and if no
1993 // other languages are used (lang_opts is then empty)
1994 if (lang_opts.empty())
1996 // If Vietnamese is used, babel must directly be loaded with the
1997 // language options, see
1998 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1999 size_t viet = lang_opts.find("vietnam");
2000 // viet = string::npos when not found
2001 // the same is for all other languages that are not directly supported by
2002 // babel, but where LaTeX-packages add babel support.
2003 // this is currently the case for Latvian, Lithuanian, and Mongolian
2004 size_t latvian = lang_opts.find("latvian");
2005 size_t lithu = lang_opts.find("lithuanian");
2006 size_t mongo = lang_opts.find("mongolian");
2007 // If Japanese is used, babel must directly be loaded with the
2008 // language options, see
2009 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
2010 size_t japan = lang_opts.find("japanese");
2011 if (!lyxrc.language_global_options || viet != string::npos
2012 || japan != string::npos || latvian != string::npos
2013 || lithu != string::npos || mongo != string::npos)
2014 return "\\usepackage[" + lang_opts + "]{babel}";
2019 docstring BufferParams::getGraphicsDriver(string const & package) const
2023 if (package == "geometry") {
2024 if (graphicsDriver == "dvips"
2025 || graphicsDriver == "dvipdfm"
2026 || graphicsDriver == "pdftex"
2027 || graphicsDriver == "vtex")
2028 result = from_ascii(graphicsDriver);
2029 else if (graphicsDriver == "dvipdfmx")
2030 result = from_ascii("dvipdfm");
2037 void BufferParams::writeEncodingPreamble(odocstream & os,
2038 LaTeXFeatures & features, TexRow & texrow) const
2042 if (inputenc == "auto") {
2043 string const doc_encoding =
2044 language->encoding()->latexName();
2045 Encoding::Package const package =
2046 language->encoding()->package();
2048 // Create a list with all the input encodings used
2050 set<string> encodings =
2051 features.getEncodingSet(doc_encoding);
2053 // If the "japanese" package (i.e. pLaTeX) is used,
2054 // inputenc must be omitted.
2055 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2056 if (package == Encoding::japanese)
2057 features.require("japanese");
2059 if ((!encodings.empty() || package == Encoding::inputenc)
2060 && !features.isRequired("japanese")) {
2061 os << "\\usepackage[";
2062 set<string>::const_iterator it = encodings.begin();
2063 set<string>::const_iterator const end = encodings.end();
2065 os << from_ascii(*it);
2068 for (; it != end; ++it)
2069 os << ',' << from_ascii(*it);
2070 if (package == Encoding::inputenc) {
2071 if (!encodings.empty())
2073 os << from_ascii(doc_encoding);
2075 os << "]{inputenc}\n";
2078 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2079 if (language->encoding()->name() == "utf8-cjk"
2080 && LaTeXFeatures::isAvailable("CJKutf8"))
2081 os << "\\usepackage{CJKutf8}\n";
2083 os << "\\usepackage{CJK}\n";
2086 } else if (inputenc != "default") {
2087 switch (encoding().package()) {
2088 case Encoding::none:
2089 case Encoding::japanese:
2091 case Encoding::inputenc:
2092 // do not load inputenc if japanese is used
2093 if (features.isRequired("japanese"))
2095 os << "\\usepackage[" << from_ascii(inputenc)
2100 if (encoding().name() == "utf8-cjk"
2101 && LaTeXFeatures::isAvailable("CJKutf8"))
2102 os << "\\usepackage{CJKutf8}\n";
2104 os << "\\usepackage{CJK}\n";
2110 // The encoding "armscii8" (for Armenian) is only available when
2111 // the package "armtex" is loaded.
2112 if (language->encoding()->latexName() == "armscii8"
2113 || inputenc == "armscii8") {
2114 os << "\\usepackage{armtex}\n";
2120 string const BufferParams::parseFontName(string const & name) const
2122 string mangled = name;
2123 size_t const idx = mangled.find('[');
2124 if (idx == string::npos || idx == 0)
2127 return mangled.substr(0, idx - 1);
2131 string const BufferParams::loadFonts(string const & rm,
2132 string const & sf, string const & tt,
2133 bool const & sc, bool const & osf,
2134 int const & sfscale, int const & ttscale,
2135 bool const & xetex) const
2137 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2138 several packages have been replaced by others, that might not
2139 be installed on every system. We have to take care for that
2140 (see psnfss.pdf). We try to support all psnfss fonts as well
2141 as the fonts that have become de facto standard in the LaTeX
2142 world (e.g. Latin Modern). We do not support obsolete fonts
2143 (like PSLatex). In general, it should be possible to mix any
2144 rm font with any sf or tt font, respectively. (JSpitzm)
2146 -- separate math fonts.
2149 if (rm == "default" && sf == "default" && tt == "default")
2156 if (rm != "default")
2157 os << "\\setmainfont[Mapping=tex-text]{"
2158 << parseFontName(rm) << "}\n";
2159 if (sf != "default") {
2160 string const sans = parseFontName(sf);
2162 os << "\\setsansfont[Scale="
2163 << float(sfscale) / 100
2164 << ",Mapping=tex-text]{"
2167 os << "\\setsansfont[Mapping=tex-text]{"
2170 if (tt != "default") {
2171 string const mono = parseFontName(tt);
2173 os << "\\setmonofont[Scale="
2174 << float(sfscale) / 100
2178 os << "\\setmonofont[Mapping=tex-text]{"
2182 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2187 // Computer Modern (must be explicitely selectable -- there might be classes
2188 // that define a different default font!
2190 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2191 // osf for Computer Modern needs eco.sty
2193 os << "\\usepackage{eco}\n";
2195 // Latin Modern Roman
2196 else if (rm == "lmodern")
2197 os << "\\usepackage{lmodern}\n";
2199 else if (rm == "ae") {
2200 // not needed when using OT1 font encoding.
2201 if (lyxrc.fontenc != "default")
2202 os << "\\usepackage{ae,aecompl}\n";
2205 else if (rm == "times") {
2206 // try to load the best available package
2207 if (LaTeXFeatures::isAvailable("mathptmx"))
2208 os << "\\usepackage{mathptmx}\n";
2209 else if (LaTeXFeatures::isAvailable("mathptm"))
2210 os << "\\usepackage{mathptm}\n";
2212 os << "\\usepackage{times}\n";
2215 else if (rm == "palatino") {
2216 // try to load the best available package
2217 if (LaTeXFeatures::isAvailable("mathpazo")) {
2218 os << "\\usepackage";
2224 // "osf" includes "sc"!
2228 os << "{mathpazo}\n";
2230 else if (LaTeXFeatures::isAvailable("mathpple"))
2231 os << "\\usepackage{mathpple}\n";
2233 os << "\\usepackage{palatino}\n";
2236 else if (rm == "utopia") {
2237 // fourier supersedes utopia.sty, but does
2238 // not work with OT1 encoding.
2239 if (LaTeXFeatures::isAvailable("fourier")
2240 && lyxrc.fontenc != "default") {
2241 os << "\\usepackage";
2252 os << "{fourier}\n";
2255 os << "\\usepackage{utopia}\n";
2257 // Bera (complete fontset)
2258 else if (rm == "bera" && sf == "default" && tt == "default")
2259 os << "\\usepackage{bera}\n";
2261 else if (rm != "default")
2262 os << "\\usepackage" << "{" << rm << "}\n";
2265 // Helvetica, Bera Sans
2266 if (sf == "helvet" || sf == "berasans") {
2268 os << "\\usepackage[scaled=" << float(sfscale) / 100
2269 << "]{" << sf << "}\n";
2271 os << "\\usepackage{" << sf << "}\n";
2274 else if (sf == "avant")
2275 os << "\\usepackage{" << sf << "}\n";
2276 // Computer Modern, Latin Modern, CM Bright
2277 else if (sf != "default")
2278 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2280 // monospaced/typewriter
2281 // Courier, LuxiMono
2282 if (tt == "luximono" || tt == "beramono") {
2284 os << "\\usepackage[scaled=" << float(ttscale) / 100
2285 << "]{" << tt << "}\n";
2287 os << "\\usepackage{" << tt << "}\n";
2290 else if (tt == "courier" )
2291 os << "\\usepackage{" << tt << "}\n";
2292 // Computer Modern, Latin Modern, CM Bright
2293 else if (tt != "default")
2294 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2300 Encoding const & BufferParams::encoding() const
2303 return *(encodings.fromLaTeXName("utf8-plain"));
2304 if (inputenc == "auto" || inputenc == "default")
2305 return *language->encoding();
2306 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2309 LYXERR0("Unknown inputenc value `" << inputenc
2310 << "'. Using `auto' instead.");
2311 return *language->encoding();
2315 CiteEngine BufferParams::citeEngine() const
2317 // FIXME the class should provide the numerical/
2318 // authoryear choice
2319 if (documentClass().provides("natbib")
2320 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2321 return ENGINE_NATBIB_AUTHORYEAR;
2322 return cite_engine_;
2326 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2328 cite_engine_ = cite_engine;