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;
346 maintain_unincluded_children = false;
349 language = default_language;
351 fontsRoman = "default";
352 fontsSans = "default";
353 fontsTypewriter = "default";
354 fontsDefaultFamily = "default";
358 fontsSansScale = 100;
359 fontsTypewriterScale = 100;
361 graphicsDriver = "default";
362 defaultOutputFormat = "default";
363 bibtex_command = "default";
364 index_command = "default";
367 listings_params = string();
368 pagestyle = "default";
369 suppress_date = false;
370 // no color is the default (white)
371 backgroundcolor = lyx::rgbFromHexName("#ffffff");
372 isbackgroundcolor = false;
373 // no color is the default (black)
374 fontcolor = lyx::rgbFromHexName("#000000");
376 // light gray is the default font color for greyed-out notes
377 notefontcolor = lyx::rgbFromHexName("#cccccc");
378 boxbgcolor = lyx::rgbFromHexName("#ff0000");
379 compressed = lyxrc.save_compressed;
380 for (int iter = 0; iter < 4; ++iter) {
381 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
382 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
385 indiceslist().addDefault(B_("Index"));
386 html_be_strict = false;
387 html_math_output = MathML;
388 html_math_img_scale = 1.0;
389 html_latex_start = "<span class='latex'>";
390 html_latex_end = "</span>";
394 docstring BufferParams::B_(string const & l10n) const
396 LASSERT(language, /**/);
397 return getMessages(language->code()).get(l10n);
401 AuthorList & BufferParams::authors()
403 return pimpl_->authorlist;
407 AuthorList const & BufferParams::authors() const
409 return pimpl_->authorlist;
413 BranchList & BufferParams::branchlist()
415 return pimpl_->branchlist;
419 BranchList const & BufferParams::branchlist() const
421 return pimpl_->branchlist;
425 IndicesList & BufferParams::indiceslist()
427 return pimpl_->indiceslist;
431 IndicesList const & BufferParams::indiceslist() const
433 return pimpl_->indiceslist;
437 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
439 LASSERT(index < 4, /**/);
440 return pimpl_->temp_bullets[index];
444 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
446 LASSERT(index < 4, /**/);
447 return pimpl_->temp_bullets[index];
451 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
453 LASSERT(index < 4, /**/);
454 return pimpl_->user_defined_bullets[index];
458 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
460 LASSERT(index < 4, /**/);
461 return pimpl_->user_defined_bullets[index];
465 Spacing & BufferParams::spacing()
467 return pimpl_->spacing;
471 Spacing const & BufferParams::spacing() const
473 return pimpl_->spacing;
477 PDFOptions & BufferParams::pdfoptions()
479 return pimpl_->pdfoptions;
483 PDFOptions const & BufferParams::pdfoptions() const
485 return pimpl_->pdfoptions;
489 HSpace const & BufferParams::getIndentation() const
491 return pimpl_->indentation;
495 void BufferParams::setIndentation(HSpace const & indent)
497 pimpl_->indentation = indent;
501 VSpace const & BufferParams::getDefSkip() const
503 return pimpl_->defskip;
507 void BufferParams::setDefSkip(VSpace const & vs)
509 pimpl_->defskip = vs;
513 string BufferParams::readToken(Lexer & lex, string const & token,
514 FileName const & filepath)
516 if (token == "\\textclass") {
518 string const classname = lex.getString();
519 // if there exists a local layout file, ignore the system one
520 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
522 LayoutFileList & bcl = LayoutFileList::get();
523 if (tcp.empty() && !filepath.empty())
524 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
528 setBaseClass(classname);
529 // We assume that a tex class exists for local or unknown layouts so this warning
530 // will only be given for system layouts.
531 if (!baseClass()->isTeXClassAvailable()) {
533 translateIfPossible(from_utf8(baseClass()->description()));
534 docstring const msg =
535 bformat(_("The document class requested\n"
537 "requires external files that are not available.\n"
538 "The document class can still be used, but LyX\n"
539 "will not be able to produce output until the\n"
540 "following prerequisites are installed:\n"
542 "See section 3.1.2.2 of the User's Guide for\n"
543 "more information."),
544 desc, from_utf8(baseClass()->prerequisites()));
545 frontend::Alert::warning(_("Document class not available"),
548 } else if (token == "\\begin_preamble") {
550 } else if (token == "\\begin_local_layout") {
551 readLocalLayout(lex);
552 } else if (token == "\\begin_modules") {
554 } else if (token == "\\begin_removed_modules") {
555 readRemovedModules(lex);
556 } else if (token == "\\begin_includeonly") {
557 readIncludeonly(lex);
558 } else if (token == "\\maintain_unincluded_children") {
559 lex >> maintain_unincluded_children;
560 } else if (token == "\\options") {
562 options = lex.getString();
563 } else if (token == "\\use_default_options") {
564 lex >> use_default_options;
565 } else if (token == "\\master") {
567 master = lex.getString();
568 } else if (token == "\\suppress_date") {
569 lex >> suppress_date;
570 } else if (token == "\\language") {
572 } else if (token == "\\inputencoding") {
574 } else if (token == "\\graphics") {
575 readGraphicsDriver(lex);
576 } else if (token == "\\default_output_format") {
577 lex >> defaultOutputFormat;
578 } else if (token == "\\bibtex_command") {
580 bibtex_command = lex.getString();
581 } else if (token == "\\index_command") {
583 index_command = lex.getString();
584 } else if (token == "\\fontencoding") {
586 fontenc = lex.getString();
587 } else if (token == "\\font_roman") {
589 fontsRoman = lex.getString();
590 } else if (token == "\\font_sans") {
592 fontsSans = lex.getString();
593 } else if (token == "\\font_typewriter") {
595 fontsTypewriter = lex.getString();
596 } else if (token == "\\font_default_family") {
597 lex >> fontsDefaultFamily;
598 } else if (token == "\\use_xetex") {
600 } else if (token == "\\font_sc") {
602 } else if (token == "\\font_osf") {
604 } else if (token == "\\font_sf_scale") {
605 lex >> fontsSansScale;
606 } else if (token == "\\font_tt_scale") {
607 lex >> fontsTypewriterScale;
608 } else if (token == "\\font_cjk") {
610 } else if (token == "\\paragraph_separation") {
613 paragraph_separation = parseptranslator().find(parsep);
614 } else if (token == "\\paragraph_indentation") {
616 string indentation = lex.getString();
617 pimpl_->indentation = HSpace(indentation);
618 } else if (token == "\\defskip") {
620 string defskip = lex.getString();
621 if (defskip == "defskip")
624 pimpl_->defskip = VSpace(defskip);
625 } else if (token == "\\quotes_language") {
628 quotes_language = quoteslangtranslator().find(quotes_lang);
629 } else if (token == "\\papersize") {
632 papersize = papersizetranslator().find(ppsize);
633 } else if (token == "\\use_geometry") {
635 } else if (token == "\\use_amsmath") {
638 use_amsmath = packagetranslator().find(use_ams);
639 } else if (token == "\\use_esint") {
642 use_esint = packagetranslator().find(useesint);
643 } else if (token == "\\use_mhchem") {
646 use_mhchem = packagetranslator().find(usemhchem);
647 } else if (token == "\\cite_engine") {
650 cite_engine_ = citeenginetranslator().find(engine);
651 } else if (token == "\\use_bibtopic") {
653 } else if (token == "\\use_indices") {
655 } else if (token == "\\tracking_changes") {
657 } else if (token == "\\output_changes") {
658 lex >> outputChanges;
659 } else if (token == "\\branch") {
661 docstring branch = lex.getDocString();
662 branchlist().add(branch);
665 string const tok = lex.getString();
666 if (tok == "\\end_branch")
668 Branch * branch_ptr = branchlist().find(branch);
669 if (tok == "\\selected") {
672 branch_ptr->setSelected(lex.getInteger());
674 if (tok == "\\filename_suffix") {
677 branch_ptr->setFileNameSuffix(lex.getInteger());
679 if (tok == "\\color") {
681 string color = lex.getString();
683 branch_ptr->setColor(color);
684 // Update also the Color table:
686 color = lcolor.getX11Name(Color_background);
688 lcolor.setColor(to_utf8(branch), color);
691 } else if (token == "\\index") {
693 docstring index = lex.getDocString();
695 indiceslist().add(index);
698 string const tok = lex.getString();
699 if (tok == "\\end_index")
701 Index * index_ptr = indiceslist().find(index);
702 if (tok == "\\shortcut") {
704 shortcut = lex.getDocString();
706 index_ptr->setShortcut(shortcut);
708 if (tok == "\\color") {
710 string color = lex.getString();
712 index_ptr->setColor(color);
713 // Update also the Color table:
715 color = lcolor.getX11Name(Color_background);
717 if (!shortcut.empty())
718 lcolor.setColor(to_utf8(shortcut), color);
721 } else if (token == "\\author") {
723 istringstream ss(lex.getString());
726 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
727 } else if (token == "\\paperorientation") {
730 orientation = paperorientationtranslator().find(orient);
731 } else if (token == "\\backgroundcolor") {
733 backgroundcolor = lyx::rgbFromHexName(lex.getString());
734 isbackgroundcolor = true;
735 } else if (token == "\\fontcolor") {
737 fontcolor = lyx::rgbFromHexName(lex.getString());
739 } else if (token == "\\notefontcolor") {
741 string color = lex.getString();
742 notefontcolor = lyx::rgbFromHexName(color);
743 } else if (token == "\\boxbgcolor") {
745 string color = lex.getString();
746 boxbgcolor = lyx::rgbFromHexName(color);
747 } else if (token == "\\paperwidth") {
749 } else if (token == "\\paperheight") {
751 } else if (token == "\\leftmargin") {
753 } else if (token == "\\topmargin") {
755 } else if (token == "\\rightmargin") {
757 } else if (token == "\\bottommargin") {
759 } else if (token == "\\headheight") {
761 } else if (token == "\\headsep") {
763 } else if (token == "\\footskip") {
765 } else if (token == "\\columnsep") {
767 } else if (token == "\\paperfontsize") {
769 } else if (token == "\\papercolumns") {
771 } else if (token == "\\listings_params") {
774 listings_params = InsetListingsParams(par).params();
775 } else if (token == "\\papersides") {
778 sides = sidestranslator().find(psides);
779 } else if (token == "\\paperpagestyle") {
781 } else if (token == "\\bullet") {
783 } else if (token == "\\bulletLaTeX") {
784 readBulletsLaTeX(lex);
785 } else if (token == "\\secnumdepth") {
787 } else if (token == "\\tocdepth") {
789 } else if (token == "\\spacing") {
793 if (nspacing == "other") {
796 spacing().set(spacetranslator().find(nspacing), tmp_val);
797 } else if (token == "\\float_placement") {
798 lex >> float_placement;
800 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
801 string toktmp = pdfoptions().readToken(lex, token);
802 if (!toktmp.empty()) {
803 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
807 } else if (token == "\\html_math_output") {
810 html_math_output = static_cast<MathOutput>(temp);
811 } else if (token == "\\html_be_strict") {
812 lex >> html_be_strict;
813 } else if (token == "\\html_math_img_scale") {
814 lex >> html_math_img_scale;
815 } else if (token == "\\html_latex_start") {
816 lex >> html_latex_start;
817 } else if (token == "\\html_latex_end") {
818 lex >> html_latex_end;
820 lyxerr << "BufferParams::readToken(): Unknown token: " <<
829 void BufferParams::writeFile(ostream & os) const
831 // The top of the file is written by the buffer.
832 // Prints out the buffer info into the .lyx file given by file
835 os << "\\textclass " << baseClass()->name() << '\n';
838 if (!preamble.empty()) {
839 // remove '\n' from the end of preamble
840 string const tmppreamble = rtrim(preamble, "\n");
841 os << "\\begin_preamble\n"
843 << "\n\\end_preamble\n";
847 if (!options.empty()) {
848 os << "\\options " << options << '\n';
851 // use the class options defined in the layout?
852 os << "\\use_default_options "
853 << convert<string>(use_default_options) << "\n";
855 // the master document
856 if (!master.empty()) {
857 os << "\\master " << master << '\n';
861 if (!removedModules_.empty()) {
862 os << "\\begin_removed_modules" << '\n';
863 list<string>::const_iterator it = removedModules_.begin();
864 list<string>::const_iterator en = removedModules_.end();
865 for (; it != en; it++)
867 os << "\\end_removed_modules" << '\n';
871 if (!layoutModules_.empty()) {
872 os << "\\begin_modules" << '\n';
873 LayoutModuleList::const_iterator it = layoutModules_.begin();
874 LayoutModuleList::const_iterator en = layoutModules_.end();
875 for (; it != en; it++)
877 os << "\\end_modules" << '\n';
881 if (!includedChildren_.empty()) {
882 os << "\\begin_includeonly" << '\n';
883 list<string>::const_iterator it = includedChildren_.begin();
884 list<string>::const_iterator en = includedChildren_.end();
885 for (; it != en; it++)
887 os << "\\end_includeonly" << '\n';
889 os << "\\maintain_unincluded_children "
890 << convert<string>(maintain_unincluded_children) << '\n';
892 // local layout information
893 if (!local_layout.empty()) {
894 // remove '\n' from the end
895 string const tmplocal = rtrim(local_layout, "\n");
896 os << "\\begin_local_layout\n"
898 << "\n\\end_local_layout\n";
901 // then the text parameters
902 if (language != ignore_language)
903 os << "\\language " << language->lang() << '\n';
904 os << "\\inputencoding " << inputenc
905 << "\n\\fontencoding " << fontenc
906 << "\n\\font_roman " << fontsRoman
907 << "\n\\font_sans " << fontsSans
908 << "\n\\font_typewriter " << fontsTypewriter
909 << "\n\\font_default_family " << fontsDefaultFamily
910 << "\n\\use_xetex " << convert<string>(useXetex)
911 << "\n\\font_sc " << convert<string>(fontsSC)
912 << "\n\\font_osf " << convert<string>(fontsOSF)
913 << "\n\\font_sf_scale " << fontsSansScale
914 << "\n\\font_tt_scale " << fontsTypewriterScale
916 if (!fontsCJK.empty()) {
917 os << "\\font_cjk " << fontsCJK << '\n';
919 os << "\n\\graphics " << graphicsDriver << '\n';
920 os << "\\default_output_format " << defaultOutputFormat << '\n';
921 os << "\\bibtex_command " << bibtex_command << '\n';
922 os << "\\index_command " << index_command << '\n';
924 if (!float_placement.empty()) {
925 os << "\\float_placement " << float_placement << '\n';
927 os << "\\paperfontsize " << fontsize << '\n';
929 spacing().writeFile(os);
930 pdfoptions().writeFile(os);
932 os << "\\papersize " << string_papersize[papersize]
933 << "\n\\use_geometry " << convert<string>(use_geometry)
934 << "\n\\use_amsmath " << use_amsmath
935 << "\n\\use_esint " << use_esint
936 << "\n\\use_mhchem " << use_mhchem
937 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
938 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
939 << "\n\\use_indices " << convert<string>(use_indices)
940 << "\n\\paperorientation " << string_orientation[orientation]
941 << "\n\\suppress_date " << convert<string>(suppress_date)
943 if (isbackgroundcolor == true)
944 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
945 if (isfontcolor == true)
946 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
947 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
948 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
949 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
950 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
952 BranchList::const_iterator it = branchlist().begin();
953 BranchList::const_iterator end = branchlist().end();
954 for (; it != end; ++it) {
955 os << "\\branch " << to_utf8(it->branch())
956 << "\n\\selected " << it->isSelected()
957 << "\n\\filename_suffix " << it->hasFileNameSuffix()
958 << "\n\\color " << lyx::X11hexname(it->color())
963 IndicesList::const_iterator iit = indiceslist().begin();
964 IndicesList::const_iterator iend = indiceslist().end();
965 for (; iit != iend; ++iit) {
966 os << "\\index " << to_utf8(iit->index())
967 << "\n\\shortcut " << to_utf8(iit->shortcut())
968 << "\n\\color " << lyx::X11hexname(iit->color())
973 if (!paperwidth.empty())
974 os << "\\paperwidth "
975 << VSpace(paperwidth).asLyXCommand() << '\n';
976 if (!paperheight.empty())
977 os << "\\paperheight "
978 << VSpace(paperheight).asLyXCommand() << '\n';
979 if (!leftmargin.empty())
980 os << "\\leftmargin "
981 << VSpace(leftmargin).asLyXCommand() << '\n';
982 if (!topmargin.empty())
984 << VSpace(topmargin).asLyXCommand() << '\n';
985 if (!rightmargin.empty())
986 os << "\\rightmargin "
987 << VSpace(rightmargin).asLyXCommand() << '\n';
988 if (!bottommargin.empty())
989 os << "\\bottommargin "
990 << VSpace(bottommargin).asLyXCommand() << '\n';
991 if (!headheight.empty())
992 os << "\\headheight "
993 << VSpace(headheight).asLyXCommand() << '\n';
994 if (!headsep.empty())
996 << VSpace(headsep).asLyXCommand() << '\n';
997 if (!footskip.empty())
999 << VSpace(footskip).asLyXCommand() << '\n';
1000 if (!columnsep.empty())
1001 os << "\\columnsep "
1002 << VSpace(columnsep).asLyXCommand() << '\n';
1003 os << "\\secnumdepth " << secnumdepth
1004 << "\n\\tocdepth " << tocdepth
1005 << "\n\\paragraph_separation "
1006 << string_paragraph_separation[paragraph_separation];
1007 if (!paragraph_separation)
1008 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1010 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1011 os << "\n\\quotes_language "
1012 << string_quotes_language[quotes_language]
1013 << "\n\\papercolumns " << columns
1014 << "\n\\papersides " << sides
1015 << "\n\\paperpagestyle " << pagestyle << '\n';
1016 if (!listings_params.empty())
1017 os << "\\listings_params \"" <<
1018 InsetListingsParams(listings_params).encodedString() << "\"\n";
1019 for (int i = 0; i < 4; ++i) {
1020 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1021 if (user_defined_bullet(i).getFont() != -1) {
1022 os << "\\bullet " << i << " "
1023 << user_defined_bullet(i).getFont() << " "
1024 << user_defined_bullet(i).getCharacter() << " "
1025 << user_defined_bullet(i).getSize() << "\n";
1029 os << "\\bulletLaTeX " << i << " \""
1030 << lyx::to_ascii(user_defined_bullet(i).getText())
1036 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1037 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1038 << "\\html_math_output " << html_math_output << '\n'
1039 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n'
1040 << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n'
1041 << "\\html_latex_start \"" << html_latex_start << "\"\n"
1042 << "\\html_latex_end \"" << html_latex_end << "\"\n";
1044 os << pimpl_->authorlist;
1048 void BufferParams::validate(LaTeXFeatures & features) const
1050 features.require(documentClass().requires());
1052 if (outputChanges) {
1053 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1054 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1055 LaTeXFeatures::isAvailable("xcolor");
1057 switch (features.runparams().flavor) {
1058 case OutputParams::LATEX:
1060 features.require("ct-dvipost");
1061 features.require("dvipost");
1062 } else if (xcolorulem) {
1063 features.require("ct-xcolor-ulem");
1064 features.require("ulem");
1065 features.require("xcolor");
1067 features.require("ct-none");
1070 case OutputParams::PDFLATEX:
1071 case OutputParams::XETEX:
1073 features.require("ct-xcolor-ulem");
1074 features.require("ulem");
1075 features.require("xcolor");
1076 // improves color handling in PDF output
1077 features.require("pdfcolmk");
1079 features.require("ct-none");
1087 // Floats with 'Here definitely' as default setting.
1088 if (float_placement.find('H') != string::npos)
1089 features.require("float");
1091 // AMS Style is at document level
1092 if (use_amsmath == package_on
1093 || documentClass().provides("amsmath"))
1094 features.require("amsmath");
1095 if (use_esint == package_on)
1096 features.require("esint");
1097 if (use_mhchem == package_on)
1098 features.require("mhchem");
1100 // Document-level line spacing
1101 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1102 features.require("setspace");
1104 // the bullet shapes are buffer level not paragraph level
1105 // so they are tested here
1106 for (int i = 0; i < 4; ++i) {
1107 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1109 int const font = user_defined_bullet(i).getFont();
1111 int const c = user_defined_bullet(i).getCharacter();
1117 features.require("latexsym");
1119 } else if (font == 1) {
1120 features.require("amssymb");
1121 } else if (font >= 2 && font <= 5) {
1122 features.require("pifont");
1126 if (pdfoptions().use_hyperref) {
1127 features.require("hyperref");
1128 // due to interferences with babel and hyperref, the color package has to
1129 // be loaded after hyperref when hyperref is used with the colorlinks
1130 // option, see http://www.lyx.org/trac/ticket/5291
1131 if (pdfoptions().colorlinks)
1132 features.require("color");
1136 features.require("xetex");
1138 if (language->lang() == "vietnamese")
1139 features.require("vietnamese");
1140 else if (language->lang() == "japanese")
1141 features.require("japanese");
1145 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1146 TexRow & texrow, FileName const & filepath) const
1148 os << "\\documentclass";
1150 DocumentClass const & tclass = documentClass();
1152 ostringstream clsoptions; // the document class options.
1154 if (tokenPos(tclass.opt_fontsize(),
1155 '|', fontsize) >= 0) {
1156 // only write if existing in list (and not default)
1157 clsoptions << fontsize << "pt,";
1160 // custom, A3, B3 and B4 paper sizes need geometry
1161 bool nonstandard_papersize = papersize == PAPER_B3
1162 || papersize == PAPER_B4
1163 || papersize == PAPER_A3
1164 || papersize == PAPER_CUSTOM;
1166 if (!use_geometry) {
1167 switch (papersize) {
1169 clsoptions << "a4paper,";
1171 case PAPER_USLETTER:
1172 clsoptions << "letterpaper,";
1175 clsoptions << "a5paper,";
1178 clsoptions << "b5paper,";
1180 case PAPER_USEXECUTIVE:
1181 clsoptions << "executivepaper,";
1184 clsoptions << "legalpaper,";
1196 if (sides != tclass.sides()) {
1199 clsoptions << "oneside,";
1202 clsoptions << "twoside,";
1208 if (columns != tclass.columns()) {
1210 clsoptions << "twocolumn,";
1212 clsoptions << "onecolumn,";
1216 && orientation == ORIENTATION_LANDSCAPE)
1217 clsoptions << "landscape,";
1219 // language should be a parameter to \documentclass
1220 if (language->babel() == "hebrew"
1221 && default_language->babel() != "hebrew")
1222 // This seems necessary
1223 features.useLanguage(default_language);
1225 ostringstream language_options;
1226 bool const use_babel = features.useBabel();
1228 language_options << features.getLanguages();
1229 if (!language->babel().empty()) {
1230 if (!language_options.str().empty())
1231 language_options << ',';
1232 language_options << language->babel();
1234 // if Vietnamese is used, babel must directly be loaded
1235 // with language options, not in the class options, see
1236 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1237 size_t viet = language_options.str().find("vietnam");
1238 // viet = string::npos when not found
1239 // the same is for all other languages that are not directly supported by
1240 // babel, but where LaTeX-packages add babel support.
1241 // this is currently the case for Latvian, Lithuanian, Mongolian
1243 size_t latvian = language_options.str().find("latvian");
1244 size_t lithu = language_options.str().find("lithuanian");
1245 size_t mongo = language_options.str().find("mongolian");
1246 size_t turkmen = language_options.str().find("turkmen");
1247 // if Japanese is used, babel must directly be loaded
1248 // with language options, not in the class options, see
1249 // http://www.lyx.org/trac/ticket/4597#c4
1250 size_t japan = language_options.str().find("japanese");
1251 if (lyxrc.language_global_options && !language_options.str().empty()
1252 && viet == string::npos && japan == string::npos
1253 && latvian == string::npos && lithu == string::npos
1254 && mongo == string::npos && turkmen == string::npos)
1255 clsoptions << language_options.str() << ',';
1258 // the predefined options from the layout
1259 if (use_default_options && !tclass.options().empty())
1260 clsoptions << tclass.options() << ',';
1262 // the user-defined options
1263 if (!options.empty()) {
1264 clsoptions << options << ',';
1267 string strOptions(clsoptions.str());
1268 if (!strOptions.empty()) {
1269 strOptions = rtrim(strOptions, ",");
1271 os << '[' << from_utf8(strOptions) << ']';
1274 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1276 // end of \documentclass defs
1279 os << "\\usepackage{fontspec}\n";
1283 // font selection must be done before loading fontenc.sty
1284 string const fonts =
1285 loadFonts(fontsRoman, fontsSans,
1286 fontsTypewriter, fontsSC, fontsOSF,
1287 fontsSansScale, fontsTypewriterScale, useXetex);
1288 if (!fonts.empty()) {
1289 os << from_ascii(fonts);
1292 if (fontsDefaultFamily != "default")
1293 os << "\\renewcommand{\\familydefault}{\\"
1294 << from_ascii(fontsDefaultFamily) << "}\n";
1296 // set font encoding
1297 // for arabic_arabi and farsi we also need to load the LAE and
1299 // XeTeX works without fontenc
1300 if (font_encoding() != "default" && language->lang() != "japanese"
1302 if (language->lang() == "arabic_arabi"
1303 || language->lang() == "farsi") {
1304 os << "\\usepackage[" << from_ascii(font_encoding())
1305 << ",LFE,LAE]{fontenc}\n";
1308 os << "\\usepackage[" << from_ascii(font_encoding())
1314 // handle inputenc etc.
1315 writeEncodingPreamble(os, features, texrow);
1318 if (!features.runparams().includeall && !includedChildren_.empty()) {
1319 os << "\\includeonly{";
1320 list<string>::const_iterator it = includedChildren_.begin();
1322 for (; it != includedChildren_.end() ; ++it) {
1323 string incfile = *it;
1324 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1325 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1327 if (!features.runparams().nice)
1329 // \includeonly doesn't want an extension
1330 incfile = changeExtension(incfile, string());
1331 incfile = support::latex_path(incfile);
1332 if (!incfile.empty()) {
1335 os << from_utf8(incfile);
1342 if (!listings_params.empty() || features.isRequired("listings")) {
1343 os << "\\usepackage{listings}\n";
1346 if (!listings_params.empty()) {
1348 // do not test validity because listings_params is
1349 // supposed to be valid
1351 InsetListingsParams(listings_params).separatedParams(true);
1352 // we can't support all packages, but we should load the color package
1353 if (par.find("\\color", 0) != string::npos)
1354 features.require("color");
1355 os << from_utf8(par);
1356 // count the number of newlines
1357 for (size_t i = 0; i < par.size(); ++i)
1363 if (!tclass.provides("geometry")
1364 && (use_geometry || nonstandard_papersize)) {
1365 odocstringstream ods;
1366 if (!getGraphicsDriver("geometry").empty())
1367 ods << getGraphicsDriver("geometry");
1368 if (orientation == ORIENTATION_LANDSCAPE)
1369 ods << ",landscape";
1370 switch (papersize) {
1372 if (!paperwidth.empty())
1373 ods << ",paperwidth="
1374 << from_ascii(paperwidth);
1375 if (!paperheight.empty())
1376 ods << ",paperheight="
1377 << from_ascii(paperheight);
1379 case PAPER_USLETTER:
1380 ods << ",letterpaper";
1383 ods << ",legalpaper";
1385 case PAPER_USEXECUTIVE:
1386 ods << ",executivepaper";
1407 // default papersize ie PAPER_DEFAULT
1408 switch (lyxrc.default_papersize) {
1409 case PAPER_DEFAULT: // keep compiler happy
1410 case PAPER_USLETTER:
1411 ods << ",letterpaper";
1414 ods << ",legalpaper";
1416 case PAPER_USEXECUTIVE:
1417 ods << ",executivepaper";
1437 docstring const g_options = trim(ods.str(), ",");
1438 os << "\\usepackage";
1439 if (!g_options.empty())
1440 os << '[' << g_options << ']';
1441 os << "{geometry}\n";
1443 os << "\\geometry{verbose";
1444 if (!topmargin.empty())
1445 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1446 if (!bottommargin.empty())
1447 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1448 if (!leftmargin.empty())
1449 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1450 if (!rightmargin.empty())
1451 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1452 if (!headheight.empty())
1453 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1454 if (!headsep.empty())
1455 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1456 if (!footskip.empty())
1457 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1458 if (!columnsep.empty())
1459 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1462 } else if (orientation == ORIENTATION_LANDSCAPE) {
1463 features.require("papersize");
1466 if (tokenPos(tclass.opt_pagestyle(),
1467 '|', pagestyle) >= 0) {
1468 if (pagestyle == "fancy") {
1469 os << "\\usepackage{fancyhdr}\n";
1472 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1476 // only output when the background color is not default
1477 if (isbackgroundcolor == true) {
1478 // only require color here, the background color will be defined
1479 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1481 features.require("color");
1482 features.require("pagecolor");
1485 // only output when the font color is not default
1486 if (isfontcolor == true) {
1487 // only require color here, the font color will be defined
1488 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1490 features.require("color");
1491 features.require("fontcolor");
1494 // Only if class has a ToC hierarchy
1495 if (tclass.hasTocLevels()) {
1496 if (secnumdepth != tclass.secnumdepth()) {
1497 os << "\\setcounter{secnumdepth}{"
1502 if (tocdepth != tclass.tocdepth()) {
1503 os << "\\setcounter{tocdepth}{"
1510 if (paragraph_separation) {
1511 // when skip separation
1512 switch (getDefSkip().kind()) {
1513 case VSpace::SMALLSKIP:
1514 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1516 case VSpace::MEDSKIP:
1517 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1519 case VSpace::BIGSKIP:
1520 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1522 case VSpace::LENGTH:
1523 os << "\\setlength{\\parskip}{"
1524 << from_utf8(getDefSkip().length().asLatexString())
1527 default: // should never happen // Then delete it.
1528 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1532 os << "\\setlength{\\parindent}{0pt}\n";
1535 // when separation by indentation
1536 // only output something when a width is given
1537 if (getIndentation().asLyXCommand() != "default") {
1538 os << "\\setlength{\\parindent}{"
1539 << from_utf8(getIndentation().asLatexCommand())
1545 // Now insert the LyX specific LaTeX commands...
1546 docstring lyxpreamble;
1548 // due to interferences with babel and hyperref, the color package has to
1549 // be loaded (when it is not already loaded) before babel when hyperref
1550 // is used with the colorlinks option, see
1551 // http://www.lyx.org/trac/ticket/5291
1552 // we decided therefore to load color always before babel, see
1553 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1554 lyxpreamble += from_ascii(features.getColorOptions());
1556 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1558 && (features.isRequired("jurabib")
1559 || features.isRequired("hyperref")
1560 || features.isRequired("vietnamese")
1561 || features.isRequired("japanese") ) ) {
1563 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1564 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1567 // The optional packages;
1568 lyxpreamble += from_ascii(features.getPackages());
1570 // Additional Indices
1571 if (features.isRequired("splitidx")) {
1572 IndicesList::const_iterator iit = indiceslist().begin();
1573 IndicesList::const_iterator iend = indiceslist().end();
1574 for (; iit != iend; ++iit) {
1575 lyxpreamble += "\\newindex[";
1576 lyxpreamble += iit->index();
1577 lyxpreamble += "]{";
1578 lyxpreamble += iit->shortcut();
1579 lyxpreamble += "}\n";
1584 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1587 // * Hyperref manual: "Make sure it comes last of your loaded
1588 // packages, to give it a fighting chance of not being over-written,
1589 // since its job is to redefine many LaTeX commands."
1590 // * Email from Heiko Oberdiek: "It is usually better to load babel
1591 // before hyperref. Then hyperref has a chance to detect babel.
1592 // * Has to be loaded before the "LyX specific LaTeX commands" to
1593 // avoid errors with algorithm floats.
1594 // use hyperref explicitly if it is required
1595 if (features.isRequired("hyperref")) {
1596 // pass what we have to stream here, since we need
1597 // to access the stream itself in PDFOptions.
1601 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1603 OutputParams tmp_params = features.runparams();
1604 lines += pdfoptions().writeLaTeX(tmp_params, os,
1605 documentClass().provides("hyperref"));
1606 texrow.newlines(lines);
1607 // set back for the rest
1608 lyxpreamble.clear();
1611 // Will be surrounded by \makeatletter and \makeatother when not empty
1612 docstring atlyxpreamble;
1614 // Some macros LyX will need
1615 docstring tmppreamble(features.getMacros());
1617 if (!tmppreamble.empty())
1618 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1619 "LyX specific LaTeX commands.\n"
1620 + tmppreamble + '\n';
1622 // the text class specific preamble
1623 tmppreamble = features.getTClassPreamble();
1624 if (!tmppreamble.empty())
1625 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1626 "Textclass specific LaTeX commands.\n"
1627 + tmppreamble + '\n';
1629 // suppress date if selected
1630 // use \@ifundefined because we cannot be sure that every document class
1631 // has a \date command
1633 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1635 /* the user-defined preamble */
1636 if (!containsOnly(preamble, " \n\t"))
1638 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1639 "User specified LaTeX commands.\n"
1640 + from_utf8(preamble) + '\n';
1642 // subfig loads internally the LaTeX package "caption". As
1643 // caption is a very popular package, users will load it in
1644 // the preamble. Therefore we must load subfig behind the
1645 // user-defined preamble and check if the caption package was
1646 // loaded or not. For the case that caption is loaded before
1647 // subfig, there is the subfig option "caption=false". This
1648 // option also works when a koma-script class is used and
1649 // koma's own caption commands are used instead of caption. We
1650 // use \PassOptionsToPackage here because the user could have
1651 // already loaded subfig in the preamble.
1652 if (features.isRequired("subfig")) {
1653 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1654 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1655 "\\usepackage{subfig}\n";
1658 // Itemize bullet settings need to be last in case the user
1659 // defines their own bullets that use a package included
1660 // in the user-defined preamble -- ARRae
1661 // Actually it has to be done much later than that
1662 // since some packages like frenchb make modifications
1663 // at \begin{document} time -- JMarc
1664 docstring bullets_def;
1665 for (int i = 0; i < 4; ++i) {
1666 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1667 if (bullets_def.empty())
1668 bullets_def += "\\AtBeginDocument{\n";
1669 bullets_def += " \\def\\labelitemi";
1671 // `i' is one less than the item to modify
1678 bullets_def += "ii";
1684 bullets_def += '{' +
1685 user_defined_bullet(i).getText()
1690 if (!bullets_def.empty())
1691 atlyxpreamble += bullets_def + "}\n\n";
1693 if (!atlyxpreamble.empty())
1694 lyxpreamble += "\n\\makeatletter\n"
1695 + atlyxpreamble + "\\makeatother\n\n";
1697 // We try to load babel late, in case it interferes with other packages.
1698 // Jurabib and Hyperref have to be called after babel, though.
1699 if (use_babel && !features.isRequired("jurabib")
1700 && !features.isRequired("hyperref")
1701 && !features.isRequired("vietnamese")
1702 && !features.isRequired("japanese")) {
1704 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1705 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1708 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1709 if (!i18npreamble.empty())
1710 lyxpreamble += i18npreamble + '\n';
1713 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1714 texrow.newlines(nlines);
1718 // these packages (xunicode, for that matter) need to be loaded at least
1719 // after amsmath, amssymb, esint and the other packages that provide
1722 os << "\\usepackage{xunicode}\n";
1724 os << "\\usepackage{xltxtra}\n";
1731 void BufferParams::useClassDefaults()
1733 DocumentClass const & tclass = documentClass();
1735 sides = tclass.sides();
1736 columns = tclass.columns();
1737 pagestyle = tclass.pagestyle();
1738 use_default_options = true;
1739 // Only if class has a ToC hierarchy
1740 if (tclass.hasTocLevels()) {
1741 secnumdepth = tclass.secnumdepth();
1742 tocdepth = tclass.tocdepth();
1747 bool BufferParams::hasClassDefaults() const
1749 DocumentClass const & tclass = documentClass();
1751 return sides == tclass.sides()
1752 && columns == tclass.columns()
1753 && pagestyle == tclass.pagestyle()
1754 && use_default_options
1755 && secnumdepth == tclass.secnumdepth()
1756 && tocdepth == tclass.tocdepth();
1760 DocumentClass const & BufferParams::documentClass() const
1766 DocumentClass const * BufferParams::documentClassPtr() const {
1771 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1772 // evil, but this function is evil
1773 doc_class_ = const_cast<DocumentClass *>(tc);
1777 bool BufferParams::setBaseClass(string const & classname)
1779 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1780 LayoutFileList & bcl = LayoutFileList::get();
1781 if (!bcl.haveClass(classname)) {
1783 bformat(_("The layout file:\n"
1785 "could not be found. A default textclass with default\n"
1786 "layouts will be used. LyX will not be able to produce\n"
1788 from_utf8(classname));
1789 frontend::Alert::error(_("Document class not found"), s);
1790 bcl.addEmptyClass(classname);
1793 bool const success = bcl[classname].load();
1796 bformat(_("Due to some error in it, the layout file:\n"
1798 "could not be loaded. A default textclass with default\n"
1799 "layouts will be used. LyX will not be able to produce\n"
1801 from_utf8(classname));
1802 frontend::Alert::error(_("Could not load class"), s);
1803 bcl.addEmptyClass(classname);
1806 pimpl_->baseClass_ = classname;
1807 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1812 LayoutFile const * BufferParams::baseClass() const
1814 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1815 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1821 LayoutFileIndex const & BufferParams::baseClassID() const
1823 return pimpl_->baseClass_;
1827 void BufferParams::makeDocumentClass()
1832 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1834 if (!local_layout.empty()) {
1835 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1836 docstring const msg = _("Error reading internal layout information");
1837 frontend::Alert::warning(_("Read Error"), msg);
1843 bool BufferParams::moduleCanBeAdded(string const & modName) const
1845 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1849 bool BufferParams::addLayoutModule(string const & modName)
1851 LayoutModuleList::const_iterator it = layoutModules_.begin();
1852 LayoutModuleList::const_iterator end = layoutModules_.end();
1853 for (; it != end; it++)
1856 layoutModules_.push_back(modName);
1861 Font const BufferParams::getFont() const
1863 FontInfo f = documentClass().defaultfont();
1864 if (fontsDefaultFamily == "rmdefault")
1865 f.setFamily(ROMAN_FAMILY);
1866 else if (fontsDefaultFamily == "sfdefault")
1867 f.setFamily(SANS_FAMILY);
1868 else if (fontsDefaultFamily == "ttdefault")
1869 f.setFamily(TYPEWRITER_FAMILY);
1870 return Font(f, language);
1874 void BufferParams::readPreamble(Lexer & lex)
1876 if (lex.getString() != "\\begin_preamble")
1877 lyxerr << "Error (BufferParams::readPreamble):"
1878 "consistency check failed." << endl;
1880 preamble = lex.getLongString("\\end_preamble");
1884 void BufferParams::readLocalLayout(Lexer & lex)
1886 if (lex.getString() != "\\begin_local_layout")
1887 lyxerr << "Error (BufferParams::readLocalLayout):"
1888 "consistency check failed." << endl;
1890 local_layout = lex.getLongString("\\end_local_layout");
1894 void BufferParams::readLanguage(Lexer & lex)
1896 if (!lex.next()) return;
1898 string const tmptok = lex.getString();
1900 // check if tmptok is part of tex_babel in tex-defs.h
1901 language = languages.getLanguage(tmptok);
1903 // Language tmptok was not found
1904 language = default_language;
1905 lyxerr << "Warning: Setting language `"
1906 << tmptok << "' to `" << language->lang()
1912 void BufferParams::readGraphicsDriver(Lexer & lex)
1917 string const tmptok = lex.getString();
1918 // check if tmptok is part of tex_graphics in tex_defs.h
1921 string const test = tex_graphics[n++];
1923 if (test == tmptok) {
1924 graphicsDriver = tmptok;
1929 "Warning: graphics driver `$$Token' not recognized!\n"
1930 " Setting graphics driver to `default'.\n");
1931 graphicsDriver = "default";
1938 void BufferParams::readBullets(Lexer & lex)
1943 int const index = lex.getInteger();
1945 int temp_int = lex.getInteger();
1946 user_defined_bullet(index).setFont(temp_int);
1947 temp_bullet(index).setFont(temp_int);
1949 user_defined_bullet(index).setCharacter(temp_int);
1950 temp_bullet(index).setCharacter(temp_int);
1952 user_defined_bullet(index).setSize(temp_int);
1953 temp_bullet(index).setSize(temp_int);
1957 void BufferParams::readBulletsLaTeX(Lexer & lex)
1959 // The bullet class should be able to read this.
1962 int const index = lex.getInteger();
1964 docstring const temp_str = lex.getDocString();
1966 user_defined_bullet(index).setText(temp_str);
1967 temp_bullet(index).setText(temp_str);
1971 void BufferParams::readModules(Lexer & lex)
1973 if (!lex.eatLine()) {
1974 lyxerr << "Error (BufferParams::readModules):"
1975 "Unexpected end of input." << endl;
1979 string mod = lex.getString();
1980 if (mod == "\\end_modules")
1982 addLayoutModule(mod);
1988 void BufferParams::readRemovedModules(Lexer & lex)
1990 if (!lex.eatLine()) {
1991 lyxerr << "Error (BufferParams::readRemovedModules):"
1992 "Unexpected end of input." << endl;
1996 string mod = lex.getString();
1997 if (mod == "\\end_removed_modules")
1999 removedModules_.push_back(mod);
2002 // now we want to remove any removed modules that were previously
2003 // added. normally, that will be because default modules were added in
2004 // setBaseClass(), which gets called when \textclass is read at the
2005 // start of the read.
2006 list<string>::const_iterator rit = removedModules_.begin();
2007 list<string>::const_iterator const ren = removedModules_.end();
2008 for (; rit != ren; rit++) {
2009 LayoutModuleList::iterator const mit = layoutModules_.begin();
2010 LayoutModuleList::iterator const men = layoutModules_.end();
2011 LayoutModuleList::iterator found = find(mit, men, *rit);
2014 layoutModules_.erase(found);
2019 void BufferParams::readIncludeonly(Lexer & lex)
2021 if (!lex.eatLine()) {
2022 lyxerr << "Error (BufferParams::readIncludeonly):"
2023 "Unexpected end of input." << endl;
2027 string child = lex.getString();
2028 if (child == "\\end_includeonly")
2030 includedChildren_.push_back(child);
2036 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2038 char real_papersize = papersize;
2039 if (real_papersize == PAPER_DEFAULT)
2040 real_papersize = lyxrc.default_papersize;
2042 switch (real_papersize) {
2044 // could be anything, so don't guess
2046 case PAPER_CUSTOM: {
2047 if (purpose == XDVI && !paperwidth.empty() &&
2048 !paperheight.empty()) {
2049 // heightxwidth<unit>
2050 string first = paperwidth;
2051 string second = paperheight;
2052 if (orientation == ORIENTATION_LANDSCAPE)
2055 return first.erase(first.length() - 2)
2067 // dvips and dvipdfm do not know this
2068 if (purpose == DVIPS || purpose == DVIPDFM)
2072 // dvipdfm does not know this
2073 if (purpose == DVIPDFM)
2077 // dvipdfm does not know this
2078 if (purpose == DVIPDFM)
2081 case PAPER_USEXECUTIVE:
2082 // dvipdfm does not know this
2083 if (purpose == DVIPDFM)
2088 case PAPER_USLETTER:
2090 if (purpose == XDVI)
2097 string const BufferParams::dvips_options() const
2102 && papersize == PAPER_CUSTOM
2103 && !lyxrc.print_paper_dimension_flag.empty()
2104 && !paperwidth.empty()
2105 && !paperheight.empty()) {
2106 // using a custom papersize
2107 result = lyxrc.print_paper_dimension_flag;
2108 result += ' ' + paperwidth;
2109 result += ',' + paperheight;
2111 string const paper_option = paperSizeName(DVIPS);
2112 if (!paper_option.empty() && (paper_option != "letter" ||
2113 orientation != ORIENTATION_LANDSCAPE)) {
2114 // dvips won't accept -t letter -t landscape.
2115 // In all other cases, include the paper size
2117 result = lyxrc.print_paper_flag;
2118 result += ' ' + paper_option;
2121 if (orientation == ORIENTATION_LANDSCAPE &&
2122 papersize != PAPER_CUSTOM)
2123 result += ' ' + lyxrc.print_landscape_flag;
2128 string const BufferParams::font_encoding() const
2130 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2134 string BufferParams::babelCall(string const & lang_opts) const
2136 string lang_pack = lyxrc.language_package;
2137 if (lang_pack != "\\usepackage{babel}")
2139 // suppress the babel call when there is no babel language defined
2140 // for the document language in the lib/languages file and if no
2141 // other languages are used (lang_opts is then empty)
2142 if (lang_opts.empty())
2144 // If Vietnamese is used, babel must directly be loaded with the
2145 // language options, see
2146 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2147 size_t viet = lang_opts.find("vietnam");
2148 // viet = string::npos when not found
2149 // the same is for all other languages that are not directly supported by
2150 // babel, but where LaTeX-packages add babel support.
2151 // this is currently the case for Latvian, Lithuanian, Mongolian
2153 size_t latvian = lang_opts.find("latvian");
2154 size_t lithu = lang_opts.find("lithuanian");
2155 size_t mongo = lang_opts.find("mongolian");
2156 size_t turkmen = lang_opts.find("turkmen");
2157 // If Japanese is used, babel must directly be loaded with the
2158 // language options, see
2159 // http://www.lyx.org/trac/ticket/4597#c4
2160 size_t japan = lang_opts.find("japanese");
2161 if (!lyxrc.language_global_options || viet != string::npos
2162 || japan != string::npos || latvian != string::npos
2163 || lithu != string::npos || mongo != string::npos
2164 || turkmen != string::npos)
2165 return "\\usepackage[" + lang_opts + "]{babel}";
2170 docstring BufferParams::getGraphicsDriver(string const & package) const
2174 if (package == "geometry") {
2175 if (graphicsDriver == "dvips"
2176 || graphicsDriver == "dvipdfm"
2177 || graphicsDriver == "pdftex"
2178 || graphicsDriver == "vtex")
2179 result = from_ascii(graphicsDriver);
2180 else if (graphicsDriver == "dvipdfmx")
2181 result = from_ascii("dvipdfm");
2188 void BufferParams::writeEncodingPreamble(odocstream & os,
2189 LaTeXFeatures & features, TexRow & texrow) const
2193 if (inputenc == "auto") {
2194 string const doc_encoding =
2195 language->encoding()->latexName();
2196 Encoding::Package const package =
2197 language->encoding()->package();
2199 // Create a list with all the input encodings used
2201 set<string> encodings =
2202 features.getEncodingSet(doc_encoding);
2204 // If the "japanese" package (i.e. pLaTeX) is used,
2205 // inputenc must be omitted.
2206 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2207 if (package == Encoding::japanese)
2208 features.require("japanese");
2210 if ((!encodings.empty() || package == Encoding::inputenc)
2211 && !features.isRequired("japanese")) {
2212 os << "\\usepackage[";
2213 set<string>::const_iterator it = encodings.begin();
2214 set<string>::const_iterator const end = encodings.end();
2216 os << from_ascii(*it);
2219 for (; it != end; ++it)
2220 os << ',' << from_ascii(*it);
2221 if (package == Encoding::inputenc) {
2222 if (!encodings.empty())
2224 os << from_ascii(doc_encoding);
2226 os << "]{inputenc}\n";
2229 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2230 if (language->encoding()->name() == "utf8-cjk"
2231 && LaTeXFeatures::isAvailable("CJKutf8"))
2232 os << "\\usepackage{CJKutf8}\n";
2234 os << "\\usepackage{CJK}\n";
2237 } else if (inputenc != "default") {
2238 switch (encoding().package()) {
2239 case Encoding::none:
2240 case Encoding::japanese:
2242 case Encoding::inputenc:
2243 // do not load inputenc if japanese is used
2244 if (features.isRequired("japanese"))
2246 os << "\\usepackage[" << from_ascii(inputenc)
2251 if (encoding().name() == "utf8-cjk"
2252 && LaTeXFeatures::isAvailable("CJKutf8"))
2253 os << "\\usepackage{CJKutf8}\n";
2255 os << "\\usepackage{CJK}\n";
2261 // The encoding "armscii8" (for Armenian) is only available when
2262 // the package "armtex" is loaded.
2263 if (language->encoding()->latexName() == "armscii8"
2264 || inputenc == "armscii8") {
2265 os << "\\usepackage{armtex}\n";
2271 string const BufferParams::parseFontName(string const & name) const
2273 string mangled = name;
2274 size_t const idx = mangled.find('[');
2275 if (idx == string::npos || idx == 0)
2278 return mangled.substr(0, idx - 1);
2282 string const BufferParams::loadFonts(string const & rm,
2283 string const & sf, string const & tt,
2284 bool const & sc, bool const & osf,
2285 int const & sfscale, int const & ttscale,
2286 bool const & xetex) const
2288 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2289 several packages have been replaced by others, that might not
2290 be installed on every system. We have to take care for that
2291 (see psnfss.pdf). We try to support all psnfss fonts as well
2292 as the fonts that have become de facto standard in the LaTeX
2293 world (e.g. Latin Modern). We do not support obsolete fonts
2294 (like PSLatex). In general, it should be possible to mix any
2295 rm font with any sf or tt font, respectively. (JSpitzm)
2297 -- separate math fonts.
2300 if (rm == "default" && sf == "default" && tt == "default")
2307 if (rm != "default")
2308 os << "\\setmainfont[Mapping=tex-text]{"
2309 << parseFontName(rm) << "}\n";
2310 if (sf != "default") {
2311 string const sans = parseFontName(sf);
2313 os << "\\setsansfont[Scale="
2314 << float(sfscale) / 100
2315 << ",Mapping=tex-text]{"
2318 os << "\\setsansfont[Mapping=tex-text]{"
2321 if (tt != "default") {
2322 string const mono = parseFontName(tt);
2324 os << "\\setmonofont[Scale="
2325 << float(sfscale) / 100
2329 os << "\\setmonofont[Mapping=tex-text]{"
2333 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2338 // Computer Modern (must be explicitly selectable -- there might be classes
2339 // that define a different default font!
2341 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2342 // osf for Computer Modern needs eco.sty
2344 os << "\\usepackage{eco}\n";
2346 // Latin Modern Roman
2347 else if (rm == "lmodern")
2348 os << "\\usepackage{lmodern}\n";
2350 else if (rm == "ae") {
2351 // not needed when using OT1 font encoding.
2352 if (font_encoding() != "default")
2353 os << "\\usepackage{ae,aecompl}\n";
2356 else if (rm == "times") {
2357 // try to load the best available package
2358 if (LaTeXFeatures::isAvailable("mathptmx"))
2359 os << "\\usepackage{mathptmx}\n";
2360 else if (LaTeXFeatures::isAvailable("mathptm"))
2361 os << "\\usepackage{mathptm}\n";
2363 os << "\\usepackage{times}\n";
2366 else if (rm == "palatino") {
2367 // try to load the best available package
2368 if (LaTeXFeatures::isAvailable("mathpazo")) {
2369 os << "\\usepackage";
2375 // "osf" includes "sc"!
2379 os << "{mathpazo}\n";
2381 else if (LaTeXFeatures::isAvailable("mathpple"))
2382 os << "\\usepackage{mathpple}\n";
2384 os << "\\usepackage{palatino}\n";
2387 else if (rm == "utopia") {
2388 // fourier supersedes utopia.sty, but does
2389 // not work with OT1 encoding.
2390 if (LaTeXFeatures::isAvailable("fourier")
2391 && font_encoding() != "default") {
2392 os << "\\usepackage";
2403 os << "{fourier}\n";
2406 os << "\\usepackage{utopia}\n";
2408 // Bera (complete fontset)
2409 else if (rm == "bera" && sf == "default" && tt == "default")
2410 os << "\\usepackage{bera}\n";
2412 else if (rm != "default")
2413 os << "\\usepackage" << "{" << rm << "}\n";
2416 // Helvetica, Bera Sans
2417 if (sf == "helvet" || sf == "berasans") {
2419 os << "\\usepackage[scaled=" << float(sfscale) / 100
2420 << "]{" << sf << "}\n";
2422 os << "\\usepackage{" << sf << "}\n";
2425 else if (sf == "avant")
2426 os << "\\usepackage{" << sf << "}\n";
2427 // Computer Modern, Latin Modern, CM Bright
2428 else if (sf != "default")
2429 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2431 // monospaced/typewriter
2432 // Courier, LuxiMono
2433 if (tt == "luximono" || tt == "beramono") {
2435 os << "\\usepackage[scaled=" << float(ttscale) / 100
2436 << "]{" << tt << "}\n";
2438 os << "\\usepackage{" << tt << "}\n";
2441 else if (tt == "courier" )
2442 os << "\\usepackage{" << tt << "}\n";
2443 // Computer Modern, Latin Modern, CM Bright
2444 else if (tt != "default")
2445 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2451 Encoding const & BufferParams::encoding() const
2454 return *(encodings.fromLaTeXName("utf8-plain"));
2455 if (inputenc == "auto" || inputenc == "default")
2456 return *language->encoding();
2457 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2460 LYXERR0("Unknown inputenc value `" << inputenc
2461 << "'. Using `auto' instead.");
2462 return *language->encoding();
2466 CiteEngine BufferParams::citeEngine() const
2468 // FIXME the class should provide the numerical/
2469 // authoryear choice
2470 if (documentClass().provides("natbib")
2471 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2472 return ENGINE_NATBIB_AUTHORYEAR;
2473 return cite_engine_;
2477 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2479 cite_engine_ = cite_engine;