2 * \file BufferParams.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Alfredo Braunstein
7 * \author Lars Gullik Bjønnes
8 * \author Jean-Marc Lasgouttes
10 * \author André Pönitz
11 * \author Martin Vermeer
13 * Full author contact details are available in file CREDITS.
18 #include "BufferParams.h"
21 #include "LayoutFile.h"
22 #include "BranchList.h"
23 #include "buffer_funcs.h"
29 #include "IndicesList.h"
31 #include "LaTeXFeatures.h"
32 #include "ModuleList.h"
36 #include "OutputParams.h"
40 #include "PDFOptions.h"
42 #include "frontends/alert.h"
44 #include "insets/InsetListingsParams.h"
46 #include "support/convert.h"
47 #include "support/debug.h"
48 #include "support/docstream.h"
49 #include "support/FileName.h"
50 #include "support/filetools.h"
51 #include "support/gettext.h"
52 #include "support/Messages.h"
53 #include "support/Translator.h"
54 #include "support/lstrings.h"
60 using namespace lyx::support;
63 static char const * const string_paragraph_separation[] = {
68 static char const * const string_quotes_language[] = {
69 "english", "swedish", "german", "polish", "french", "danish", ""
73 static char const * const string_papersize[] = {
74 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
75 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
79 static char const * const string_orientation[] = {
80 "portrait", "landscape", ""
84 static char const * const string_footnotekinds[] = {
85 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
89 static char const * const tex_graphics[] = {
90 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
91 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
92 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
93 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
104 // Paragraph separation
105 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
108 ParSepTranslator const init_parseptranslator()
110 ParSepTranslator translator
111 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
112 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
117 ParSepTranslator const & parseptranslator()
119 static ParSepTranslator translator = init_parseptranslator();
125 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
128 QuotesLangTranslator const init_quoteslangtranslator()
130 QuotesLangTranslator translator
131 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
132 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
133 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
134 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
135 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
136 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
141 QuotesLangTranslator const & quoteslangtranslator()
143 static QuotesLangTranslator translator = init_quoteslangtranslator();
149 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
152 static PaperSizeTranslator initPaperSizeTranslator()
154 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
155 translator.addPair(string_papersize[1], PAPER_CUSTOM);
156 translator.addPair(string_papersize[2], PAPER_USLETTER);
157 translator.addPair(string_papersize[3], PAPER_USLEGAL);
158 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
159 translator.addPair(string_papersize[5], PAPER_A3);
160 translator.addPair(string_papersize[6], PAPER_A4);
161 translator.addPair(string_papersize[7], PAPER_A5);
162 translator.addPair(string_papersize[8], PAPER_B3);
163 translator.addPair(string_papersize[9], PAPER_B4);
164 translator.addPair(string_papersize[10], PAPER_B5);
169 PaperSizeTranslator const & papersizetranslator()
171 static PaperSizeTranslator translator = initPaperSizeTranslator();
177 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
180 PaperOrientationTranslator const init_paperorientationtranslator()
182 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
183 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
188 PaperOrientationTranslator const & paperorientationtranslator()
190 static PaperOrientationTranslator translator = init_paperorientationtranslator();
196 typedef Translator<int, PageSides> SidesTranslator;
199 SidesTranslator const init_sidestranslator()
201 SidesTranslator translator(1, OneSide);
202 translator.addPair(2, TwoSides);
207 SidesTranslator const & sidestranslator()
209 static SidesTranslator translator = init_sidestranslator();
215 typedef Translator<int, BufferParams::Package> PackageTranslator;
218 PackageTranslator const init_packagetranslator()
220 PackageTranslator translator(0, BufferParams::package_off);
221 translator.addPair(1, BufferParams::package_auto);
222 translator.addPair(2, BufferParams::package_on);
227 PackageTranslator const & packagetranslator()
229 static PackageTranslator translator = init_packagetranslator();
235 typedef Translator<string, CiteEngine> CiteEngineTranslator;
238 CiteEngineTranslator const init_citeenginetranslator()
240 CiteEngineTranslator translator("basic", ENGINE_BASIC);
241 translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
242 translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
243 translator.addPair("jurabib", ENGINE_JURABIB);
248 CiteEngineTranslator const & citeenginetranslator()
250 static CiteEngineTranslator translator = init_citeenginetranslator();
256 typedef Translator<string, Spacing::Space> SpaceTranslator;
259 SpaceTranslator const init_spacetranslator()
261 SpaceTranslator translator("default", Spacing::Default);
262 translator.addPair("single", Spacing::Single);
263 translator.addPair("onehalf", Spacing::Onehalf);
264 translator.addPair("double", Spacing::Double);
265 translator.addPair("other", Spacing::Other);
270 SpaceTranslator const & spacetranslator()
272 static SpaceTranslator translator = init_spacetranslator();
279 class BufferParams::Impl
284 AuthorList authorlist;
285 BranchList branchlist;
286 Bullet temp_bullets[4];
287 Bullet user_defined_bullets[4];
288 IndicesList indiceslist;
290 /** This is the amount of space used for paragraph_separation "skip",
291 * and for detached paragraphs in "indented" documents.
295 PDFOptions pdfoptions;
296 LayoutFileIndex baseClass_;
300 BufferParams::Impl::Impl()
301 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
303 // set initial author
305 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
310 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
314 return new BufferParams::Impl(*ptr);
318 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
324 BufferParams::BufferParams()
327 setBaseClass(defaultBaseclass());
329 paragraph_separation = ParagraphIndentSeparation;
330 quotes_language = InsetQuotes::EnglishQuotes;
331 fontsize = "default";
334 papersize = PAPER_DEFAULT;
335 orientation = ORIENTATION_PORTRAIT;
336 use_geometry = false;
337 use_amsmath = package_auto;
338 use_esint = package_auto;
339 use_mhchem = package_auto;
340 cite_engine_ = ENGINE_BASIC;
341 use_bibtopic = false;
343 trackChanges = false;
344 outputChanges = false;
345 use_default_options = true;
348 language = default_language;
350 fontsRoman = "default";
351 fontsSans = "default";
352 fontsTypewriter = "default";
353 fontsDefaultFamily = "default";
357 fontsSansScale = 100;
358 fontsTypewriterScale = 100;
360 graphicsDriver = "default";
361 defaultOutputFormat = "default";
362 bibtex_command = "default";
363 index_command = "default";
366 listings_params = string();
367 pagestyle = "default";
368 suppress_date = false;
369 // white is equal to no background color
370 backgroundcolor = lyx::rgbFromHexName("#ffffff");
372 for (int iter = 0; iter < 4; ++iter) {
373 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
374 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
377 indiceslist().addDefault(B_("Index"));
378 html_be_strict = true;
379 html_use_mathml = true;
383 docstring BufferParams::B_(string const & l10n) const
385 LASSERT(language, /**/);
386 return getMessages(language->code()).get(l10n);
390 AuthorList & BufferParams::authors()
392 return pimpl_->authorlist;
396 AuthorList const & BufferParams::authors() const
398 return pimpl_->authorlist;
402 BranchList & BufferParams::branchlist()
404 return pimpl_->branchlist;
408 BranchList const & BufferParams::branchlist() const
410 return pimpl_->branchlist;
414 IndicesList & BufferParams::indiceslist()
416 return pimpl_->indiceslist;
420 IndicesList const & BufferParams::indiceslist() const
422 return pimpl_->indiceslist;
426 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
428 LASSERT(index < 4, /**/);
429 return pimpl_->temp_bullets[index];
433 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
435 LASSERT(index < 4, /**/);
436 return pimpl_->temp_bullets[index];
440 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
442 LASSERT(index < 4, /**/);
443 return pimpl_->user_defined_bullets[index];
447 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
449 LASSERT(index < 4, /**/);
450 return pimpl_->user_defined_bullets[index];
454 Spacing & BufferParams::spacing()
456 return pimpl_->spacing;
460 Spacing const & BufferParams::spacing() const
462 return pimpl_->spacing;
466 PDFOptions & BufferParams::pdfoptions()
468 return pimpl_->pdfoptions;
472 PDFOptions const & BufferParams::pdfoptions() const
474 return pimpl_->pdfoptions;
478 HSpace const & BufferParams::getIndentation() const
480 return pimpl_->indentation;
484 void BufferParams::setIndentation(HSpace const & indent)
486 pimpl_->indentation = indent;
490 VSpace const & BufferParams::getDefSkip() const
492 return pimpl_->defskip;
496 void BufferParams::setDefSkip(VSpace const & vs)
498 pimpl_->defskip = vs;
502 string BufferParams::readToken(Lexer & lex, string const & token,
503 FileName const & filepath)
505 if (token == "\\textclass") {
507 string const classname = lex.getString();
508 // if there exists a local layout file, ignore the system one
509 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
511 LayoutFileList & bcl = LayoutFileList::get();
512 if (tcp.empty() && !filepath.empty())
513 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
517 setBaseClass(classname);
518 // We assume that a tex class exists for local or unknown layouts so this warning
519 // will only be given for system layouts.
520 if (!baseClass()->isTeXClassAvailable()) {
521 docstring const msg =
522 bformat(_("The layout file requested by this document,\n"
524 "is not usable. This is probably because a LaTeX\n"
525 "class or style file required by it is not\n"
526 "available. See the Customization documentation\n"
527 "for more information.\n"), from_utf8(classname));
528 frontend::Alert::warning(_("Document class not available"),
529 msg + _("LyX will not be able to produce output."));
531 } else if (token == "\\begin_preamble") {
533 } else if (token == "\\begin_local_layout") {
534 readLocalLayout(lex);
535 } else if (token == "\\begin_modules") {
537 } else if (token == "\\begin_removed_modules") {
538 readRemovedModules(lex);
539 } else if (token == "\\options") {
541 options = lex.getString();
542 } else if (token == "\\use_default_options") {
543 lex >> use_default_options;
544 } else if (token == "\\master") {
546 master = lex.getString();
547 } else if (token == "\\suppress_date") {
548 lex >> suppress_date;
549 } else if (token == "\\language") {
551 } else if (token == "\\inputencoding") {
553 } else if (token == "\\graphics") {
554 readGraphicsDriver(lex);
555 } else if (token == "\\default_output_format") {
556 lex >> defaultOutputFormat;
557 } else if (token == "\\bibtex_command") {
559 bibtex_command = lex.getString();
560 } else if (token == "\\index_command") {
562 index_command = lex.getString();
563 } else if (token == "\\fontencoding") {
565 fontenc = lex.getString();
566 } else if (token == "\\font_roman") {
568 fontsRoman = lex.getString();
569 } else if (token == "\\font_sans") {
571 fontsSans = lex.getString();
572 } else if (token == "\\font_typewriter") {
574 fontsTypewriter = lex.getString();
575 } else if (token == "\\font_default_family") {
576 lex >> fontsDefaultFamily;
577 } else if (token == "\\use_xetex") {
579 } else if (token == "\\font_sc") {
581 } else if (token == "\\font_osf") {
583 } else if (token == "\\font_sf_scale") {
584 lex >> fontsSansScale;
585 } else if (token == "\\font_tt_scale") {
586 lex >> fontsTypewriterScale;
587 } else if (token == "\\font_cjk") {
589 } else if (token == "\\paragraph_separation") {
592 paragraph_separation = parseptranslator().find(parsep);
593 } else if (token == "\\paragraph_indentation") {
595 string indentation = lex.getString();
596 pimpl_->indentation = HSpace(indentation);
597 } else if (token == "\\defskip") {
599 string defskip = lex.getString();
600 if (defskip == "defskip")
603 pimpl_->defskip = VSpace(defskip);
604 } else if (token == "\\quotes_language") {
607 quotes_language = quoteslangtranslator().find(quotes_lang);
608 } else if (token == "\\papersize") {
611 papersize = papersizetranslator().find(ppsize);
612 } else if (token == "\\use_geometry") {
614 } else if (token == "\\use_amsmath") {
617 use_amsmath = packagetranslator().find(use_ams);
618 } else if (token == "\\use_esint") {
621 use_esint = packagetranslator().find(useesint);
622 } else if (token == "\\use_mhchem") {
625 use_mhchem = packagetranslator().find(usemhchem);
626 } else if (token == "\\cite_engine") {
629 cite_engine_ = citeenginetranslator().find(engine);
630 } else if (token == "\\use_bibtopic") {
632 } else if (token == "\\use_indices") {
634 } else if (token == "\\tracking_changes") {
636 } else if (token == "\\output_changes") {
637 lex >> outputChanges;
638 } else if (token == "\\branch") {
640 docstring branch = lex.getDocString();
641 branchlist().add(branch);
644 string const tok = lex.getString();
645 if (tok == "\\end_branch")
647 Branch * branch_ptr = branchlist().find(branch);
648 if (tok == "\\selected") {
651 branch_ptr->setSelected(lex.getInteger());
653 if (tok == "\\filename_suffix") {
656 branch_ptr->setFilenameSuffix(lex.getInteger());
658 if (tok == "\\color") {
660 string color = lex.getString();
662 branch_ptr->setColor(color);
663 // Update also the Color table:
665 color = lcolor.getX11Name(Color_background);
667 lcolor.setColor(to_utf8(branch), color);
670 } else if (token == "\\index") {
672 docstring index = lex.getDocString();
674 indiceslist().add(index);
677 string const tok = lex.getString();
678 if (tok == "\\end_index")
680 Index * index_ptr = indiceslist().find(index);
681 if (tok == "\\shortcut") {
683 shortcut = lex.getDocString();
685 index_ptr->setShortcut(shortcut);
687 if (tok == "\\color") {
689 string color = lex.getString();
691 index_ptr->setColor(color);
692 // Update also the Color table:
694 color = lcolor.getX11Name(Color_background);
696 if (!shortcut.empty())
697 lcolor.setColor(to_utf8(shortcut), color);
700 } else if (token == "\\author") {
702 istringstream ss(lex.getString());
705 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
706 } else if (token == "\\paperorientation") {
709 orientation = paperorientationtranslator().find(orient);
710 } else if (token == "\\backgroundcolor") {
712 backgroundcolor = lyx::rgbFromHexName(lex.getString());
713 } else if (token == "\\paperwidth") {
715 } else if (token == "\\paperheight") {
717 } else if (token == "\\leftmargin") {
719 } else if (token == "\\topmargin") {
721 } else if (token == "\\rightmargin") {
723 } else if (token == "\\bottommargin") {
725 } else if (token == "\\headheight") {
727 } else if (token == "\\headsep") {
729 } else if (token == "\\footskip") {
731 } else if (token == "\\columnsep") {
733 } else if (token == "\\paperfontsize") {
735 } else if (token == "\\papercolumns") {
737 } else if (token == "\\listings_params") {
740 listings_params = InsetListingsParams(par).params();
741 } else if (token == "\\papersides") {
744 sides = sidestranslator().find(psides);
745 } else if (token == "\\paperpagestyle") {
747 } else if (token == "\\bullet") {
749 } else if (token == "\\bulletLaTeX") {
750 readBulletsLaTeX(lex);
751 } else if (token == "\\secnumdepth") {
753 } else if (token == "\\tocdepth") {
755 } else if (token == "\\spacing") {
759 if (nspacing == "other") {
762 spacing().set(spacetranslator().find(nspacing), tmp_val);
763 } else if (token == "\\float_placement") {
764 lex >> float_placement;
766 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
767 string toktmp = pdfoptions().readToken(lex, token);
768 if (!toktmp.empty()) {
769 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
773 } else if (token == "\\html_use_mathml") {
774 lex >> html_use_mathml;
775 } else if (token == "\\html_be_strict") {
776 lex >> html_be_strict;
778 lyxerr << "BufferParams::readToken(): Unknown token: " <<
787 void BufferParams::writeFile(ostream & os) const
789 // The top of the file is written by the buffer.
790 // Prints out the buffer info into the .lyx file given by file
793 os << "\\textclass " << baseClass()->name() << '\n';
796 if (!preamble.empty()) {
797 // remove '\n' from the end of preamble
798 string const tmppreamble = rtrim(preamble, "\n");
799 os << "\\begin_preamble\n"
801 << "\n\\end_preamble\n";
805 if (!options.empty()) {
806 os << "\\options " << options << '\n';
809 // use the class options defined in the layout?
810 os << "\\use_default_options "
811 << convert<string>(use_default_options) << "\n";
813 // the master document
814 if (!master.empty()) {
815 os << "\\master " << master << '\n';
819 if (!removedModules_.empty()) {
820 os << "\\begin_removed_modules" << '\n';
821 list<string>::const_iterator it = removedModules_.begin();
822 list<string>::const_iterator en = removedModules_.end();
823 for (; it != en; it++)
825 os << "\\end_removed_modules" << '\n';
829 if (!layoutModules_.empty()) {
830 os << "\\begin_modules" << '\n';
831 LayoutModuleList::const_iterator it = layoutModules_.begin();
832 LayoutModuleList::const_iterator en = layoutModules_.end();
833 for (; it != en; it++)
835 os << "\\end_modules" << '\n';
838 // local layout information
839 if (!local_layout.empty()) {
840 // remove '\n' from the end
841 string const tmplocal = rtrim(local_layout, "\n");
842 os << "\\begin_local_layout\n"
844 << "\n\\end_local_layout\n";
847 // then the text parameters
848 if (language != ignore_language)
849 os << "\\language " << language->lang() << '\n';
850 os << "\\inputencoding " << inputenc
851 << "\n\\fontencoding " << fontenc
852 << "\n\\font_roman " << fontsRoman
853 << "\n\\font_sans " << fontsSans
854 << "\n\\font_typewriter " << fontsTypewriter
855 << "\n\\font_default_family " << fontsDefaultFamily
856 << "\n\\use_xetex " << convert<string>(useXetex)
857 << "\n\\font_sc " << convert<string>(fontsSC)
858 << "\n\\font_osf " << convert<string>(fontsOSF)
859 << "\n\\font_sf_scale " << fontsSansScale
860 << "\n\\font_tt_scale " << fontsTypewriterScale
862 if (!fontsCJK.empty()) {
863 os << "\\font_cjk " << fontsCJK << '\n';
865 os << "\n\\graphics " << graphicsDriver << '\n';
866 os << "\\default_output_format " << defaultOutputFormat << '\n';
867 os << "\\bibtex_command " << bibtex_command << '\n';
868 os << "\\index_command " << index_command << '\n';
870 if (!float_placement.empty()) {
871 os << "\\float_placement " << float_placement << '\n';
873 os << "\\paperfontsize " << fontsize << '\n';
875 spacing().writeFile(os);
876 pdfoptions().writeFile(os);
878 os << "\\papersize " << string_papersize[papersize]
879 << "\n\\use_geometry " << convert<string>(use_geometry)
880 << "\n\\use_amsmath " << use_amsmath
881 << "\n\\use_esint " << use_esint
882 << "\n\\use_mhchem " << use_mhchem
883 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
884 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
885 << "\n\\use_indices " << convert<string>(use_indices)
886 << "\n\\paperorientation " << string_orientation[orientation]
887 << "\n\\suppress_date " << convert<string>(suppress_date)
889 if (backgroundcolor != lyx::rgbFromHexName("#ffffff"))
890 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
892 BranchList::const_iterator it = branchlist().begin();
893 BranchList::const_iterator end = branchlist().end();
894 for (; it != end; ++it) {
895 os << "\\branch " << to_utf8(it->branch())
896 << "\n\\selected " << it->isSelected()
897 << "\n\\filename_suffix " << it->hasFilenameSuffix()
898 << "\n\\color " << lyx::X11hexname(it->color())
903 IndicesList::const_iterator iit = indiceslist().begin();
904 IndicesList::const_iterator iend = indiceslist().end();
905 for (; iit != iend; ++iit) {
906 os << "\\index " << to_utf8(iit->index())
907 << "\n\\shortcut " << to_utf8(iit->shortcut())
908 << "\n\\color " << lyx::X11hexname(iit->color())
913 if (!paperwidth.empty())
914 os << "\\paperwidth "
915 << VSpace(paperwidth).asLyXCommand() << '\n';
916 if (!paperheight.empty())
917 os << "\\paperheight "
918 << VSpace(paperheight).asLyXCommand() << '\n';
919 if (!leftmargin.empty())
920 os << "\\leftmargin "
921 << VSpace(leftmargin).asLyXCommand() << '\n';
922 if (!topmargin.empty())
924 << VSpace(topmargin).asLyXCommand() << '\n';
925 if (!rightmargin.empty())
926 os << "\\rightmargin "
927 << VSpace(rightmargin).asLyXCommand() << '\n';
928 if (!bottommargin.empty())
929 os << "\\bottommargin "
930 << VSpace(bottommargin).asLyXCommand() << '\n';
931 if (!headheight.empty())
932 os << "\\headheight "
933 << VSpace(headheight).asLyXCommand() << '\n';
934 if (!headsep.empty())
936 << VSpace(headsep).asLyXCommand() << '\n';
937 if (!footskip.empty())
939 << VSpace(footskip).asLyXCommand() << '\n';
940 if (!columnsep.empty())
942 << VSpace(columnsep).asLyXCommand() << '\n';
943 os << "\\secnumdepth " << secnumdepth
944 << "\n\\tocdepth " << tocdepth
945 << "\n\\paragraph_separation "
946 << string_paragraph_separation[paragraph_separation];
947 if (!paragraph_separation)
948 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
950 os << "\n\\defskip " << getDefSkip().asLyXCommand();
951 os << "\n\\quotes_language "
952 << string_quotes_language[quotes_language]
953 << "\n\\papercolumns " << columns
954 << "\n\\papersides " << sides
955 << "\n\\paperpagestyle " << pagestyle << '\n';
956 if (!listings_params.empty())
957 os << "\\listings_params \"" <<
958 InsetListingsParams(listings_params).encodedString() << "\"\n";
959 for (int i = 0; i < 4; ++i) {
960 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
961 if (user_defined_bullet(i).getFont() != -1) {
962 os << "\\bullet " << i << " "
963 << user_defined_bullet(i).getFont() << " "
964 << user_defined_bullet(i).getCharacter() << " "
965 << user_defined_bullet(i).getSize() << "\n";
969 os << "\\bulletLaTeX " << i << " \""
970 << lyx::to_ascii(user_defined_bullet(i).getText())
976 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n"
977 << "\\output_changes " << convert<string>(outputChanges) << "\n"
978 << "\\html_use_mathml " << convert<string>(html_use_mathml) << "\n"
979 << "\\html_be_strict " << convert<string>(html_be_strict) << "\n";
981 os << pimpl_->authorlist;
985 void BufferParams::validate(LaTeXFeatures & features) const
987 features.require(documentClass().requires());
990 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
991 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
992 LaTeXFeatures::isAvailable("xcolor");
994 switch (features.runparams().flavor) {
995 case OutputParams::LATEX:
997 features.require("ct-dvipost");
998 features.require("dvipost");
999 } else if (xcolorulem) {
1000 features.require("ct-xcolor-ulem");
1001 features.require("ulem");
1002 features.require("xcolor");
1004 features.require("ct-none");
1007 case OutputParams::PDFLATEX:
1008 case OutputParams::XETEX:
1010 features.require("ct-xcolor-ulem");
1011 features.require("ulem");
1012 features.require("xcolor");
1013 // improves color handling in PDF output
1014 features.require("pdfcolmk");
1016 features.require("ct-none");
1024 // Floats with 'Here definitely' as default setting.
1025 if (float_placement.find('H') != string::npos)
1026 features.require("float");
1028 // AMS Style is at document level
1029 if (use_amsmath == package_on
1030 || documentClass().provides("amsmath"))
1031 features.require("amsmath");
1032 if (use_esint == package_on)
1033 features.require("esint");
1034 if (use_mhchem == package_on)
1035 features.require("mhchem");
1037 // Document-level line spacing
1038 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1039 features.require("setspace");
1041 // the bullet shapes are buffer level not paragraph level
1042 // so they are tested here
1043 for (int i = 0; i < 4; ++i) {
1044 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1046 int const font = user_defined_bullet(i).getFont();
1048 int const c = user_defined_bullet(i).getCharacter();
1054 features.require("latexsym");
1056 } else if (font == 1) {
1057 features.require("amssymb");
1058 } else if (font >= 2 && font <= 5) {
1059 features.require("pifont");
1063 if (pdfoptions().use_hyperref) {
1064 features.require("hyperref");
1065 // due to interferences with babel and hyperref, the color package has to
1066 // be loaded after hyperref when hyperref is used with the colorlinks
1067 // option, see http://www.lyx.org/trac/ticket/5291
1068 if (pdfoptions().colorlinks)
1069 features.require("color");
1073 features.require("xetex");
1075 if (language->lang() == "vietnamese")
1076 features.require("vietnamese");
1077 else if (language->lang() == "japanese")
1078 features.require("japanese");
1082 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1083 TexRow & texrow) const
1085 os << "\\documentclass";
1087 DocumentClass const & tclass = documentClass();
1089 ostringstream clsoptions; // the document class options.
1091 if (tokenPos(tclass.opt_fontsize(),
1092 '|', fontsize) >= 0) {
1093 // only write if existing in list (and not default)
1094 clsoptions << fontsize << "pt,";
1097 // custom, A3, B3 and B4 paper sizes need geometry
1098 bool nonstandard_papersize = papersize == PAPER_B3
1099 || papersize == PAPER_B4
1100 || papersize == PAPER_A3
1101 || papersize == PAPER_CUSTOM;
1103 if (!use_geometry) {
1104 switch (papersize) {
1106 clsoptions << "a4paper,";
1108 case PAPER_USLETTER:
1109 clsoptions << "letterpaper,";
1112 clsoptions << "a5paper,";
1115 clsoptions << "b5paper,";
1117 case PAPER_USEXECUTIVE:
1118 clsoptions << "executivepaper,";
1121 clsoptions << "legalpaper,";
1133 if (sides != tclass.sides()) {
1136 clsoptions << "oneside,";
1139 clsoptions << "twoside,";
1145 if (columns != tclass.columns()) {
1147 clsoptions << "twocolumn,";
1149 clsoptions << "onecolumn,";
1153 && orientation == ORIENTATION_LANDSCAPE)
1154 clsoptions << "landscape,";
1156 // language should be a parameter to \documentclass
1157 if (language->babel() == "hebrew"
1158 && default_language->babel() != "hebrew")
1159 // This seems necessary
1160 features.useLanguage(default_language);
1162 ostringstream language_options;
1163 bool const use_babel = features.useBabel();
1165 language_options << features.getLanguages();
1166 if (!language->babel().empty()) {
1167 if (!language_options.str().empty())
1168 language_options << ',';
1169 language_options << language->babel();
1171 // if Vietnamese is used, babel must directly be loaded
1172 // with language options, not in the class options, see
1173 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1174 size_t viet = language_options.str().find("vietnam");
1175 // viet = string::npos when not found
1176 // the same is for all other languages that are not directly supported by
1177 // babel, but where LaTeX-packages add babel support.
1178 // this is currently the case for Latvian, Lithuanian, and Mongolian
1179 size_t latvian = language_options.str().find("latvian");
1180 size_t lithu = language_options.str().find("lithuanian");
1181 size_t mongo = language_options.str().find("mongolian");
1182 // if Japanese is used, babel must directly be loaded
1183 // with language options, not in the class options, see
1184 // http://www.lyx.org/trac/ticket/4597#c4
1185 size_t japan = language_options.str().find("japanese");
1186 if (lyxrc.language_global_options && !language_options.str().empty()
1187 && viet == string::npos && japan == string::npos
1188 && latvian == string::npos && lithu == string::npos
1189 && mongo == string::npos)
1190 clsoptions << language_options.str() << ',';
1193 // the predefined options from the layout
1194 if (use_default_options && !tclass.options().empty())
1195 clsoptions << tclass.options() << ',';
1197 // the user-defined options
1198 if (!options.empty()) {
1199 clsoptions << options << ',';
1202 string strOptions(clsoptions.str());
1203 if (!strOptions.empty()) {
1204 strOptions = rtrim(strOptions, ",");
1206 os << '[' << from_utf8(strOptions) << ']';
1209 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1211 // end of \documentclass defs
1214 os << "\\usepackage{fontspec}\n";
1218 // font selection must be done before loading fontenc.sty
1219 string const fonts =
1220 loadFonts(fontsRoman, fontsSans,
1221 fontsTypewriter, fontsSC, fontsOSF,
1222 fontsSansScale, fontsTypewriterScale, useXetex);
1223 if (!fonts.empty()) {
1224 os << from_ascii(fonts);
1227 if (fontsDefaultFamily != "default")
1228 os << "\\renewcommand{\\familydefault}{\\"
1229 << from_ascii(fontsDefaultFamily) << "}\n";
1231 // set font encoding
1232 // for arabic_arabi and farsi we also need to load the LAE and
1234 // XeTeX works without fontenc
1235 if (font_encoding() != "default" && language->lang() != "japanese"
1237 if (language->lang() == "arabic_arabi"
1238 || language->lang() == "farsi") {
1239 os << "\\usepackage[" << from_ascii(font_encoding())
1240 << ",LFE,LAE]{fontenc}\n";
1243 os << "\\usepackage[" << from_ascii(font_encoding())
1249 // handle inputenc etc.
1250 writeEncodingPreamble(os, features, texrow);
1252 if (!listings_params.empty() || features.isRequired("listings")) {
1253 os << "\\usepackage{listings}\n";
1256 if (!listings_params.empty()) {
1258 // do not test validity because listings_params is
1259 // supposed to be valid
1261 InsetListingsParams(listings_params).separatedParams(true);
1262 // we can't support all packages, but we should load the color package
1263 if (par.find("\\color", 0) != string::npos)
1264 features.require("color");
1265 os << from_utf8(par);
1266 // count the number of newlines
1267 for (size_t i = 0; i < par.size(); ++i)
1273 if (!tclass.provides("geometry")
1274 && (use_geometry || nonstandard_papersize)) {
1275 odocstringstream ods;
1276 if (!getGraphicsDriver("geometry").empty())
1277 ods << getGraphicsDriver("geometry");
1278 if (orientation == ORIENTATION_LANDSCAPE)
1279 ods << ",landscape";
1280 switch (papersize) {
1282 if (!paperwidth.empty())
1283 ods << ",paperwidth="
1284 << from_ascii(paperwidth);
1285 if (!paperheight.empty())
1286 ods << ",paperheight="
1287 << from_ascii(paperheight);
1289 case PAPER_USLETTER:
1290 ods << ",letterpaper";
1293 ods << ",legalpaper";
1295 case PAPER_USEXECUTIVE:
1296 ods << ",executivepaper";
1317 // default papersize ie PAPER_DEFAULT
1318 switch (lyxrc.default_papersize) {
1319 case PAPER_DEFAULT: // keep compiler happy
1320 case PAPER_USLETTER:
1321 ods << ",letterpaper";
1324 ods << ",legalpaper";
1326 case PAPER_USEXECUTIVE:
1327 ods << ",executivepaper";
1347 docstring const g_options = trim(ods.str(), ",");
1348 os << "\\usepackage";
1349 if (!g_options.empty())
1350 os << '[' << g_options << ']';
1351 os << "{geometry}\n";
1353 os << "\\geometry{verbose";
1354 if (!topmargin.empty())
1355 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1356 if (!bottommargin.empty())
1357 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1358 if (!leftmargin.empty())
1359 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1360 if (!rightmargin.empty())
1361 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1362 if (!headheight.empty())
1363 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1364 if (!headsep.empty())
1365 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1366 if (!footskip.empty())
1367 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1368 if (!columnsep.empty())
1369 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1372 } else if (orientation == ORIENTATION_LANDSCAPE) {
1373 features.require("papersize");
1376 if (tokenPos(tclass.opt_pagestyle(),
1377 '|', pagestyle) >= 0) {
1378 if (pagestyle == "fancy") {
1379 os << "\\usepackage{fancyhdr}\n";
1382 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1386 // only output when the background color is not white
1387 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1388 // only require color here, the background color will be defined
1389 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1391 features.require("color");
1392 features.require("pagecolor");
1395 // Only if class has a ToC hierarchy
1396 if (tclass.hasTocLevels()) {
1397 if (secnumdepth != tclass.secnumdepth()) {
1398 os << "\\setcounter{secnumdepth}{"
1403 if (tocdepth != tclass.tocdepth()) {
1404 os << "\\setcounter{tocdepth}{"
1411 if (paragraph_separation) {
1412 // when skip separation
1413 switch (getDefSkip().kind()) {
1414 case VSpace::SMALLSKIP:
1415 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1417 case VSpace::MEDSKIP:
1418 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1420 case VSpace::BIGSKIP:
1421 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1423 case VSpace::LENGTH:
1424 os << "\\setlength{\\parskip}{"
1425 << from_utf8(getDefSkip().length().asLatexString())
1428 default: // should never happen // Then delete it.
1429 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1433 os << "\\setlength{\\parindent}{0pt}\n";
1436 // when separation by indentation
1437 // only output something when a width is given
1438 if (getIndentation().asLyXCommand() != "default") {
1439 os << "\\setlength{\\parindent}{"
1440 << from_utf8(getIndentation().asLatexCommand())
1446 // Now insert the LyX specific LaTeX commands...
1447 docstring lyxpreamble;
1449 // due to interferences with babel and hyperref, the color package has to
1450 // be loaded (when it is not already loaded) before babel when hyperref
1451 // is used with the colorlinks option, see
1452 // http://www.lyx.org/trac/ticket/5291
1453 // we decided therefore to load color always before babel, see
1454 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1455 lyxpreamble += from_ascii(features.getColorOptions());
1457 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1459 && (features.isRequired("jurabib")
1460 || features.isRequired("hyperref")
1461 || features.isRequired("vietnamese")
1462 || features.isRequired("japanese") ) ) {
1464 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1465 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1468 // The optional packages;
1469 lyxpreamble += from_ascii(features.getPackages());
1471 // Additional Indices
1472 if (features.isRequired("splitidx")) {
1473 IndicesList::const_iterator iit = indiceslist().begin();
1474 IndicesList::const_iterator iend = indiceslist().end();
1475 for (; iit != iend; ++iit) {
1476 lyxpreamble += "\\newindex[";
1477 lyxpreamble += iit->index();
1478 lyxpreamble += "]{";
1479 lyxpreamble += iit->shortcut();
1480 lyxpreamble += "}\n";
1485 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1488 // * Hyperref manual: "Make sure it comes last of your loaded
1489 // packages, to give it a fighting chance of not being over-written,
1490 // since its job is to redefine many LaTeX commands."
1491 // * Email from Heiko Oberdiek: "It is usually better to load babel
1492 // before hyperref. Then hyperref has a chance to detect babel.
1493 // * Has to be loaded before the "LyX specific LaTeX commands" to
1494 // avoid errors with algorithm floats.
1495 // use hyperref explicitely when it is required
1496 if (features.isRequired("hyperref")) {
1497 odocstringstream oss;
1498 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1499 lyxpreamble += oss.str();
1502 // Will be surrounded by \makeatletter and \makeatother when not empty
1503 docstring atlyxpreamble;
1505 // Some macros LyX will need
1506 docstring tmppreamble(features.getMacros());
1508 if (!tmppreamble.empty())
1509 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1510 "LyX specific LaTeX commands.\n"
1511 + tmppreamble + '\n';
1513 // the text class specific preamble
1514 tmppreamble = features.getTClassPreamble();
1515 if (!tmppreamble.empty())
1516 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1517 "Textclass specific LaTeX commands.\n"
1518 + tmppreamble + '\n';
1520 // suppress date if selected
1521 // use \@ifundefined because we cannot be sure that every document class
1522 // has a \date command
1524 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1526 /* the user-defined preamble */
1527 if (!containsOnly(preamble, " \n\t"))
1529 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1530 "User specified LaTeX commands.\n"
1531 + from_utf8(preamble) + '\n';
1533 // subfig loads internally the LaTeX package "caption". As
1534 // caption is a very popular package, users will load it in
1535 // the preamble. Therefore we must load subfig behind the
1536 // user-defined preamble and check if the caption package was
1537 // loaded or not. For the case that caption is loaded before
1538 // subfig, there is the subfig option "caption=false". This
1539 // option also works when a koma-script class is used and
1540 // koma's own caption commands are used instead of caption. We
1541 // use \PassOptionsToPackage here because the user could have
1542 // already loaded subfig in the preamble.
1543 if (features.isRequired("subfig")) {
1544 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1545 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1546 "\\usepackage{subfig}\n";
1549 // Itemize bullet settings need to be last in case the user
1550 // defines their own bullets that use a package included
1551 // in the user-defined preamble -- ARRae
1552 // Actually it has to be done much later than that
1553 // since some packages like frenchb make modifications
1554 // at \begin{document} time -- JMarc
1555 docstring bullets_def;
1556 for (int i = 0; i < 4; ++i) {
1557 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1558 if (bullets_def.empty())
1559 bullets_def += "\\AtBeginDocument{\n";
1560 bullets_def += " \\def\\labelitemi";
1562 // `i' is one less than the item to modify
1569 bullets_def += "ii";
1575 bullets_def += '{' +
1576 user_defined_bullet(i).getText()
1581 if (!bullets_def.empty())
1582 atlyxpreamble += bullets_def + "}\n\n";
1584 if (!atlyxpreamble.empty())
1585 lyxpreamble += "\n\\makeatletter\n"
1586 + atlyxpreamble + "\\makeatother\n\n";
1588 // We try to load babel late, in case it interferes with other packages.
1589 // Jurabib and Hyperref have to be called after babel, though.
1590 if (use_babel && !features.isRequired("jurabib")
1591 && !features.isRequired("hyperref")
1592 && !features.isRequired("vietnamese")
1593 && !features.isRequired("japanese")) {
1595 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1596 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1599 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1600 if (!i18npreamble.empty())
1601 lyxpreamble += i18npreamble + '\n';
1604 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1605 for (int j = 0; j != nlines; ++j) {
1611 // these packages (xunicode, for that matter) need to be loaded at least
1612 // after amsmath, amssymb, esint and the other packages that provide
1615 os << "\\usepackage{xunicode}\n";
1617 os << "\\usepackage{xltxtra}\n";
1624 void BufferParams::useClassDefaults()
1626 DocumentClass const & tclass = documentClass();
1628 sides = tclass.sides();
1629 columns = tclass.columns();
1630 pagestyle = tclass.pagestyle();
1631 use_default_options = true;
1632 // Only if class has a ToC hierarchy
1633 if (tclass.hasTocLevels()) {
1634 secnumdepth = tclass.secnumdepth();
1635 tocdepth = tclass.tocdepth();
1640 bool BufferParams::hasClassDefaults() const
1642 DocumentClass const & tclass = documentClass();
1644 return sides == tclass.sides()
1645 && columns == tclass.columns()
1646 && pagestyle == tclass.pagestyle()
1647 && use_default_options
1648 && secnumdepth == tclass.secnumdepth()
1649 && tocdepth == tclass.tocdepth();
1653 DocumentClass const & BufferParams::documentClass() const
1659 DocumentClass const * BufferParams::documentClassPtr() const {
1664 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1665 // evil, but this function is evil
1666 doc_class_ = const_cast<DocumentClass *>(tc);
1670 bool BufferParams::setBaseClass(string const & classname)
1672 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1673 LayoutFileList & bcl = LayoutFileList::get();
1674 if (!bcl.haveClass(classname)) {
1676 bformat(_("The document class %1$s could not be found. "
1677 "A default textclass with default layouts will be used. "
1678 "LyX might not be able to produce output unless a correct "
1679 "textclass is selected from the document settings dialog."),
1680 from_utf8(classname));
1681 frontend::Alert::error(_("Document class not found"), s);
1682 bcl.addEmptyClass(classname);
1685 bool const success = bcl[classname].load();
1688 bformat(_("The document class %1$s could not be loaded."),
1689 from_utf8(classname));
1690 frontend::Alert::error(_("Could not load class"), s);
1694 pimpl_->baseClass_ = classname;
1695 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1700 LayoutFile const * BufferParams::baseClass() const
1702 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1703 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1709 LayoutFileIndex const & BufferParams::baseClassID() const
1711 return pimpl_->baseClass_;
1715 void BufferParams::makeDocumentClass()
1720 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1722 if (!local_layout.empty()) {
1723 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1724 docstring const msg = _("Error reading internal layout information");
1725 frontend::Alert::warning(_("Read Error"), msg);
1730 bool BufferParams::moduleCanBeAdded(string const & modName) const
1732 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1736 bool BufferParams::addLayoutModule(string const & modName)
1738 LayoutModuleList::const_iterator it = layoutModules_.begin();
1739 LayoutModuleList::const_iterator end = layoutModules_.end();
1740 for (; it != end; it++)
1743 layoutModules_.push_back(modName);
1748 Font const BufferParams::getFont() const
1750 FontInfo f = documentClass().defaultfont();
1751 if (fontsDefaultFamily == "rmdefault")
1752 f.setFamily(ROMAN_FAMILY);
1753 else if (fontsDefaultFamily == "sfdefault")
1754 f.setFamily(SANS_FAMILY);
1755 else if (fontsDefaultFamily == "ttdefault")
1756 f.setFamily(TYPEWRITER_FAMILY);
1757 return Font(f, language);
1761 void BufferParams::readPreamble(Lexer & lex)
1763 if (lex.getString() != "\\begin_preamble")
1764 lyxerr << "Error (BufferParams::readPreamble):"
1765 "consistency check failed." << endl;
1767 preamble = lex.getLongString("\\end_preamble");
1771 void BufferParams::readLocalLayout(Lexer & lex)
1773 if (lex.getString() != "\\begin_local_layout")
1774 lyxerr << "Error (BufferParams::readLocalLayout):"
1775 "consistency check failed." << endl;
1777 local_layout = lex.getLongString("\\end_local_layout");
1781 void BufferParams::readLanguage(Lexer & lex)
1783 if (!lex.next()) return;
1785 string const tmptok = lex.getString();
1787 // check if tmptok is part of tex_babel in tex-defs.h
1788 language = languages.getLanguage(tmptok);
1790 // Language tmptok was not found
1791 language = default_language;
1792 lyxerr << "Warning: Setting language `"
1793 << tmptok << "' to `" << language->lang()
1799 void BufferParams::readGraphicsDriver(Lexer & lex)
1804 string const tmptok = lex.getString();
1805 // check if tmptok is part of tex_graphics in tex_defs.h
1808 string const test = tex_graphics[n++];
1810 if (test == tmptok) {
1811 graphicsDriver = tmptok;
1816 "Warning: graphics driver `$$Token' not recognized!\n"
1817 " Setting graphics driver to `default'.\n");
1818 graphicsDriver = "default";
1825 void BufferParams::readBullets(Lexer & lex)
1830 int const index = lex.getInteger();
1832 int temp_int = lex.getInteger();
1833 user_defined_bullet(index).setFont(temp_int);
1834 temp_bullet(index).setFont(temp_int);
1836 user_defined_bullet(index).setCharacter(temp_int);
1837 temp_bullet(index).setCharacter(temp_int);
1839 user_defined_bullet(index).setSize(temp_int);
1840 temp_bullet(index).setSize(temp_int);
1844 void BufferParams::readBulletsLaTeX(Lexer & lex)
1846 // The bullet class should be able to read this.
1849 int const index = lex.getInteger();
1851 docstring const temp_str = lex.getDocString();
1853 user_defined_bullet(index).setText(temp_str);
1854 temp_bullet(index).setText(temp_str);
1858 void BufferParams::readModules(Lexer & lex)
1860 if (!lex.eatLine()) {
1861 lyxerr << "Error (BufferParams::readModules):"
1862 "Unexpected end of input." << endl;
1866 string mod = lex.getString();
1867 if (mod == "\\end_modules")
1869 addLayoutModule(mod);
1875 void BufferParams::readRemovedModules(Lexer & lex)
1877 if (!lex.eatLine()) {
1878 lyxerr << "Error (BufferParams::readRemovedModules):"
1879 "Unexpected end of input." << endl;
1883 string mod = lex.getString();
1884 if (mod == "\\end_removed_modules")
1886 removedModules_.push_back(mod);
1889 // now we want to remove any removed modules that were previously
1890 // added. normally, that will be because default modules were added in
1891 // setBaseClass(), which gets called when \textclass is read at the
1892 // start of the read.
1893 list<string>::const_iterator rit = removedModules_.begin();
1894 list<string>::const_iterator const ren = removedModules_.end();
1895 for (; rit != ren; rit++) {
1896 LayoutModuleList::iterator const mit = layoutModules_.begin();
1897 LayoutModuleList::iterator const men = layoutModules_.end();
1898 LayoutModuleList::iterator found = find(mit, men, *rit);
1901 layoutModules_.erase(found);
1906 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1908 char real_papersize = papersize;
1909 if (real_papersize == PAPER_DEFAULT)
1910 real_papersize = lyxrc.default_papersize;
1912 switch (real_papersize) {
1914 // could be anything, so don't guess
1916 case PAPER_CUSTOM: {
1917 if (purpose == XDVI && !paperwidth.empty() &&
1918 !paperheight.empty()) {
1919 // heightxwidth<unit>
1920 string first = paperwidth;
1921 string second = paperheight;
1922 if (orientation == ORIENTATION_LANDSCAPE)
1925 return first.erase(first.length() - 2)
1937 // dvips and dvipdfm do not know this
1938 if (purpose == DVIPS || purpose == DVIPDFM)
1942 // dvipdfm does not know this
1943 if (purpose == DVIPDFM)
1947 // dvipdfm does not know this
1948 if (purpose == DVIPDFM)
1951 case PAPER_USEXECUTIVE:
1952 // dvipdfm does not know this
1953 if (purpose == DVIPDFM)
1958 case PAPER_USLETTER:
1960 if (purpose == XDVI)
1967 string const BufferParams::dvips_options() const
1972 && papersize == PAPER_CUSTOM
1973 && !lyxrc.print_paper_dimension_flag.empty()
1974 && !paperwidth.empty()
1975 && !paperheight.empty()) {
1976 // using a custom papersize
1977 result = lyxrc.print_paper_dimension_flag;
1978 result += ' ' + paperwidth;
1979 result += ',' + paperheight;
1981 string const paper_option = paperSizeName(DVIPS);
1982 if (!paper_option.empty() && (paper_option != "letter" ||
1983 orientation != ORIENTATION_LANDSCAPE)) {
1984 // dvips won't accept -t letter -t landscape.
1985 // In all other cases, include the paper size
1987 result = lyxrc.print_paper_flag;
1988 result += ' ' + paper_option;
1991 if (orientation == ORIENTATION_LANDSCAPE &&
1992 papersize != PAPER_CUSTOM)
1993 result += ' ' + lyxrc.print_landscape_flag;
1998 string const BufferParams::font_encoding() const
2000 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2004 string BufferParams::babelCall(string const & lang_opts) const
2006 string lang_pack = lyxrc.language_package;
2007 if (lang_pack != "\\usepackage{babel}")
2009 // suppress the babel call when there is no babel language defined
2010 // for the document language in the lib/languages file and if no
2011 // other languages are used (lang_opts is then empty)
2012 if (lang_opts.empty())
2014 // If Vietnamese is used, babel must directly be loaded with the
2015 // language options, see
2016 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2017 size_t viet = lang_opts.find("vietnam");
2018 // viet = string::npos when not found
2019 // the same is for all other languages that are not directly supported by
2020 // babel, but where LaTeX-packages add babel support.
2021 // this is currently the case for Latvian, Lithuanian, and Mongolian
2022 size_t latvian = lang_opts.find("latvian");
2023 size_t lithu = lang_opts.find("lithuanian");
2024 size_t mongo = lang_opts.find("mongolian");
2025 // If Japanese is used, babel must directly be loaded with the
2026 // language options, see
2027 // http://www.lyx.org/trac/ticket/4597#c4
2028 size_t japan = lang_opts.find("japanese");
2029 if (!lyxrc.language_global_options || viet != string::npos
2030 || japan != string::npos || latvian != string::npos
2031 || lithu != string::npos || mongo != string::npos)
2032 return "\\usepackage[" + lang_opts + "]{babel}";
2037 docstring BufferParams::getGraphicsDriver(string const & package) const
2041 if (package == "geometry") {
2042 if (graphicsDriver == "dvips"
2043 || graphicsDriver == "dvipdfm"
2044 || graphicsDriver == "pdftex"
2045 || graphicsDriver == "vtex")
2046 result = from_ascii(graphicsDriver);
2047 else if (graphicsDriver == "dvipdfmx")
2048 result = from_ascii("dvipdfm");
2055 void BufferParams::writeEncodingPreamble(odocstream & os,
2056 LaTeXFeatures & features, TexRow & texrow) const
2060 if (inputenc == "auto") {
2061 string const doc_encoding =
2062 language->encoding()->latexName();
2063 Encoding::Package const package =
2064 language->encoding()->package();
2066 // Create a list with all the input encodings used
2068 set<string> encodings =
2069 features.getEncodingSet(doc_encoding);
2071 // If the "japanese" package (i.e. pLaTeX) is used,
2072 // inputenc must be omitted.
2073 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2074 if (package == Encoding::japanese)
2075 features.require("japanese");
2077 if ((!encodings.empty() || package == Encoding::inputenc)
2078 && !features.isRequired("japanese")) {
2079 os << "\\usepackage[";
2080 set<string>::const_iterator it = encodings.begin();
2081 set<string>::const_iterator const end = encodings.end();
2083 os << from_ascii(*it);
2086 for (; it != end; ++it)
2087 os << ',' << from_ascii(*it);
2088 if (package == Encoding::inputenc) {
2089 if (!encodings.empty())
2091 os << from_ascii(doc_encoding);
2093 os << "]{inputenc}\n";
2096 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2097 if (language->encoding()->name() == "utf8-cjk"
2098 && LaTeXFeatures::isAvailable("CJKutf8"))
2099 os << "\\usepackage{CJKutf8}\n";
2101 os << "\\usepackage{CJK}\n";
2104 } else if (inputenc != "default") {
2105 switch (encoding().package()) {
2106 case Encoding::none:
2107 case Encoding::japanese:
2109 case Encoding::inputenc:
2110 // do not load inputenc if japanese is used
2111 if (features.isRequired("japanese"))
2113 os << "\\usepackage[" << from_ascii(inputenc)
2118 if (encoding().name() == "utf8-cjk"
2119 && LaTeXFeatures::isAvailable("CJKutf8"))
2120 os << "\\usepackage{CJKutf8}\n";
2122 os << "\\usepackage{CJK}\n";
2128 // The encoding "armscii8" (for Armenian) is only available when
2129 // the package "armtex" is loaded.
2130 if (language->encoding()->latexName() == "armscii8"
2131 || inputenc == "armscii8") {
2132 os << "\\usepackage{armtex}\n";
2138 string const BufferParams::parseFontName(string const & name) const
2140 string mangled = name;
2141 size_t const idx = mangled.find('[');
2142 if (idx == string::npos || idx == 0)
2145 return mangled.substr(0, idx - 1);
2149 string const BufferParams::loadFonts(string const & rm,
2150 string const & sf, string const & tt,
2151 bool const & sc, bool const & osf,
2152 int const & sfscale, int const & ttscale,
2153 bool const & xetex) const
2155 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2156 several packages have been replaced by others, that might not
2157 be installed on every system. We have to take care for that
2158 (see psnfss.pdf). We try to support all psnfss fonts as well
2159 as the fonts that have become de facto standard in the LaTeX
2160 world (e.g. Latin Modern). We do not support obsolete fonts
2161 (like PSLatex). In general, it should be possible to mix any
2162 rm font with any sf or tt font, respectively. (JSpitzm)
2164 -- separate math fonts.
2167 if (rm == "default" && sf == "default" && tt == "default")
2174 if (rm != "default")
2175 os << "\\setmainfont[Mapping=tex-text]{"
2176 << parseFontName(rm) << "}\n";
2177 if (sf != "default") {
2178 string const sans = parseFontName(sf);
2180 os << "\\setsansfont[Scale="
2181 << float(sfscale) / 100
2182 << ",Mapping=tex-text]{"
2185 os << "\\setsansfont[Mapping=tex-text]{"
2188 if (tt != "default") {
2189 string const mono = parseFontName(tt);
2191 os << "\\setmonofont[Scale="
2192 << float(sfscale) / 100
2196 os << "\\setmonofont[Mapping=tex-text]{"
2200 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2205 // Computer Modern (must be explicitely selectable -- there might be classes
2206 // that define a different default font!
2208 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2209 // osf for Computer Modern needs eco.sty
2211 os << "\\usepackage{eco}\n";
2213 // Latin Modern Roman
2214 else if (rm == "lmodern")
2215 os << "\\usepackage{lmodern}\n";
2217 else if (rm == "ae") {
2218 // not needed when using OT1 font encoding.
2219 if (font_encoding() != "default")
2220 os << "\\usepackage{ae,aecompl}\n";
2223 else if (rm == "times") {
2224 // try to load the best available package
2225 if (LaTeXFeatures::isAvailable("mathptmx"))
2226 os << "\\usepackage{mathptmx}\n";
2227 else if (LaTeXFeatures::isAvailable("mathptm"))
2228 os << "\\usepackage{mathptm}\n";
2230 os << "\\usepackage{times}\n";
2233 else if (rm == "palatino") {
2234 // try to load the best available package
2235 if (LaTeXFeatures::isAvailable("mathpazo")) {
2236 os << "\\usepackage";
2242 // "osf" includes "sc"!
2246 os << "{mathpazo}\n";
2248 else if (LaTeXFeatures::isAvailable("mathpple"))
2249 os << "\\usepackage{mathpple}\n";
2251 os << "\\usepackage{palatino}\n";
2254 else if (rm == "utopia") {
2255 // fourier supersedes utopia.sty, but does
2256 // not work with OT1 encoding.
2257 if (LaTeXFeatures::isAvailable("fourier")
2258 && font_encoding() != "default") {
2259 os << "\\usepackage";
2270 os << "{fourier}\n";
2273 os << "\\usepackage{utopia}\n";
2275 // Bera (complete fontset)
2276 else if (rm == "bera" && sf == "default" && tt == "default")
2277 os << "\\usepackage{bera}\n";
2279 else if (rm != "default")
2280 os << "\\usepackage" << "{" << rm << "}\n";
2283 // Helvetica, Bera Sans
2284 if (sf == "helvet" || sf == "berasans") {
2286 os << "\\usepackage[scaled=" << float(sfscale) / 100
2287 << "]{" << sf << "}\n";
2289 os << "\\usepackage{" << sf << "}\n";
2292 else if (sf == "avant")
2293 os << "\\usepackage{" << sf << "}\n";
2294 // Computer Modern, Latin Modern, CM Bright
2295 else if (sf != "default")
2296 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2298 // monospaced/typewriter
2299 // Courier, LuxiMono
2300 if (tt == "luximono" || tt == "beramono") {
2302 os << "\\usepackage[scaled=" << float(ttscale) / 100
2303 << "]{" << tt << "}\n";
2305 os << "\\usepackage{" << tt << "}\n";
2308 else if (tt == "courier" )
2309 os << "\\usepackage{" << tt << "}\n";
2310 // Computer Modern, Latin Modern, CM Bright
2311 else if (tt != "default")
2312 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2318 Encoding const & BufferParams::encoding() const
2321 return *(encodings.fromLaTeXName("utf8-plain"));
2322 if (inputenc == "auto" || inputenc == "default")
2323 return *language->encoding();
2324 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2327 LYXERR0("Unknown inputenc value `" << inputenc
2328 << "'. Using `auto' instead.");
2329 return *language->encoding();
2333 CiteEngine BufferParams::citeEngine() const
2335 // FIXME the class should provide the numerical/
2336 // authoryear choice
2337 if (documentClass().provides("natbib")
2338 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2339 return ENGINE_NATBIB_AUTHORYEAR;
2340 return cite_engine_;
2344 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2346 cite_engine_ = cite_engine;