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();
664 indiceslist().add(index);
667 string const tok = lex.getString();
668 if (tok == "\\end_index")
670 Index * index_ptr = indiceslist().find(index);
671 if (tok == "\\shortcut") {
673 shortcut = lex.getDocString();
675 index_ptr->setShortcut(shortcut);
677 // not yet operational
678 if (tok == "\\color") {
680 string color = lex.getString();
682 index_ptr->setColor(color);
683 // Update also the Color table:
685 color = lcolor.getX11Name(Color_background);
687 if (!shortcut.empty())
688 lcolor.setColor(to_utf8(shortcut), color);
691 } else if (token == "\\author") {
693 istringstream ss(lex.getString());
696 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
697 } else if (token == "\\paperorientation") {
700 orientation = paperorientationtranslator().find(orient);
701 } else if (token == "\\backgroundcolor") {
703 backgroundcolor = lyx::rgbFromHexName(lex.getString());
704 } else if (token == "\\paperwidth") {
706 } else if (token == "\\paperheight") {
708 } else if (token == "\\leftmargin") {
710 } else if (token == "\\topmargin") {
712 } else if (token == "\\rightmargin") {
714 } else if (token == "\\bottommargin") {
716 } else if (token == "\\headheight") {
718 } else if (token == "\\headsep") {
720 } else if (token == "\\footskip") {
722 } else if (token == "\\columnsep") {
724 } else if (token == "\\paperfontsize") {
726 } else if (token == "\\papercolumns") {
728 } else if (token == "\\listings_params") {
731 listings_params = InsetListingsParams(par).params();
732 } else if (token == "\\papersides") {
735 sides = sidestranslator().find(psides);
736 } else if (token == "\\paperpagestyle") {
738 } else if (token == "\\bullet") {
740 } else if (token == "\\bulletLaTeX") {
741 readBulletsLaTeX(lex);
742 } else if (token == "\\secnumdepth") {
744 } else if (token == "\\tocdepth") {
746 } else if (token == "\\spacing") {
750 if (nspacing == "other") {
753 spacing().set(spacetranslator().find(nspacing), tmp_val);
754 } else if (token == "\\float_placement") {
755 lex >> float_placement;
757 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
758 string toktmp = pdfoptions().readToken(lex, token);
759 if (!toktmp.empty()) {
760 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
765 lyxerr << "BufferParams::readToken(): Unknown token: " <<
774 void BufferParams::writeFile(ostream & os) const
776 // The top of the file is written by the buffer.
777 // Prints out the buffer info into the .lyx file given by file
780 os << "\\textclass " << baseClass()->name() << '\n';
783 if (!preamble.empty()) {
784 // remove '\n' from the end of preamble
785 string const tmppreamble = rtrim(preamble, "\n");
786 os << "\\begin_preamble\n"
788 << "\n\\end_preamble\n";
792 if (!options.empty()) {
793 os << "\\options " << options << '\n';
796 // use the class options defined in the layout?
797 os << "\\use_default_options "
798 << convert<string>(use_default_options) << "\n";
800 // the master document
801 if (!master.empty()) {
802 os << "\\master " << master << '\n';
806 if (!removedModules_.empty()) {
807 os << "\\begin_removed_modules" << '\n';
808 list<string>::const_iterator it = removedModules_.begin();
809 list<string>::const_iterator en = removedModules_.end();
810 for (; it != en; it++)
812 os << "\\end_removed_modules" << '\n';
816 if (!layoutModules_.empty()) {
817 os << "\\begin_modules" << '\n';
818 LayoutModuleList::const_iterator it = layoutModules_.begin();
819 LayoutModuleList::const_iterator en = layoutModules_.end();
820 for (; it != en; it++)
822 os << "\\end_modules" << '\n';
825 // local layout information
826 if (!local_layout.empty()) {
827 // remove '\n' from the end
828 string const tmplocal = rtrim(local_layout, "\n");
829 os << "\\begin_local_layout\n"
831 << "\n\\end_local_layout\n";
834 // then the text parameters
835 if (language != ignore_language)
836 os << "\\language " << language->lang() << '\n';
837 os << "\\inputencoding " << inputenc
838 << "\n\\font_roman " << fontsRoman
839 << "\n\\font_sans " << fontsSans
840 << "\n\\font_typewriter " << fontsTypewriter
841 << "\n\\font_default_family " << fontsDefaultFamily
842 << "\n\\use_xetex " << convert<string>(useXetex)
843 << "\n\\font_sc " << convert<string>(fontsSC)
844 << "\n\\font_osf " << convert<string>(fontsOSF)
845 << "\n\\font_sf_scale " << fontsSansScale
846 << "\n\\font_tt_scale " << fontsTypewriterScale
848 if (!fontsCJK.empty()) {
849 os << "\\font_cjk " << fontsCJK << '\n';
851 os << "\n\\graphics " << graphicsDriver << '\n';
852 os << "\\default_output_format " << defaultOutputFormat << '\n';
853 os << "\\bibtex_command " << bibtex_command << '\n';
854 os << "\\index_command " << index_command << '\n';
856 if (!float_placement.empty()) {
857 os << "\\float_placement " << float_placement << '\n';
859 os << "\\paperfontsize " << fontsize << '\n';
861 spacing().writeFile(os);
862 pdfoptions().writeFile(os);
864 os << "\\papersize " << string_papersize[papersize]
865 << "\n\\use_geometry " << convert<string>(use_geometry)
866 << "\n\\use_amsmath " << use_amsmath
867 << "\n\\use_esint " << use_esint
868 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
869 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
870 << "\n\\use_indices " << convert<string>(use_indices)
871 << "\n\\paperorientation " << string_orientation[orientation]
872 << "\n\\suppress_date " << convert<string>(suppress_date)
874 if (backgroundcolor != lyx::rgbFromHexName("#ffffff"))
875 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
877 BranchList::const_iterator it = branchlist().begin();
878 BranchList::const_iterator end = branchlist().end();
879 for (; it != end; ++it) {
880 os << "\\branch " << to_utf8(it->branch())
881 << "\n\\selected " << it->isSelected()
882 << "\n\\filename_suffix " << it->hasFilenameSuffix()
883 << "\n\\color " << lyx::X11hexname(it->color())
888 IndicesList::const_iterator iit = indiceslist().begin();
889 IndicesList::const_iterator iend = indiceslist().end();
890 for (; iit != iend; ++iit) {
891 os << "\\index " << to_utf8(iit->index())
892 << "\n\\shortcut " << to_utf8(iit->shortcut())
893 << "\n\\color " << lyx::X11hexname(iit->color())
898 if (!paperwidth.empty())
899 os << "\\paperwidth "
900 << VSpace(paperwidth).asLyXCommand() << '\n';
901 if (!paperheight.empty())
902 os << "\\paperheight "
903 << VSpace(paperheight).asLyXCommand() << '\n';
904 if (!leftmargin.empty())
905 os << "\\leftmargin "
906 << VSpace(leftmargin).asLyXCommand() << '\n';
907 if (!topmargin.empty())
909 << VSpace(topmargin).asLyXCommand() << '\n';
910 if (!rightmargin.empty())
911 os << "\\rightmargin "
912 << VSpace(rightmargin).asLyXCommand() << '\n';
913 if (!bottommargin.empty())
914 os << "\\bottommargin "
915 << VSpace(bottommargin).asLyXCommand() << '\n';
916 if (!headheight.empty())
917 os << "\\headheight "
918 << VSpace(headheight).asLyXCommand() << '\n';
919 if (!headsep.empty())
921 << VSpace(headsep).asLyXCommand() << '\n';
922 if (!footskip.empty())
924 << VSpace(footskip).asLyXCommand() << '\n';
925 if (!columnsep.empty())
927 << VSpace(columnsep).asLyXCommand() << '\n';
928 os << "\\secnumdepth " << secnumdepth
929 << "\n\\tocdepth " << tocdepth
930 << "\n\\paragraph_separation "
931 << string_paragraph_separation[paragraph_separation];
932 if (!paragraph_separation)
933 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
935 os << "\n\\defskip " << getDefSkip().asLyXCommand();
936 os << "\n\\quotes_language "
937 << string_quotes_language[quotes_language]
938 << "\n\\papercolumns " << columns
939 << "\n\\papersides " << sides
940 << "\n\\paperpagestyle " << pagestyle << '\n';
941 if (!listings_params.empty())
942 os << "\\listings_params \"" <<
943 InsetListingsParams(listings_params).encodedString() << "\"\n";
944 for (int i = 0; i < 4; ++i) {
945 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
946 if (user_defined_bullet(i).getFont() != -1) {
947 os << "\\bullet " << i << " "
948 << user_defined_bullet(i).getFont() << " "
949 << user_defined_bullet(i).getCharacter() << " "
950 << user_defined_bullet(i).getSize() << "\n";
954 os << "\\bulletLaTeX " << i << " \""
955 << lyx::to_ascii(user_defined_bullet(i).getText())
961 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
962 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
964 os << pimpl_->authorlist;
968 void BufferParams::validate(LaTeXFeatures & features) const
970 features.require(documentClass().requires());
973 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
974 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
975 LaTeXFeatures::isAvailable("xcolor");
977 switch (features.runparams().flavor) {
978 case OutputParams::LATEX:
980 features.require("ct-dvipost");
981 features.require("dvipost");
982 } else if (xcolorulem) {
983 features.require("ct-xcolor-ulem");
984 features.require("ulem");
985 features.require("xcolor");
987 features.require("ct-none");
990 case OutputParams::PDFLATEX:
991 case OutputParams::XETEX:
993 features.require("ct-xcolor-ulem");
994 features.require("ulem");
995 features.require("xcolor");
996 // improves color handling in PDF output
997 features.require("pdfcolmk");
999 features.require("ct-none");
1007 // Floats with 'Here definitely' as default setting.
1008 if (float_placement.find('H') != string::npos)
1009 features.require("float");
1011 // AMS Style is at document level
1012 if (use_amsmath == package_on
1013 || documentClass().provides("amsmath"))
1014 features.require("amsmath");
1015 if (use_esint == package_on)
1016 features.require("esint");
1018 // Document-level line spacing
1019 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1020 features.require("setspace");
1022 // the bullet shapes are buffer level not paragraph level
1023 // so they are tested here
1024 for (int i = 0; i < 4; ++i) {
1025 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1027 int const font = user_defined_bullet(i).getFont();
1029 int const c = user_defined_bullet(i).getCharacter();
1035 features.require("latexsym");
1037 } else if (font == 1) {
1038 features.require("amssymb");
1039 } else if (font >= 2 && font <= 5) {
1040 features.require("pifont");
1044 if (pdfoptions().use_hyperref) {
1045 features.require("hyperref");
1046 // due to interferences with babel and hyperref, the color package has to
1047 // be loaded after hyperref when hyperref is used with the colorlinks
1048 // option, see http://bugzilla.lyx.org/show_bug.cgi?id=5291
1049 if (pdfoptions().colorlinks)
1050 features.require("color");
1054 features.require("xetex");
1056 if (language->lang() == "vietnamese")
1057 features.require("vietnamese");
1058 else if (language->lang() == "japanese")
1059 features.require("japanese");
1063 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1064 TexRow & texrow) const
1066 os << "\\documentclass";
1068 DocumentClass const & tclass = documentClass();
1070 ostringstream clsoptions; // the document class options.
1072 if (tokenPos(tclass.opt_fontsize(),
1073 '|', fontsize) >= 0) {
1074 // only write if existing in list (and not default)
1075 clsoptions << fontsize << "pt,";
1078 // custom, A3, B3 and B4 paper sizes need geometry
1079 bool nonstandard_papersize = papersize == PAPER_B3
1080 || papersize == PAPER_B4
1081 || papersize == PAPER_A3
1082 || papersize == PAPER_CUSTOM;
1084 if (!use_geometry) {
1085 switch (papersize) {
1087 clsoptions << "a4paper,";
1089 case PAPER_USLETTER:
1090 clsoptions << "letterpaper,";
1093 clsoptions << "a5paper,";
1096 clsoptions << "b5paper,";
1098 case PAPER_USEXECUTIVE:
1099 clsoptions << "executivepaper,";
1102 clsoptions << "legalpaper,";
1114 if (sides != tclass.sides()) {
1117 clsoptions << "oneside,";
1120 clsoptions << "twoside,";
1126 if (columns != tclass.columns()) {
1128 clsoptions << "twocolumn,";
1130 clsoptions << "onecolumn,";
1134 && orientation == ORIENTATION_LANDSCAPE)
1135 clsoptions << "landscape,";
1137 // language should be a parameter to \documentclass
1138 if (language->babel() == "hebrew"
1139 && default_language->babel() != "hebrew")
1140 // This seems necessary
1141 features.useLanguage(default_language);
1143 ostringstream language_options;
1144 bool const use_babel = features.useBabel();
1146 language_options << features.getLanguages();
1147 if (!language->babel().empty()) {
1148 if (!language_options.str().empty())
1149 language_options << ',';
1150 language_options << language->babel();
1152 // if Vietnamese is used, babel must directly be loaded
1153 // with language options, not in the class options, see
1154 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1155 size_t viet = language_options.str().find("vietnam");
1156 // viet = string::npos when not found
1157 // the same is for all other languages that are not directly supported by
1158 // babel, but where LaTeX-packages add babel support.
1159 // this is currently the case for Latvian, Lithuanian, and Mongolian
1160 size_t latvian = language_options.str().find("latvian");
1161 size_t lithu = language_options.str().find("lithuanian");
1162 size_t mongo = language_options.str().find("mongolian");
1163 // if Japanese is used, babel must directly be loaded
1164 // with language options, not in the class options, see
1165 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1166 size_t japan = language_options.str().find("japanese");
1167 if (lyxrc.language_global_options && !language_options.str().empty()
1168 && viet == string::npos && japan == string::npos
1169 && latvian == string::npos && lithu == string::npos
1170 && mongo == string::npos)
1171 clsoptions << language_options.str() << ',';
1174 // the predefined options from the layout
1175 if (use_default_options && !tclass.options().empty())
1176 clsoptions << tclass.options() << ',';
1178 // the user-defined options
1179 if (!options.empty()) {
1180 clsoptions << options << ',';
1183 string strOptions(clsoptions.str());
1184 if (!strOptions.empty()) {
1185 strOptions = rtrim(strOptions, ",");
1187 os << '[' << from_utf8(strOptions) << ']';
1190 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1192 // end of \documentclass defs
1195 os << "\\usepackage{fontspec}\n";
1199 // font selection must be done before loading fontenc.sty
1200 string const fonts =
1201 loadFonts(fontsRoman, fontsSans,
1202 fontsTypewriter, fontsSC, fontsOSF,
1203 fontsSansScale, fontsTypewriterScale, useXetex);
1204 if (!fonts.empty()) {
1205 os << from_ascii(fonts);
1208 if (fontsDefaultFamily != "default")
1209 os << "\\renewcommand{\\familydefault}{\\"
1210 << from_ascii(fontsDefaultFamily) << "}\n";
1212 // set font encoding
1213 // this one is not per buffer
1214 // for arabic_arabi and farsi we also need to load the LAE and
1216 // XeTeX works without fontenc
1217 if (lyxrc.fontenc != "default" && language->lang() != "japanese"
1219 if (language->lang() == "arabic_arabi"
1220 || language->lang() == "farsi") {
1221 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1222 << ",LFE,LAE]{fontenc}\n";
1225 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1231 // handle inputenc etc.
1232 writeEncodingPreamble(os, features, texrow);
1234 if (!listings_params.empty() || features.isRequired("listings")) {
1235 os << "\\usepackage{listings}\n";
1238 if (!listings_params.empty()) {
1240 // do not test validity because listings_params is
1241 // supposed to be valid
1243 InsetListingsParams(listings_params).separatedParams(true);
1244 // we can't support all packages, but we should load the color package
1245 if (par.find("\\color", 0) != string::npos)
1246 features.require("color");
1247 os << from_utf8(par);
1248 // count the number of newlines
1249 for (size_t i = 0; i < par.size(); ++i)
1255 if (!tclass.provides("geometry")
1256 && (use_geometry || nonstandard_papersize)) {
1257 odocstringstream ods;
1258 if (!getGraphicsDriver("geometry").empty())
1259 ods << getGraphicsDriver("geometry");
1260 if (orientation == ORIENTATION_LANDSCAPE)
1261 ods << ",landscape";
1262 switch (papersize) {
1264 if (!paperwidth.empty())
1265 ods << ",paperwidth="
1266 << from_ascii(paperwidth);
1267 if (!paperheight.empty())
1268 ods << ",paperheight="
1269 << from_ascii(paperheight);
1271 case PAPER_USLETTER:
1272 ods << ",letterpaper";
1275 ods << ",legalpaper";
1277 case PAPER_USEXECUTIVE:
1278 ods << ",executivepaper";
1299 // default papersize ie PAPER_DEFAULT
1300 switch (lyxrc.default_papersize) {
1301 case PAPER_DEFAULT: // keep compiler happy
1302 case PAPER_USLETTER:
1303 ods << ",letterpaper";
1306 ods << ",legalpaper";
1308 case PAPER_USEXECUTIVE:
1309 ods << ",executivepaper";
1329 docstring const g_options = trim(ods.str(), ",");
1330 os << "\\usepackage";
1331 if (!g_options.empty())
1332 os << '[' << g_options << ']';
1333 os << "{geometry}\n";
1335 os << "\\geometry{verbose";
1336 if (!topmargin.empty())
1337 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1338 if (!bottommargin.empty())
1339 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1340 if (!leftmargin.empty())
1341 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1342 if (!rightmargin.empty())
1343 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1344 if (!headheight.empty())
1345 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1346 if (!headsep.empty())
1347 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1348 if (!footskip.empty())
1349 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1350 if (!columnsep.empty())
1351 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1354 } else if (orientation == ORIENTATION_LANDSCAPE) {
1355 features.require("papersize");
1358 if (tokenPos(tclass.opt_pagestyle(),
1359 '|', pagestyle) >= 0) {
1360 if (pagestyle == "fancy") {
1361 os << "\\usepackage{fancyhdr}\n";
1364 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1368 // only output when the background color is not white
1369 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1370 // only require color here, the background color will be defined
1371 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1373 features.require("color");
1374 features.require("pagecolor");
1377 // Only if class has a ToC hierarchy
1378 if (tclass.hasTocLevels()) {
1379 if (secnumdepth != tclass.secnumdepth()) {
1380 os << "\\setcounter{secnumdepth}{"
1385 if (tocdepth != tclass.tocdepth()) {
1386 os << "\\setcounter{tocdepth}{"
1393 if (paragraph_separation) {
1394 // when skip separation
1395 switch (getDefSkip().kind()) {
1396 case VSpace::SMALLSKIP:
1397 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1399 case VSpace::MEDSKIP:
1400 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1402 case VSpace::BIGSKIP:
1403 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1405 case VSpace::LENGTH:
1406 os << "\\setlength{\\parskip}{"
1407 << from_utf8(getDefSkip().length().asLatexString())
1410 default: // should never happen // Then delete it.
1411 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1415 os << "\\setlength{\\parindent}{0pt}\n";
1418 // when separation by indentation
1419 // only output something when a width is given
1420 if (getIndentation().asLyXCommand() != "default") {
1421 os << "\\setlength{\\parindent}{"
1422 << from_utf8(getIndentation().asLatexCommand())
1428 // Now insert the LyX specific LaTeX commands...
1429 docstring lyxpreamble;
1431 // due to interferences with babel and hyperref, the color package has to
1432 // be loaded (when it is not already loaded) before babel when hyperref
1433 // is used with the colorlinks option, see
1434 // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1435 // we decided therefore to load color always before babel, see
1436 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1437 lyxpreamble += from_ascii(features.getColorOptions());
1439 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1441 && (features.isRequired("jurabib")
1442 || features.isRequired("hyperref")
1443 || features.isRequired("vietnamese")
1444 || features.isRequired("japanese") ) ) {
1446 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1447 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1450 // The optional packages;
1451 lyxpreamble += from_ascii(features.getPackages());
1453 // Additional Indices
1454 if (features.isRequired("splitidx")) {
1455 IndicesList::const_iterator iit = indiceslist().begin();
1456 IndicesList::const_iterator iend = indiceslist().end();
1457 for (; iit != iend; ++iit) {
1458 lyxpreamble += "\\newindex[";
1459 lyxpreamble += iit->index();
1460 lyxpreamble += "]{";
1461 lyxpreamble += iit->shortcut();
1462 lyxpreamble += "}\n";
1467 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1470 // * Hyperref manual: "Make sure it comes last of your loaded
1471 // packages, to give it a fighting chance of not being over-written,
1472 // since its job is to redefine many LaTeX commands."
1473 // * Email from Heiko Oberdiek: "It is usually better to load babel
1474 // before hyperref. Then hyperref has a chance to detect babel.
1475 // * Has to be loaded before the "LyX specific LaTeX commands" to
1476 // avoid errors with algorithm floats.
1477 // use hyperref explicitely when it is required
1478 if (features.isRequired("hyperref")) {
1479 odocstringstream oss;
1480 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1481 lyxpreamble += oss.str();
1484 // Will be surrounded by \makeatletter and \makeatother when not empty
1485 docstring atlyxpreamble;
1487 // Some macros LyX will need
1488 docstring tmppreamble(features.getMacros());
1490 if (!tmppreamble.empty())
1491 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1492 "LyX specific LaTeX commands.\n"
1493 + tmppreamble + '\n';
1495 // the text class specific preamble
1496 tmppreamble = features.getTClassPreamble();
1497 if (!tmppreamble.empty())
1498 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1499 "Textclass specific LaTeX commands.\n"
1500 + tmppreamble + '\n';
1502 // suppress date if selected
1503 // use \@ifundefined because we cannot be sure that every document class
1504 // has a \date command
1506 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1508 /* the user-defined preamble */
1509 if (!containsOnly(preamble, " \n\t"))
1511 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1512 "User specified LaTeX commands.\n"
1513 + from_utf8(preamble) + '\n';
1515 // subfig loads internally the LaTeX package "caption". As
1516 // caption is a very popular package, users will load it in
1517 // the preamble. Therefore we must load subfig behind the
1518 // user-defined preamble and check if the caption package was
1519 // loaded or not. For the case that caption is loaded before
1520 // subfig, there is the subfig option "caption=false". This
1521 // option also works when a koma-script class is used and
1522 // koma's own caption commands are used instead of caption. We
1523 // use \PassOptionsToPackage here because the user could have
1524 // already loaded subfig in the preamble.
1525 if (features.isRequired("subfig")) {
1526 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1527 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1528 "\\usepackage{subfig}\n";
1531 // Itemize bullet settings need to be last in case the user
1532 // defines their own bullets that use a package included
1533 // in the user-defined preamble -- ARRae
1534 // Actually it has to be done much later than that
1535 // since some packages like frenchb make modifications
1536 // at \begin{document} time -- JMarc
1537 docstring bullets_def;
1538 for (int i = 0; i < 4; ++i) {
1539 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1540 if (bullets_def.empty())
1541 bullets_def += "\\AtBeginDocument{\n";
1542 bullets_def += " \\def\\labelitemi";
1544 // `i' is one less than the item to modify
1551 bullets_def += "ii";
1557 bullets_def += '{' +
1558 user_defined_bullet(i).getText()
1563 if (!bullets_def.empty())
1564 atlyxpreamble += bullets_def + "}\n\n";
1566 if (!atlyxpreamble.empty())
1567 lyxpreamble += "\n\\makeatletter\n"
1568 + atlyxpreamble + "\\makeatother\n\n";
1570 // We try to load babel late, in case it interferes with other packages.
1571 // Jurabib and Hyperref have to be called after babel, though.
1572 if (use_babel && !features.isRequired("jurabib")
1573 && !features.isRequired("hyperref")
1574 && !features.isRequired("vietnamese")
1575 && !features.isRequired("japanese")) {
1577 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1578 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1581 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1582 if (!i18npreamble.empty())
1583 lyxpreamble += i18npreamble + '\n';
1586 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1587 for (int j = 0; j != nlines; ++j) {
1593 // these packages (xunicode, for that matter) need to be loaded at least
1594 // after amsmath, amssymb, esint and the other packages that provide
1597 os << "\\usepackage{xunicode}\n";
1599 os << "\\usepackage{xltxtra}\n";
1606 void BufferParams::useClassDefaults()
1608 DocumentClass const & tclass = documentClass();
1610 sides = tclass.sides();
1611 columns = tclass.columns();
1612 pagestyle = tclass.pagestyle();
1613 use_default_options = true;
1614 // Only if class has a ToC hierarchy
1615 if (tclass.hasTocLevels()) {
1616 secnumdepth = tclass.secnumdepth();
1617 tocdepth = tclass.tocdepth();
1622 bool BufferParams::hasClassDefaults() const
1624 DocumentClass const & tclass = documentClass();
1626 return sides == tclass.sides()
1627 && columns == tclass.columns()
1628 && pagestyle == tclass.pagestyle()
1629 && use_default_options
1630 && secnumdepth == tclass.secnumdepth()
1631 && tocdepth == tclass.tocdepth();
1635 DocumentClass const & BufferParams::documentClass() const
1641 DocumentClass const * BufferParams::documentClassPtr() const {
1646 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1647 // evil, but this function is evil
1648 doc_class_ = const_cast<DocumentClass *>(tc);
1652 bool BufferParams::setBaseClass(string const & classname)
1654 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1655 LayoutFileList & bcl = LayoutFileList::get();
1656 if (!bcl.haveClass(classname)) {
1658 bformat(_("The document class %1$s could not be found. "
1659 "A default textclass with default layouts will be used. "
1660 "LyX might not be able to produce output unless a correct "
1661 "textclass is selected from the document settings dialog."),
1662 from_utf8(classname));
1663 frontend::Alert::error(_("Document class not found"), s);
1664 bcl.addEmptyClass(classname);
1667 bool const success = bcl[classname].load();
1670 bformat(_("The document class %1$s could not be loaded."),
1671 from_utf8(classname));
1672 frontend::Alert::error(_("Could not load class"), s);
1676 pimpl_->baseClass_ = classname;
1677 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1682 LayoutFile const * BufferParams::baseClass() const
1684 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1685 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1691 LayoutFileIndex const & BufferParams::baseClassID() const
1693 return pimpl_->baseClass_;
1697 void BufferParams::makeDocumentClass()
1702 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1704 if (!local_layout.empty()) {
1705 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1706 docstring const msg = _("Error reading internal layout information");
1707 frontend::Alert::warning(_("Read Error"), msg);
1712 bool BufferParams::moduleCanBeAdded(string const & modName) const
1714 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1718 bool BufferParams::addLayoutModule(string const & modName)
1720 LayoutModuleList::const_iterator it = layoutModules_.begin();
1721 LayoutModuleList::const_iterator end = layoutModules_.end();
1722 for (; it != end; it++)
1725 layoutModules_.push_back(modName);
1730 Font const BufferParams::getFont() const
1732 FontInfo f = documentClass().defaultfont();
1733 if (fontsDefaultFamily == "rmdefault")
1734 f.setFamily(ROMAN_FAMILY);
1735 else if (fontsDefaultFamily == "sfdefault")
1736 f.setFamily(SANS_FAMILY);
1737 else if (fontsDefaultFamily == "ttdefault")
1738 f.setFamily(TYPEWRITER_FAMILY);
1739 return Font(f, language);
1743 void BufferParams::readPreamble(Lexer & lex)
1745 if (lex.getString() != "\\begin_preamble")
1746 lyxerr << "Error (BufferParams::readPreamble):"
1747 "consistency check failed." << endl;
1749 preamble = lex.getLongString("\\end_preamble");
1753 void BufferParams::readLocalLayout(Lexer & lex)
1755 if (lex.getString() != "\\begin_local_layout")
1756 lyxerr << "Error (BufferParams::readLocalLayout):"
1757 "consistency check failed." << endl;
1759 local_layout = lex.getLongString("\\end_local_layout");
1763 void BufferParams::readLanguage(Lexer & lex)
1765 if (!lex.next()) return;
1767 string const tmptok = lex.getString();
1769 // check if tmptok is part of tex_babel in tex-defs.h
1770 language = languages.getLanguage(tmptok);
1772 // Language tmptok was not found
1773 language = default_language;
1774 lyxerr << "Warning: Setting language `"
1775 << tmptok << "' to `" << language->lang()
1781 void BufferParams::readGraphicsDriver(Lexer & lex)
1786 string const tmptok = lex.getString();
1787 // check if tmptok is part of tex_graphics in tex_defs.h
1790 string const test = tex_graphics[n++];
1792 if (test == tmptok) {
1793 graphicsDriver = tmptok;
1798 "Warning: graphics driver `$$Token' not recognized!\n"
1799 " Setting graphics driver to `default'.\n");
1800 graphicsDriver = "default";
1807 void BufferParams::readBullets(Lexer & lex)
1812 int const index = lex.getInteger();
1814 int temp_int = lex.getInteger();
1815 user_defined_bullet(index).setFont(temp_int);
1816 temp_bullet(index).setFont(temp_int);
1818 user_defined_bullet(index).setCharacter(temp_int);
1819 temp_bullet(index).setCharacter(temp_int);
1821 user_defined_bullet(index).setSize(temp_int);
1822 temp_bullet(index).setSize(temp_int);
1826 void BufferParams::readBulletsLaTeX(Lexer & lex)
1828 // The bullet class should be able to read this.
1831 int const index = lex.getInteger();
1833 docstring const temp_str = lex.getDocString();
1835 user_defined_bullet(index).setText(temp_str);
1836 temp_bullet(index).setText(temp_str);
1840 void BufferParams::readModules(Lexer & lex)
1842 if (!lex.eatLine()) {
1843 lyxerr << "Error (BufferParams::readModules):"
1844 "Unexpected end of input." << endl;
1848 string mod = lex.getString();
1849 if (mod == "\\end_modules")
1851 addLayoutModule(mod);
1857 void BufferParams::readRemovedModules(Lexer & lex)
1859 if (!lex.eatLine()) {
1860 lyxerr << "Error (BufferParams::readRemovedModules):"
1861 "Unexpected end of input." << endl;
1865 string mod = lex.getString();
1866 if (mod == "\\end_removed_modules")
1868 removedModules_.push_back(mod);
1871 // now we want to remove any removed modules that were previously
1872 // added. normally, that will be because default modules were added in
1873 // setBaseClass(), which gets called when \textclass is read at the
1874 // start of the read.
1875 list<string>::const_iterator rit = removedModules_.begin();
1876 list<string>::const_iterator const ren = removedModules_.end();
1877 for (; rit != ren; rit++) {
1878 LayoutModuleList::iterator const mit = layoutModules_.begin();
1879 LayoutModuleList::iterator const men = layoutModules_.end();
1880 LayoutModuleList::iterator found = find(mit, men, *rit);
1883 layoutModules_.erase(found);
1888 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1890 char real_papersize = papersize;
1891 if (real_papersize == PAPER_DEFAULT)
1892 real_papersize = lyxrc.default_papersize;
1894 switch (real_papersize) {
1896 // could be anything, so don't guess
1898 case PAPER_CUSTOM: {
1899 if (purpose == XDVI && !paperwidth.empty() &&
1900 !paperheight.empty()) {
1901 // heightxwidth<unit>
1902 string first = paperwidth;
1903 string second = paperheight;
1904 if (orientation == ORIENTATION_LANDSCAPE)
1907 return first.erase(first.length() - 2)
1919 // dvips and dvipdfm do not know this
1920 if (purpose == DVIPS || purpose == DVIPDFM)
1924 // dvipdfm does not know this
1925 if (purpose == DVIPDFM)
1929 // dvipdfm does not know this
1930 if (purpose == DVIPDFM)
1933 case PAPER_USEXECUTIVE:
1934 // dvipdfm does not know this
1935 if (purpose == DVIPDFM)
1940 case PAPER_USLETTER:
1942 if (purpose == XDVI)
1949 string const BufferParams::dvips_options() const
1954 && papersize == PAPER_CUSTOM
1955 && !lyxrc.print_paper_dimension_flag.empty()
1956 && !paperwidth.empty()
1957 && !paperheight.empty()) {
1958 // using a custom papersize
1959 result = lyxrc.print_paper_dimension_flag;
1960 result += ' ' + paperwidth;
1961 result += ',' + paperheight;
1963 string const paper_option = paperSizeName(DVIPS);
1964 if (!paper_option.empty() && (paper_option != "letter" ||
1965 orientation != ORIENTATION_LANDSCAPE)) {
1966 // dvips won't accept -t letter -t landscape.
1967 // In all other cases, include the paper size
1969 result = lyxrc.print_paper_flag;
1970 result += ' ' + paper_option;
1973 if (orientation == ORIENTATION_LANDSCAPE &&
1974 papersize != PAPER_CUSTOM)
1975 result += ' ' + lyxrc.print_landscape_flag;
1980 string BufferParams::babelCall(string const & lang_opts) const
1982 string lang_pack = lyxrc.language_package;
1983 if (lang_pack != "\\usepackage{babel}")
1985 // suppress the babel call when there is no babel language defined
1986 // for the document language in the lib/languages file and if no
1987 // other languages are used (lang_opts is then empty)
1988 if (lang_opts.empty())
1990 // If Vietnamese is used, babel must directly be loaded with the
1991 // language options, see
1992 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1993 size_t viet = lang_opts.find("vietnam");
1994 // viet = string::npos when not found
1995 // the same is for all other languages that are not directly supported by
1996 // babel, but where LaTeX-packages add babel support.
1997 // this is currently the case for Latvian, Lithuanian, and Mongolian
1998 size_t latvian = lang_opts.find("latvian");
1999 size_t lithu = lang_opts.find("lithuanian");
2000 size_t mongo = lang_opts.find("mongolian");
2001 // If Japanese is used, babel must directly be loaded with the
2002 // language options, see
2003 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
2004 size_t japan = lang_opts.find("japanese");
2005 if (!lyxrc.language_global_options || viet != string::npos
2006 || japan != string::npos || latvian != string::npos
2007 || lithu != string::npos || mongo != string::npos)
2008 return "\\usepackage[" + lang_opts + "]{babel}";
2013 docstring BufferParams::getGraphicsDriver(string const & package) const
2017 if (package == "geometry") {
2018 if (graphicsDriver == "dvips"
2019 || graphicsDriver == "dvipdfm"
2020 || graphicsDriver == "pdftex"
2021 || graphicsDriver == "vtex")
2022 result = from_ascii(graphicsDriver);
2023 else if (graphicsDriver == "dvipdfmx")
2024 result = from_ascii("dvipdfm");
2031 void BufferParams::writeEncodingPreamble(odocstream & os,
2032 LaTeXFeatures & features, TexRow & texrow) const
2036 if (inputenc == "auto") {
2037 string const doc_encoding =
2038 language->encoding()->latexName();
2039 Encoding::Package const package =
2040 language->encoding()->package();
2042 // Create a list with all the input encodings used
2044 set<string> encodings =
2045 features.getEncodingSet(doc_encoding);
2047 // If the "japanese" package (i.e. pLaTeX) is used,
2048 // inputenc must be omitted.
2049 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2050 if (package == Encoding::japanese)
2051 features.require("japanese");
2053 if ((!encodings.empty() || package == Encoding::inputenc)
2054 && !features.isRequired("japanese")) {
2055 os << "\\usepackage[";
2056 set<string>::const_iterator it = encodings.begin();
2057 set<string>::const_iterator const end = encodings.end();
2059 os << from_ascii(*it);
2062 for (; it != end; ++it)
2063 os << ',' << from_ascii(*it);
2064 if (package == Encoding::inputenc) {
2065 if (!encodings.empty())
2067 os << from_ascii(doc_encoding);
2069 os << "]{inputenc}\n";
2072 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2073 if (language->encoding()->name() == "utf8-cjk"
2074 && LaTeXFeatures::isAvailable("CJKutf8"))
2075 os << "\\usepackage{CJKutf8}\n";
2077 os << "\\usepackage{CJK}\n";
2080 } else if (inputenc != "default") {
2081 switch (encoding().package()) {
2082 case Encoding::none:
2083 case Encoding::japanese:
2085 case Encoding::inputenc:
2086 // do not load inputenc if japanese is used
2087 if (features.isRequired("japanese"))
2089 os << "\\usepackage[" << from_ascii(inputenc)
2094 if (encoding().name() == "utf8-cjk"
2095 && LaTeXFeatures::isAvailable("CJKutf8"))
2096 os << "\\usepackage{CJKutf8}\n";
2098 os << "\\usepackage{CJK}\n";
2104 // The encoding "armscii8" (for Armenian) is only available when
2105 // the package "armtex" is loaded.
2106 if (language->encoding()->latexName() == "armscii8"
2107 || inputenc == "armscii8") {
2108 os << "\\usepackage{armtex}\n";
2114 string const BufferParams::parseFontName(string const & name) const
2116 string mangled = name;
2117 size_t const idx = mangled.find('[');
2118 if (idx == string::npos || idx == 0)
2121 return mangled.substr(0, idx - 1);
2125 string const BufferParams::loadFonts(string const & rm,
2126 string const & sf, string const & tt,
2127 bool const & sc, bool const & osf,
2128 int const & sfscale, int const & ttscale,
2129 bool const & xetex) const
2131 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2132 several packages have been replaced by others, that might not
2133 be installed on every system. We have to take care for that
2134 (see psnfss.pdf). We try to support all psnfss fonts as well
2135 as the fonts that have become de facto standard in the LaTeX
2136 world (e.g. Latin Modern). We do not support obsolete fonts
2137 (like PSLatex). In general, it should be possible to mix any
2138 rm font with any sf or tt font, respectively. (JSpitzm)
2140 -- separate math fonts.
2143 if (rm == "default" && sf == "default" && tt == "default")
2150 if (rm != "default")
2151 os << "\\setmainfont[Mapping=tex-text]{"
2152 << parseFontName(rm) << "}\n";
2153 if (sf != "default") {
2154 string const sans = parseFontName(sf);
2156 os << "\\setsansfont[Scale="
2157 << float(sfscale) / 100
2158 << ",Mapping=tex-text]{"
2161 os << "\\setsansfont[Mapping=tex-text]{"
2164 if (tt != "default") {
2165 string const mono = parseFontName(tt);
2167 os << "\\setmonofont[Scale="
2168 << float(sfscale) / 100
2172 os << "\\setmonofont[Mapping=tex-text]{"
2176 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2181 // Computer Modern (must be explicitely selectable -- there might be classes
2182 // that define a different default font!
2184 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2185 // osf for Computer Modern needs eco.sty
2187 os << "\\usepackage{eco}\n";
2189 // Latin Modern Roman
2190 else if (rm == "lmodern")
2191 os << "\\usepackage{lmodern}\n";
2193 else if (rm == "ae") {
2194 // not needed when using OT1 font encoding.
2195 if (lyxrc.fontenc != "default")
2196 os << "\\usepackage{ae,aecompl}\n";
2199 else if (rm == "times") {
2200 // try to load the best available package
2201 if (LaTeXFeatures::isAvailable("mathptmx"))
2202 os << "\\usepackage{mathptmx}\n";
2203 else if (LaTeXFeatures::isAvailable("mathptm"))
2204 os << "\\usepackage{mathptm}\n";
2206 os << "\\usepackage{times}\n";
2209 else if (rm == "palatino") {
2210 // try to load the best available package
2211 if (LaTeXFeatures::isAvailable("mathpazo")) {
2212 os << "\\usepackage";
2218 // "osf" includes "sc"!
2222 os << "{mathpazo}\n";
2224 else if (LaTeXFeatures::isAvailable("mathpple"))
2225 os << "\\usepackage{mathpple}\n";
2227 os << "\\usepackage{palatino}\n";
2230 else if (rm == "utopia") {
2231 // fourier supersedes utopia.sty, but does
2232 // not work with OT1 encoding.
2233 if (LaTeXFeatures::isAvailable("fourier")
2234 && lyxrc.fontenc != "default") {
2235 os << "\\usepackage";
2246 os << "{fourier}\n";
2249 os << "\\usepackage{utopia}\n";
2251 // Bera (complete fontset)
2252 else if (rm == "bera" && sf == "default" && tt == "default")
2253 os << "\\usepackage{bera}\n";
2255 else if (rm != "default")
2256 os << "\\usepackage" << "{" << rm << "}\n";
2259 // Helvetica, Bera Sans
2260 if (sf == "helvet" || sf == "berasans") {
2262 os << "\\usepackage[scaled=" << float(sfscale) / 100
2263 << "]{" << sf << "}\n";
2265 os << "\\usepackage{" << sf << "}\n";
2268 else if (sf == "avant")
2269 os << "\\usepackage{" << sf << "}\n";
2270 // Computer Modern, Latin Modern, CM Bright
2271 else if (sf != "default")
2272 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2274 // monospaced/typewriter
2275 // Courier, LuxiMono
2276 if (tt == "luximono" || tt == "beramono") {
2278 os << "\\usepackage[scaled=" << float(ttscale) / 100
2279 << "]{" << tt << "}\n";
2281 os << "\\usepackage{" << tt << "}\n";
2284 else if (tt == "courier" )
2285 os << "\\usepackage{" << tt << "}\n";
2286 // Computer Modern, Latin Modern, CM Bright
2287 else if (tt != "default")
2288 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2294 Encoding const & BufferParams::encoding() const
2297 return *(encodings.fromLaTeXName("utf8-plain"));
2298 if (inputenc == "auto" || inputenc == "default")
2299 return *language->encoding();
2300 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2303 LYXERR0("Unknown inputenc value `" << inputenc
2304 << "'. Using `auto' instead.");
2305 return *language->encoding();
2309 CiteEngine BufferParams::citeEngine() const
2311 // FIXME the class should provide the numerical/
2312 // authoryear choice
2313 if (documentClass().provides("natbib")
2314 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2315 return ENGINE_NATBIB_AUTHORYEAR;
2316 return cite_engine_;
2320 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2322 cite_engine_ = cite_engine;