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;
350 fontsRoman = "default";
351 fontsSans = "default";
352 fontsTypewriter = "default";
353 fontsDefaultFamily = "default";
357 fontsSansScale = 100;
358 fontsTypewriterScale = 100;
360 graphicsDriver = "default";
361 defaultOutputFormat = "default";
362 bibtex_command = "default";
363 index_command = "default";
366 listings_params = string();
367 pagestyle = "default";
368 suppress_date = false;
369 // white is equal to no background color
370 backgroundcolor = lyx::rgbFromHexName("#ffffff");
372 for (int iter = 0; iter < 4; ++iter) {
373 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
374 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
377 indiceslist().addDefault(B_("Index"));
381 docstring BufferParams::B_(string const & l10n) const
383 LASSERT(language, /**/);
384 return getMessages(language->code()).get(l10n);
388 AuthorList & BufferParams::authors()
390 return pimpl_->authorlist;
394 AuthorList const & BufferParams::authors() const
396 return pimpl_->authorlist;
400 BranchList & BufferParams::branchlist()
402 return pimpl_->branchlist;
406 BranchList const & BufferParams::branchlist() const
408 return pimpl_->branchlist;
412 IndicesList & BufferParams::indiceslist()
414 return pimpl_->indiceslist;
418 IndicesList const & BufferParams::indiceslist() const
420 return pimpl_->indiceslist;
424 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
426 LASSERT(index < 4, /**/);
427 return pimpl_->temp_bullets[index];
431 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
433 LASSERT(index < 4, /**/);
434 return pimpl_->temp_bullets[index];
438 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
440 LASSERT(index < 4, /**/);
441 return pimpl_->user_defined_bullets[index];
445 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
447 LASSERT(index < 4, /**/);
448 return pimpl_->user_defined_bullets[index];
452 Spacing & BufferParams::spacing()
454 return pimpl_->spacing;
458 Spacing const & BufferParams::spacing() const
460 return pimpl_->spacing;
464 PDFOptions & BufferParams::pdfoptions()
466 return pimpl_->pdfoptions;
470 PDFOptions const & BufferParams::pdfoptions() const
472 return pimpl_->pdfoptions;
476 HSpace const & BufferParams::getIndentation() const
478 return pimpl_->indentation;
482 void BufferParams::setIndentation(HSpace const & indent)
484 pimpl_->indentation = indent;
488 VSpace const & BufferParams::getDefSkip() const
490 return pimpl_->defskip;
494 void BufferParams::setDefSkip(VSpace const & vs)
496 pimpl_->defskip = vs;
500 string BufferParams::readToken(Lexer & lex, string const & token,
501 FileName const & filepath)
503 if (token == "\\textclass") {
505 string const classname = lex.getString();
506 // if there exists a local layout file, ignore the system one
507 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
509 LayoutFileList & bcl = LayoutFileList::get();
510 if (tcp.empty() && !filepath.empty())
511 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
515 setBaseClass(classname);
516 // We assume that a tex class exists for local or unknown layouts so this warning
517 // will only be given for system layouts.
518 if (!baseClass()->isTeXClassAvailable()) {
519 docstring const msg =
520 bformat(_("The layout file requested by this document,\n"
522 "is not usable. This is probably because a LaTeX\n"
523 "class or style file required by it is not\n"
524 "available. See the Customization documentation\n"
525 "for more information.\n"), from_utf8(classname));
526 frontend::Alert::warning(_("Document class not available"),
527 msg + _("LyX will not be able to produce output."));
529 } else if (token == "\\begin_preamble") {
531 } else if (token == "\\begin_local_layout") {
532 readLocalLayout(lex);
533 } else if (token == "\\begin_modules") {
535 } else if (token == "\\begin_removed_modules") {
536 readRemovedModules(lex);
537 } else if (token == "\\options") {
539 options = lex.getString();
540 } else if (token == "\\use_default_options") {
541 lex >> use_default_options;
542 } else if (token == "\\master") {
544 master = lex.getString();
545 } else if (token == "\\suppress_date") {
546 lex >> suppress_date;
547 } else if (token == "\\language") {
549 } else if (token == "\\inputencoding") {
551 } else if (token == "\\graphics") {
552 readGraphicsDriver(lex);
553 } else if (token == "\\default_output_format") {
554 lex >> defaultOutputFormat;
555 } else if (token == "\\bibtex_command") {
557 bibtex_command = lex.getString();
558 } else if (token == "\\index_command") {
560 index_command = lex.getString();
561 } else if (token == "\\fontencoding") {
563 fontenc = lex.getString();
564 } else if (token == "\\font_roman") {
566 fontsRoman = lex.getString();
567 } else if (token == "\\font_sans") {
569 fontsSans = lex.getString();
570 } else if (token == "\\font_typewriter") {
572 fontsTypewriter = lex.getString();
573 } else if (token == "\\font_default_family") {
574 lex >> fontsDefaultFamily;
575 } else if (token == "\\use_xetex") {
577 } else if (token == "\\font_sc") {
579 } else if (token == "\\font_osf") {
581 } else if (token == "\\font_sf_scale") {
582 lex >> fontsSansScale;
583 } else if (token == "\\font_tt_scale") {
584 lex >> fontsTypewriterScale;
585 } else if (token == "\\font_cjk") {
587 } else if (token == "\\paragraph_separation") {
590 paragraph_separation = parseptranslator().find(parsep);
591 } else if (token == "\\paragraph_indentation") {
593 string indentation = lex.getString();
594 pimpl_->indentation = HSpace(indentation);
595 } else if (token == "\\defskip") {
597 string defskip = lex.getString();
598 if (defskip == "defskip")
601 pimpl_->defskip = VSpace(defskip);
602 } else if (token == "\\quotes_language") {
605 quotes_language = quoteslangtranslator().find(quotes_lang);
606 } else if (token == "\\papersize") {
609 papersize = papersizetranslator().find(ppsize);
610 } else if (token == "\\use_geometry") {
612 } else if (token == "\\use_amsmath") {
615 use_amsmath = packagetranslator().find(use_ams);
616 } else if (token == "\\use_esint") {
619 use_esint = packagetranslator().find(useesint);
620 } else if (token == "\\use_mhchem") {
623 use_mhchem = packagetranslator().find(usemhchem);
624 } else if (token == "\\cite_engine") {
627 cite_engine_ = citeenginetranslator().find(engine);
628 } else if (token == "\\use_bibtopic") {
630 } else if (token == "\\use_indices") {
632 } else if (token == "\\tracking_changes") {
634 } else if (token == "\\output_changes") {
635 lex >> outputChanges;
636 } else if (token == "\\branch") {
638 docstring branch = lex.getDocString();
639 branchlist().add(branch);
642 string const tok = lex.getString();
643 if (tok == "\\end_branch")
645 Branch * branch_ptr = branchlist().find(branch);
646 if (tok == "\\selected") {
649 branch_ptr->setSelected(lex.getInteger());
651 if (tok == "\\filename_suffix") {
654 branch_ptr->setFilenameSuffix(lex.getInteger());
656 if (tok == "\\color") {
658 string color = lex.getString();
660 branch_ptr->setColor(color);
661 // Update also the Color table:
663 color = lcolor.getX11Name(Color_background);
665 lcolor.setColor(to_utf8(branch), color);
668 } else if (token == "\\index") {
670 docstring index = lex.getDocString();
672 indiceslist().add(index);
675 string const tok = lex.getString();
676 if (tok == "\\end_index")
678 Index * index_ptr = indiceslist().find(index);
679 if (tok == "\\shortcut") {
681 shortcut = lex.getDocString();
683 index_ptr->setShortcut(shortcut);
685 if (tok == "\\color") {
687 string color = lex.getString();
689 index_ptr->setColor(color);
690 // Update also the Color table:
692 color = lcolor.getX11Name(Color_background);
694 if (!shortcut.empty())
695 lcolor.setColor(to_utf8(shortcut), color);
698 } else if (token == "\\author") {
700 istringstream ss(lex.getString());
703 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
704 } else if (token == "\\paperorientation") {
707 orientation = paperorientationtranslator().find(orient);
708 } else if (token == "\\backgroundcolor") {
710 backgroundcolor = lyx::rgbFromHexName(lex.getString());
711 } else if (token == "\\paperwidth") {
713 } else if (token == "\\paperheight") {
715 } else if (token == "\\leftmargin") {
717 } else if (token == "\\topmargin") {
719 } else if (token == "\\rightmargin") {
721 } else if (token == "\\bottommargin") {
723 } else if (token == "\\headheight") {
725 } else if (token == "\\headsep") {
727 } else if (token == "\\footskip") {
729 } else if (token == "\\columnsep") {
731 } else if (token == "\\paperfontsize") {
733 } else if (token == "\\papercolumns") {
735 } else if (token == "\\listings_params") {
738 listings_params = InsetListingsParams(par).params();
739 } else if (token == "\\papersides") {
742 sides = sidestranslator().find(psides);
743 } else if (token == "\\paperpagestyle") {
745 } else if (token == "\\bullet") {
747 } else if (token == "\\bulletLaTeX") {
748 readBulletsLaTeX(lex);
749 } else if (token == "\\secnumdepth") {
751 } else if (token == "\\tocdepth") {
753 } else if (token == "\\spacing") {
757 if (nspacing == "other") {
760 spacing().set(spacetranslator().find(nspacing), tmp_val);
761 } else if (token == "\\float_placement") {
762 lex >> float_placement;
764 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
765 string toktmp = pdfoptions().readToken(lex, token);
766 if (!toktmp.empty()) {
767 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
772 lyxerr << "BufferParams::readToken(): Unknown token: " <<
781 void BufferParams::writeFile(ostream & os) const
783 // The top of the file is written by the buffer.
784 // Prints out the buffer info into the .lyx file given by file
787 os << "\\textclass " << baseClass()->name() << '\n';
790 if (!preamble.empty()) {
791 // remove '\n' from the end of preamble
792 string const tmppreamble = rtrim(preamble, "\n");
793 os << "\\begin_preamble\n"
795 << "\n\\end_preamble\n";
799 if (!options.empty()) {
800 os << "\\options " << options << '\n';
803 // use the class options defined in the layout?
804 os << "\\use_default_options "
805 << convert<string>(use_default_options) << "\n";
807 // the master document
808 if (!master.empty()) {
809 os << "\\master " << master << '\n';
813 if (!removedModules_.empty()) {
814 os << "\\begin_removed_modules" << '\n';
815 list<string>::const_iterator it = removedModules_.begin();
816 list<string>::const_iterator en = removedModules_.end();
817 for (; it != en; it++)
819 os << "\\end_removed_modules" << '\n';
823 if (!layoutModules_.empty()) {
824 os << "\\begin_modules" << '\n';
825 LayoutModuleList::const_iterator it = layoutModules_.begin();
826 LayoutModuleList::const_iterator en = layoutModules_.end();
827 for (; it != en; it++)
829 os << "\\end_modules" << '\n';
832 // local layout information
833 if (!local_layout.empty()) {
834 // remove '\n' from the end
835 string const tmplocal = rtrim(local_layout, "\n");
836 os << "\\begin_local_layout\n"
838 << "\n\\end_local_layout\n";
841 // then the text parameters
842 if (language != ignore_language)
843 os << "\\language " << language->lang() << '\n';
844 os << "\\inputencoding " << inputenc
845 << "\n\\fontencoding " << fontenc
846 << "\n\\font_roman " << fontsRoman
847 << "\n\\font_sans " << fontsSans
848 << "\n\\font_typewriter " << fontsTypewriter
849 << "\n\\font_default_family " << fontsDefaultFamily
850 << "\n\\use_xetex " << convert<string>(useXetex)
851 << "\n\\font_sc " << convert<string>(fontsSC)
852 << "\n\\font_osf " << convert<string>(fontsOSF)
853 << "\n\\font_sf_scale " << fontsSansScale
854 << "\n\\font_tt_scale " << fontsTypewriterScale
856 if (!fontsCJK.empty()) {
857 os << "\\font_cjk " << fontsCJK << '\n';
859 os << "\n\\graphics " << graphicsDriver << '\n';
860 os << "\\default_output_format " << defaultOutputFormat << '\n';
861 os << "\\bibtex_command " << bibtex_command << '\n';
862 os << "\\index_command " << index_command << '\n';
864 if (!float_placement.empty()) {
865 os << "\\float_placement " << float_placement << '\n';
867 os << "\\paperfontsize " << fontsize << '\n';
869 spacing().writeFile(os);
870 pdfoptions().writeFile(os);
872 os << "\\papersize " << string_papersize[papersize]
873 << "\n\\use_geometry " << convert<string>(use_geometry)
874 << "\n\\use_amsmath " << use_amsmath
875 << "\n\\use_esint " << use_esint
876 << "\n\\use_mhchem " << use_mhchem
877 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
878 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
879 << "\n\\use_indices " << convert<string>(use_indices)
880 << "\n\\paperorientation " << string_orientation[orientation]
881 << "\n\\suppress_date " << convert<string>(suppress_date)
883 if (backgroundcolor != lyx::rgbFromHexName("#ffffff"))
884 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
886 BranchList::const_iterator it = branchlist().begin();
887 BranchList::const_iterator end = branchlist().end();
888 for (; it != end; ++it) {
889 os << "\\branch " << to_utf8(it->branch())
890 << "\n\\selected " << it->isSelected()
891 << "\n\\filename_suffix " << it->hasFilenameSuffix()
892 << "\n\\color " << lyx::X11hexname(it->color())
897 IndicesList::const_iterator iit = indiceslist().begin();
898 IndicesList::const_iterator iend = indiceslist().end();
899 for (; iit != iend; ++iit) {
900 os << "\\index " << to_utf8(iit->index())
901 << "\n\\shortcut " << to_utf8(iit->shortcut())
902 << "\n\\color " << lyx::X11hexname(iit->color())
907 if (!paperwidth.empty())
908 os << "\\paperwidth "
909 << VSpace(paperwidth).asLyXCommand() << '\n';
910 if (!paperheight.empty())
911 os << "\\paperheight "
912 << VSpace(paperheight).asLyXCommand() << '\n';
913 if (!leftmargin.empty())
914 os << "\\leftmargin "
915 << VSpace(leftmargin).asLyXCommand() << '\n';
916 if (!topmargin.empty())
918 << VSpace(topmargin).asLyXCommand() << '\n';
919 if (!rightmargin.empty())
920 os << "\\rightmargin "
921 << VSpace(rightmargin).asLyXCommand() << '\n';
922 if (!bottommargin.empty())
923 os << "\\bottommargin "
924 << VSpace(bottommargin).asLyXCommand() << '\n';
925 if (!headheight.empty())
926 os << "\\headheight "
927 << VSpace(headheight).asLyXCommand() << '\n';
928 if (!headsep.empty())
930 << VSpace(headsep).asLyXCommand() << '\n';
931 if (!footskip.empty())
933 << VSpace(footskip).asLyXCommand() << '\n';
934 if (!columnsep.empty())
936 << VSpace(columnsep).asLyXCommand() << '\n';
937 os << "\\secnumdepth " << secnumdepth
938 << "\n\\tocdepth " << tocdepth
939 << "\n\\paragraph_separation "
940 << string_paragraph_separation[paragraph_separation];
941 if (!paragraph_separation)
942 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
944 os << "\n\\defskip " << getDefSkip().asLyXCommand();
945 os << "\n\\quotes_language "
946 << string_quotes_language[quotes_language]
947 << "\n\\papercolumns " << columns
948 << "\n\\papersides " << sides
949 << "\n\\paperpagestyle " << pagestyle << '\n';
950 if (!listings_params.empty())
951 os << "\\listings_params \"" <<
952 InsetListingsParams(listings_params).encodedString() << "\"\n";
953 for (int i = 0; i < 4; ++i) {
954 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
955 if (user_defined_bullet(i).getFont() != -1) {
956 os << "\\bullet " << i << " "
957 << user_defined_bullet(i).getFont() << " "
958 << user_defined_bullet(i).getCharacter() << " "
959 << user_defined_bullet(i).getSize() << "\n";
963 os << "\\bulletLaTeX " << i << " \""
964 << lyx::to_ascii(user_defined_bullet(i).getText())
970 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
971 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
973 os << pimpl_->authorlist;
977 void BufferParams::validate(LaTeXFeatures & features) const
979 features.require(documentClass().requires());
982 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
983 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
984 LaTeXFeatures::isAvailable("xcolor");
986 switch (features.runparams().flavor) {
987 case OutputParams::LATEX:
989 features.require("ct-dvipost");
990 features.require("dvipost");
991 } else if (xcolorulem) {
992 features.require("ct-xcolor-ulem");
993 features.require("ulem");
994 features.require("xcolor");
996 features.require("ct-none");
999 case OutputParams::PDFLATEX:
1000 case OutputParams::XETEX:
1002 features.require("ct-xcolor-ulem");
1003 features.require("ulem");
1004 features.require("xcolor");
1005 // improves color handling in PDF output
1006 features.require("pdfcolmk");
1008 features.require("ct-none");
1016 // Floats with 'Here definitely' as default setting.
1017 if (float_placement.find('H') != string::npos)
1018 features.require("float");
1020 // AMS Style is at document level
1021 if (use_amsmath == package_on
1022 || documentClass().provides("amsmath"))
1023 features.require("amsmath");
1024 if (use_esint == package_on)
1025 features.require("esint");
1026 if (use_mhchem == package_on)
1027 features.require("mhchem");
1029 // Document-level line spacing
1030 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1031 features.require("setspace");
1033 // the bullet shapes are buffer level not paragraph level
1034 // so they are tested here
1035 for (int i = 0; i < 4; ++i) {
1036 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1038 int const font = user_defined_bullet(i).getFont();
1040 int const c = user_defined_bullet(i).getCharacter();
1046 features.require("latexsym");
1048 } else if (font == 1) {
1049 features.require("amssymb");
1050 } else if (font >= 2 && font <= 5) {
1051 features.require("pifont");
1055 if (pdfoptions().use_hyperref) {
1056 features.require("hyperref");
1057 // due to interferences with babel and hyperref, the color package has to
1058 // be loaded after hyperref when hyperref is used with the colorlinks
1059 // option, see http://bugzilla.lyx.org/show_bug.cgi?id=5291
1060 if (pdfoptions().colorlinks)
1061 features.require("color");
1065 features.require("xetex");
1067 if (language->lang() == "vietnamese")
1068 features.require("vietnamese");
1069 else if (language->lang() == "japanese")
1070 features.require("japanese");
1074 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1075 TexRow & texrow) const
1077 os << "\\documentclass";
1079 DocumentClass const & tclass = documentClass();
1081 ostringstream clsoptions; // the document class options.
1083 if (tokenPos(tclass.opt_fontsize(),
1084 '|', fontsize) >= 0) {
1085 // only write if existing in list (and not default)
1086 clsoptions << fontsize << "pt,";
1089 // custom, A3, B3 and B4 paper sizes need geometry
1090 bool nonstandard_papersize = papersize == PAPER_B3
1091 || papersize == PAPER_B4
1092 || papersize == PAPER_A3
1093 || papersize == PAPER_CUSTOM;
1095 if (!use_geometry) {
1096 switch (papersize) {
1098 clsoptions << "a4paper,";
1100 case PAPER_USLETTER:
1101 clsoptions << "letterpaper,";
1104 clsoptions << "a5paper,";
1107 clsoptions << "b5paper,";
1109 case PAPER_USEXECUTIVE:
1110 clsoptions << "executivepaper,";
1113 clsoptions << "legalpaper,";
1125 if (sides != tclass.sides()) {
1128 clsoptions << "oneside,";
1131 clsoptions << "twoside,";
1137 if (columns != tclass.columns()) {
1139 clsoptions << "twocolumn,";
1141 clsoptions << "onecolumn,";
1145 && orientation == ORIENTATION_LANDSCAPE)
1146 clsoptions << "landscape,";
1148 // language should be a parameter to \documentclass
1149 if (language->babel() == "hebrew"
1150 && default_language->babel() != "hebrew")
1151 // This seems necessary
1152 features.useLanguage(default_language);
1154 ostringstream language_options;
1155 bool const use_babel = features.useBabel();
1157 language_options << features.getLanguages();
1158 if (!language->babel().empty()) {
1159 if (!language_options.str().empty())
1160 language_options << ',';
1161 language_options << language->babel();
1163 // if Vietnamese is used, babel must directly be loaded
1164 // with language options, not in the class options, see
1165 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1166 size_t viet = language_options.str().find("vietnam");
1167 // viet = string::npos when not found
1168 // the same is for all other languages that are not directly supported by
1169 // babel, but where LaTeX-packages add babel support.
1170 // this is currently the case for Latvian, Lithuanian, and Mongolian
1171 size_t latvian = language_options.str().find("latvian");
1172 size_t lithu = language_options.str().find("lithuanian");
1173 size_t mongo = language_options.str().find("mongolian");
1174 // if Japanese is used, babel must directly be loaded
1175 // with language options, not in the class options, see
1176 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1177 size_t japan = language_options.str().find("japanese");
1178 if (lyxrc.language_global_options && !language_options.str().empty()
1179 && viet == string::npos && japan == string::npos
1180 && latvian == string::npos && lithu == string::npos
1181 && mongo == string::npos)
1182 clsoptions << language_options.str() << ',';
1185 // the predefined options from the layout
1186 if (use_default_options && !tclass.options().empty())
1187 clsoptions << tclass.options() << ',';
1189 // the user-defined options
1190 if (!options.empty()) {
1191 clsoptions << options << ',';
1194 string strOptions(clsoptions.str());
1195 if (!strOptions.empty()) {
1196 strOptions = rtrim(strOptions, ",");
1198 os << '[' << from_utf8(strOptions) << ']';
1201 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1203 // end of \documentclass defs
1206 os << "\\usepackage{fontspec}\n";
1210 // font selection must be done before loading fontenc.sty
1211 string const fonts =
1212 loadFonts(fontsRoman, fontsSans,
1213 fontsTypewriter, fontsSC, fontsOSF,
1214 fontsSansScale, fontsTypewriterScale, useXetex);
1215 if (!fonts.empty()) {
1216 os << from_ascii(fonts);
1219 if (fontsDefaultFamily != "default")
1220 os << "\\renewcommand{\\familydefault}{\\"
1221 << from_ascii(fontsDefaultFamily) << "}\n";
1223 // set font encoding
1224 // for arabic_arabi and farsi we also need to load the LAE and
1226 // XeTeX works without fontenc
1227 if (font_encoding() != "default" && language->lang() != "japanese"
1229 if (language->lang() == "arabic_arabi"
1230 || language->lang() == "farsi") {
1231 os << "\\usepackage[" << from_ascii(font_encoding())
1232 << ",LFE,LAE]{fontenc}\n";
1235 os << "\\usepackage[" << from_ascii(font_encoding())
1241 // handle inputenc etc.
1242 writeEncodingPreamble(os, features, texrow);
1244 if (!listings_params.empty() || features.isRequired("listings")) {
1245 os << "\\usepackage{listings}\n";
1248 if (!listings_params.empty()) {
1250 // do not test validity because listings_params is
1251 // supposed to be valid
1253 InsetListingsParams(listings_params).separatedParams(true);
1254 // we can't support all packages, but we should load the color package
1255 if (par.find("\\color", 0) != string::npos)
1256 features.require("color");
1257 os << from_utf8(par);
1258 // count the number of newlines
1259 for (size_t i = 0; i < par.size(); ++i)
1265 if (!tclass.provides("geometry")
1266 && (use_geometry || nonstandard_papersize)) {
1267 odocstringstream ods;
1268 if (!getGraphicsDriver("geometry").empty())
1269 ods << getGraphicsDriver("geometry");
1270 if (orientation == ORIENTATION_LANDSCAPE)
1271 ods << ",landscape";
1272 switch (papersize) {
1274 if (!paperwidth.empty())
1275 ods << ",paperwidth="
1276 << from_ascii(paperwidth);
1277 if (!paperheight.empty())
1278 ods << ",paperheight="
1279 << from_ascii(paperheight);
1281 case PAPER_USLETTER:
1282 ods << ",letterpaper";
1285 ods << ",legalpaper";
1287 case PAPER_USEXECUTIVE:
1288 ods << ",executivepaper";
1309 // default papersize ie PAPER_DEFAULT
1310 switch (lyxrc.default_papersize) {
1311 case PAPER_DEFAULT: // keep compiler happy
1312 case PAPER_USLETTER:
1313 ods << ",letterpaper";
1316 ods << ",legalpaper";
1318 case PAPER_USEXECUTIVE:
1319 ods << ",executivepaper";
1339 docstring const g_options = trim(ods.str(), ",");
1340 os << "\\usepackage";
1341 if (!g_options.empty())
1342 os << '[' << g_options << ']';
1343 os << "{geometry}\n";
1345 os << "\\geometry{verbose";
1346 if (!topmargin.empty())
1347 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1348 if (!bottommargin.empty())
1349 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1350 if (!leftmargin.empty())
1351 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1352 if (!rightmargin.empty())
1353 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1354 if (!headheight.empty())
1355 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1356 if (!headsep.empty())
1357 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1358 if (!footskip.empty())
1359 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1360 if (!columnsep.empty())
1361 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1364 } else if (orientation == ORIENTATION_LANDSCAPE) {
1365 features.require("papersize");
1368 if (tokenPos(tclass.opt_pagestyle(),
1369 '|', pagestyle) >= 0) {
1370 if (pagestyle == "fancy") {
1371 os << "\\usepackage{fancyhdr}\n";
1374 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1378 // only output when the background color is not white
1379 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1380 // only require color here, the background color will be defined
1381 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1383 features.require("color");
1384 features.require("pagecolor");
1387 // Only if class has a ToC hierarchy
1388 if (tclass.hasTocLevels()) {
1389 if (secnumdepth != tclass.secnumdepth()) {
1390 os << "\\setcounter{secnumdepth}{"
1395 if (tocdepth != tclass.tocdepth()) {
1396 os << "\\setcounter{tocdepth}{"
1403 if (paragraph_separation) {
1404 // when skip separation
1405 switch (getDefSkip().kind()) {
1406 case VSpace::SMALLSKIP:
1407 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1409 case VSpace::MEDSKIP:
1410 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1412 case VSpace::BIGSKIP:
1413 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1415 case VSpace::LENGTH:
1416 os << "\\setlength{\\parskip}{"
1417 << from_utf8(getDefSkip().length().asLatexString())
1420 default: // should never happen // Then delete it.
1421 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1425 os << "\\setlength{\\parindent}{0pt}\n";
1428 // when separation by indentation
1429 // only output something when a width is given
1430 if (getIndentation().asLyXCommand() != "default") {
1431 os << "\\setlength{\\parindent}{"
1432 << from_utf8(getIndentation().asLatexCommand())
1438 // Now insert the LyX specific LaTeX commands...
1439 docstring lyxpreamble;
1441 // due to interferences with babel and hyperref, the color package has to
1442 // be loaded (when it is not already loaded) before babel when hyperref
1443 // is used with the colorlinks option, see
1444 // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1445 // we decided therefore to load color always before babel, see
1446 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1447 lyxpreamble += from_ascii(features.getColorOptions());
1449 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1451 && (features.isRequired("jurabib")
1452 || features.isRequired("hyperref")
1453 || features.isRequired("vietnamese")
1454 || features.isRequired("japanese") ) ) {
1456 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1457 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1460 // The optional packages;
1461 lyxpreamble += from_ascii(features.getPackages());
1463 // Additional Indices
1464 if (features.isRequired("splitidx")) {
1465 IndicesList::const_iterator iit = indiceslist().begin();
1466 IndicesList::const_iterator iend = indiceslist().end();
1467 for (; iit != iend; ++iit) {
1468 lyxpreamble += "\\newindex[";
1469 lyxpreamble += iit->index();
1470 lyxpreamble += "]{";
1471 lyxpreamble += iit->shortcut();
1472 lyxpreamble += "}\n";
1477 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1480 // * Hyperref manual: "Make sure it comes last of your loaded
1481 // packages, to give it a fighting chance of not being over-written,
1482 // since its job is to redefine many LaTeX commands."
1483 // * Email from Heiko Oberdiek: "It is usually better to load babel
1484 // before hyperref. Then hyperref has a chance to detect babel.
1485 // * Has to be loaded before the "LyX specific LaTeX commands" to
1486 // avoid errors with algorithm floats.
1487 // use hyperref explicitely when it is required
1488 if (features.isRequired("hyperref")) {
1489 odocstringstream oss;
1490 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1491 lyxpreamble += oss.str();
1494 // Will be surrounded by \makeatletter and \makeatother when not empty
1495 docstring atlyxpreamble;
1497 // Some macros LyX will need
1498 docstring tmppreamble(features.getMacros());
1500 if (!tmppreamble.empty())
1501 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1502 "LyX specific LaTeX commands.\n"
1503 + tmppreamble + '\n';
1505 // the text class specific preamble
1506 tmppreamble = features.getTClassPreamble();
1507 if (!tmppreamble.empty())
1508 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1509 "Textclass specific LaTeX commands.\n"
1510 + tmppreamble + '\n';
1512 // suppress date if selected
1513 // use \@ifundefined because we cannot be sure that every document class
1514 // has a \date command
1516 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1518 /* the user-defined preamble */
1519 if (!containsOnly(preamble, " \n\t"))
1521 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1522 "User specified LaTeX commands.\n"
1523 + from_utf8(preamble) + '\n';
1525 // subfig loads internally the LaTeX package "caption". As
1526 // caption is a very popular package, users will load it in
1527 // the preamble. Therefore we must load subfig behind the
1528 // user-defined preamble and check if the caption package was
1529 // loaded or not. For the case that caption is loaded before
1530 // subfig, there is the subfig option "caption=false". This
1531 // option also works when a koma-script class is used and
1532 // koma's own caption commands are used instead of caption. We
1533 // use \PassOptionsToPackage here because the user could have
1534 // already loaded subfig in the preamble.
1535 if (features.isRequired("subfig")) {
1536 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1537 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1538 "\\usepackage{subfig}\n";
1541 // Itemize bullet settings need to be last in case the user
1542 // defines their own bullets that use a package included
1543 // in the user-defined preamble -- ARRae
1544 // Actually it has to be done much later than that
1545 // since some packages like frenchb make modifications
1546 // at \begin{document} time -- JMarc
1547 docstring bullets_def;
1548 for (int i = 0; i < 4; ++i) {
1549 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1550 if (bullets_def.empty())
1551 bullets_def += "\\AtBeginDocument{\n";
1552 bullets_def += " \\def\\labelitemi";
1554 // `i' is one less than the item to modify
1561 bullets_def += "ii";
1567 bullets_def += '{' +
1568 user_defined_bullet(i).getText()
1573 if (!bullets_def.empty())
1574 atlyxpreamble += bullets_def + "}\n\n";
1576 if (!atlyxpreamble.empty())
1577 lyxpreamble += "\n\\makeatletter\n"
1578 + atlyxpreamble + "\\makeatother\n\n";
1580 // We try to load babel late, in case it interferes with other packages.
1581 // Jurabib and Hyperref have to be called after babel, though.
1582 if (use_babel && !features.isRequired("jurabib")
1583 && !features.isRequired("hyperref")
1584 && !features.isRequired("vietnamese")
1585 && !features.isRequired("japanese")) {
1587 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1588 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1591 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1592 if (!i18npreamble.empty())
1593 lyxpreamble += i18npreamble + '\n';
1596 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1597 for (int j = 0; j != nlines; ++j) {
1603 // these packages (xunicode, for that matter) need to be loaded at least
1604 // after amsmath, amssymb, esint and the other packages that provide
1607 os << "\\usepackage{xunicode}\n";
1609 os << "\\usepackage{xltxtra}\n";
1616 void BufferParams::useClassDefaults()
1618 DocumentClass const & tclass = documentClass();
1620 sides = tclass.sides();
1621 columns = tclass.columns();
1622 pagestyle = tclass.pagestyle();
1623 use_default_options = true;
1624 // Only if class has a ToC hierarchy
1625 if (tclass.hasTocLevels()) {
1626 secnumdepth = tclass.secnumdepth();
1627 tocdepth = tclass.tocdepth();
1632 bool BufferParams::hasClassDefaults() const
1634 DocumentClass const & tclass = documentClass();
1636 return sides == tclass.sides()
1637 && columns == tclass.columns()
1638 && pagestyle == tclass.pagestyle()
1639 && use_default_options
1640 && secnumdepth == tclass.secnumdepth()
1641 && tocdepth == tclass.tocdepth();
1645 DocumentClass const & BufferParams::documentClass() const
1651 DocumentClass const * BufferParams::documentClassPtr() const {
1656 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1657 // evil, but this function is evil
1658 doc_class_ = const_cast<DocumentClass *>(tc);
1662 bool BufferParams::setBaseClass(string const & classname)
1664 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1665 LayoutFileList & bcl = LayoutFileList::get();
1666 if (!bcl.haveClass(classname)) {
1668 bformat(_("The document class %1$s could not be found. "
1669 "A default textclass with default layouts will be used. "
1670 "LyX might not be able to produce output unless a correct "
1671 "textclass is selected from the document settings dialog."),
1672 from_utf8(classname));
1673 frontend::Alert::error(_("Document class not found"), s);
1674 bcl.addEmptyClass(classname);
1677 bool const success = bcl[classname].load();
1680 bformat(_("The document class %1$s could not be loaded."),
1681 from_utf8(classname));
1682 frontend::Alert::error(_("Could not load class"), s);
1686 pimpl_->baseClass_ = classname;
1687 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1692 LayoutFile const * BufferParams::baseClass() const
1694 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1695 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1701 LayoutFileIndex const & BufferParams::baseClassID() const
1703 return pimpl_->baseClass_;
1707 void BufferParams::makeDocumentClass()
1712 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1714 if (!local_layout.empty()) {
1715 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1716 docstring const msg = _("Error reading internal layout information");
1717 frontend::Alert::warning(_("Read Error"), msg);
1722 bool BufferParams::moduleCanBeAdded(string const & modName) const
1724 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1728 bool BufferParams::addLayoutModule(string const & modName)
1730 LayoutModuleList::const_iterator it = layoutModules_.begin();
1731 LayoutModuleList::const_iterator end = layoutModules_.end();
1732 for (; it != end; it++)
1735 layoutModules_.push_back(modName);
1740 Font const BufferParams::getFont() const
1742 FontInfo f = documentClass().defaultfont();
1743 if (fontsDefaultFamily == "rmdefault")
1744 f.setFamily(ROMAN_FAMILY);
1745 else if (fontsDefaultFamily == "sfdefault")
1746 f.setFamily(SANS_FAMILY);
1747 else if (fontsDefaultFamily == "ttdefault")
1748 f.setFamily(TYPEWRITER_FAMILY);
1749 return Font(f, language);
1753 void BufferParams::readPreamble(Lexer & lex)
1755 if (lex.getString() != "\\begin_preamble")
1756 lyxerr << "Error (BufferParams::readPreamble):"
1757 "consistency check failed." << endl;
1759 preamble = lex.getLongString("\\end_preamble");
1763 void BufferParams::readLocalLayout(Lexer & lex)
1765 if (lex.getString() != "\\begin_local_layout")
1766 lyxerr << "Error (BufferParams::readLocalLayout):"
1767 "consistency check failed." << endl;
1769 local_layout = lex.getLongString("\\end_local_layout");
1773 void BufferParams::readLanguage(Lexer & lex)
1775 if (!lex.next()) return;
1777 string const tmptok = lex.getString();
1779 // check if tmptok is part of tex_babel in tex-defs.h
1780 language = languages.getLanguage(tmptok);
1782 // Language tmptok was not found
1783 language = default_language;
1784 lyxerr << "Warning: Setting language `"
1785 << tmptok << "' to `" << language->lang()
1791 void BufferParams::readGraphicsDriver(Lexer & lex)
1796 string const tmptok = lex.getString();
1797 // check if tmptok is part of tex_graphics in tex_defs.h
1800 string const test = tex_graphics[n++];
1802 if (test == tmptok) {
1803 graphicsDriver = tmptok;
1808 "Warning: graphics driver `$$Token' not recognized!\n"
1809 " Setting graphics driver to `default'.\n");
1810 graphicsDriver = "default";
1817 void BufferParams::readBullets(Lexer & lex)
1822 int const index = lex.getInteger();
1824 int temp_int = lex.getInteger();
1825 user_defined_bullet(index).setFont(temp_int);
1826 temp_bullet(index).setFont(temp_int);
1828 user_defined_bullet(index).setCharacter(temp_int);
1829 temp_bullet(index).setCharacter(temp_int);
1831 user_defined_bullet(index).setSize(temp_int);
1832 temp_bullet(index).setSize(temp_int);
1836 void BufferParams::readBulletsLaTeX(Lexer & lex)
1838 // The bullet class should be able to read this.
1841 int const index = lex.getInteger();
1843 docstring const temp_str = lex.getDocString();
1845 user_defined_bullet(index).setText(temp_str);
1846 temp_bullet(index).setText(temp_str);
1850 void BufferParams::readModules(Lexer & lex)
1852 if (!lex.eatLine()) {
1853 lyxerr << "Error (BufferParams::readModules):"
1854 "Unexpected end of input." << endl;
1858 string mod = lex.getString();
1859 if (mod == "\\end_modules")
1861 addLayoutModule(mod);
1867 void BufferParams::readRemovedModules(Lexer & lex)
1869 if (!lex.eatLine()) {
1870 lyxerr << "Error (BufferParams::readRemovedModules):"
1871 "Unexpected end of input." << endl;
1875 string mod = lex.getString();
1876 if (mod == "\\end_removed_modules")
1878 removedModules_.push_back(mod);
1881 // now we want to remove any removed modules that were previously
1882 // added. normally, that will be because default modules were added in
1883 // setBaseClass(), which gets called when \textclass is read at the
1884 // start of the read.
1885 list<string>::const_iterator rit = removedModules_.begin();
1886 list<string>::const_iterator const ren = removedModules_.end();
1887 for (; rit != ren; rit++) {
1888 LayoutModuleList::iterator const mit = layoutModules_.begin();
1889 LayoutModuleList::iterator const men = layoutModules_.end();
1890 LayoutModuleList::iterator found = find(mit, men, *rit);
1893 layoutModules_.erase(found);
1898 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1900 char real_papersize = papersize;
1901 if (real_papersize == PAPER_DEFAULT)
1902 real_papersize = lyxrc.default_papersize;
1904 switch (real_papersize) {
1906 // could be anything, so don't guess
1908 case PAPER_CUSTOM: {
1909 if (purpose == XDVI && !paperwidth.empty() &&
1910 !paperheight.empty()) {
1911 // heightxwidth<unit>
1912 string first = paperwidth;
1913 string second = paperheight;
1914 if (orientation == ORIENTATION_LANDSCAPE)
1917 return first.erase(first.length() - 2)
1929 // dvips and dvipdfm do not know this
1930 if (purpose == DVIPS || purpose == DVIPDFM)
1934 // dvipdfm does not know this
1935 if (purpose == DVIPDFM)
1939 // dvipdfm does not know this
1940 if (purpose == DVIPDFM)
1943 case PAPER_USEXECUTIVE:
1944 // dvipdfm does not know this
1945 if (purpose == DVIPDFM)
1950 case PAPER_USLETTER:
1952 if (purpose == XDVI)
1959 string const BufferParams::dvips_options() const
1964 && papersize == PAPER_CUSTOM
1965 && !lyxrc.print_paper_dimension_flag.empty()
1966 && !paperwidth.empty()
1967 && !paperheight.empty()) {
1968 // using a custom papersize
1969 result = lyxrc.print_paper_dimension_flag;
1970 result += ' ' + paperwidth;
1971 result += ',' + paperheight;
1973 string const paper_option = paperSizeName(DVIPS);
1974 if (!paper_option.empty() && (paper_option != "letter" ||
1975 orientation != ORIENTATION_LANDSCAPE)) {
1976 // dvips won't accept -t letter -t landscape.
1977 // In all other cases, include the paper size
1979 result = lyxrc.print_paper_flag;
1980 result += ' ' + paper_option;
1983 if (orientation == ORIENTATION_LANDSCAPE &&
1984 papersize != PAPER_CUSTOM)
1985 result += ' ' + lyxrc.print_landscape_flag;
1990 string const BufferParams::font_encoding() const
1992 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
1996 string BufferParams::babelCall(string const & lang_opts) const
1998 string lang_pack = lyxrc.language_package;
1999 if (lang_pack != "\\usepackage{babel}")
2001 // suppress the babel call when there is no babel language defined
2002 // for the document language in the lib/languages file and if no
2003 // other languages are used (lang_opts is then empty)
2004 if (lang_opts.empty())
2006 // If Vietnamese is used, babel must directly be loaded with the
2007 // language options, see
2008 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2009 size_t viet = lang_opts.find("vietnam");
2010 // viet = string::npos when not found
2011 // the same is for all other languages that are not directly supported by
2012 // babel, but where LaTeX-packages add babel support.
2013 // this is currently the case for Latvian, Lithuanian, and Mongolian
2014 size_t latvian = lang_opts.find("latvian");
2015 size_t lithu = lang_opts.find("lithuanian");
2016 size_t mongo = lang_opts.find("mongolian");
2017 // If Japanese is used, babel must directly be loaded with the
2018 // language options, see
2019 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
2020 size_t japan = lang_opts.find("japanese");
2021 if (!lyxrc.language_global_options || viet != string::npos
2022 || japan != string::npos || latvian != string::npos
2023 || lithu != string::npos || mongo != string::npos)
2024 return "\\usepackage[" + lang_opts + "]{babel}";
2029 docstring BufferParams::getGraphicsDriver(string const & package) const
2033 if (package == "geometry") {
2034 if (graphicsDriver == "dvips"
2035 || graphicsDriver == "dvipdfm"
2036 || graphicsDriver == "pdftex"
2037 || graphicsDriver == "vtex")
2038 result = from_ascii(graphicsDriver);
2039 else if (graphicsDriver == "dvipdfmx")
2040 result = from_ascii("dvipdfm");
2047 void BufferParams::writeEncodingPreamble(odocstream & os,
2048 LaTeXFeatures & features, TexRow & texrow) const
2052 if (inputenc == "auto") {
2053 string const doc_encoding =
2054 language->encoding()->latexName();
2055 Encoding::Package const package =
2056 language->encoding()->package();
2058 // Create a list with all the input encodings used
2060 set<string> encodings =
2061 features.getEncodingSet(doc_encoding);
2063 // If the "japanese" package (i.e. pLaTeX) is used,
2064 // inputenc must be omitted.
2065 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2066 if (package == Encoding::japanese)
2067 features.require("japanese");
2069 if ((!encodings.empty() || package == Encoding::inputenc)
2070 && !features.isRequired("japanese")) {
2071 os << "\\usepackage[";
2072 set<string>::const_iterator it = encodings.begin();
2073 set<string>::const_iterator const end = encodings.end();
2075 os << from_ascii(*it);
2078 for (; it != end; ++it)
2079 os << ',' << from_ascii(*it);
2080 if (package == Encoding::inputenc) {
2081 if (!encodings.empty())
2083 os << from_ascii(doc_encoding);
2085 os << "]{inputenc}\n";
2088 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2089 if (language->encoding()->name() == "utf8-cjk"
2090 && LaTeXFeatures::isAvailable("CJKutf8"))
2091 os << "\\usepackage{CJKutf8}\n";
2093 os << "\\usepackage{CJK}\n";
2096 } else if (inputenc != "default") {
2097 switch (encoding().package()) {
2098 case Encoding::none:
2099 case Encoding::japanese:
2101 case Encoding::inputenc:
2102 // do not load inputenc if japanese is used
2103 if (features.isRequired("japanese"))
2105 os << "\\usepackage[" << from_ascii(inputenc)
2110 if (encoding().name() == "utf8-cjk"
2111 && LaTeXFeatures::isAvailable("CJKutf8"))
2112 os << "\\usepackage{CJKutf8}\n";
2114 os << "\\usepackage{CJK}\n";
2120 // The encoding "armscii8" (for Armenian) is only available when
2121 // the package "armtex" is loaded.
2122 if (language->encoding()->latexName() == "armscii8"
2123 || inputenc == "armscii8") {
2124 os << "\\usepackage{armtex}\n";
2130 string const BufferParams::parseFontName(string const & name) const
2132 string mangled = name;
2133 size_t const idx = mangled.find('[');
2134 if (idx == string::npos || idx == 0)
2137 return mangled.substr(0, idx - 1);
2141 string const BufferParams::loadFonts(string const & rm,
2142 string const & sf, string const & tt,
2143 bool const & sc, bool const & osf,
2144 int const & sfscale, int const & ttscale,
2145 bool const & xetex) const
2147 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2148 several packages have been replaced by others, that might not
2149 be installed on every system. We have to take care for that
2150 (see psnfss.pdf). We try to support all psnfss fonts as well
2151 as the fonts that have become de facto standard in the LaTeX
2152 world (e.g. Latin Modern). We do not support obsolete fonts
2153 (like PSLatex). In general, it should be possible to mix any
2154 rm font with any sf or tt font, respectively. (JSpitzm)
2156 -- separate math fonts.
2159 if (rm == "default" && sf == "default" && tt == "default")
2166 if (rm != "default")
2167 os << "\\setmainfont[Mapping=tex-text]{"
2168 << parseFontName(rm) << "}\n";
2169 if (sf != "default") {
2170 string const sans = parseFontName(sf);
2172 os << "\\setsansfont[Scale="
2173 << float(sfscale) / 100
2174 << ",Mapping=tex-text]{"
2177 os << "\\setsansfont[Mapping=tex-text]{"
2180 if (tt != "default") {
2181 string const mono = parseFontName(tt);
2183 os << "\\setmonofont[Scale="
2184 << float(sfscale) / 100
2188 os << "\\setmonofont[Mapping=tex-text]{"
2192 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2197 // Computer Modern (must be explicitely selectable -- there might be classes
2198 // that define a different default font!
2200 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2201 // osf for Computer Modern needs eco.sty
2203 os << "\\usepackage{eco}\n";
2205 // Latin Modern Roman
2206 else if (rm == "lmodern")
2207 os << "\\usepackage{lmodern}\n";
2209 else if (rm == "ae") {
2210 // not needed when using OT1 font encoding.
2211 if (font_encoding() != "default")
2212 os << "\\usepackage{ae,aecompl}\n";
2215 else if (rm == "times") {
2216 // try to load the best available package
2217 if (LaTeXFeatures::isAvailable("mathptmx"))
2218 os << "\\usepackage{mathptmx}\n";
2219 else if (LaTeXFeatures::isAvailable("mathptm"))
2220 os << "\\usepackage{mathptm}\n";
2222 os << "\\usepackage{times}\n";
2225 else if (rm == "palatino") {
2226 // try to load the best available package
2227 if (LaTeXFeatures::isAvailable("mathpazo")) {
2228 os << "\\usepackage";
2234 // "osf" includes "sc"!
2238 os << "{mathpazo}\n";
2240 else if (LaTeXFeatures::isAvailable("mathpple"))
2241 os << "\\usepackage{mathpple}\n";
2243 os << "\\usepackage{palatino}\n";
2246 else if (rm == "utopia") {
2247 // fourier supersedes utopia.sty, but does
2248 // not work with OT1 encoding.
2249 if (LaTeXFeatures::isAvailable("fourier")
2250 && font_encoding() != "default") {
2251 os << "\\usepackage";
2262 os << "{fourier}\n";
2265 os << "\\usepackage{utopia}\n";
2267 // Bera (complete fontset)
2268 else if (rm == "bera" && sf == "default" && tt == "default")
2269 os << "\\usepackage{bera}\n";
2271 else if (rm != "default")
2272 os << "\\usepackage" << "{" << rm << "}\n";
2275 // Helvetica, Bera Sans
2276 if (sf == "helvet" || sf == "berasans") {
2278 os << "\\usepackage[scaled=" << float(sfscale) / 100
2279 << "]{" << sf << "}\n";
2281 os << "\\usepackage{" << sf << "}\n";
2284 else if (sf == "avant")
2285 os << "\\usepackage{" << sf << "}\n";
2286 // Computer Modern, Latin Modern, CM Bright
2287 else if (sf != "default")
2288 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2290 // monospaced/typewriter
2291 // Courier, LuxiMono
2292 if (tt == "luximono" || tt == "beramono") {
2294 os << "\\usepackage[scaled=" << float(ttscale) / 100
2295 << "]{" << tt << "}\n";
2297 os << "\\usepackage{" << tt << "}\n";
2300 else if (tt == "courier" )
2301 os << "\\usepackage{" << tt << "}\n";
2302 // Computer Modern, Latin Modern, CM Bright
2303 else if (tt != "default")
2304 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2310 Encoding const & BufferParams::encoding() const
2313 return *(encodings.fromLaTeXName("utf8-plain"));
2314 if (inputenc == "auto" || inputenc == "default")
2315 return *language->encoding();
2316 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2319 LYXERR0("Unknown inputenc value `" << inputenc
2320 << "'. Using `auto' instead.");
2321 return *language->encoding();
2325 CiteEngine BufferParams::citeEngine() const
2327 // FIXME the class should provide the numerical/
2328 // authoryear choice
2329 if (documentClass().provides("natbib")
2330 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2331 return ENGINE_NATBIB_AUTHORYEAR;
2332 return cite_engine_;
2336 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2338 cite_engine_ = cite_engine;