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 // white is equal to no background color
367 backgroundcolor = lyx::rgbFromHexName("#ffffff");
369 for (int iter = 0; iter < 4; ++iter) {
370 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
371 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
374 indiceslist().addDefault(B_("Index"));
378 docstring BufferParams::B_(string const & l10n) const
380 LASSERT(language, /**/);
381 return getMessages(language->code()).get(l10n);
385 AuthorList & BufferParams::authors()
387 return pimpl_->authorlist;
391 AuthorList const & BufferParams::authors() const
393 return pimpl_->authorlist;
397 BranchList & BufferParams::branchlist()
399 return pimpl_->branchlist;
403 BranchList const & BufferParams::branchlist() const
405 return pimpl_->branchlist;
409 IndicesList & BufferParams::indiceslist()
411 return pimpl_->indiceslist;
415 IndicesList const & BufferParams::indiceslist() const
417 return pimpl_->indiceslist;
421 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
423 LASSERT(index < 4, /**/);
424 return pimpl_->temp_bullets[index];
428 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
430 LASSERT(index < 4, /**/);
431 return pimpl_->temp_bullets[index];
435 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
437 LASSERT(index < 4, /**/);
438 return pimpl_->user_defined_bullets[index];
442 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
444 LASSERT(index < 4, /**/);
445 return pimpl_->user_defined_bullets[index];
449 Spacing & BufferParams::spacing()
451 return pimpl_->spacing;
455 Spacing const & BufferParams::spacing() const
457 return pimpl_->spacing;
461 PDFOptions & BufferParams::pdfoptions()
463 return pimpl_->pdfoptions;
467 PDFOptions const & BufferParams::pdfoptions() const
469 return pimpl_->pdfoptions;
473 HSpace const & BufferParams::getIndentation() const
475 return pimpl_->indentation;
479 void BufferParams::setIndentation(HSpace const & indent)
481 pimpl_->indentation = indent;
485 VSpace const & BufferParams::getDefSkip() const
487 return pimpl_->defskip;
491 void BufferParams::setDefSkip(VSpace const & vs)
493 pimpl_->defskip = vs;
497 string BufferParams::readToken(Lexer & lex, string const & token,
498 FileName const & filepath)
500 if (token == "\\textclass") {
502 string const classname = lex.getString();
503 // if there exists a local layout file, ignore the system one
504 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
506 LayoutFileList & bcl = LayoutFileList::get();
507 if (tcp.empty() && !filepath.empty())
508 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
512 setBaseClass(classname);
513 // We assume that a tex class exists for local or unknown layouts so this warning
514 // will only be given for system layouts.
515 if (!baseClass()->isTeXClassAvailable()) {
516 docstring const msg =
517 bformat(_("The layout file requested by this document,\n"
519 "is not usable. This is probably because a LaTeX\n"
520 "class or style file required by it is not\n"
521 "available. See the Customization documentation\n"
522 "for more information.\n"), from_utf8(classname));
523 frontend::Alert::warning(_("Document class not available"),
524 msg + _("LyX will not be able to produce output."));
526 } else if (token == "\\begin_preamble") {
528 } else if (token == "\\begin_local_layout") {
529 readLocalLayout(lex);
530 } else if (token == "\\begin_modules") {
532 } else if (token == "\\begin_removed_modules") {
533 readRemovedModules(lex);
534 } else if (token == "\\options") {
536 options = lex.getString();
537 } else if (token == "\\use_default_options") {
538 lex >> use_default_options;
539 } else if (token == "\\master") {
541 master = lex.getString();
542 } else if (token == "\\language") {
544 } else if (token == "\\inputencoding") {
546 } else if (token == "\\graphics") {
547 readGraphicsDriver(lex);
548 } else if (token == "\\default_output_format") {
549 lex >> defaultOutputFormat;
550 } else if (token == "\\bibtex_command") {
552 bibtex_command = lex.getString();
553 } else if (token == "\\index_command") {
555 index_command = lex.getString();
556 } else if (token == "\\font_roman") {
558 fontsRoman = lex.getString();
559 } else if (token == "\\font_sans") {
561 fontsSans = lex.getString();
562 } else if (token == "\\font_typewriter") {
564 fontsTypewriter = lex.getString();
565 } else if (token == "\\font_default_family") {
566 lex >> fontsDefaultFamily;
567 } else if (token == "\\use_xetex") {
569 } else if (token == "\\font_sc") {
571 } else if (token == "\\font_osf") {
573 } else if (token == "\\font_sf_scale") {
574 lex >> fontsSansScale;
575 } else if (token == "\\font_tt_scale") {
576 lex >> fontsTypewriterScale;
577 } else if (token == "\\font_cjk") {
579 } else if (token == "\\paragraph_separation") {
582 paragraph_separation = parseptranslator().find(parsep);
583 } else if (token == "\\paragraph_indentation") {
585 string indentation = lex.getString();
586 pimpl_->indentation = HSpace(indentation);
587 } else if (token == "\\defskip") {
589 string defskip = lex.getString();
590 if (defskip == "defskip")
593 pimpl_->defskip = VSpace(defskip);
594 } else if (token == "\\quotes_language") {
597 quotes_language = quoteslangtranslator().find(quotes_lang);
598 } else if (token == "\\papersize") {
601 papersize = papersizetranslator().find(ppsize);
602 } else if (token == "\\use_geometry") {
604 } else if (token == "\\use_amsmath") {
607 use_amsmath = packagetranslator().find(use_ams);
608 } else if (token == "\\use_esint") {
611 use_esint = packagetranslator().find(useesint);
612 } else if (token == "\\cite_engine") {
615 cite_engine_ = citeenginetranslator().find(engine);
616 } else if (token == "\\use_bibtopic") {
618 } else if (token == "\\use_indices") {
620 } else if (token == "\\tracking_changes") {
622 } else if (token == "\\output_changes") {
623 lex >> outputChanges;
624 } else if (token == "\\branch") {
626 docstring branch = lex.getDocString();
627 branchlist().add(branch);
630 string const tok = lex.getString();
631 if (tok == "\\end_branch")
633 Branch * branch_ptr = branchlist().find(branch);
634 if (tok == "\\selected") {
637 branch_ptr->setSelected(lex.getInteger());
639 if (tok == "\\filename_suffix") {
642 branch_ptr->setFilenameSuffix(lex.getInteger());
644 // not yet operational
645 if (tok == "\\color") {
647 string color = lex.getString();
649 branch_ptr->setColor(color);
650 // Update also the Color table:
652 color = lcolor.getX11Name(Color_background);
654 lcolor.setColor(to_utf8(branch), color);
657 } else if (token == "\\index") {
659 docstring index = lex.getDocString();
660 indiceslist().add(index);
663 string const tok = lex.getString();
664 if (tok == "\\end_index")
666 Index * index_ptr = indiceslist().find(index);
667 if (tok == "\\shortcut") {
670 index_ptr->setShortcut(lex.getDocString());
672 // not yet operational
673 if (tok == "\\color") {
675 string color = lex.getString();
677 index_ptr->setColor(color);
678 // Update also the Color table:
680 color = lcolor.getX11Name(Color_background);
682 lcolor.setColor(to_utf8(index), color);
685 } else if (token == "\\author") {
687 istringstream ss(lex.getString());
690 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
691 } else if (token == "\\paperorientation") {
694 orientation = paperorientationtranslator().find(orient);
695 } else if (token == "\\backgroundcolor") {
697 backgroundcolor = lyx::rgbFromHexName(lex.getString());
698 } else if (token == "\\paperwidth") {
700 } else if (token == "\\paperheight") {
702 } else if (token == "\\leftmargin") {
704 } else if (token == "\\topmargin") {
706 } else if (token == "\\rightmargin") {
708 } else if (token == "\\bottommargin") {
710 } else if (token == "\\headheight") {
712 } else if (token == "\\headsep") {
714 } else if (token == "\\footskip") {
716 } else if (token == "\\columnsep") {
718 } else if (token == "\\paperfontsize") {
720 } else if (token == "\\papercolumns") {
722 } else if (token == "\\listings_params") {
725 listings_params = InsetListingsParams(par).params();
726 } else if (token == "\\papersides") {
729 sides = sidestranslator().find(psides);
730 } else if (token == "\\paperpagestyle") {
732 } else if (token == "\\bullet") {
734 } else if (token == "\\bulletLaTeX") {
735 readBulletsLaTeX(lex);
736 } else if (token == "\\secnumdepth") {
738 } else if (token == "\\tocdepth") {
740 } else if (token == "\\spacing") {
744 if (nspacing == "other") {
747 spacing().set(spacetranslator().find(nspacing), tmp_val);
748 } else if (token == "\\float_placement") {
749 lex >> float_placement;
751 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
752 string toktmp = pdfoptions().readToken(lex, token);
753 if (!toktmp.empty()) {
754 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
759 lyxerr << "BufferParams::readToken(): Unknown token: " <<
768 void BufferParams::writeFile(ostream & os) const
770 // The top of the file is written by the buffer.
771 // Prints out the buffer info into the .lyx file given by file
774 os << "\\textclass " << baseClass()->name() << '\n';
777 if (!preamble.empty()) {
778 // remove '\n' from the end of preamble
779 string const tmppreamble = rtrim(preamble, "\n");
780 os << "\\begin_preamble\n"
782 << "\n\\end_preamble\n";
786 if (!options.empty()) {
787 os << "\\options " << options << '\n';
790 // use the class options defined in the layout?
791 os << "\\use_default_options "
792 << convert<string>(use_default_options) << "\n";
794 // the master document
795 if (!master.empty()) {
796 os << "\\master " << master << '\n';
800 if (!removedModules_.empty()) {
801 os << "\\begin_removed_modules" << '\n';
802 list<string>::const_iterator it = removedModules_.begin();
803 list<string>::const_iterator en = removedModules_.end();
804 for (; it != en; it++)
806 os << "\\end_removed_modules" << '\n';
810 if (!layoutModules_.empty()) {
811 os << "\\begin_modules" << '\n';
812 LayoutModuleList::const_iterator it = layoutModules_.begin();
813 LayoutModuleList::const_iterator en = layoutModules_.end();
814 for (; it != en; it++)
816 os << "\\end_modules" << '\n';
819 // local layout information
820 if (!local_layout.empty()) {
821 // remove '\n' from the end
822 string const tmplocal = rtrim(local_layout, "\n");
823 os << "\\begin_local_layout\n"
825 << "\n\\end_local_layout\n";
828 // then the text parameters
829 if (language != ignore_language)
830 os << "\\language " << language->lang() << '\n';
831 os << "\\inputencoding " << inputenc
832 << "\n\\font_roman " << fontsRoman
833 << "\n\\font_sans " << fontsSans
834 << "\n\\font_typewriter " << fontsTypewriter
835 << "\n\\font_default_family " << fontsDefaultFamily
836 << "\n\\use_xetex " << convert<string>(useXetex)
837 << "\n\\font_sc " << convert<string>(fontsSC)
838 << "\n\\font_osf " << convert<string>(fontsOSF)
839 << "\n\\font_sf_scale " << fontsSansScale
840 << "\n\\font_tt_scale " << fontsTypewriterScale
842 if (!fontsCJK.empty()) {
843 os << "\\font_cjk " << fontsCJK << '\n';
845 os << "\n\\graphics " << graphicsDriver << '\n';
846 os << "\\default_output_format " << defaultOutputFormat << '\n';
847 os << "\\bibtex_command " << bibtex_command << '\n';
848 os << "\\index_command " << index_command << '\n';
850 if (!float_placement.empty()) {
851 os << "\\float_placement " << float_placement << '\n';
853 os << "\\paperfontsize " << fontsize << '\n';
855 spacing().writeFile(os);
856 pdfoptions().writeFile(os);
858 os << "\\papersize " << string_papersize[papersize]
859 << "\n\\use_geometry " << convert<string>(use_geometry)
860 << "\n\\use_amsmath " << use_amsmath
861 << "\n\\use_esint " << use_esint
862 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
863 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
864 << "\n\\use_indices " << convert<string>(use_indices)
865 << "\n\\paperorientation " << string_orientation[orientation]
867 if (backgroundcolor != lyx::rgbFromHexName("#ffffff"))
868 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
870 BranchList::const_iterator it = branchlist().begin();
871 BranchList::const_iterator end = branchlist().end();
872 for (; it != end; ++it) {
873 os << "\\branch " << to_utf8(it->branch())
874 << "\n\\selected " << it->isSelected()
875 << "\n\\filename_suffix " << it->hasFilenameSuffix()
876 << "\n\\color " << lyx::X11hexname(it->color())
881 IndicesList::const_iterator iit = indiceslist().begin();
882 IndicesList::const_iterator iend = indiceslist().end();
883 for (; iit != iend; ++iit) {
884 os << "\\index " << to_utf8(iit->index())
885 << "\n\\shortcut " << to_utf8(iit->shortcut())
886 << "\n\\color " << lyx::X11hexname(iit->color())
891 if (!paperwidth.empty())
892 os << "\\paperwidth "
893 << VSpace(paperwidth).asLyXCommand() << '\n';
894 if (!paperheight.empty())
895 os << "\\paperheight "
896 << VSpace(paperheight).asLyXCommand() << '\n';
897 if (!leftmargin.empty())
898 os << "\\leftmargin "
899 << VSpace(leftmargin).asLyXCommand() << '\n';
900 if (!topmargin.empty())
902 << VSpace(topmargin).asLyXCommand() << '\n';
903 if (!rightmargin.empty())
904 os << "\\rightmargin "
905 << VSpace(rightmargin).asLyXCommand() << '\n';
906 if (!bottommargin.empty())
907 os << "\\bottommargin "
908 << VSpace(bottommargin).asLyXCommand() << '\n';
909 if (!headheight.empty())
910 os << "\\headheight "
911 << VSpace(headheight).asLyXCommand() << '\n';
912 if (!headsep.empty())
914 << VSpace(headsep).asLyXCommand() << '\n';
915 if (!footskip.empty())
917 << VSpace(footskip).asLyXCommand() << '\n';
918 if (!columnsep.empty())
920 << VSpace(columnsep).asLyXCommand() << '\n';
921 os << "\\secnumdepth " << secnumdepth
922 << "\n\\tocdepth " << tocdepth
923 << "\n\\paragraph_separation "
924 << string_paragraph_separation[paragraph_separation];
925 if (!paragraph_separation)
926 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
928 os << "\n\\defskip " << getDefSkip().asLyXCommand();
929 os << "\n\\quotes_language "
930 << string_quotes_language[quotes_language]
931 << "\n\\papercolumns " << columns
932 << "\n\\papersides " << sides
933 << "\n\\paperpagestyle " << pagestyle << '\n';
934 if (!listings_params.empty())
935 os << "\\listings_params \"" <<
936 InsetListingsParams(listings_params).encodedString() << "\"\n";
937 for (int i = 0; i < 4; ++i) {
938 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
939 if (user_defined_bullet(i).getFont() != -1) {
940 os << "\\bullet " << i << " "
941 << user_defined_bullet(i).getFont() << " "
942 << user_defined_bullet(i).getCharacter() << " "
943 << user_defined_bullet(i).getSize() << "\n";
947 os << "\\bulletLaTeX " << i << " \""
948 << lyx::to_ascii(user_defined_bullet(i).getText())
954 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
955 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
957 os << pimpl_->authorlist;
961 void BufferParams::validate(LaTeXFeatures & features) const
963 features.require(documentClass().requires());
966 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
967 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
968 LaTeXFeatures::isAvailable("xcolor");
970 switch (features.runparams().flavor) {
971 case OutputParams::LATEX:
973 features.require("ct-dvipost");
974 features.require("dvipost");
975 } else if (xcolorulem) {
976 features.require("ct-xcolor-ulem");
977 features.require("ulem");
978 features.require("xcolor");
980 features.require("ct-none");
983 case OutputParams::PDFLATEX:
984 case OutputParams::XETEX:
986 features.require("ct-xcolor-ulem");
987 features.require("ulem");
988 features.require("xcolor");
989 // improves color handling in PDF output
990 features.require("pdfcolmk");
992 features.require("ct-none");
1000 // Floats with 'Here definitely' as default setting.
1001 if (float_placement.find('H') != string::npos)
1002 features.require("float");
1004 // AMS Style is at document level
1005 if (use_amsmath == package_on
1006 || documentClass().provides("amsmath"))
1007 features.require("amsmath");
1008 if (use_esint == package_on)
1009 features.require("esint");
1011 // Document-level line spacing
1012 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1013 features.require("setspace");
1015 // the bullet shapes are buffer level not paragraph level
1016 // so they are tested here
1017 for (int i = 0; i < 4; ++i) {
1018 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1020 int const font = user_defined_bullet(i).getFont();
1022 int const c = user_defined_bullet(i).getCharacter();
1028 features.require("latexsym");
1030 } else if (font == 1) {
1031 features.require("amssymb");
1032 } else if (font >= 2 && font <= 5) {
1033 features.require("pifont");
1037 if (pdfoptions().use_hyperref) {
1038 features.require("hyperref");
1039 // due to interferences with babel and hyperref, the color package has to
1040 // be loaded after hyperref when hyperref is used with the colorlinks
1041 // option, see http://bugzilla.lyx.org/show_bug.cgi?id=5291
1042 if (pdfoptions().colorlinks)
1043 features.require("color");
1047 features.require("xetex");
1049 if (language->lang() == "vietnamese")
1050 features.require("vietnamese");
1051 else if (language->lang() == "japanese")
1052 features.require("japanese");
1056 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1057 TexRow & texrow) const
1059 os << "\\documentclass";
1061 DocumentClass const & tclass = documentClass();
1063 ostringstream clsoptions; // the document class options.
1065 if (tokenPos(tclass.opt_fontsize(),
1066 '|', fontsize) >= 0) {
1067 // only write if existing in list (and not default)
1068 clsoptions << fontsize << "pt,";
1071 // custom, A3, B3 and B4 paper sizes need geometry
1072 bool nonstandard_papersize = papersize == PAPER_B3
1073 || papersize == PAPER_B4
1074 || papersize == PAPER_A3
1075 || papersize == PAPER_CUSTOM;
1077 if (!use_geometry) {
1078 switch (papersize) {
1080 clsoptions << "a4paper,";
1082 case PAPER_USLETTER:
1083 clsoptions << "letterpaper,";
1086 clsoptions << "a5paper,";
1089 clsoptions << "b5paper,";
1091 case PAPER_USEXECUTIVE:
1092 clsoptions << "executivepaper,";
1095 clsoptions << "legalpaper,";
1107 if (sides != tclass.sides()) {
1110 clsoptions << "oneside,";
1113 clsoptions << "twoside,";
1119 if (columns != tclass.columns()) {
1121 clsoptions << "twocolumn,";
1123 clsoptions << "onecolumn,";
1127 && orientation == ORIENTATION_LANDSCAPE)
1128 clsoptions << "landscape,";
1130 // language should be a parameter to \documentclass
1131 if (language->babel() == "hebrew"
1132 && default_language->babel() != "hebrew")
1133 // This seems necessary
1134 features.useLanguage(default_language);
1136 ostringstream language_options;
1137 bool const use_babel = features.useBabel();
1139 language_options << features.getLanguages();
1140 if (!language->babel().empty()) {
1141 if (!language_options.str().empty())
1142 language_options << ',';
1143 language_options << language->babel();
1145 // if Vietnamese is used, babel must directly be loaded
1146 // with language options, not in the class options, see
1147 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1148 size_t viet = language_options.str().find("vietnam");
1149 // viet = string::npos when not found
1150 // the same is for all other languages that are not directly supported by
1151 // babel, but where LaTeX-packages add babel support.
1152 // this is currently the case for Latvian, Lithuanian, and Mongolian
1153 size_t latvian = language_options.str().find("latvian");
1154 size_t lithu = language_options.str().find("lithuanian");
1155 size_t mongo = language_options.str().find("mongolian");
1156 // if Japanese is used, babel must directly be loaded
1157 // with language options, not in the class options, see
1158 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1159 size_t japan = language_options.str().find("japanese");
1160 if (lyxrc.language_global_options && !language_options.str().empty()
1161 && viet == string::npos && japan == string::npos
1162 && latvian == string::npos && lithu == string::npos
1163 && mongo == string::npos)
1164 clsoptions << language_options.str() << ',';
1167 // the predefined options from the layout
1168 if (use_default_options && !tclass.options().empty())
1169 clsoptions << tclass.options() << ',';
1171 // the user-defined options
1172 if (!options.empty()) {
1173 clsoptions << options << ',';
1176 string strOptions(clsoptions.str());
1177 if (!strOptions.empty()) {
1178 strOptions = rtrim(strOptions, ",");
1180 os << '[' << from_utf8(strOptions) << ']';
1183 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1185 // end of \documentclass defs
1188 os << "\\usepackage{fontspec}\n";
1192 // font selection must be done before loading fontenc.sty
1193 string const fonts =
1194 loadFonts(fontsRoman, fontsSans,
1195 fontsTypewriter, fontsSC, fontsOSF,
1196 fontsSansScale, fontsTypewriterScale, useXetex);
1197 if (!fonts.empty()) {
1198 os << from_ascii(fonts);
1201 if (fontsDefaultFamily != "default")
1202 os << "\\renewcommand{\\familydefault}{\\"
1203 << from_ascii(fontsDefaultFamily) << "}\n";
1205 // set font encoding
1206 // this one is not per buffer
1207 // for arabic_arabi and farsi we also need to load the LAE and
1209 // XeTeX works without fontenc
1210 if (lyxrc.fontenc != "default" && language->lang() != "japanese"
1212 if (language->lang() == "arabic_arabi"
1213 || language->lang() == "farsi") {
1214 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1215 << ",LFE,LAE]{fontenc}\n";
1218 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1224 // handle inputenc etc.
1225 writeEncodingPreamble(os, features, texrow);
1227 if (!listings_params.empty() || features.isRequired("listings")) {
1228 os << "\\usepackage{listings}\n";
1231 if (!listings_params.empty()) {
1233 // do not test validity because listings_params is
1234 // supposed to be valid
1236 InsetListingsParams(listings_params).separatedParams(true);
1237 // we can't support all packages, but we should load the color package
1238 if (par.find("\\color", 0) != string::npos)
1239 features.require("color");
1240 os << from_utf8(par);
1241 // count the number of newlines
1242 for (size_t i = 0; i < par.size(); ++i)
1248 if (!tclass.provides("geometry")
1249 && (use_geometry || nonstandard_papersize)) {
1250 odocstringstream ods;
1251 if (!getGraphicsDriver("geometry").empty())
1252 ods << getGraphicsDriver("geometry");
1253 if (orientation == ORIENTATION_LANDSCAPE)
1254 ods << ",landscape";
1255 switch (papersize) {
1257 if (!paperwidth.empty())
1258 ods << ",paperwidth="
1259 << from_ascii(paperwidth);
1260 if (!paperheight.empty())
1261 ods << ",paperheight="
1262 << from_ascii(paperheight);
1264 case PAPER_USLETTER:
1265 ods << ",letterpaper";
1268 ods << ",legalpaper";
1270 case PAPER_USEXECUTIVE:
1271 ods << ",executivepaper";
1292 // default papersize ie PAPER_DEFAULT
1293 switch (lyxrc.default_papersize) {
1294 case PAPER_DEFAULT: // keep compiler happy
1295 case PAPER_USLETTER:
1296 ods << ",letterpaper";
1299 ods << ",legalpaper";
1301 case PAPER_USEXECUTIVE:
1302 ods << ",executivepaper";
1322 docstring const g_options = trim(ods.str(), ",");
1323 os << "\\usepackage";
1324 if (!g_options.empty())
1325 os << '[' << g_options << ']';
1326 os << "{geometry}\n";
1328 os << "\\geometry{verbose";
1329 if (!topmargin.empty())
1330 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1331 if (!bottommargin.empty())
1332 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1333 if (!leftmargin.empty())
1334 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1335 if (!rightmargin.empty())
1336 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1337 if (!headheight.empty())
1338 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1339 if (!headsep.empty())
1340 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1341 if (!footskip.empty())
1342 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1343 if (!columnsep.empty())
1344 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1347 } else if (orientation == ORIENTATION_LANDSCAPE) {
1348 features.require("papersize");
1351 if (tokenPos(tclass.opt_pagestyle(),
1352 '|', pagestyle) >= 0) {
1353 if (pagestyle == "fancy") {
1354 os << "\\usepackage{fancyhdr}\n";
1357 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1361 // only output when the background color is not white
1362 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1363 // only require color here, the background color will be defined
1364 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1366 features.require("color");
1367 features.require("pagecolor");
1370 // Only if class has a ToC hierarchy
1371 if (tclass.hasTocLevels()) {
1372 if (secnumdepth != tclass.secnumdepth()) {
1373 os << "\\setcounter{secnumdepth}{"
1378 if (tocdepth != tclass.tocdepth()) {
1379 os << "\\setcounter{tocdepth}{"
1386 if (paragraph_separation) {
1387 // when skip separation
1388 switch (getDefSkip().kind()) {
1389 case VSpace::SMALLSKIP:
1390 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1392 case VSpace::MEDSKIP:
1393 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1395 case VSpace::BIGSKIP:
1396 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1398 case VSpace::LENGTH:
1399 os << "\\setlength{\\parskip}{"
1400 << from_utf8(getDefSkip().length().asLatexString())
1403 default: // should never happen // Then delete it.
1404 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1408 os << "\\setlength{\\parindent}{0pt}\n";
1411 // when separation by indentation
1412 // only output something when a width is given
1413 if (getIndentation().asLyXCommand() != "default") {
1414 os << "\\setlength{\\parindent}{"
1415 << from_utf8(getIndentation().asLatexCommand())
1421 // Now insert the LyX specific LaTeX commands...
1422 docstring lyxpreamble;
1424 // due to interferences with babel and hyperref, the color package has to
1425 // be loaded (when it is not already loaded) before babel when hyperref
1426 // is used with the colorlinks option, see
1427 // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1428 // we decided therefore to load color always before babel, see
1429 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1430 lyxpreamble += from_ascii(features.getColorOptions());
1432 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1434 && (features.isRequired("jurabib")
1435 || features.isRequired("hyperref")
1436 || features.isRequired("vietnamese")
1437 || features.isRequired("japanese") ) ) {
1439 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1440 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1443 // The optional packages;
1444 lyxpreamble += from_ascii(features.getPackages());
1446 // Additional Indices
1447 if (features.isRequired("splitidx")) {
1448 IndicesList::const_iterator iit = indiceslist().begin();
1449 IndicesList::const_iterator iend = indiceslist().end();
1450 for (; iit != iend; ++iit) {
1451 lyxpreamble += "\\newindex[";
1452 lyxpreamble += iit->index();
1453 lyxpreamble += "]{";
1454 lyxpreamble += iit->shortcut();
1455 lyxpreamble += "}\n";
1460 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1463 // * Hyperref manual: "Make sure it comes last of your loaded
1464 // packages, to give it a fighting chance of not being over-written,
1465 // since its job is to redefine many LaTeX commands."
1466 // * Email from Heiko Oberdiek: "It is usually better to load babel
1467 // before hyperref. Then hyperref has a chance to detect babel.
1468 // * Has to be loaded before the "LyX specific LaTeX commands" to
1469 // avoid errors with algorithm floats.
1470 // use hyperref explicitely when it is required
1471 if (features.isRequired("hyperref")) {
1472 odocstringstream oss;
1473 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1474 lyxpreamble += oss.str();
1477 // Will be surrounded by \makeatletter and \makeatother when not empty
1478 docstring atlyxpreamble;
1480 // Some macros LyX will need
1481 docstring tmppreamble(features.getMacros());
1483 if (!tmppreamble.empty())
1484 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1485 "LyX specific LaTeX commands.\n"
1486 + tmppreamble + '\n';
1488 // the text class specific preamble
1489 tmppreamble = features.getTClassPreamble();
1490 if (!tmppreamble.empty())
1491 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1492 "Textclass specific LaTeX commands.\n"
1493 + tmppreamble + '\n';
1495 /* the user-defined preamble */
1496 if (!containsOnly(preamble, " \n\t"))
1498 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1499 "User specified LaTeX commands.\n"
1500 + from_utf8(preamble) + '\n';
1502 // subfig loads internally the LaTeX package "caption". As
1503 // caption is a very popular package, users will load it in
1504 // the preamble. Therefore we must load subfig behind the
1505 // user-defined preamble and check if the caption package was
1506 // loaded or not. For the case that caption is loaded before
1507 // subfig, there is the subfig option "caption=false". This
1508 // option also works when a koma-script class is used and
1509 // koma's own caption commands are used instead of caption. We
1510 // use \PassOptionsToPackage here because the user could have
1511 // already loaded subfig in the preamble.
1512 if (features.isRequired("subfig")) {
1513 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1514 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1515 "\\usepackage{subfig}\n";
1518 // Itemize bullet settings need to be last in case the user
1519 // defines their own bullets that use a package included
1520 // in the user-defined preamble -- ARRae
1521 // Actually it has to be done much later than that
1522 // since some packages like frenchb make modifications
1523 // at \begin{document} time -- JMarc
1524 docstring bullets_def;
1525 for (int i = 0; i < 4; ++i) {
1526 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1527 if (bullets_def.empty())
1528 bullets_def += "\\AtBeginDocument{\n";
1529 bullets_def += " \\def\\labelitemi";
1531 // `i' is one less than the item to modify
1538 bullets_def += "ii";
1544 bullets_def += '{' +
1545 user_defined_bullet(i).getText()
1550 if (!bullets_def.empty())
1551 atlyxpreamble += bullets_def + "}\n\n";
1553 if (!atlyxpreamble.empty())
1554 lyxpreamble += "\n\\makeatletter\n"
1555 + atlyxpreamble + "\\makeatother\n\n";
1557 // We try to load babel late, in case it interferes with other packages.
1558 // Jurabib and Hyperref have to be called after babel, though.
1559 if (use_babel && !features.isRequired("jurabib")
1560 && !features.isRequired("hyperref")
1561 && !features.isRequired("vietnamese")
1562 && !features.isRequired("japanese")) {
1564 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1565 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1568 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1569 if (!i18npreamble.empty())
1570 lyxpreamble += i18npreamble + '\n';
1573 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1574 for (int j = 0; j != nlines; ++j) {
1580 // these packages (xunicode, for that matter) need to be loaded at least
1581 // after amsmath, amssymb, esint and the other packages that provide
1584 os << "\\usepackage{xunicode}\n";
1586 os << "\\usepackage{xltxtra}\n";
1593 void BufferParams::useClassDefaults()
1595 DocumentClass const & tclass = documentClass();
1597 sides = tclass.sides();
1598 columns = tclass.columns();
1599 pagestyle = tclass.pagestyle();
1600 use_default_options = true;
1601 // Only if class has a ToC hierarchy
1602 if (tclass.hasTocLevels()) {
1603 secnumdepth = tclass.secnumdepth();
1604 tocdepth = tclass.tocdepth();
1609 bool BufferParams::hasClassDefaults() const
1611 DocumentClass const & tclass = documentClass();
1613 return sides == tclass.sides()
1614 && columns == tclass.columns()
1615 && pagestyle == tclass.pagestyle()
1616 && use_default_options
1617 && secnumdepth == tclass.secnumdepth()
1618 && tocdepth == tclass.tocdepth();
1622 DocumentClass const & BufferParams::documentClass() const
1628 DocumentClass const * BufferParams::documentClassPtr() const {
1633 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1634 // evil, but this function is evil
1635 doc_class_ = const_cast<DocumentClass *>(tc);
1639 bool BufferParams::setBaseClass(string const & classname)
1641 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1642 LayoutFileList & bcl = LayoutFileList::get();
1643 if (!bcl.haveClass(classname)) {
1645 bformat(_("The document class %1$s could not be found. "
1646 "A default textclass with default layouts will be used. "
1647 "LyX might not be able to produce output unless a correct "
1648 "textclass is selected from the document settings dialog."),
1649 from_utf8(classname));
1650 frontend::Alert::error(_("Document class not found"), s);
1651 bcl.addEmptyClass(classname);
1654 bool const success = bcl[classname].load();
1657 bformat(_("The document class %1$s could not be loaded."),
1658 from_utf8(classname));
1659 frontend::Alert::error(_("Could not load class"), s);
1663 pimpl_->baseClass_ = classname;
1664 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1669 LayoutFile const * BufferParams::baseClass() const
1671 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1672 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1678 LayoutFileIndex const & BufferParams::baseClassID() const
1680 return pimpl_->baseClass_;
1684 void BufferParams::makeDocumentClass()
1689 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1691 if (!local_layout.empty()) {
1692 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1693 docstring const msg = _("Error reading internal layout information");
1694 frontend::Alert::warning(_("Read Error"), msg);
1699 bool BufferParams::moduleCanBeAdded(string const & modName) const
1701 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1705 bool BufferParams::addLayoutModule(string const & modName)
1707 LayoutModuleList::const_iterator it = layoutModules_.begin();
1708 LayoutModuleList::const_iterator end = layoutModules_.end();
1709 for (; it != end; it++)
1712 layoutModules_.push_back(modName);
1717 Font const BufferParams::getFont() const
1719 FontInfo f = documentClass().defaultfont();
1720 if (fontsDefaultFamily == "rmdefault")
1721 f.setFamily(ROMAN_FAMILY);
1722 else if (fontsDefaultFamily == "sfdefault")
1723 f.setFamily(SANS_FAMILY);
1724 else if (fontsDefaultFamily == "ttdefault")
1725 f.setFamily(TYPEWRITER_FAMILY);
1726 return Font(f, language);
1730 void BufferParams::readPreamble(Lexer & lex)
1732 if (lex.getString() != "\\begin_preamble")
1733 lyxerr << "Error (BufferParams::readPreamble):"
1734 "consistency check failed." << endl;
1736 preamble = lex.getLongString("\\end_preamble");
1740 void BufferParams::readLocalLayout(Lexer & lex)
1742 if (lex.getString() != "\\begin_local_layout")
1743 lyxerr << "Error (BufferParams::readLocalLayout):"
1744 "consistency check failed." << endl;
1746 local_layout = lex.getLongString("\\end_local_layout");
1750 void BufferParams::readLanguage(Lexer & lex)
1752 if (!lex.next()) return;
1754 string const tmptok = lex.getString();
1756 // check if tmptok is part of tex_babel in tex-defs.h
1757 language = languages.getLanguage(tmptok);
1759 // Language tmptok was not found
1760 language = default_language;
1761 lyxerr << "Warning: Setting language `"
1762 << tmptok << "' to `" << language->lang()
1768 void BufferParams::readGraphicsDriver(Lexer & lex)
1773 string const tmptok = lex.getString();
1774 // check if tmptok is part of tex_graphics in tex_defs.h
1777 string const test = tex_graphics[n++];
1779 if (test == tmptok) {
1780 graphicsDriver = tmptok;
1785 "Warning: graphics driver `$$Token' not recognized!\n"
1786 " Setting graphics driver to `default'.\n");
1787 graphicsDriver = "default";
1794 void BufferParams::readBullets(Lexer & lex)
1799 int const index = lex.getInteger();
1801 int temp_int = lex.getInteger();
1802 user_defined_bullet(index).setFont(temp_int);
1803 temp_bullet(index).setFont(temp_int);
1805 user_defined_bullet(index).setCharacter(temp_int);
1806 temp_bullet(index).setCharacter(temp_int);
1808 user_defined_bullet(index).setSize(temp_int);
1809 temp_bullet(index).setSize(temp_int);
1813 void BufferParams::readBulletsLaTeX(Lexer & lex)
1815 // The bullet class should be able to read this.
1818 int const index = lex.getInteger();
1820 docstring const temp_str = lex.getDocString();
1822 user_defined_bullet(index).setText(temp_str);
1823 temp_bullet(index).setText(temp_str);
1827 void BufferParams::readModules(Lexer & lex)
1829 if (!lex.eatLine()) {
1830 lyxerr << "Error (BufferParams::readModules):"
1831 "Unexpected end of input." << endl;
1835 string mod = lex.getString();
1836 if (mod == "\\end_modules")
1838 addLayoutModule(mod);
1844 void BufferParams::readRemovedModules(Lexer & lex)
1846 if (!lex.eatLine()) {
1847 lyxerr << "Error (BufferParams::readRemovedModules):"
1848 "Unexpected end of input." << endl;
1852 string mod = lex.getString();
1853 if (mod == "\\end_removed_modules")
1855 removedModules_.push_back(mod);
1858 // now we want to remove any removed modules that were previously
1859 // added. normally, that will be because default modules were added in
1860 // setBaseClass(), which gets called when \textclass is read at the
1861 // start of the read.
1862 list<string>::const_iterator rit = removedModules_.begin();
1863 list<string>::const_iterator const ren = removedModules_.end();
1864 for (; rit != ren; rit++) {
1865 LayoutModuleList::iterator const mit = layoutModules_.begin();
1866 LayoutModuleList::iterator const men = layoutModules_.end();
1867 LayoutModuleList::iterator found = find(mit, men, *rit);
1870 layoutModules_.erase(found);
1875 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1877 char real_papersize = papersize;
1878 if (real_papersize == PAPER_DEFAULT)
1879 real_papersize = lyxrc.default_papersize;
1881 switch (real_papersize) {
1883 // could be anything, so don't guess
1885 case PAPER_CUSTOM: {
1886 if (purpose == XDVI && !paperwidth.empty() &&
1887 !paperheight.empty()) {
1888 // heightxwidth<unit>
1889 string first = paperwidth;
1890 string second = paperheight;
1891 if (orientation == ORIENTATION_LANDSCAPE)
1894 return first.erase(first.length() - 2)
1906 // dvips and dvipdfm do not know this
1907 if (purpose == DVIPS || purpose == DVIPDFM)
1911 // dvipdfm does not know this
1912 if (purpose == DVIPDFM)
1916 // dvipdfm does not know this
1917 if (purpose == DVIPDFM)
1920 case PAPER_USEXECUTIVE:
1921 // dvipdfm does not know this
1922 if (purpose == DVIPDFM)
1927 case PAPER_USLETTER:
1929 if (purpose == XDVI)
1936 string const BufferParams::dvips_options() const
1941 && papersize == PAPER_CUSTOM
1942 && !lyxrc.print_paper_dimension_flag.empty()
1943 && !paperwidth.empty()
1944 && !paperheight.empty()) {
1945 // using a custom papersize
1946 result = lyxrc.print_paper_dimension_flag;
1947 result += ' ' + paperwidth;
1948 result += ',' + paperheight;
1950 string const paper_option = paperSizeName(DVIPS);
1951 if (!paper_option.empty() && (paper_option != "letter" ||
1952 orientation != ORIENTATION_LANDSCAPE)) {
1953 // dvips won't accept -t letter -t landscape.
1954 // In all other cases, include the paper size
1956 result = lyxrc.print_paper_flag;
1957 result += ' ' + paper_option;
1960 if (orientation == ORIENTATION_LANDSCAPE &&
1961 papersize != PAPER_CUSTOM)
1962 result += ' ' + lyxrc.print_landscape_flag;
1967 string BufferParams::babelCall(string const & lang_opts) const
1969 string lang_pack = lyxrc.language_package;
1970 if (lang_pack != "\\usepackage{babel}")
1972 // suppress the babel call when there is no babel language defined
1973 // for the document language in the lib/languages file and if no
1974 // other languages are used (lang_opts is then empty)
1975 if (lang_opts.empty())
1977 // If Vietnamese is used, babel must directly be loaded with the
1978 // language options, see
1979 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1980 size_t viet = lang_opts.find("vietnam");
1981 // viet = string::npos when not found
1982 // the same is for all other languages that are not directly supported by
1983 // babel, but where LaTeX-packages add babel support.
1984 // this is currently the case for Latvian, Lithuanian, and Mongolian
1985 size_t latvian = lang_opts.find("latvian");
1986 size_t lithu = lang_opts.find("lithuanian");
1987 size_t mongo = lang_opts.find("mongolian");
1988 // If Japanese is used, babel must directly be loaded with the
1989 // language options, see
1990 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1991 size_t japan = lang_opts.find("japanese");
1992 if (!lyxrc.language_global_options || viet != string::npos
1993 || japan != string::npos || latvian != string::npos
1994 || lithu != string::npos || mongo != string::npos)
1995 return "\\usepackage[" + lang_opts + "]{babel}";
2000 docstring BufferParams::getGraphicsDriver(string const & package) const
2004 if (package == "geometry") {
2005 if (graphicsDriver == "dvips"
2006 || graphicsDriver == "dvipdfm"
2007 || graphicsDriver == "pdftex"
2008 || graphicsDriver == "vtex")
2009 result = from_ascii(graphicsDriver);
2010 else if (graphicsDriver == "dvipdfmx")
2011 result = from_ascii("dvipdfm");
2018 void BufferParams::writeEncodingPreamble(odocstream & os,
2019 LaTeXFeatures & features, TexRow & texrow) const
2023 if (inputenc == "auto") {
2024 string const doc_encoding =
2025 language->encoding()->latexName();
2026 Encoding::Package const package =
2027 language->encoding()->package();
2029 // Create a list with all the input encodings used
2031 set<string> encodings =
2032 features.getEncodingSet(doc_encoding);
2034 // If the "japanese" package (i.e. pLaTeX) is used,
2035 // inputenc must be omitted.
2036 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2037 if (package == Encoding::japanese)
2038 features.require("japanese");
2040 if ((!encodings.empty() || package == Encoding::inputenc)
2041 && !features.isRequired("japanese")) {
2042 os << "\\usepackage[";
2043 set<string>::const_iterator it = encodings.begin();
2044 set<string>::const_iterator const end = encodings.end();
2046 os << from_ascii(*it);
2049 for (; it != end; ++it)
2050 os << ',' << from_ascii(*it);
2051 if (package == Encoding::inputenc) {
2052 if (!encodings.empty())
2054 os << from_ascii(doc_encoding);
2056 os << "]{inputenc}\n";
2059 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2060 if (language->encoding()->name() == "utf8-cjk"
2061 && LaTeXFeatures::isAvailable("CJKutf8"))
2062 os << "\\usepackage{CJKutf8}\n";
2064 os << "\\usepackage{CJK}\n";
2067 } else if (inputenc != "default") {
2068 switch (encoding().package()) {
2069 case Encoding::none:
2070 case Encoding::japanese:
2072 case Encoding::inputenc:
2073 // do not load inputenc if japanese is used
2074 if (features.isRequired("japanese"))
2076 os << "\\usepackage[" << from_ascii(inputenc)
2081 if (encoding().name() == "utf8-cjk"
2082 && LaTeXFeatures::isAvailable("CJKutf8"))
2083 os << "\\usepackage{CJKutf8}\n";
2085 os << "\\usepackage{CJK}\n";
2091 // The encoding "armscii8" (for Armenian) is only available when
2092 // the package "armtex" is loaded.
2093 if (language->encoding()->latexName() == "armscii8"
2094 || inputenc == "armscii8") {
2095 os << "\\usepackage{armtex}\n";
2101 string const BufferParams::parseFontName(string const & name) const
2103 string mangled = name;
2104 size_t const idx = mangled.find('[');
2105 if (idx == string::npos || idx == 0)
2108 return mangled.substr(0, idx - 1);
2112 string const BufferParams::loadFonts(string const & rm,
2113 string const & sf, string const & tt,
2114 bool const & sc, bool const & osf,
2115 int const & sfscale, int const & ttscale,
2116 bool const & xetex) const
2118 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2119 several packages have been replaced by others, that might not
2120 be installed on every system. We have to take care for that
2121 (see psnfss.pdf). We try to support all psnfss fonts as well
2122 as the fonts that have become de facto standard in the LaTeX
2123 world (e.g. Latin Modern). We do not support obsolete fonts
2124 (like PSLatex). In general, it should be possible to mix any
2125 rm font with any sf or tt font, respectively. (JSpitzm)
2127 -- separate math fonts.
2130 if (rm == "default" && sf == "default" && tt == "default")
2137 if (rm != "default")
2138 os << "\\setmainfont[Mapping=tex-text]{"
2139 << parseFontName(rm) << "}\n";
2140 if (sf != "default") {
2141 string const sans = parseFontName(sf);
2143 os << "\\setsansfont[Scale="
2144 << float(sfscale) / 100
2145 << ",Mapping=tex-text]{"
2148 os << "\\setsansfont[Mapping=tex-text]{"
2151 if (tt != "default") {
2152 string const mono = parseFontName(tt);
2154 os << "\\setmonofont[Scale="
2155 << float(sfscale) / 100
2159 os << "\\setmonofont[Mapping=tex-text]{"
2163 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2168 // Computer Modern (must be explicitely selectable -- there might be classes
2169 // that define a different default font!
2171 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2172 // osf for Computer Modern needs eco.sty
2174 os << "\\usepackage{eco}\n";
2176 // Latin Modern Roman
2177 else if (rm == "lmodern")
2178 os << "\\usepackage{lmodern}\n";
2180 else if (rm == "ae") {
2181 // not needed when using OT1 font encoding.
2182 if (lyxrc.fontenc != "default")
2183 os << "\\usepackage{ae,aecompl}\n";
2186 else if (rm == "times") {
2187 // try to load the best available package
2188 if (LaTeXFeatures::isAvailable("mathptmx"))
2189 os << "\\usepackage{mathptmx}\n";
2190 else if (LaTeXFeatures::isAvailable("mathptm"))
2191 os << "\\usepackage{mathptm}\n";
2193 os << "\\usepackage{times}\n";
2196 else if (rm == "palatino") {
2197 // try to load the best available package
2198 if (LaTeXFeatures::isAvailable("mathpazo")) {
2199 os << "\\usepackage";
2205 // "osf" includes "sc"!
2209 os << "{mathpazo}\n";
2211 else if (LaTeXFeatures::isAvailable("mathpple"))
2212 os << "\\usepackage{mathpple}\n";
2214 os << "\\usepackage{palatino}\n";
2217 else if (rm == "utopia") {
2218 // fourier supersedes utopia.sty, but does
2219 // not work with OT1 encoding.
2220 if (LaTeXFeatures::isAvailable("fourier")
2221 && lyxrc.fontenc != "default") {
2222 os << "\\usepackage";
2233 os << "{fourier}\n";
2236 os << "\\usepackage{utopia}\n";
2238 // Bera (complete fontset)
2239 else if (rm == "bera" && sf == "default" && tt == "default")
2240 os << "\\usepackage{bera}\n";
2242 else if (rm != "default")
2243 os << "\\usepackage" << "{" << rm << "}\n";
2246 // Helvetica, Bera Sans
2247 if (sf == "helvet" || sf == "berasans") {
2249 os << "\\usepackage[scaled=" << float(sfscale) / 100
2250 << "]{" << sf << "}\n";
2252 os << "\\usepackage{" << sf << "}\n";
2255 else if (sf == "avant")
2256 os << "\\usepackage{" << sf << "}\n";
2257 // Computer Modern, Latin Modern, CM Bright
2258 else if (sf != "default")
2259 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2261 // monospaced/typewriter
2262 // Courier, LuxiMono
2263 if (tt == "luximono" || tt == "beramono") {
2265 os << "\\usepackage[scaled=" << float(ttscale) / 100
2266 << "]{" << tt << "}\n";
2268 os << "\\usepackage{" << tt << "}\n";
2271 else if (tt == "courier" )
2272 os << "\\usepackage{" << tt << "}\n";
2273 // Computer Modern, Latin Modern, CM Bright
2274 else if (tt != "default")
2275 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2281 Encoding const & BufferParams::encoding() const
2284 return *(encodings.fromLaTeXName("utf8-plain"));
2285 if (inputenc == "auto" || inputenc == "default")
2286 return *language->encoding();
2287 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2290 LYXERR0("Unknown inputenc value `" << inputenc
2291 << "'. Using `auto' instead.");
2292 return *language->encoding();
2296 CiteEngine BufferParams::citeEngine() const
2298 // FIXME the class should provide the numerical/
2299 // authoryear choice
2300 if (documentClass().provides("natbib")
2301 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2302 return ENGINE_NATBIB_AUTHORYEAR;
2303 return cite_engine_;
2307 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2309 cite_engine_ = cite_engine;