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 cite_engine_ = ENGINE_BASIC;
340 use_bibtopic = false;
342 trackChanges = false;
343 outputChanges = false;
344 use_default_options = true;
347 language = default_language;
348 fontsRoman = "default";
349 fontsSans = "default";
350 fontsTypewriter = "default";
351 fontsDefaultFamily = "default";
355 fontsSansScale = 100;
356 fontsTypewriterScale = 100;
358 graphicsDriver = "default";
359 defaultOutputFormat = "default";
360 bibtex_command = "default";
361 index_command = "default";
364 listings_params = string();
365 pagestyle = "default";
366 suppress_date = false;
367 // white is equal to no background color
368 backgroundcolor = lyx::rgbFromHexName("#ffffff");
370 for (int iter = 0; iter < 4; ++iter) {
371 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
372 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
375 indiceslist().addDefault(B_("Index"));
379 docstring BufferParams::B_(string const & l10n) const
381 LASSERT(language, /**/);
382 return getMessages(language->code()).get(l10n);
386 AuthorList & BufferParams::authors()
388 return pimpl_->authorlist;
392 AuthorList const & BufferParams::authors() const
394 return pimpl_->authorlist;
398 BranchList & BufferParams::branchlist()
400 return pimpl_->branchlist;
404 BranchList const & BufferParams::branchlist() const
406 return pimpl_->branchlist;
410 IndicesList & BufferParams::indiceslist()
412 return pimpl_->indiceslist;
416 IndicesList const & BufferParams::indiceslist() const
418 return pimpl_->indiceslist;
422 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
424 LASSERT(index < 4, /**/);
425 return pimpl_->temp_bullets[index];
429 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
431 LASSERT(index < 4, /**/);
432 return pimpl_->temp_bullets[index];
436 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
438 LASSERT(index < 4, /**/);
439 return pimpl_->user_defined_bullets[index];
443 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
445 LASSERT(index < 4, /**/);
446 return pimpl_->user_defined_bullets[index];
450 Spacing & BufferParams::spacing()
452 return pimpl_->spacing;
456 Spacing const & BufferParams::spacing() const
458 return pimpl_->spacing;
462 PDFOptions & BufferParams::pdfoptions()
464 return pimpl_->pdfoptions;
468 PDFOptions const & BufferParams::pdfoptions() const
470 return pimpl_->pdfoptions;
474 HSpace const & BufferParams::getIndentation() const
476 return pimpl_->indentation;
480 void BufferParams::setIndentation(HSpace const & indent)
482 pimpl_->indentation = indent;
486 VSpace const & BufferParams::getDefSkip() const
488 return pimpl_->defskip;
492 void BufferParams::setDefSkip(VSpace const & vs)
494 pimpl_->defskip = vs;
498 string BufferParams::readToken(Lexer & lex, string const & token,
499 FileName const & filepath)
501 if (token == "\\textclass") {
503 string const classname = lex.getString();
504 // if there exists a local layout file, ignore the system one
505 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
507 LayoutFileList & bcl = LayoutFileList::get();
508 if (tcp.empty() && !filepath.empty())
509 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
513 setBaseClass(classname);
514 // We assume that a tex class exists for local or unknown layouts so this warning
515 // will only be given for system layouts.
516 if (!baseClass()->isTeXClassAvailable()) {
517 docstring const msg =
518 bformat(_("The layout file requested by this document,\n"
520 "is not usable. This is probably because a LaTeX\n"
521 "class or style file required by it is not\n"
522 "available. See the Customization documentation\n"
523 "for more information.\n"), from_utf8(classname));
524 frontend::Alert::warning(_("Document class not available"),
525 msg + _("LyX will not be able to produce output."));
527 } else if (token == "\\begin_preamble") {
529 } else if (token == "\\begin_local_layout") {
530 readLocalLayout(lex);
531 } else if (token == "\\begin_modules") {
533 } else if (token == "\\begin_removed_modules") {
534 readRemovedModules(lex);
535 } else if (token == "\\options") {
537 options = lex.getString();
538 } else if (token == "\\use_default_options") {
539 lex >> use_default_options;
540 } else if (token == "\\master") {
542 master = lex.getString();
543 } else if (token == "\\suppress_date") {
544 lex >> suppress_date;
545 } else if (token == "\\language") {
547 } else if (token == "\\inputencoding") {
549 } else if (token == "\\graphics") {
550 readGraphicsDriver(lex);
551 } else if (token == "\\default_output_format") {
552 lex >> defaultOutputFormat;
553 } else if (token == "\\bibtex_command") {
555 bibtex_command = lex.getString();
556 } else if (token == "\\index_command") {
558 index_command = lex.getString();
559 } else if (token == "\\font_roman") {
561 fontsRoman = lex.getString();
562 } else if (token == "\\font_sans") {
564 fontsSans = lex.getString();
565 } else if (token == "\\font_typewriter") {
567 fontsTypewriter = lex.getString();
568 } else if (token == "\\font_default_family") {
569 lex >> fontsDefaultFamily;
570 } else if (token == "\\use_xetex") {
572 } else if (token == "\\font_sc") {
574 } else if (token == "\\font_osf") {
576 } else if (token == "\\font_sf_scale") {
577 lex >> fontsSansScale;
578 } else if (token == "\\font_tt_scale") {
579 lex >> fontsTypewriterScale;
580 } else if (token == "\\font_cjk") {
582 } else if (token == "\\paragraph_separation") {
585 paragraph_separation = parseptranslator().find(parsep);
586 } else if (token == "\\paragraph_indentation") {
588 string indentation = lex.getString();
589 pimpl_->indentation = HSpace(indentation);
590 } else if (token == "\\defskip") {
592 string defskip = lex.getString();
593 if (defskip == "defskip")
596 pimpl_->defskip = VSpace(defskip);
597 } else if (token == "\\quotes_language") {
600 quotes_language = quoteslangtranslator().find(quotes_lang);
601 } else if (token == "\\papersize") {
604 papersize = papersizetranslator().find(ppsize);
605 } else if (token == "\\use_geometry") {
607 } else if (token == "\\use_amsmath") {
610 use_amsmath = packagetranslator().find(use_ams);
611 } else if (token == "\\use_esint") {
614 use_esint = packagetranslator().find(useesint);
615 } else if (token == "\\cite_engine") {
618 cite_engine_ = citeenginetranslator().find(engine);
619 } else if (token == "\\use_bibtopic") {
621 } else if (token == "\\use_indices") {
623 } else if (token == "\\tracking_changes") {
625 } else if (token == "\\output_changes") {
626 lex >> outputChanges;
627 } else if (token == "\\branch") {
629 docstring branch = lex.getDocString();
630 branchlist().add(branch);
633 string const tok = lex.getString();
634 if (tok == "\\end_branch")
636 Branch * branch_ptr = branchlist().find(branch);
637 if (tok == "\\selected") {
640 branch_ptr->setSelected(lex.getInteger());
642 if (tok == "\\filename_suffix") {
645 branch_ptr->setFilenameSuffix(lex.getInteger());
647 if (tok == "\\color") {
649 string color = lex.getString();
651 branch_ptr->setColor(color);
652 // Update also the Color table:
654 color = lcolor.getX11Name(Color_background);
656 lcolor.setColor(to_utf8(branch), color);
659 } else if (token == "\\index") {
661 docstring index = lex.getDocString();
663 indiceslist().add(index);
666 string const tok = lex.getString();
667 if (tok == "\\end_index")
669 Index * index_ptr = indiceslist().find(index);
670 if (tok == "\\shortcut") {
672 shortcut = lex.getDocString();
674 index_ptr->setShortcut(shortcut);
676 if (tok == "\\color") {
678 string color = lex.getString();
680 index_ptr->setColor(color);
681 // Update also the Color table:
683 color = lcolor.getX11Name(Color_background);
685 if (!shortcut.empty())
686 lcolor.setColor(to_utf8(shortcut), color);
689 } else if (token == "\\author") {
691 istringstream ss(lex.getString());
694 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
695 } else if (token == "\\paperorientation") {
698 orientation = paperorientationtranslator().find(orient);
699 } else if (token == "\\backgroundcolor") {
701 backgroundcolor = lyx::rgbFromHexName(lex.getString());
702 } else if (token == "\\paperwidth") {
704 } else if (token == "\\paperheight") {
706 } else if (token == "\\leftmargin") {
708 } else if (token == "\\topmargin") {
710 } else if (token == "\\rightmargin") {
712 } else if (token == "\\bottommargin") {
714 } else if (token == "\\headheight") {
716 } else if (token == "\\headsep") {
718 } else if (token == "\\footskip") {
720 } else if (token == "\\columnsep") {
722 } else if (token == "\\paperfontsize") {
724 } else if (token == "\\papercolumns") {
726 } else if (token == "\\listings_params") {
729 listings_params = InsetListingsParams(par).params();
730 } else if (token == "\\papersides") {
733 sides = sidestranslator().find(psides);
734 } else if (token == "\\paperpagestyle") {
736 } else if (token == "\\bullet") {
738 } else if (token == "\\bulletLaTeX") {
739 readBulletsLaTeX(lex);
740 } else if (token == "\\secnumdepth") {
742 } else if (token == "\\tocdepth") {
744 } else if (token == "\\spacing") {
748 if (nspacing == "other") {
751 spacing().set(spacetranslator().find(nspacing), tmp_val);
752 } else if (token == "\\float_placement") {
753 lex >> float_placement;
755 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
756 string toktmp = pdfoptions().readToken(lex, token);
757 if (!toktmp.empty()) {
758 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
763 lyxerr << "BufferParams::readToken(): Unknown token: " <<
772 void BufferParams::writeFile(ostream & os) const
774 // The top of the file is written by the buffer.
775 // Prints out the buffer info into the .lyx file given by file
778 os << "\\textclass " << baseClass()->name() << '\n';
781 if (!preamble.empty()) {
782 // remove '\n' from the end of preamble
783 string const tmppreamble = rtrim(preamble, "\n");
784 os << "\\begin_preamble\n"
786 << "\n\\end_preamble\n";
790 if (!options.empty()) {
791 os << "\\options " << options << '\n';
794 // use the class options defined in the layout?
795 os << "\\use_default_options "
796 << convert<string>(use_default_options) << "\n";
798 // the master document
799 if (!master.empty()) {
800 os << "\\master " << master << '\n';
804 if (!removedModules_.empty()) {
805 os << "\\begin_removed_modules" << '\n';
806 list<string>::const_iterator it = removedModules_.begin();
807 list<string>::const_iterator en = removedModules_.end();
808 for (; it != en; it++)
810 os << "\\end_removed_modules" << '\n';
814 if (!layoutModules_.empty()) {
815 os << "\\begin_modules" << '\n';
816 LayoutModuleList::const_iterator it = layoutModules_.begin();
817 LayoutModuleList::const_iterator en = layoutModules_.end();
818 for (; it != en; it++)
820 os << "\\end_modules" << '\n';
823 // local layout information
824 if (!local_layout.empty()) {
825 // remove '\n' from the end
826 string const tmplocal = rtrim(local_layout, "\n");
827 os << "\\begin_local_layout\n"
829 << "\n\\end_local_layout\n";
832 // then the text parameters
833 if (language != ignore_language)
834 os << "\\language " << language->lang() << '\n';
835 os << "\\inputencoding " << inputenc
836 << "\n\\font_roman " << fontsRoman
837 << "\n\\font_sans " << fontsSans
838 << "\n\\font_typewriter " << fontsTypewriter
839 << "\n\\font_default_family " << fontsDefaultFamily
840 << "\n\\use_xetex " << convert<string>(useXetex)
841 << "\n\\font_sc " << convert<string>(fontsSC)
842 << "\n\\font_osf " << convert<string>(fontsOSF)
843 << "\n\\font_sf_scale " << fontsSansScale
844 << "\n\\font_tt_scale " << fontsTypewriterScale
846 if (!fontsCJK.empty()) {
847 os << "\\font_cjk " << fontsCJK << '\n';
849 os << "\n\\graphics " << graphicsDriver << '\n';
850 os << "\\default_output_format " << defaultOutputFormat << '\n';
851 os << "\\bibtex_command " << bibtex_command << '\n';
852 os << "\\index_command " << index_command << '\n';
854 if (!float_placement.empty()) {
855 os << "\\float_placement " << float_placement << '\n';
857 os << "\\paperfontsize " << fontsize << '\n';
859 spacing().writeFile(os);
860 pdfoptions().writeFile(os);
862 os << "\\papersize " << string_papersize[papersize]
863 << "\n\\use_geometry " << convert<string>(use_geometry)
864 << "\n\\use_amsmath " << use_amsmath
865 << "\n\\use_esint " << use_esint
866 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
867 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
868 << "\n\\use_indices " << convert<string>(use_indices)
869 << "\n\\paperorientation " << string_orientation[orientation]
870 << "\n\\suppress_date " << convert<string>(suppress_date)
872 if (backgroundcolor != lyx::rgbFromHexName("#ffffff"))
873 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
875 BranchList::const_iterator it = branchlist().begin();
876 BranchList::const_iterator end = branchlist().end();
877 for (; it != end; ++it) {
878 os << "\\branch " << to_utf8(it->branch())
879 << "\n\\selected " << it->isSelected()
880 << "\n\\filename_suffix " << it->hasFilenameSuffix()
881 << "\n\\color " << lyx::X11hexname(it->color())
886 IndicesList::const_iterator iit = indiceslist().begin();
887 IndicesList::const_iterator iend = indiceslist().end();
888 for (; iit != iend; ++iit) {
889 os << "\\index " << to_utf8(iit->index())
890 << "\n\\shortcut " << to_utf8(iit->shortcut())
891 << "\n\\color " << lyx::X11hexname(iit->color())
896 if (!paperwidth.empty())
897 os << "\\paperwidth "
898 << VSpace(paperwidth).asLyXCommand() << '\n';
899 if (!paperheight.empty())
900 os << "\\paperheight "
901 << VSpace(paperheight).asLyXCommand() << '\n';
902 if (!leftmargin.empty())
903 os << "\\leftmargin "
904 << VSpace(leftmargin).asLyXCommand() << '\n';
905 if (!topmargin.empty())
907 << VSpace(topmargin).asLyXCommand() << '\n';
908 if (!rightmargin.empty())
909 os << "\\rightmargin "
910 << VSpace(rightmargin).asLyXCommand() << '\n';
911 if (!bottommargin.empty())
912 os << "\\bottommargin "
913 << VSpace(bottommargin).asLyXCommand() << '\n';
914 if (!headheight.empty())
915 os << "\\headheight "
916 << VSpace(headheight).asLyXCommand() << '\n';
917 if (!headsep.empty())
919 << VSpace(headsep).asLyXCommand() << '\n';
920 if (!footskip.empty())
922 << VSpace(footskip).asLyXCommand() << '\n';
923 if (!columnsep.empty())
925 << VSpace(columnsep).asLyXCommand() << '\n';
926 os << "\\secnumdepth " << secnumdepth
927 << "\n\\tocdepth " << tocdepth
928 << "\n\\paragraph_separation "
929 << string_paragraph_separation[paragraph_separation];
930 if (!paragraph_separation)
931 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
933 os << "\n\\defskip " << getDefSkip().asLyXCommand();
934 os << "\n\\quotes_language "
935 << string_quotes_language[quotes_language]
936 << "\n\\papercolumns " << columns
937 << "\n\\papersides " << sides
938 << "\n\\paperpagestyle " << pagestyle << '\n';
939 if (!listings_params.empty())
940 os << "\\listings_params \"" <<
941 InsetListingsParams(listings_params).encodedString() << "\"\n";
942 for (int i = 0; i < 4; ++i) {
943 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
944 if (user_defined_bullet(i).getFont() != -1) {
945 os << "\\bullet " << i << " "
946 << user_defined_bullet(i).getFont() << " "
947 << user_defined_bullet(i).getCharacter() << " "
948 << user_defined_bullet(i).getSize() << "\n";
952 os << "\\bulletLaTeX " << i << " \""
953 << lyx::to_ascii(user_defined_bullet(i).getText())
959 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
960 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
962 os << pimpl_->authorlist;
966 void BufferParams::validate(LaTeXFeatures & features) const
968 features.require(documentClass().requires());
971 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
972 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
973 LaTeXFeatures::isAvailable("xcolor");
975 switch (features.runparams().flavor) {
976 case OutputParams::LATEX:
978 features.require("ct-dvipost");
979 features.require("dvipost");
980 } else if (xcolorulem) {
981 features.require("ct-xcolor-ulem");
982 features.require("ulem");
983 features.require("xcolor");
985 features.require("ct-none");
988 case OutputParams::PDFLATEX:
989 case OutputParams::XETEX:
991 features.require("ct-xcolor-ulem");
992 features.require("ulem");
993 features.require("xcolor");
994 // improves color handling in PDF output
995 features.require("pdfcolmk");
997 features.require("ct-none");
1005 // Floats with 'Here definitely' as default setting.
1006 if (float_placement.find('H') != string::npos)
1007 features.require("float");
1009 // AMS Style is at document level
1010 if (use_amsmath == package_on
1011 || documentClass().provides("amsmath"))
1012 features.require("amsmath");
1013 if (use_esint == package_on)
1014 features.require("esint");
1016 // Document-level line spacing
1017 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1018 features.require("setspace");
1020 // the bullet shapes are buffer level not paragraph level
1021 // so they are tested here
1022 for (int i = 0; i < 4; ++i) {
1023 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1025 int const font = user_defined_bullet(i).getFont();
1027 int const c = user_defined_bullet(i).getCharacter();
1033 features.require("latexsym");
1035 } else if (font == 1) {
1036 features.require("amssymb");
1037 } else if (font >= 2 && font <= 5) {
1038 features.require("pifont");
1042 if (pdfoptions().use_hyperref) {
1043 features.require("hyperref");
1044 // due to interferences with babel and hyperref, the color package has to
1045 // be loaded after hyperref when hyperref is used with the colorlinks
1046 // option, see http://bugzilla.lyx.org/show_bug.cgi?id=5291
1047 if (pdfoptions().colorlinks)
1048 features.require("color");
1052 features.require("xetex");
1054 if (language->lang() == "vietnamese")
1055 features.require("vietnamese");
1056 else if (language->lang() == "japanese")
1057 features.require("japanese");
1061 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1062 TexRow & texrow) const
1064 os << "\\documentclass";
1066 DocumentClass const & tclass = documentClass();
1068 ostringstream clsoptions; // the document class options.
1070 if (tokenPos(tclass.opt_fontsize(),
1071 '|', fontsize) >= 0) {
1072 // only write if existing in list (and not default)
1073 clsoptions << fontsize << "pt,";
1076 // custom, A3, B3 and B4 paper sizes need geometry
1077 bool nonstandard_papersize = papersize == PAPER_B3
1078 || papersize == PAPER_B4
1079 || papersize == PAPER_A3
1080 || papersize == PAPER_CUSTOM;
1082 if (!use_geometry) {
1083 switch (papersize) {
1085 clsoptions << "a4paper,";
1087 case PAPER_USLETTER:
1088 clsoptions << "letterpaper,";
1091 clsoptions << "a5paper,";
1094 clsoptions << "b5paper,";
1096 case PAPER_USEXECUTIVE:
1097 clsoptions << "executivepaper,";
1100 clsoptions << "legalpaper,";
1112 if (sides != tclass.sides()) {
1115 clsoptions << "oneside,";
1118 clsoptions << "twoside,";
1124 if (columns != tclass.columns()) {
1126 clsoptions << "twocolumn,";
1128 clsoptions << "onecolumn,";
1132 && orientation == ORIENTATION_LANDSCAPE)
1133 clsoptions << "landscape,";
1135 // language should be a parameter to \documentclass
1136 if (language->babel() == "hebrew"
1137 && default_language->babel() != "hebrew")
1138 // This seems necessary
1139 features.useLanguage(default_language);
1141 ostringstream language_options;
1142 bool const use_babel = features.useBabel();
1144 language_options << features.getLanguages();
1145 if (!language->babel().empty()) {
1146 if (!language_options.str().empty())
1147 language_options << ',';
1148 language_options << language->babel();
1150 // if Vietnamese is used, babel must directly be loaded
1151 // with language options, not in the class options, see
1152 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1153 size_t viet = language_options.str().find("vietnam");
1154 // viet = string::npos when not found
1155 // the same is for all other languages that are not directly supported by
1156 // babel, but where LaTeX-packages add babel support.
1157 // this is currently the case for Latvian, Lithuanian, and Mongolian
1158 size_t latvian = language_options.str().find("latvian");
1159 size_t lithu = language_options.str().find("lithuanian");
1160 size_t mongo = language_options.str().find("mongolian");
1161 // if Japanese is used, babel must directly be loaded
1162 // with language options, not in the class options, see
1163 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1164 size_t japan = language_options.str().find("japanese");
1165 if (lyxrc.language_global_options && !language_options.str().empty()
1166 && viet == string::npos && japan == string::npos
1167 && latvian == string::npos && lithu == string::npos
1168 && mongo == string::npos)
1169 clsoptions << language_options.str() << ',';
1172 // the predefined options from the layout
1173 if (use_default_options && !tclass.options().empty())
1174 clsoptions << tclass.options() << ',';
1176 // the user-defined options
1177 if (!options.empty()) {
1178 clsoptions << options << ',';
1181 string strOptions(clsoptions.str());
1182 if (!strOptions.empty()) {
1183 strOptions = rtrim(strOptions, ",");
1185 os << '[' << from_utf8(strOptions) << ']';
1188 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1190 // end of \documentclass defs
1193 os << "\\usepackage{fontspec}\n";
1197 // font selection must be done before loading fontenc.sty
1198 string const fonts =
1199 loadFonts(fontsRoman, fontsSans,
1200 fontsTypewriter, fontsSC, fontsOSF,
1201 fontsSansScale, fontsTypewriterScale, useXetex);
1202 if (!fonts.empty()) {
1203 os << from_ascii(fonts);
1206 if (fontsDefaultFamily != "default")
1207 os << "\\renewcommand{\\familydefault}{\\"
1208 << from_ascii(fontsDefaultFamily) << "}\n";
1210 // set font encoding
1211 // this one is not per buffer
1212 // for arabic_arabi and farsi we also need to load the LAE and
1214 // XeTeX works without fontenc
1215 if (lyxrc.fontenc != "default" && language->lang() != "japanese"
1217 if (language->lang() == "arabic_arabi"
1218 || language->lang() == "farsi") {
1219 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1220 << ",LFE,LAE]{fontenc}\n";
1223 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1229 // handle inputenc etc.
1230 writeEncodingPreamble(os, features, texrow);
1232 if (!listings_params.empty() || features.isRequired("listings")) {
1233 os << "\\usepackage{listings}\n";
1236 if (!listings_params.empty()) {
1238 // do not test validity because listings_params is
1239 // supposed to be valid
1241 InsetListingsParams(listings_params).separatedParams(true);
1242 // we can't support all packages, but we should load the color package
1243 if (par.find("\\color", 0) != string::npos)
1244 features.require("color");
1245 os << from_utf8(par);
1246 // count the number of newlines
1247 for (size_t i = 0; i < par.size(); ++i)
1253 if (!tclass.provides("geometry")
1254 && (use_geometry || nonstandard_papersize)) {
1255 odocstringstream ods;
1256 if (!getGraphicsDriver("geometry").empty())
1257 ods << getGraphicsDriver("geometry");
1258 if (orientation == ORIENTATION_LANDSCAPE)
1259 ods << ",landscape";
1260 switch (papersize) {
1262 if (!paperwidth.empty())
1263 ods << ",paperwidth="
1264 << from_ascii(paperwidth);
1265 if (!paperheight.empty())
1266 ods << ",paperheight="
1267 << from_ascii(paperheight);
1269 case PAPER_USLETTER:
1270 ods << ",letterpaper";
1273 ods << ",legalpaper";
1275 case PAPER_USEXECUTIVE:
1276 ods << ",executivepaper";
1297 // default papersize ie PAPER_DEFAULT
1298 switch (lyxrc.default_papersize) {
1299 case PAPER_DEFAULT: // keep compiler happy
1300 case PAPER_USLETTER:
1301 ods << ",letterpaper";
1304 ods << ",legalpaper";
1306 case PAPER_USEXECUTIVE:
1307 ods << ",executivepaper";
1327 docstring const g_options = trim(ods.str(), ",");
1328 os << "\\usepackage";
1329 if (!g_options.empty())
1330 os << '[' << g_options << ']';
1331 os << "{geometry}\n";
1333 os << "\\geometry{verbose";
1334 if (!topmargin.empty())
1335 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1336 if (!bottommargin.empty())
1337 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1338 if (!leftmargin.empty())
1339 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1340 if (!rightmargin.empty())
1341 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1342 if (!headheight.empty())
1343 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1344 if (!headsep.empty())
1345 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1346 if (!footskip.empty())
1347 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1348 if (!columnsep.empty())
1349 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1352 } else if (orientation == ORIENTATION_LANDSCAPE) {
1353 features.require("papersize");
1356 if (tokenPos(tclass.opt_pagestyle(),
1357 '|', pagestyle) >= 0) {
1358 if (pagestyle == "fancy") {
1359 os << "\\usepackage{fancyhdr}\n";
1362 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1366 // only output when the background color is not white
1367 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1368 // only require color here, the background color will be defined
1369 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1371 features.require("color");
1372 features.require("pagecolor");
1375 // Only if class has a ToC hierarchy
1376 if (tclass.hasTocLevels()) {
1377 if (secnumdepth != tclass.secnumdepth()) {
1378 os << "\\setcounter{secnumdepth}{"
1383 if (tocdepth != tclass.tocdepth()) {
1384 os << "\\setcounter{tocdepth}{"
1391 if (paragraph_separation) {
1392 // when skip separation
1393 switch (getDefSkip().kind()) {
1394 case VSpace::SMALLSKIP:
1395 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1397 case VSpace::MEDSKIP:
1398 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1400 case VSpace::BIGSKIP:
1401 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1403 case VSpace::LENGTH:
1404 os << "\\setlength{\\parskip}{"
1405 << from_utf8(getDefSkip().length().asLatexString())
1408 default: // should never happen // Then delete it.
1409 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1413 os << "\\setlength{\\parindent}{0pt}\n";
1416 // when separation by indentation
1417 // only output something when a width is given
1418 if (getIndentation().asLyXCommand() != "default") {
1419 os << "\\setlength{\\parindent}{"
1420 << from_utf8(getIndentation().asLatexCommand())
1426 // Now insert the LyX specific LaTeX commands...
1427 docstring lyxpreamble;
1429 // due to interferences with babel and hyperref, the color package has to
1430 // be loaded (when it is not already loaded) before babel when hyperref
1431 // is used with the colorlinks option, see
1432 // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1433 // we decided therefore to load color always before babel, see
1434 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1435 lyxpreamble += from_ascii(features.getColorOptions());
1437 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1439 && (features.isRequired("jurabib")
1440 || features.isRequired("hyperref")
1441 || features.isRequired("vietnamese")
1442 || features.isRequired("japanese") ) ) {
1444 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1445 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1448 // The optional packages;
1449 lyxpreamble += from_ascii(features.getPackages());
1451 // Additional Indices
1452 if (features.isRequired("splitidx")) {
1453 IndicesList::const_iterator iit = indiceslist().begin();
1454 IndicesList::const_iterator iend = indiceslist().end();
1455 for (; iit != iend; ++iit) {
1456 lyxpreamble += "\\newindex[";
1457 lyxpreamble += iit->index();
1458 lyxpreamble += "]{";
1459 lyxpreamble += iit->shortcut();
1460 lyxpreamble += "}\n";
1465 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1468 // * Hyperref manual: "Make sure it comes last of your loaded
1469 // packages, to give it a fighting chance of not being over-written,
1470 // since its job is to redefine many LaTeX commands."
1471 // * Email from Heiko Oberdiek: "It is usually better to load babel
1472 // before hyperref. Then hyperref has a chance to detect babel.
1473 // * Has to be loaded before the "LyX specific LaTeX commands" to
1474 // avoid errors with algorithm floats.
1475 // use hyperref explicitely when it is required
1476 if (features.isRequired("hyperref")) {
1477 odocstringstream oss;
1478 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1479 lyxpreamble += oss.str();
1482 // Will be surrounded by \makeatletter and \makeatother when not empty
1483 docstring atlyxpreamble;
1485 // Some macros LyX will need
1486 docstring tmppreamble(features.getMacros());
1488 if (!tmppreamble.empty())
1489 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1490 "LyX specific LaTeX commands.\n"
1491 + tmppreamble + '\n';
1493 // the text class specific preamble
1494 tmppreamble = features.getTClassPreamble();
1495 if (!tmppreamble.empty())
1496 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1497 "Textclass specific LaTeX commands.\n"
1498 + tmppreamble + '\n';
1500 // suppress date if selected
1501 // use \@ifundefined because we cannot be sure that every document class
1502 // has a \date command
1504 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1506 /* the user-defined preamble */
1507 if (!containsOnly(preamble, " \n\t"))
1509 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1510 "User specified LaTeX commands.\n"
1511 + from_utf8(preamble) + '\n';
1513 // subfig loads internally the LaTeX package "caption". As
1514 // caption is a very popular package, users will load it in
1515 // the preamble. Therefore we must load subfig behind the
1516 // user-defined preamble and check if the caption package was
1517 // loaded or not. For the case that caption is loaded before
1518 // subfig, there is the subfig option "caption=false". This
1519 // option also works when a koma-script class is used and
1520 // koma's own caption commands are used instead of caption. We
1521 // use \PassOptionsToPackage here because the user could have
1522 // already loaded subfig in the preamble.
1523 if (features.isRequired("subfig")) {
1524 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1525 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1526 "\\usepackage{subfig}\n";
1529 // Itemize bullet settings need to be last in case the user
1530 // defines their own bullets that use a package included
1531 // in the user-defined preamble -- ARRae
1532 // Actually it has to be done much later than that
1533 // since some packages like frenchb make modifications
1534 // at \begin{document} time -- JMarc
1535 docstring bullets_def;
1536 for (int i = 0; i < 4; ++i) {
1537 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1538 if (bullets_def.empty())
1539 bullets_def += "\\AtBeginDocument{\n";
1540 bullets_def += " \\def\\labelitemi";
1542 // `i' is one less than the item to modify
1549 bullets_def += "ii";
1555 bullets_def += '{' +
1556 user_defined_bullet(i).getText()
1561 if (!bullets_def.empty())
1562 atlyxpreamble += bullets_def + "}\n\n";
1564 if (!atlyxpreamble.empty())
1565 lyxpreamble += "\n\\makeatletter\n"
1566 + atlyxpreamble + "\\makeatother\n\n";
1568 // We try to load babel late, in case it interferes with other packages.
1569 // Jurabib and Hyperref have to be called after babel, though.
1570 if (use_babel && !features.isRequired("jurabib")
1571 && !features.isRequired("hyperref")
1572 && !features.isRequired("vietnamese")
1573 && !features.isRequired("japanese")) {
1575 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1576 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1579 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1580 if (!i18npreamble.empty())
1581 lyxpreamble += i18npreamble + '\n';
1584 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1585 for (int j = 0; j != nlines; ++j) {
1591 // these packages (xunicode, for that matter) need to be loaded at least
1592 // after amsmath, amssymb, esint and the other packages that provide
1595 os << "\\usepackage{xunicode}\n";
1597 os << "\\usepackage{xltxtra}\n";
1604 void BufferParams::useClassDefaults()
1606 DocumentClass const & tclass = documentClass();
1608 sides = tclass.sides();
1609 columns = tclass.columns();
1610 pagestyle = tclass.pagestyle();
1611 use_default_options = true;
1612 // Only if class has a ToC hierarchy
1613 if (tclass.hasTocLevels()) {
1614 secnumdepth = tclass.secnumdepth();
1615 tocdepth = tclass.tocdepth();
1620 bool BufferParams::hasClassDefaults() const
1622 DocumentClass const & tclass = documentClass();
1624 return sides == tclass.sides()
1625 && columns == tclass.columns()
1626 && pagestyle == tclass.pagestyle()
1627 && use_default_options
1628 && secnumdepth == tclass.secnumdepth()
1629 && tocdepth == tclass.tocdepth();
1633 DocumentClass const & BufferParams::documentClass() const
1639 DocumentClass const * BufferParams::documentClassPtr() const {
1644 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1645 // evil, but this function is evil
1646 doc_class_ = const_cast<DocumentClass *>(tc);
1650 bool BufferParams::setBaseClass(string const & classname)
1652 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1653 LayoutFileList & bcl = LayoutFileList::get();
1654 if (!bcl.haveClass(classname)) {
1656 bformat(_("The document class %1$s could not be found. "
1657 "A default textclass with default layouts will be used. "
1658 "LyX might not be able to produce output unless a correct "
1659 "textclass is selected from the document settings dialog."),
1660 from_utf8(classname));
1661 frontend::Alert::error(_("Document class not found"), s);
1662 bcl.addEmptyClass(classname);
1665 bool const success = bcl[classname].load();
1668 bformat(_("The document class %1$s could not be loaded."),
1669 from_utf8(classname));
1670 frontend::Alert::error(_("Could not load class"), s);
1674 pimpl_->baseClass_ = classname;
1675 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1680 LayoutFile const * BufferParams::baseClass() const
1682 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1683 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1689 LayoutFileIndex const & BufferParams::baseClassID() const
1691 return pimpl_->baseClass_;
1695 void BufferParams::makeDocumentClass()
1700 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1702 if (!local_layout.empty()) {
1703 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1704 docstring const msg = _("Error reading internal layout information");
1705 frontend::Alert::warning(_("Read Error"), msg);
1710 bool BufferParams::moduleCanBeAdded(string const & modName) const
1712 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1716 bool BufferParams::addLayoutModule(string const & modName)
1718 LayoutModuleList::const_iterator it = layoutModules_.begin();
1719 LayoutModuleList::const_iterator end = layoutModules_.end();
1720 for (; it != end; it++)
1723 layoutModules_.push_back(modName);
1728 Font const BufferParams::getFont() const
1730 FontInfo f = documentClass().defaultfont();
1731 if (fontsDefaultFamily == "rmdefault")
1732 f.setFamily(ROMAN_FAMILY);
1733 else if (fontsDefaultFamily == "sfdefault")
1734 f.setFamily(SANS_FAMILY);
1735 else if (fontsDefaultFamily == "ttdefault")
1736 f.setFamily(TYPEWRITER_FAMILY);
1737 return Font(f, language);
1741 void BufferParams::readPreamble(Lexer & lex)
1743 if (lex.getString() != "\\begin_preamble")
1744 lyxerr << "Error (BufferParams::readPreamble):"
1745 "consistency check failed." << endl;
1747 preamble = lex.getLongString("\\end_preamble");
1751 void BufferParams::readLocalLayout(Lexer & lex)
1753 if (lex.getString() != "\\begin_local_layout")
1754 lyxerr << "Error (BufferParams::readLocalLayout):"
1755 "consistency check failed." << endl;
1757 local_layout = lex.getLongString("\\end_local_layout");
1761 void BufferParams::readLanguage(Lexer & lex)
1763 if (!lex.next()) return;
1765 string const tmptok = lex.getString();
1767 // check if tmptok is part of tex_babel in tex-defs.h
1768 language = languages.getLanguage(tmptok);
1770 // Language tmptok was not found
1771 language = default_language;
1772 lyxerr << "Warning: Setting language `"
1773 << tmptok << "' to `" << language->lang()
1779 void BufferParams::readGraphicsDriver(Lexer & lex)
1784 string const tmptok = lex.getString();
1785 // check if tmptok is part of tex_graphics in tex_defs.h
1788 string const test = tex_graphics[n++];
1790 if (test == tmptok) {
1791 graphicsDriver = tmptok;
1796 "Warning: graphics driver `$$Token' not recognized!\n"
1797 " Setting graphics driver to `default'.\n");
1798 graphicsDriver = "default";
1805 void BufferParams::readBullets(Lexer & lex)
1810 int const index = lex.getInteger();
1812 int temp_int = lex.getInteger();
1813 user_defined_bullet(index).setFont(temp_int);
1814 temp_bullet(index).setFont(temp_int);
1816 user_defined_bullet(index).setCharacter(temp_int);
1817 temp_bullet(index).setCharacter(temp_int);
1819 user_defined_bullet(index).setSize(temp_int);
1820 temp_bullet(index).setSize(temp_int);
1824 void BufferParams::readBulletsLaTeX(Lexer & lex)
1826 // The bullet class should be able to read this.
1829 int const index = lex.getInteger();
1831 docstring const temp_str = lex.getDocString();
1833 user_defined_bullet(index).setText(temp_str);
1834 temp_bullet(index).setText(temp_str);
1838 void BufferParams::readModules(Lexer & lex)
1840 if (!lex.eatLine()) {
1841 lyxerr << "Error (BufferParams::readModules):"
1842 "Unexpected end of input." << endl;
1846 string mod = lex.getString();
1847 if (mod == "\\end_modules")
1849 addLayoutModule(mod);
1855 void BufferParams::readRemovedModules(Lexer & lex)
1857 if (!lex.eatLine()) {
1858 lyxerr << "Error (BufferParams::readRemovedModules):"
1859 "Unexpected end of input." << endl;
1863 string mod = lex.getString();
1864 if (mod == "\\end_removed_modules")
1866 removedModules_.push_back(mod);
1869 // now we want to remove any removed modules that were previously
1870 // added. normally, that will be because default modules were added in
1871 // setBaseClass(), which gets called when \textclass is read at the
1872 // start of the read.
1873 list<string>::const_iterator rit = removedModules_.begin();
1874 list<string>::const_iterator const ren = removedModules_.end();
1875 for (; rit != ren; rit++) {
1876 LayoutModuleList::iterator const mit = layoutModules_.begin();
1877 LayoutModuleList::iterator const men = layoutModules_.end();
1878 LayoutModuleList::iterator found = find(mit, men, *rit);
1881 layoutModules_.erase(found);
1886 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1888 char real_papersize = papersize;
1889 if (real_papersize == PAPER_DEFAULT)
1890 real_papersize = lyxrc.default_papersize;
1892 switch (real_papersize) {
1894 // could be anything, so don't guess
1896 case PAPER_CUSTOM: {
1897 if (purpose == XDVI && !paperwidth.empty() &&
1898 !paperheight.empty()) {
1899 // heightxwidth<unit>
1900 string first = paperwidth;
1901 string second = paperheight;
1902 if (orientation == ORIENTATION_LANDSCAPE)
1905 return first.erase(first.length() - 2)
1917 // dvips and dvipdfm do not know this
1918 if (purpose == DVIPS || purpose == DVIPDFM)
1922 // dvipdfm does not know this
1923 if (purpose == DVIPDFM)
1927 // dvipdfm does not know this
1928 if (purpose == DVIPDFM)
1931 case PAPER_USEXECUTIVE:
1932 // dvipdfm does not know this
1933 if (purpose == DVIPDFM)
1938 case PAPER_USLETTER:
1940 if (purpose == XDVI)
1947 string const BufferParams::dvips_options() const
1952 && papersize == PAPER_CUSTOM
1953 && !lyxrc.print_paper_dimension_flag.empty()
1954 && !paperwidth.empty()
1955 && !paperheight.empty()) {
1956 // using a custom papersize
1957 result = lyxrc.print_paper_dimension_flag;
1958 result += ' ' + paperwidth;
1959 result += ',' + paperheight;
1961 string const paper_option = paperSizeName(DVIPS);
1962 if (!paper_option.empty() && (paper_option != "letter" ||
1963 orientation != ORIENTATION_LANDSCAPE)) {
1964 // dvips won't accept -t letter -t landscape.
1965 // In all other cases, include the paper size
1967 result = lyxrc.print_paper_flag;
1968 result += ' ' + paper_option;
1971 if (orientation == ORIENTATION_LANDSCAPE &&
1972 papersize != PAPER_CUSTOM)
1973 result += ' ' + lyxrc.print_landscape_flag;
1978 string BufferParams::babelCall(string const & lang_opts) const
1980 string lang_pack = lyxrc.language_package;
1981 if (lang_pack != "\\usepackage{babel}")
1983 // suppress the babel call when there is no babel language defined
1984 // for the document language in the lib/languages file and if no
1985 // other languages are used (lang_opts is then empty)
1986 if (lang_opts.empty())
1988 // If Vietnamese is used, babel must directly be loaded with the
1989 // language options, see
1990 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1991 size_t viet = lang_opts.find("vietnam");
1992 // viet = string::npos when not found
1993 // the same is for all other languages that are not directly supported by
1994 // babel, but where LaTeX-packages add babel support.
1995 // this is currently the case for Latvian, Lithuanian, and Mongolian
1996 size_t latvian = lang_opts.find("latvian");
1997 size_t lithu = lang_opts.find("lithuanian");
1998 size_t mongo = lang_opts.find("mongolian");
1999 // If Japanese is used, babel must directly be loaded with the
2000 // language options, see
2001 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
2002 size_t japan = lang_opts.find("japanese");
2003 if (!lyxrc.language_global_options || viet != string::npos
2004 || japan != string::npos || latvian != string::npos
2005 || lithu != string::npos || mongo != string::npos)
2006 return "\\usepackage[" + lang_opts + "]{babel}";
2011 docstring BufferParams::getGraphicsDriver(string const & package) const
2015 if (package == "geometry") {
2016 if (graphicsDriver == "dvips"
2017 || graphicsDriver == "dvipdfm"
2018 || graphicsDriver == "pdftex"
2019 || graphicsDriver == "vtex")
2020 result = from_ascii(graphicsDriver);
2021 else if (graphicsDriver == "dvipdfmx")
2022 result = from_ascii("dvipdfm");
2029 void BufferParams::writeEncodingPreamble(odocstream & os,
2030 LaTeXFeatures & features, TexRow & texrow) const
2034 if (inputenc == "auto") {
2035 string const doc_encoding =
2036 language->encoding()->latexName();
2037 Encoding::Package const package =
2038 language->encoding()->package();
2040 // Create a list with all the input encodings used
2042 set<string> encodings =
2043 features.getEncodingSet(doc_encoding);
2045 // If the "japanese" package (i.e. pLaTeX) is used,
2046 // inputenc must be omitted.
2047 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2048 if (package == Encoding::japanese)
2049 features.require("japanese");
2051 if ((!encodings.empty() || package == Encoding::inputenc)
2052 && !features.isRequired("japanese")) {
2053 os << "\\usepackage[";
2054 set<string>::const_iterator it = encodings.begin();
2055 set<string>::const_iterator const end = encodings.end();
2057 os << from_ascii(*it);
2060 for (; it != end; ++it)
2061 os << ',' << from_ascii(*it);
2062 if (package == Encoding::inputenc) {
2063 if (!encodings.empty())
2065 os << from_ascii(doc_encoding);
2067 os << "]{inputenc}\n";
2070 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2071 if (language->encoding()->name() == "utf8-cjk"
2072 && LaTeXFeatures::isAvailable("CJKutf8"))
2073 os << "\\usepackage{CJKutf8}\n";
2075 os << "\\usepackage{CJK}\n";
2078 } else if (inputenc != "default") {
2079 switch (encoding().package()) {
2080 case Encoding::none:
2081 case Encoding::japanese:
2083 case Encoding::inputenc:
2084 // do not load inputenc if japanese is used
2085 if (features.isRequired("japanese"))
2087 os << "\\usepackage[" << from_ascii(inputenc)
2092 if (encoding().name() == "utf8-cjk"
2093 && LaTeXFeatures::isAvailable("CJKutf8"))
2094 os << "\\usepackage{CJKutf8}\n";
2096 os << "\\usepackage{CJK}\n";
2102 // The encoding "armscii8" (for Armenian) is only available when
2103 // the package "armtex" is loaded.
2104 if (language->encoding()->latexName() == "armscii8"
2105 || inputenc == "armscii8") {
2106 os << "\\usepackage{armtex}\n";
2112 string const BufferParams::parseFontName(string const & name) const
2114 string mangled = name;
2115 size_t const idx = mangled.find('[');
2116 if (idx == string::npos || idx == 0)
2119 return mangled.substr(0, idx - 1);
2123 string const BufferParams::loadFonts(string const & rm,
2124 string const & sf, string const & tt,
2125 bool const & sc, bool const & osf,
2126 int const & sfscale, int const & ttscale,
2127 bool const & xetex) const
2129 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2130 several packages have been replaced by others, that might not
2131 be installed on every system. We have to take care for that
2132 (see psnfss.pdf). We try to support all psnfss fonts as well
2133 as the fonts that have become de facto standard in the LaTeX
2134 world (e.g. Latin Modern). We do not support obsolete fonts
2135 (like PSLatex). In general, it should be possible to mix any
2136 rm font with any sf or tt font, respectively. (JSpitzm)
2138 -- separate math fonts.
2141 if (rm == "default" && sf == "default" && tt == "default")
2148 if (rm != "default")
2149 os << "\\setmainfont[Mapping=tex-text]{"
2150 << parseFontName(rm) << "}\n";
2151 if (sf != "default") {
2152 string const sans = parseFontName(sf);
2154 os << "\\setsansfont[Scale="
2155 << float(sfscale) / 100
2156 << ",Mapping=tex-text]{"
2159 os << "\\setsansfont[Mapping=tex-text]{"
2162 if (tt != "default") {
2163 string const mono = parseFontName(tt);
2165 os << "\\setmonofont[Scale="
2166 << float(sfscale) / 100
2170 os << "\\setmonofont[Mapping=tex-text]{"
2174 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2179 // Computer Modern (must be explicitely selectable -- there might be classes
2180 // that define a different default font!
2182 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2183 // osf for Computer Modern needs eco.sty
2185 os << "\\usepackage{eco}\n";
2187 // Latin Modern Roman
2188 else if (rm == "lmodern")
2189 os << "\\usepackage{lmodern}\n";
2191 else if (rm == "ae") {
2192 // not needed when using OT1 font encoding.
2193 if (lyxrc.fontenc != "default")
2194 os << "\\usepackage{ae,aecompl}\n";
2197 else if (rm == "times") {
2198 // try to load the best available package
2199 if (LaTeXFeatures::isAvailable("mathptmx"))
2200 os << "\\usepackage{mathptmx}\n";
2201 else if (LaTeXFeatures::isAvailable("mathptm"))
2202 os << "\\usepackage{mathptm}\n";
2204 os << "\\usepackage{times}\n";
2207 else if (rm == "palatino") {
2208 // try to load the best available package
2209 if (LaTeXFeatures::isAvailable("mathpazo")) {
2210 os << "\\usepackage";
2216 // "osf" includes "sc"!
2220 os << "{mathpazo}\n";
2222 else if (LaTeXFeatures::isAvailable("mathpple"))
2223 os << "\\usepackage{mathpple}\n";
2225 os << "\\usepackage{palatino}\n";
2228 else if (rm == "utopia") {
2229 // fourier supersedes utopia.sty, but does
2230 // not work with OT1 encoding.
2231 if (LaTeXFeatures::isAvailable("fourier")
2232 && lyxrc.fontenc != "default") {
2233 os << "\\usepackage";
2244 os << "{fourier}\n";
2247 os << "\\usepackage{utopia}\n";
2249 // Bera (complete fontset)
2250 else if (rm == "bera" && sf == "default" && tt == "default")
2251 os << "\\usepackage{bera}\n";
2253 else if (rm != "default")
2254 os << "\\usepackage" << "{" << rm << "}\n";
2257 // Helvetica, Bera Sans
2258 if (sf == "helvet" || sf == "berasans") {
2260 os << "\\usepackage[scaled=" << float(sfscale) / 100
2261 << "]{" << sf << "}\n";
2263 os << "\\usepackage{" << sf << "}\n";
2266 else if (sf == "avant")
2267 os << "\\usepackage{" << sf << "}\n";
2268 // Computer Modern, Latin Modern, CM Bright
2269 else if (sf != "default")
2270 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2272 // monospaced/typewriter
2273 // Courier, LuxiMono
2274 if (tt == "luximono" || tt == "beramono") {
2276 os << "\\usepackage[scaled=" << float(ttscale) / 100
2277 << "]{" << tt << "}\n";
2279 os << "\\usepackage{" << tt << "}\n";
2282 else if (tt == "courier" )
2283 os << "\\usepackage{" << tt << "}\n";
2284 // Computer Modern, Latin Modern, CM Bright
2285 else if (tt != "default")
2286 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2292 Encoding const & BufferParams::encoding() const
2295 return *(encodings.fromLaTeXName("utf8-plain"));
2296 if (inputenc == "auto" || inputenc == "default")
2297 return *language->encoding();
2298 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2301 LYXERR0("Unknown inputenc value `" << inputenc
2302 << "'. Using `auto' instead.");
2303 return *language->encoding();
2307 CiteEngine BufferParams::citeEngine() const
2309 // FIXME the class should provide the numerical/
2310 // authoryear choice
2311 if (documentClass().provides("natbib")
2312 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2313 return ENGINE_NATBIB_AUTHORYEAR;
2314 return cite_engine_;
2318 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2320 cite_engine_ = cite_engine;