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 // not yet operational
648 if (tok == "\\color") {
650 string color = lex.getString();
652 branch_ptr->setColor(color);
653 // Update also the Color table:
655 color = lcolor.getX11Name(Color_background);
657 lcolor.setColor(to_utf8(branch), color);
660 } else if (token == "\\index") {
662 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") {
673 index_ptr->setShortcut(lex.getDocString());
675 // not yet operational
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 lcolor.setColor(to_utf8(index), color);
688 } else if (token == "\\author") {
690 istringstream ss(lex.getString());
693 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
694 } else if (token == "\\paperorientation") {
697 orientation = paperorientationtranslator().find(orient);
698 } else if (token == "\\backgroundcolor") {
700 backgroundcolor = lyx::rgbFromHexName(lex.getString());
701 } else if (token == "\\paperwidth") {
703 } else if (token == "\\paperheight") {
705 } else if (token == "\\leftmargin") {
707 } else if (token == "\\topmargin") {
709 } else if (token == "\\rightmargin") {
711 } else if (token == "\\bottommargin") {
713 } else if (token == "\\headheight") {
715 } else if (token == "\\headsep") {
717 } else if (token == "\\footskip") {
719 } else if (token == "\\columnsep") {
721 } else if (token == "\\paperfontsize") {
723 } else if (token == "\\papercolumns") {
725 } else if (token == "\\listings_params") {
728 listings_params = InsetListingsParams(par).params();
729 } else if (token == "\\papersides") {
732 sides = sidestranslator().find(psides);
733 } else if (token == "\\paperpagestyle") {
735 } else if (token == "\\bullet") {
737 } else if (token == "\\bulletLaTeX") {
738 readBulletsLaTeX(lex);
739 } else if (token == "\\secnumdepth") {
741 } else if (token == "\\tocdepth") {
743 } else if (token == "\\spacing") {
747 if (nspacing == "other") {
750 spacing().set(spacetranslator().find(nspacing), tmp_val);
751 } else if (token == "\\float_placement") {
752 lex >> float_placement;
754 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
755 string toktmp = pdfoptions().readToken(lex, token);
756 if (!toktmp.empty()) {
757 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
762 lyxerr << "BufferParams::readToken(): Unknown token: " <<
771 void BufferParams::writeFile(ostream & os) const
773 // The top of the file is written by the buffer.
774 // Prints out the buffer info into the .lyx file given by file
777 os << "\\textclass " << baseClass()->name() << '\n';
780 if (!preamble.empty()) {
781 // remove '\n' from the end of preamble
782 string const tmppreamble = rtrim(preamble, "\n");
783 os << "\\begin_preamble\n"
785 << "\n\\end_preamble\n";
789 if (!options.empty()) {
790 os << "\\options " << options << '\n';
793 // use the class options defined in the layout?
794 os << "\\use_default_options "
795 << convert<string>(use_default_options) << "\n";
797 // the master document
798 if (!master.empty()) {
799 os << "\\master " << master << '\n';
803 if (!removedModules_.empty()) {
804 os << "\\begin_removed_modules" << '\n';
805 list<string>::const_iterator it = removedModules_.begin();
806 list<string>::const_iterator en = removedModules_.end();
807 for (; it != en; it++)
809 os << "\\end_removed_modules" << '\n';
813 if (!layoutModules_.empty()) {
814 os << "\\begin_modules" << '\n';
815 LayoutModuleList::const_iterator it = layoutModules_.begin();
816 LayoutModuleList::const_iterator en = layoutModules_.end();
817 for (; it != en; it++)
819 os << "\\end_modules" << '\n';
822 // local layout information
823 if (!local_layout.empty()) {
824 // remove '\n' from the end
825 string const tmplocal = rtrim(local_layout, "\n");
826 os << "\\begin_local_layout\n"
828 << "\n\\end_local_layout\n";
831 // then the text parameters
832 if (language != ignore_language)
833 os << "\\language " << language->lang() << '\n';
834 os << "\\inputencoding " << inputenc
835 << "\n\\font_roman " << fontsRoman
836 << "\n\\font_sans " << fontsSans
837 << "\n\\font_typewriter " << fontsTypewriter
838 << "\n\\font_default_family " << fontsDefaultFamily
839 << "\n\\use_xetex " << convert<string>(useXetex)
840 << "\n\\font_sc " << convert<string>(fontsSC)
841 << "\n\\font_osf " << convert<string>(fontsOSF)
842 << "\n\\font_sf_scale " << fontsSansScale
843 << "\n\\font_tt_scale " << fontsTypewriterScale
845 if (!fontsCJK.empty()) {
846 os << "\\font_cjk " << fontsCJK << '\n';
848 os << "\n\\graphics " << graphicsDriver << '\n';
849 os << "\\default_output_format " << defaultOutputFormat << '\n';
850 os << "\\bibtex_command " << bibtex_command << '\n';
851 os << "\\index_command " << index_command << '\n';
853 if (!float_placement.empty()) {
854 os << "\\float_placement " << float_placement << '\n';
856 os << "\\paperfontsize " << fontsize << '\n';
858 spacing().writeFile(os);
859 pdfoptions().writeFile(os);
861 os << "\\papersize " << string_papersize[papersize]
862 << "\n\\use_geometry " << convert<string>(use_geometry)
863 << "\n\\use_amsmath " << use_amsmath
864 << "\n\\use_esint " << use_esint
865 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
866 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
867 << "\n\\use_indices " << convert<string>(use_indices)
868 << "\n\\paperorientation " << string_orientation[orientation]
869 << "\n\\suppress_date " << convert<string>(suppress_date)
871 if (backgroundcolor != lyx::rgbFromHexName("#ffffff"))
872 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
874 BranchList::const_iterator it = branchlist().begin();
875 BranchList::const_iterator end = branchlist().end();
876 for (; it != end; ++it) {
877 os << "\\branch " << to_utf8(it->branch())
878 << "\n\\selected " << it->isSelected()
879 << "\n\\filename_suffix " << it->hasFilenameSuffix()
880 << "\n\\color " << lyx::X11hexname(it->color())
885 IndicesList::const_iterator iit = indiceslist().begin();
886 IndicesList::const_iterator iend = indiceslist().end();
887 for (; iit != iend; ++iit) {
888 os << "\\index " << to_utf8(iit->index())
889 << "\n\\shortcut " << to_utf8(iit->shortcut())
890 << "\n\\color " << lyx::X11hexname(iit->color())
895 if (!paperwidth.empty())
896 os << "\\paperwidth "
897 << VSpace(paperwidth).asLyXCommand() << '\n';
898 if (!paperheight.empty())
899 os << "\\paperheight "
900 << VSpace(paperheight).asLyXCommand() << '\n';
901 if (!leftmargin.empty())
902 os << "\\leftmargin "
903 << VSpace(leftmargin).asLyXCommand() << '\n';
904 if (!topmargin.empty())
906 << VSpace(topmargin).asLyXCommand() << '\n';
907 if (!rightmargin.empty())
908 os << "\\rightmargin "
909 << VSpace(rightmargin).asLyXCommand() << '\n';
910 if (!bottommargin.empty())
911 os << "\\bottommargin "
912 << VSpace(bottommargin).asLyXCommand() << '\n';
913 if (!headheight.empty())
914 os << "\\headheight "
915 << VSpace(headheight).asLyXCommand() << '\n';
916 if (!headsep.empty())
918 << VSpace(headsep).asLyXCommand() << '\n';
919 if (!footskip.empty())
921 << VSpace(footskip).asLyXCommand() << '\n';
922 if (!columnsep.empty())
924 << VSpace(columnsep).asLyXCommand() << '\n';
925 os << "\\secnumdepth " << secnumdepth
926 << "\n\\tocdepth " << tocdepth
927 << "\n\\paragraph_separation "
928 << string_paragraph_separation[paragraph_separation];
929 if (!paragraph_separation)
930 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
932 os << "\n\\defskip " << getDefSkip().asLyXCommand();
933 os << "\n\\quotes_language "
934 << string_quotes_language[quotes_language]
935 << "\n\\papercolumns " << columns
936 << "\n\\papersides " << sides
937 << "\n\\paperpagestyle " << pagestyle << '\n';
938 if (!listings_params.empty())
939 os << "\\listings_params \"" <<
940 InsetListingsParams(listings_params).encodedString() << "\"\n";
941 for (int i = 0; i < 4; ++i) {
942 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
943 if (user_defined_bullet(i).getFont() != -1) {
944 os << "\\bullet " << i << " "
945 << user_defined_bullet(i).getFont() << " "
946 << user_defined_bullet(i).getCharacter() << " "
947 << user_defined_bullet(i).getSize() << "\n";
951 os << "\\bulletLaTeX " << i << " \""
952 << lyx::to_ascii(user_defined_bullet(i).getText())
958 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
959 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
961 os << pimpl_->authorlist;
965 void BufferParams::validate(LaTeXFeatures & features) const
967 features.require(documentClass().requires());
970 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
971 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
972 LaTeXFeatures::isAvailable("xcolor");
974 switch (features.runparams().flavor) {
975 case OutputParams::LATEX:
977 features.require("ct-dvipost");
978 features.require("dvipost");
979 } else if (xcolorulem) {
980 features.require("ct-xcolor-ulem");
981 features.require("ulem");
982 features.require("xcolor");
984 features.require("ct-none");
987 case OutputParams::PDFLATEX:
988 case OutputParams::XETEX:
990 features.require("ct-xcolor-ulem");
991 features.require("ulem");
992 features.require("xcolor");
993 // improves color handling in PDF output
994 features.require("pdfcolmk");
996 features.require("ct-none");
1004 // Floats with 'Here definitely' as default setting.
1005 if (float_placement.find('H') != string::npos)
1006 features.require("float");
1008 // AMS Style is at document level
1009 if (use_amsmath == package_on
1010 || documentClass().provides("amsmath"))
1011 features.require("amsmath");
1012 if (use_esint == package_on)
1013 features.require("esint");
1015 // Document-level line spacing
1016 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1017 features.require("setspace");
1019 // the bullet shapes are buffer level not paragraph level
1020 // so they are tested here
1021 for (int i = 0; i < 4; ++i) {
1022 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1024 int const font = user_defined_bullet(i).getFont();
1026 int const c = user_defined_bullet(i).getCharacter();
1032 features.require("latexsym");
1034 } else if (font == 1) {
1035 features.require("amssymb");
1036 } else if (font >= 2 && font <= 5) {
1037 features.require("pifont");
1041 if (pdfoptions().use_hyperref) {
1042 features.require("hyperref");
1043 // due to interferences with babel and hyperref, the color package has to
1044 // be loaded after hyperref when hyperref is used with the colorlinks
1045 // option, see http://bugzilla.lyx.org/show_bug.cgi?id=5291
1046 if (pdfoptions().colorlinks)
1047 features.require("color");
1051 features.require("xetex");
1053 if (language->lang() == "vietnamese")
1054 features.require("vietnamese");
1055 else if (language->lang() == "japanese")
1056 features.require("japanese");
1060 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1061 TexRow & texrow) const
1063 os << "\\documentclass";
1065 DocumentClass const & tclass = documentClass();
1067 ostringstream clsoptions; // the document class options.
1069 if (tokenPos(tclass.opt_fontsize(),
1070 '|', fontsize) >= 0) {
1071 // only write if existing in list (and not default)
1072 clsoptions << fontsize << "pt,";
1075 // custom, A3, B3 and B4 paper sizes need geometry
1076 bool nonstandard_papersize = papersize == PAPER_B3
1077 || papersize == PAPER_B4
1078 || papersize == PAPER_A3
1079 || papersize == PAPER_CUSTOM;
1081 if (!use_geometry) {
1082 switch (papersize) {
1084 clsoptions << "a4paper,";
1086 case PAPER_USLETTER:
1087 clsoptions << "letterpaper,";
1090 clsoptions << "a5paper,";
1093 clsoptions << "b5paper,";
1095 case PAPER_USEXECUTIVE:
1096 clsoptions << "executivepaper,";
1099 clsoptions << "legalpaper,";
1111 if (sides != tclass.sides()) {
1114 clsoptions << "oneside,";
1117 clsoptions << "twoside,";
1123 if (columns != tclass.columns()) {
1125 clsoptions << "twocolumn,";
1127 clsoptions << "onecolumn,";
1131 && orientation == ORIENTATION_LANDSCAPE)
1132 clsoptions << "landscape,";
1134 // language should be a parameter to \documentclass
1135 if (language->babel() == "hebrew"
1136 && default_language->babel() != "hebrew")
1137 // This seems necessary
1138 features.useLanguage(default_language);
1140 ostringstream language_options;
1141 bool const use_babel = features.useBabel();
1143 language_options << features.getLanguages();
1144 if (!language->babel().empty()) {
1145 if (!language_options.str().empty())
1146 language_options << ',';
1147 language_options << language->babel();
1149 // if Vietnamese is used, babel must directly be loaded
1150 // with language options, not in the class options, see
1151 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1152 size_t viet = language_options.str().find("vietnam");
1153 // viet = string::npos when not found
1154 // the same is for all other languages that are not directly supported by
1155 // babel, but where LaTeX-packages add babel support.
1156 // this is currently the case for Latvian, Lithuanian, and Mongolian
1157 size_t latvian = language_options.str().find("latvian");
1158 size_t lithu = language_options.str().find("lithuanian");
1159 size_t mongo = language_options.str().find("mongolian");
1160 // if Japanese is used, babel must directly be loaded
1161 // with language options, not in the class options, see
1162 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1163 size_t japan = language_options.str().find("japanese");
1164 if (lyxrc.language_global_options && !language_options.str().empty()
1165 && viet == string::npos && japan == string::npos
1166 && latvian == string::npos && lithu == string::npos
1167 && mongo == string::npos)
1168 clsoptions << language_options.str() << ',';
1171 // the predefined options from the layout
1172 if (use_default_options && !tclass.options().empty())
1173 clsoptions << tclass.options() << ',';
1175 // the user-defined options
1176 if (!options.empty()) {
1177 clsoptions << options << ',';
1180 string strOptions(clsoptions.str());
1181 if (!strOptions.empty()) {
1182 strOptions = rtrim(strOptions, ",");
1184 os << '[' << from_utf8(strOptions) << ']';
1187 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1189 // end of \documentclass defs
1192 os << "\\usepackage{fontspec}\n";
1196 // font selection must be done before loading fontenc.sty
1197 string const fonts =
1198 loadFonts(fontsRoman, fontsSans,
1199 fontsTypewriter, fontsSC, fontsOSF,
1200 fontsSansScale, fontsTypewriterScale, useXetex);
1201 if (!fonts.empty()) {
1202 os << from_ascii(fonts);
1205 if (fontsDefaultFamily != "default")
1206 os << "\\renewcommand{\\familydefault}{\\"
1207 << from_ascii(fontsDefaultFamily) << "}\n";
1209 // set font encoding
1210 // this one is not per buffer
1211 // for arabic_arabi and farsi we also need to load the LAE and
1213 // XeTeX works without fontenc
1214 if (lyxrc.fontenc != "default" && language->lang() != "japanese"
1216 if (language->lang() == "arabic_arabi"
1217 || language->lang() == "farsi") {
1218 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1219 << ",LFE,LAE]{fontenc}\n";
1222 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1228 // handle inputenc etc.
1229 writeEncodingPreamble(os, features, texrow);
1231 if (!listings_params.empty() || features.isRequired("listings")) {
1232 os << "\\usepackage{listings}\n";
1235 if (!listings_params.empty()) {
1237 // do not test validity because listings_params is
1238 // supposed to be valid
1240 InsetListingsParams(listings_params).separatedParams(true);
1241 // we can't support all packages, but we should load the color package
1242 if (par.find("\\color", 0) != string::npos)
1243 features.require("color");
1244 os << from_utf8(par);
1245 // count the number of newlines
1246 for (size_t i = 0; i < par.size(); ++i)
1252 if (!tclass.provides("geometry")
1253 && (use_geometry || nonstandard_papersize)) {
1254 odocstringstream ods;
1255 if (!getGraphicsDriver("geometry").empty())
1256 ods << getGraphicsDriver("geometry");
1257 if (orientation == ORIENTATION_LANDSCAPE)
1258 ods << ",landscape";
1259 switch (papersize) {
1261 if (!paperwidth.empty())
1262 ods << ",paperwidth="
1263 << from_ascii(paperwidth);
1264 if (!paperheight.empty())
1265 ods << ",paperheight="
1266 << from_ascii(paperheight);
1268 case PAPER_USLETTER:
1269 ods << ",letterpaper";
1272 ods << ",legalpaper";
1274 case PAPER_USEXECUTIVE:
1275 ods << ",executivepaper";
1296 // default papersize ie PAPER_DEFAULT
1297 switch (lyxrc.default_papersize) {
1298 case PAPER_DEFAULT: // keep compiler happy
1299 case PAPER_USLETTER:
1300 ods << ",letterpaper";
1303 ods << ",legalpaper";
1305 case PAPER_USEXECUTIVE:
1306 ods << ",executivepaper";
1326 docstring const g_options = trim(ods.str(), ",");
1327 os << "\\usepackage";
1328 if (!g_options.empty())
1329 os << '[' << g_options << ']';
1330 os << "{geometry}\n";
1332 os << "\\geometry{verbose";
1333 if (!topmargin.empty())
1334 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1335 if (!bottommargin.empty())
1336 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1337 if (!leftmargin.empty())
1338 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1339 if (!rightmargin.empty())
1340 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1341 if (!headheight.empty())
1342 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1343 if (!headsep.empty())
1344 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1345 if (!footskip.empty())
1346 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1347 if (!columnsep.empty())
1348 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1351 } else if (orientation == ORIENTATION_LANDSCAPE) {
1352 features.require("papersize");
1355 if (tokenPos(tclass.opt_pagestyle(),
1356 '|', pagestyle) >= 0) {
1357 if (pagestyle == "fancy") {
1358 os << "\\usepackage{fancyhdr}\n";
1361 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1365 // only output when the background color is not white
1366 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1367 // only require color here, the background color will be defined
1368 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1370 features.require("color");
1371 features.require("pagecolor");
1374 // Only if class has a ToC hierarchy
1375 if (tclass.hasTocLevels()) {
1376 if (secnumdepth != tclass.secnumdepth()) {
1377 os << "\\setcounter{secnumdepth}{"
1382 if (tocdepth != tclass.tocdepth()) {
1383 os << "\\setcounter{tocdepth}{"
1390 if (paragraph_separation) {
1391 // when skip separation
1392 switch (getDefSkip().kind()) {
1393 case VSpace::SMALLSKIP:
1394 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1396 case VSpace::MEDSKIP:
1397 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1399 case VSpace::BIGSKIP:
1400 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1402 case VSpace::LENGTH:
1403 os << "\\setlength{\\parskip}{"
1404 << from_utf8(getDefSkip().length().asLatexString())
1407 default: // should never happen // Then delete it.
1408 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1412 os << "\\setlength{\\parindent}{0pt}\n";
1415 // when separation by indentation
1416 // only output something when a width is given
1417 if (getIndentation().asLyXCommand() != "default") {
1418 os << "\\setlength{\\parindent}{"
1419 << from_utf8(getIndentation().asLatexCommand())
1425 // Now insert the LyX specific LaTeX commands...
1426 docstring lyxpreamble;
1428 // due to interferences with babel and hyperref, the color package has to
1429 // be loaded (when it is not already loaded) before babel when hyperref
1430 // is used with the colorlinks option, see
1431 // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1432 // we decided therefore to load color always before babel, see
1433 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1434 lyxpreamble += from_ascii(features.getColorOptions());
1436 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1438 && (features.isRequired("jurabib")
1439 || features.isRequired("hyperref")
1440 || features.isRequired("vietnamese")
1441 || features.isRequired("japanese") ) ) {
1443 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1444 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1447 // The optional packages;
1448 lyxpreamble += from_ascii(features.getPackages());
1450 // Additional Indices
1451 if (features.isRequired("splitidx")) {
1452 IndicesList::const_iterator iit = indiceslist().begin();
1453 IndicesList::const_iterator iend = indiceslist().end();
1454 for (; iit != iend; ++iit) {
1455 lyxpreamble += "\\newindex[";
1456 lyxpreamble += iit->index();
1457 lyxpreamble += "]{";
1458 lyxpreamble += iit->shortcut();
1459 lyxpreamble += "}\n";
1464 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1468 lyxpreamble += "\\date{}\n";
1471 // * Hyperref manual: "Make sure it comes last of your loaded
1472 // packages, to give it a fighting chance of not being over-written,
1473 // since its job is to redefine many LaTeX commands."
1474 // * Email from Heiko Oberdiek: "It is usually better to load babel
1475 // before hyperref. Then hyperref has a chance to detect babel.
1476 // * Has to be loaded before the "LyX specific LaTeX commands" to
1477 // avoid errors with algorithm floats.
1478 // use hyperref explicitely when it is required
1479 if (features.isRequired("hyperref")) {
1480 odocstringstream oss;
1481 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1482 lyxpreamble += oss.str();
1485 // Will be surrounded by \makeatletter and \makeatother when not empty
1486 docstring atlyxpreamble;
1488 // Some macros LyX will need
1489 docstring tmppreamble(features.getMacros());
1491 if (!tmppreamble.empty())
1492 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1493 "LyX specific LaTeX commands.\n"
1494 + tmppreamble + '\n';
1496 // the text class specific preamble
1497 tmppreamble = features.getTClassPreamble();
1498 if (!tmppreamble.empty())
1499 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1500 "Textclass specific LaTeX commands.\n"
1501 + tmppreamble + '\n';
1503 /* the user-defined preamble */
1504 if (!containsOnly(preamble, " \n\t"))
1506 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1507 "User specified LaTeX commands.\n"
1508 + from_utf8(preamble) + '\n';
1510 // subfig loads internally the LaTeX package "caption". As
1511 // caption is a very popular package, users will load it in
1512 // the preamble. Therefore we must load subfig behind the
1513 // user-defined preamble and check if the caption package was
1514 // loaded or not. For the case that caption is loaded before
1515 // subfig, there is the subfig option "caption=false". This
1516 // option also works when a koma-script class is used and
1517 // koma's own caption commands are used instead of caption. We
1518 // use \PassOptionsToPackage here because the user could have
1519 // already loaded subfig in the preamble.
1520 if (features.isRequired("subfig")) {
1521 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1522 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1523 "\\usepackage{subfig}\n";
1526 // Itemize bullet settings need to be last in case the user
1527 // defines their own bullets that use a package included
1528 // in the user-defined preamble -- ARRae
1529 // Actually it has to be done much later than that
1530 // since some packages like frenchb make modifications
1531 // at \begin{document} time -- JMarc
1532 docstring bullets_def;
1533 for (int i = 0; i < 4; ++i) {
1534 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1535 if (bullets_def.empty())
1536 bullets_def += "\\AtBeginDocument{\n";
1537 bullets_def += " \\def\\labelitemi";
1539 // `i' is one less than the item to modify
1546 bullets_def += "ii";
1552 bullets_def += '{' +
1553 user_defined_bullet(i).getText()
1558 if (!bullets_def.empty())
1559 atlyxpreamble += bullets_def + "}\n\n";
1561 if (!atlyxpreamble.empty())
1562 lyxpreamble += "\n\\makeatletter\n"
1563 + atlyxpreamble + "\\makeatother\n\n";
1565 // We try to load babel late, in case it interferes with other packages.
1566 // Jurabib and Hyperref have to be called after babel, though.
1567 if (use_babel && !features.isRequired("jurabib")
1568 && !features.isRequired("hyperref")
1569 && !features.isRequired("vietnamese")
1570 && !features.isRequired("japanese")) {
1572 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1573 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1576 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1577 if (!i18npreamble.empty())
1578 lyxpreamble += i18npreamble + '\n';
1581 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1582 for (int j = 0; j != nlines; ++j) {
1588 // these packages (xunicode, for that matter) need to be loaded at least
1589 // after amsmath, amssymb, esint and the other packages that provide
1592 os << "\\usepackage{xunicode}\n";
1594 os << "\\usepackage{xltxtra}\n";
1601 void BufferParams::useClassDefaults()
1603 DocumentClass const & tclass = documentClass();
1605 sides = tclass.sides();
1606 columns = tclass.columns();
1607 pagestyle = tclass.pagestyle();
1608 use_default_options = true;
1609 // Only if class has a ToC hierarchy
1610 if (tclass.hasTocLevels()) {
1611 secnumdepth = tclass.secnumdepth();
1612 tocdepth = tclass.tocdepth();
1617 bool BufferParams::hasClassDefaults() const
1619 DocumentClass const & tclass = documentClass();
1621 return sides == tclass.sides()
1622 && columns == tclass.columns()
1623 && pagestyle == tclass.pagestyle()
1624 && use_default_options
1625 && secnumdepth == tclass.secnumdepth()
1626 && tocdepth == tclass.tocdepth();
1630 DocumentClass const & BufferParams::documentClass() const
1636 DocumentClass const * BufferParams::documentClassPtr() const {
1641 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1642 // evil, but this function is evil
1643 doc_class_ = const_cast<DocumentClass *>(tc);
1647 bool BufferParams::setBaseClass(string const & classname)
1649 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1650 LayoutFileList & bcl = LayoutFileList::get();
1651 if (!bcl.haveClass(classname)) {
1653 bformat(_("The document class %1$s could not be found. "
1654 "A default textclass with default layouts will be used. "
1655 "LyX might not be able to produce output unless a correct "
1656 "textclass is selected from the document settings dialog."),
1657 from_utf8(classname));
1658 frontend::Alert::error(_("Document class not found"), s);
1659 bcl.addEmptyClass(classname);
1662 bool const success = bcl[classname].load();
1665 bformat(_("The document class %1$s could not be loaded."),
1666 from_utf8(classname));
1667 frontend::Alert::error(_("Could not load class"), s);
1671 pimpl_->baseClass_ = classname;
1672 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1677 LayoutFile const * BufferParams::baseClass() const
1679 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1680 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1686 LayoutFileIndex const & BufferParams::baseClassID() const
1688 return pimpl_->baseClass_;
1692 void BufferParams::makeDocumentClass()
1697 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1699 if (!local_layout.empty()) {
1700 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1701 docstring const msg = _("Error reading internal layout information");
1702 frontend::Alert::warning(_("Read Error"), msg);
1707 bool BufferParams::moduleCanBeAdded(string const & modName) const
1709 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1713 bool BufferParams::addLayoutModule(string const & modName)
1715 LayoutModuleList::const_iterator it = layoutModules_.begin();
1716 LayoutModuleList::const_iterator end = layoutModules_.end();
1717 for (; it != end; it++)
1720 layoutModules_.push_back(modName);
1725 Font const BufferParams::getFont() const
1727 FontInfo f = documentClass().defaultfont();
1728 if (fontsDefaultFamily == "rmdefault")
1729 f.setFamily(ROMAN_FAMILY);
1730 else if (fontsDefaultFamily == "sfdefault")
1731 f.setFamily(SANS_FAMILY);
1732 else if (fontsDefaultFamily == "ttdefault")
1733 f.setFamily(TYPEWRITER_FAMILY);
1734 return Font(f, language);
1738 void BufferParams::readPreamble(Lexer & lex)
1740 if (lex.getString() != "\\begin_preamble")
1741 lyxerr << "Error (BufferParams::readPreamble):"
1742 "consistency check failed." << endl;
1744 preamble = lex.getLongString("\\end_preamble");
1748 void BufferParams::readLocalLayout(Lexer & lex)
1750 if (lex.getString() != "\\begin_local_layout")
1751 lyxerr << "Error (BufferParams::readLocalLayout):"
1752 "consistency check failed." << endl;
1754 local_layout = lex.getLongString("\\end_local_layout");
1758 void BufferParams::readLanguage(Lexer & lex)
1760 if (!lex.next()) return;
1762 string const tmptok = lex.getString();
1764 // check if tmptok is part of tex_babel in tex-defs.h
1765 language = languages.getLanguage(tmptok);
1767 // Language tmptok was not found
1768 language = default_language;
1769 lyxerr << "Warning: Setting language `"
1770 << tmptok << "' to `" << language->lang()
1776 void BufferParams::readGraphicsDriver(Lexer & lex)
1781 string const tmptok = lex.getString();
1782 // check if tmptok is part of tex_graphics in tex_defs.h
1785 string const test = tex_graphics[n++];
1787 if (test == tmptok) {
1788 graphicsDriver = tmptok;
1793 "Warning: graphics driver `$$Token' not recognized!\n"
1794 " Setting graphics driver to `default'.\n");
1795 graphicsDriver = "default";
1802 void BufferParams::readBullets(Lexer & lex)
1807 int const index = lex.getInteger();
1809 int temp_int = lex.getInteger();
1810 user_defined_bullet(index).setFont(temp_int);
1811 temp_bullet(index).setFont(temp_int);
1813 user_defined_bullet(index).setCharacter(temp_int);
1814 temp_bullet(index).setCharacter(temp_int);
1816 user_defined_bullet(index).setSize(temp_int);
1817 temp_bullet(index).setSize(temp_int);
1821 void BufferParams::readBulletsLaTeX(Lexer & lex)
1823 // The bullet class should be able to read this.
1826 int const index = lex.getInteger();
1828 docstring const temp_str = lex.getDocString();
1830 user_defined_bullet(index).setText(temp_str);
1831 temp_bullet(index).setText(temp_str);
1835 void BufferParams::readModules(Lexer & lex)
1837 if (!lex.eatLine()) {
1838 lyxerr << "Error (BufferParams::readModules):"
1839 "Unexpected end of input." << endl;
1843 string mod = lex.getString();
1844 if (mod == "\\end_modules")
1846 addLayoutModule(mod);
1852 void BufferParams::readRemovedModules(Lexer & lex)
1854 if (!lex.eatLine()) {
1855 lyxerr << "Error (BufferParams::readRemovedModules):"
1856 "Unexpected end of input." << endl;
1860 string mod = lex.getString();
1861 if (mod == "\\end_removed_modules")
1863 removedModules_.push_back(mod);
1866 // now we want to remove any removed modules that were previously
1867 // added. normally, that will be because default modules were added in
1868 // setBaseClass(), which gets called when \textclass is read at the
1869 // start of the read.
1870 list<string>::const_iterator rit = removedModules_.begin();
1871 list<string>::const_iterator const ren = removedModules_.end();
1872 for (; rit != ren; rit++) {
1873 LayoutModuleList::iterator const mit = layoutModules_.begin();
1874 LayoutModuleList::iterator const men = layoutModules_.end();
1875 LayoutModuleList::iterator found = find(mit, men, *rit);
1878 layoutModules_.erase(found);
1883 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1885 char real_papersize = papersize;
1886 if (real_papersize == PAPER_DEFAULT)
1887 real_papersize = lyxrc.default_papersize;
1889 switch (real_papersize) {
1891 // could be anything, so don't guess
1893 case PAPER_CUSTOM: {
1894 if (purpose == XDVI && !paperwidth.empty() &&
1895 !paperheight.empty()) {
1896 // heightxwidth<unit>
1897 string first = paperwidth;
1898 string second = paperheight;
1899 if (orientation == ORIENTATION_LANDSCAPE)
1902 return first.erase(first.length() - 2)
1914 // dvips and dvipdfm do not know this
1915 if (purpose == DVIPS || purpose == DVIPDFM)
1919 // dvipdfm does not know this
1920 if (purpose == DVIPDFM)
1924 // dvipdfm does not know this
1925 if (purpose == DVIPDFM)
1928 case PAPER_USEXECUTIVE:
1929 // dvipdfm does not know this
1930 if (purpose == DVIPDFM)
1935 case PAPER_USLETTER:
1937 if (purpose == XDVI)
1944 string const BufferParams::dvips_options() const
1949 && papersize == PAPER_CUSTOM
1950 && !lyxrc.print_paper_dimension_flag.empty()
1951 && !paperwidth.empty()
1952 && !paperheight.empty()) {
1953 // using a custom papersize
1954 result = lyxrc.print_paper_dimension_flag;
1955 result += ' ' + paperwidth;
1956 result += ',' + paperheight;
1958 string const paper_option = paperSizeName(DVIPS);
1959 if (!paper_option.empty() && (paper_option != "letter" ||
1960 orientation != ORIENTATION_LANDSCAPE)) {
1961 // dvips won't accept -t letter -t landscape.
1962 // In all other cases, include the paper size
1964 result = lyxrc.print_paper_flag;
1965 result += ' ' + paper_option;
1968 if (orientation == ORIENTATION_LANDSCAPE &&
1969 papersize != PAPER_CUSTOM)
1970 result += ' ' + lyxrc.print_landscape_flag;
1975 string BufferParams::babelCall(string const & lang_opts) const
1977 string lang_pack = lyxrc.language_package;
1978 if (lang_pack != "\\usepackage{babel}")
1980 // suppress the babel call when there is no babel language defined
1981 // for the document language in the lib/languages file and if no
1982 // other languages are used (lang_opts is then empty)
1983 if (lang_opts.empty())
1985 // If Vietnamese is used, babel must directly be loaded with the
1986 // language options, see
1987 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1988 size_t viet = lang_opts.find("vietnam");
1989 // viet = string::npos when not found
1990 // the same is for all other languages that are not directly supported by
1991 // babel, but where LaTeX-packages add babel support.
1992 // this is currently the case for Latvian, Lithuanian, and Mongolian
1993 size_t latvian = lang_opts.find("latvian");
1994 size_t lithu = lang_opts.find("lithuanian");
1995 size_t mongo = lang_opts.find("mongolian");
1996 // If Japanese is used, babel must directly be loaded with the
1997 // language options, see
1998 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1999 size_t japan = lang_opts.find("japanese");
2000 if (!lyxrc.language_global_options || viet != string::npos
2001 || japan != string::npos || latvian != string::npos
2002 || lithu != string::npos || mongo != string::npos)
2003 return "\\usepackage[" + lang_opts + "]{babel}";
2008 docstring BufferParams::getGraphicsDriver(string const & package) const
2012 if (package == "geometry") {
2013 if (graphicsDriver == "dvips"
2014 || graphicsDriver == "dvipdfm"
2015 || graphicsDriver == "pdftex"
2016 || graphicsDriver == "vtex")
2017 result = from_ascii(graphicsDriver);
2018 else if (graphicsDriver == "dvipdfmx")
2019 result = from_ascii("dvipdfm");
2026 void BufferParams::writeEncodingPreamble(odocstream & os,
2027 LaTeXFeatures & features, TexRow & texrow) const
2031 if (inputenc == "auto") {
2032 string const doc_encoding =
2033 language->encoding()->latexName();
2034 Encoding::Package const package =
2035 language->encoding()->package();
2037 // Create a list with all the input encodings used
2039 set<string> encodings =
2040 features.getEncodingSet(doc_encoding);
2042 // If the "japanese" package (i.e. pLaTeX) is used,
2043 // inputenc must be omitted.
2044 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2045 if (package == Encoding::japanese)
2046 features.require("japanese");
2048 if ((!encodings.empty() || package == Encoding::inputenc)
2049 && !features.isRequired("japanese")) {
2050 os << "\\usepackage[";
2051 set<string>::const_iterator it = encodings.begin();
2052 set<string>::const_iterator const end = encodings.end();
2054 os << from_ascii(*it);
2057 for (; it != end; ++it)
2058 os << ',' << from_ascii(*it);
2059 if (package == Encoding::inputenc) {
2060 if (!encodings.empty())
2062 os << from_ascii(doc_encoding);
2064 os << "]{inputenc}\n";
2067 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2068 if (language->encoding()->name() == "utf8-cjk"
2069 && LaTeXFeatures::isAvailable("CJKutf8"))
2070 os << "\\usepackage{CJKutf8}\n";
2072 os << "\\usepackage{CJK}\n";
2075 } else if (inputenc != "default") {
2076 switch (encoding().package()) {
2077 case Encoding::none:
2078 case Encoding::japanese:
2080 case Encoding::inputenc:
2081 // do not load inputenc if japanese is used
2082 if (features.isRequired("japanese"))
2084 os << "\\usepackage[" << from_ascii(inputenc)
2089 if (encoding().name() == "utf8-cjk"
2090 && LaTeXFeatures::isAvailable("CJKutf8"))
2091 os << "\\usepackage{CJKutf8}\n";
2093 os << "\\usepackage{CJK}\n";
2099 // The encoding "armscii8" (for Armenian) is only available when
2100 // the package "armtex" is loaded.
2101 if (language->encoding()->latexName() == "armscii8"
2102 || inputenc == "armscii8") {
2103 os << "\\usepackage{armtex}\n";
2109 string const BufferParams::parseFontName(string const & name) const
2111 string mangled = name;
2112 size_t const idx = mangled.find('[');
2113 if (idx == string::npos || idx == 0)
2116 return mangled.substr(0, idx - 1);
2120 string const BufferParams::loadFonts(string const & rm,
2121 string const & sf, string const & tt,
2122 bool const & sc, bool const & osf,
2123 int const & sfscale, int const & ttscale,
2124 bool const & xetex) const
2126 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2127 several packages have been replaced by others, that might not
2128 be installed on every system. We have to take care for that
2129 (see psnfss.pdf). We try to support all psnfss fonts as well
2130 as the fonts that have become de facto standard in the LaTeX
2131 world (e.g. Latin Modern). We do not support obsolete fonts
2132 (like PSLatex). In general, it should be possible to mix any
2133 rm font with any sf or tt font, respectively. (JSpitzm)
2135 -- separate math fonts.
2138 if (rm == "default" && sf == "default" && tt == "default")
2145 if (rm != "default")
2146 os << "\\setmainfont[Mapping=tex-text]{"
2147 << parseFontName(rm) << "}\n";
2148 if (sf != "default") {
2149 string const sans = parseFontName(sf);
2151 os << "\\setsansfont[Scale="
2152 << float(sfscale) / 100
2153 << ",Mapping=tex-text]{"
2156 os << "\\setsansfont[Mapping=tex-text]{"
2159 if (tt != "default") {
2160 string const mono = parseFontName(tt);
2162 os << "\\setmonofont[Scale="
2163 << float(sfscale) / 100
2167 os << "\\setmonofont[Mapping=tex-text]{"
2171 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2176 // Computer Modern (must be explicitely selectable -- there might be classes
2177 // that define a different default font!
2179 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2180 // osf for Computer Modern needs eco.sty
2182 os << "\\usepackage{eco}\n";
2184 // Latin Modern Roman
2185 else if (rm == "lmodern")
2186 os << "\\usepackage{lmodern}\n";
2188 else if (rm == "ae") {
2189 // not needed when using OT1 font encoding.
2190 if (lyxrc.fontenc != "default")
2191 os << "\\usepackage{ae,aecompl}\n";
2194 else if (rm == "times") {
2195 // try to load the best available package
2196 if (LaTeXFeatures::isAvailable("mathptmx"))
2197 os << "\\usepackage{mathptmx}\n";
2198 else if (LaTeXFeatures::isAvailable("mathptm"))
2199 os << "\\usepackage{mathptm}\n";
2201 os << "\\usepackage{times}\n";
2204 else if (rm == "palatino") {
2205 // try to load the best available package
2206 if (LaTeXFeatures::isAvailable("mathpazo")) {
2207 os << "\\usepackage";
2213 // "osf" includes "sc"!
2217 os << "{mathpazo}\n";
2219 else if (LaTeXFeatures::isAvailable("mathpple"))
2220 os << "\\usepackage{mathpple}\n";
2222 os << "\\usepackage{palatino}\n";
2225 else if (rm == "utopia") {
2226 // fourier supersedes utopia.sty, but does
2227 // not work with OT1 encoding.
2228 if (LaTeXFeatures::isAvailable("fourier")
2229 && lyxrc.fontenc != "default") {
2230 os << "\\usepackage";
2241 os << "{fourier}\n";
2244 os << "\\usepackage{utopia}\n";
2246 // Bera (complete fontset)
2247 else if (rm == "bera" && sf == "default" && tt == "default")
2248 os << "\\usepackage{bera}\n";
2250 else if (rm != "default")
2251 os << "\\usepackage" << "{" << rm << "}\n";
2254 // Helvetica, Bera Sans
2255 if (sf == "helvet" || sf == "berasans") {
2257 os << "\\usepackage[scaled=" << float(sfscale) / 100
2258 << "]{" << sf << "}\n";
2260 os << "\\usepackage{" << sf << "}\n";
2263 else if (sf == "avant")
2264 os << "\\usepackage{" << sf << "}\n";
2265 // Computer Modern, Latin Modern, CM Bright
2266 else if (sf != "default")
2267 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2269 // monospaced/typewriter
2270 // Courier, LuxiMono
2271 if (tt == "luximono" || tt == "beramono") {
2273 os << "\\usepackage[scaled=" << float(ttscale) / 100
2274 << "]{" << tt << "}\n";
2276 os << "\\usepackage{" << tt << "}\n";
2279 else if (tt == "courier" )
2280 os << "\\usepackage{" << tt << "}\n";
2281 // Computer Modern, Latin Modern, CM Bright
2282 else if (tt != "default")
2283 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2289 Encoding const & BufferParams::encoding() const
2292 return *(encodings.fromLaTeXName("utf8-plain"));
2293 if (inputenc == "auto" || inputenc == "default")
2294 return *language->encoding();
2295 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2298 LYXERR0("Unknown inputenc value `" << inputenc
2299 << "'. Using `auto' instead.");
2300 return *language->encoding();
2304 CiteEngine BufferParams::citeEngine() const
2306 // FIXME the class should provide the numerical/
2307 // authoryear choice
2308 if (documentClass().provides("natbib")
2309 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2310 return ENGINE_NATBIB_AUTHORYEAR;
2311 return cite_engine_;
2315 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2317 cite_engine_ = cite_engine;