2 * \file BufferParams.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Alfredo Braunstein
7 * \author Lars Gullik Bjønnes
8 * \author Jean-Marc Lasgouttes
10 * \author André Pönitz
11 * \author Martin Vermeer
13 * Full author contact details are available in file CREDITS.
18 #include "BufferParams.h"
21 #include "LayoutFile.h"
22 #include "BranchList.h"
23 #include "buffer_funcs.h"
29 #include "IndicesList.h"
31 #include "LaTeXFeatures.h"
32 #include "ModuleList.h"
36 #include "OutputParams.h"
40 #include "PDFOptions.h"
42 #include "frontends/alert.h"
44 #include "insets/InsetListingsParams.h"
46 #include "support/convert.h"
47 #include "support/debug.h"
48 #include "support/docstream.h"
49 #include "support/FileName.h"
50 #include "support/filetools.h"
51 #include "support/gettext.h"
52 #include "support/Messages.h"
53 #include "support/Translator.h"
54 #include "support/lstrings.h"
60 using namespace lyx::support;
63 static char const * const string_paragraph_separation[] = {
68 static char const * const string_quotes_language[] = {
69 "english", "swedish", "german", "polish", "french", "danish", ""
73 static char const * const string_papersize[] = {
74 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
75 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
79 static char const * const string_orientation[] = {
80 "portrait", "landscape", ""
84 static char const * const string_footnotekinds[] = {
85 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
89 static char const * const tex_graphics[] = {
90 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
91 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
92 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
93 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
104 // Paragraph separation
105 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
108 ParSepTranslator const init_parseptranslator()
110 ParSepTranslator translator
111 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
112 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
117 ParSepTranslator const & parseptranslator()
119 static ParSepTranslator translator = init_parseptranslator();
125 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
128 QuotesLangTranslator const init_quoteslangtranslator()
130 QuotesLangTranslator translator
131 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
132 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
133 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
134 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
135 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
136 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
141 QuotesLangTranslator const & quoteslangtranslator()
143 static QuotesLangTranslator translator = init_quoteslangtranslator();
149 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
152 static PaperSizeTranslator initPaperSizeTranslator()
154 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
155 translator.addPair(string_papersize[1], PAPER_CUSTOM);
156 translator.addPair(string_papersize[2], PAPER_USLETTER);
157 translator.addPair(string_papersize[3], PAPER_USLEGAL);
158 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
159 translator.addPair(string_papersize[5], PAPER_A3);
160 translator.addPair(string_papersize[6], PAPER_A4);
161 translator.addPair(string_papersize[7], PAPER_A5);
162 translator.addPair(string_papersize[8], PAPER_B3);
163 translator.addPair(string_papersize[9], PAPER_B4);
164 translator.addPair(string_papersize[10], PAPER_B5);
169 PaperSizeTranslator const & papersizetranslator()
171 static PaperSizeTranslator translator = initPaperSizeTranslator();
177 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
180 PaperOrientationTranslator const init_paperorientationtranslator()
182 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
183 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
188 PaperOrientationTranslator const & paperorientationtranslator()
190 static PaperOrientationTranslator translator = init_paperorientationtranslator();
196 typedef Translator<int, PageSides> SidesTranslator;
199 SidesTranslator const init_sidestranslator()
201 SidesTranslator translator(1, OneSide);
202 translator.addPair(2, TwoSides);
207 SidesTranslator const & sidestranslator()
209 static SidesTranslator translator = init_sidestranslator();
215 typedef Translator<int, BufferParams::Package> PackageTranslator;
218 PackageTranslator const init_packagetranslator()
220 PackageTranslator translator(0, BufferParams::package_off);
221 translator.addPair(1, BufferParams::package_auto);
222 translator.addPair(2, BufferParams::package_on);
227 PackageTranslator const & packagetranslator()
229 static PackageTranslator translator = init_packagetranslator();
235 typedef Translator<string, CiteEngine> CiteEngineTranslator;
238 CiteEngineTranslator const init_citeenginetranslator()
240 CiteEngineTranslator translator("basic", ENGINE_BASIC);
241 translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
242 translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
243 translator.addPair("jurabib", ENGINE_JURABIB);
248 CiteEngineTranslator const & citeenginetranslator()
250 static CiteEngineTranslator translator = init_citeenginetranslator();
256 typedef Translator<string, Spacing::Space> SpaceTranslator;
259 SpaceTranslator const init_spacetranslator()
261 SpaceTranslator translator("default", Spacing::Default);
262 translator.addPair("single", Spacing::Single);
263 translator.addPair("onehalf", Spacing::Onehalf);
264 translator.addPair("double", Spacing::Double);
265 translator.addPair("other", Spacing::Other);
270 SpaceTranslator const & spacetranslator()
272 static SpaceTranslator translator = init_spacetranslator();
279 class BufferParams::Impl
284 AuthorList authorlist;
285 BranchList branchlist;
286 Bullet temp_bullets[4];
287 Bullet user_defined_bullets[4];
288 IndicesList indiceslist;
290 /** This is the amount of space used for paragraph_separation "skip",
291 * and for detached paragraphs in "indented" documents.
295 PDFOptions pdfoptions;
296 LayoutFileIndex baseClass_;
300 BufferParams::Impl::Impl()
301 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
303 // set initial author
305 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
310 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
314 return new BufferParams::Impl(*ptr);
318 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
324 BufferParams::BufferParams()
327 setBaseClass(defaultBaseclass());
329 paragraph_separation = ParagraphIndentSeparation;
330 quotes_language = InsetQuotes::EnglishQuotes;
331 fontsize = "default";
334 papersize = PAPER_DEFAULT;
335 orientation = ORIENTATION_PORTRAIT;
336 use_geometry = false;
337 use_amsmath = package_auto;
338 use_esint = package_auto;
339 cite_engine_ = ENGINE_BASIC;
340 use_bibtopic = false;
342 trackChanges = false;
343 outputChanges = false;
344 use_default_options = true;
347 language = default_language;
348 fontsRoman = "default";
349 fontsSans = "default";
350 fontsTypewriter = "default";
351 fontsDefaultFamily = "default";
355 fontsSansScale = 100;
356 fontsTypewriterScale = 100;
358 graphicsDriver = "default";
359 defaultOutputFormat = "default";
360 bibtex_command = "default";
361 index_command = "default";
364 listings_params = string();
365 pagestyle = "default";
366 // white is equal to no background color
367 backgroundcolor = lyx::rgbFromHexName("#ffffff");
369 for (int iter = 0; iter < 4; ++iter) {
370 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
371 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
374 indiceslist().addDefault(B_("Index"));
378 docstring BufferParams::B_(string const & l10n) const
380 LASSERT(language, /**/);
381 return getMessages(language->code()).get(l10n);
385 AuthorList & BufferParams::authors()
387 return pimpl_->authorlist;
391 AuthorList const & BufferParams::authors() const
393 return pimpl_->authorlist;
397 BranchList & BufferParams::branchlist()
399 return pimpl_->branchlist;
403 BranchList const & BufferParams::branchlist() const
405 return pimpl_->branchlist;
409 IndicesList & BufferParams::indiceslist()
411 return pimpl_->indiceslist;
415 IndicesList const & BufferParams::indiceslist() const
417 return pimpl_->indiceslist;
421 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
423 LASSERT(index < 4, /**/);
424 return pimpl_->temp_bullets[index];
428 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
430 LASSERT(index < 4, /**/);
431 return pimpl_->temp_bullets[index];
435 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
437 LASSERT(index < 4, /**/);
438 return pimpl_->user_defined_bullets[index];
442 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
444 LASSERT(index < 4, /**/);
445 return pimpl_->user_defined_bullets[index];
449 Spacing & BufferParams::spacing()
451 return pimpl_->spacing;
455 Spacing const & BufferParams::spacing() const
457 return pimpl_->spacing;
461 PDFOptions & BufferParams::pdfoptions()
463 return pimpl_->pdfoptions;
467 PDFOptions const & BufferParams::pdfoptions() const
469 return pimpl_->pdfoptions;
473 HSpace const & BufferParams::getIndentation() const
475 return pimpl_->indentation;
479 void BufferParams::setIndentation(HSpace const & indent)
481 pimpl_->indentation = indent;
485 VSpace const & BufferParams::getDefSkip() const
487 return pimpl_->defskip;
491 void BufferParams::setDefSkip(VSpace const & vs)
493 pimpl_->defskip = vs;
497 string BufferParams::readToken(Lexer & lex, string const & token,
498 FileName const & filepath)
500 if (token == "\\textclass") {
502 string const classname = lex.getString();
503 // if there exists a local layout file, ignore the system one
504 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
506 LayoutFileList & bcl = LayoutFileList::get();
507 if (tcp.empty() && !filepath.empty())
508 tcp = bcl.addLocalLayout(classname, filepath.absFilename());
512 setBaseClass(classname);
513 // We assume that a tex class exists for local or unknown layouts so this warning
514 // will only be given for system layouts.
515 if (!baseClass()->isTeXClassAvailable()) {
516 docstring const msg =
517 bformat(_("The layout file requested by this document,\n"
519 "is not usable. This is probably because a LaTeX\n"
520 "class or style file required by it is not\n"
521 "available. See the Customization documentation\n"
522 "for more information.\n"), from_utf8(classname));
523 frontend::Alert::warning(_("Document class not available"),
524 msg + _("LyX will not be able to produce output."));
526 } else if (token == "\\begin_preamble") {
528 } else if (token == "\\begin_local_layout") {
529 readLocalLayout(lex);
530 } else if (token == "\\begin_modules") {
532 } else if (token == "\\begin_removed_modules") {
533 readRemovedModules(lex);
534 } else if (token == "\\options") {
536 options = lex.getString();
537 } else if (token == "\\use_default_options") {
538 lex >> use_default_options;
539 } else if (token == "\\master") {
541 master = lex.getString();
542 } else if (token == "\\language") {
544 } else if (token == "\\inputencoding") {
546 } else if (token == "\\graphics") {
547 readGraphicsDriver(lex);
548 } else if (token == "\\default_output_format") {
549 lex >> defaultOutputFormat;
550 } else if (token == "\\bibtex_command") {
552 bibtex_command = lex.getString();
553 } else if (token == "\\index_command") {
555 index_command = lex.getString();
556 } else if (token == "\\font_roman") {
558 fontsRoman = lex.getString();
559 } else if (token == "\\font_sans") {
561 fontsSans = lex.getString();
562 } else if (token == "\\font_typewriter") {
564 fontsTypewriter = lex.getString();
565 } else if (token == "\\font_default_family") {
566 lex >> fontsDefaultFamily;
567 } else if (token == "\\use_xetex") {
569 } else if (token == "\\font_sc") {
571 } else if (token == "\\font_osf") {
573 } else if (token == "\\font_sf_scale") {
574 lex >> fontsSansScale;
575 } else if (token == "\\font_tt_scale") {
576 lex >> fontsTypewriterScale;
577 } else if (token == "\\font_cjk") {
579 } else if (token == "\\paragraph_separation") {
582 paragraph_separation = parseptranslator().find(parsep);
583 } else if (token == "\\paragraph_indentation") {
585 string indentation = lex.getString();
586 pimpl_->indentation = HSpace(indentation);
587 } else if (token == "\\defskip") {
589 string defskip = lex.getString();
590 if (defskip == "defskip")
593 pimpl_->defskip = VSpace(defskip);
594 } else if (token == "\\quotes_language") {
597 quotes_language = quoteslangtranslator().find(quotes_lang);
598 } else if (token == "\\papersize") {
601 papersize = papersizetranslator().find(ppsize);
602 } else if (token == "\\use_geometry") {
604 } else if (token == "\\use_amsmath") {
607 use_amsmath = packagetranslator().find(use_ams);
608 } else if (token == "\\use_esint") {
611 use_esint = packagetranslator().find(useesint);
612 } else if (token == "\\cite_engine") {
615 cite_engine_ = citeenginetranslator().find(engine);
616 } else if (token == "\\use_bibtopic") {
618 } else if (token == "\\use_indices") {
620 } else if (token == "\\tracking_changes") {
622 } else if (token == "\\output_changes") {
623 lex >> outputChanges;
624 } else if (token == "\\branch") {
626 docstring branch = lex.getDocString();
627 branchlist().add(branch);
630 string const tok = lex.getString();
631 if (tok == "\\end_branch")
633 Branch * branch_ptr = branchlist().find(branch);
634 if (tok == "\\selected") {
637 branch_ptr->setSelected(lex.getInteger());
639 if (tok == "\\filename_suffix") {
642 branch_ptr->setFilenameSuffix(lex.getInteger());
644 // not yet operational
645 if (tok == "\\color") {
647 string color = lex.getString();
649 branch_ptr->setColor(color);
650 // Update also the Color table:
652 color = lcolor.getX11Name(Color_background);
654 lcolor.setColor(to_utf8(branch), color);
657 } else if (token == "\\index") {
659 docstring index = lex.getDocString();
660 indiceslist().add(index);
663 string const tok = lex.getString();
664 if (tok == "\\end_index")
666 Index * index_ptr = indiceslist().find(index);
667 if (tok == "\\shortcut") {
670 index_ptr->setShortcut(lex.getDocString());
672 // not yet operational
673 if (tok == "\\color") {
675 string color = lex.getString();
677 index_ptr->setColor(color);
678 // Update also the Color table:
680 color = lcolor.getX11Name(Color_background);
682 lcolor.setColor(to_utf8(index), color);
685 } else if (token == "\\author") {
687 istringstream ss(lex.getString());
690 author_map.push_back(pimpl_->authorlist.record(a));
691 } else if (token == "\\paperorientation") {
694 orientation = paperorientationtranslator().find(orient);
695 } else if (token == "\\backgroundcolor") {
697 backgroundcolor = lyx::rgbFromHexName(lex.getString());
698 } else if (token == "\\paperwidth") {
700 } else if (token == "\\paperheight") {
702 } else if (token == "\\leftmargin") {
704 } else if (token == "\\topmargin") {
706 } else if (token == "\\rightmargin") {
708 } else if (token == "\\bottommargin") {
710 } else if (token == "\\headheight") {
712 } else if (token == "\\headsep") {
714 } else if (token == "\\footskip") {
716 } else if (token == "\\columnsep") {
718 } else if (token == "\\paperfontsize") {
720 } else if (token == "\\papercolumns") {
722 } else if (token == "\\listings_params") {
725 listings_params = InsetListingsParams(par).params();
726 } else if (token == "\\papersides") {
729 sides = sidestranslator().find(psides);
730 } else if (token == "\\paperpagestyle") {
732 } else if (token == "\\bullet") {
734 } else if (token == "\\bulletLaTeX") {
735 readBulletsLaTeX(lex);
736 } else if (token == "\\secnumdepth") {
738 } else if (token == "\\tocdepth") {
740 } else if (token == "\\spacing") {
744 if (nspacing == "other") {
747 spacing().set(spacetranslator().find(nspacing), tmp_val);
748 } else if (token == "\\float_placement") {
749 lex >> float_placement;
751 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
752 string toktmp = pdfoptions().readToken(lex, token);
753 if (!toktmp.empty()) {
754 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
759 lyxerr << "BufferParams::readToken(): Unknown token: " <<
768 void BufferParams::writeFile(ostream & os) const
770 // The top of the file is written by the buffer.
771 // Prints out the buffer info into the .lyx file given by file
774 os << "\\textclass " << baseClass()->name() << '\n';
777 if (!preamble.empty()) {
778 // remove '\n' from the end of preamble
779 string const tmppreamble = rtrim(preamble, "\n");
780 os << "\\begin_preamble\n"
782 << "\n\\end_preamble\n";
786 if (!options.empty()) {
787 os << "\\options " << options << '\n';
790 // use the class options defined in the layout?
791 os << "\\use_default_options "
792 << convert<string>(use_default_options) << "\n";
794 // the master document
795 if (!master.empty()) {
796 os << "\\master " << master << '\n';
800 if (!removedModules_.empty()) {
801 os << "\\begin_removed_modules" << '\n';
802 list<string>::const_iterator it = removedModules_.begin();
803 list<string>::const_iterator en = removedModules_.end();
804 for (; it != en; it++)
806 os << "\\end_removed_modules" << '\n';
810 if (!layoutModules_.empty()) {
811 os << "\\begin_modules" << '\n';
812 LayoutModuleList::const_iterator it = layoutModules_.begin();
813 LayoutModuleList::const_iterator en = layoutModules_.end();
814 for (; it != en; it++)
816 os << "\\end_modules" << '\n';
819 // local layout information
820 if (!local_layout.empty()) {
821 // remove '\n' from the end
822 string const tmplocal = rtrim(local_layout, "\n");
823 os << "\\begin_local_layout\n"
825 << "\n\\end_local_layout\n";
828 // then the text parameters
829 if (language != ignore_language)
830 os << "\\language " << language->lang() << '\n';
831 os << "\\inputencoding " << inputenc
832 << "\n\\font_roman " << fontsRoman
833 << "\n\\font_sans " << fontsSans
834 << "\n\\font_typewriter " << fontsTypewriter
835 << "\n\\font_default_family " << fontsDefaultFamily
836 << "\n\\use_xetex " << convert<string>(useXetex)
837 << "\n\\font_sc " << convert<string>(fontsSC)
838 << "\n\\font_osf " << convert<string>(fontsOSF)
839 << "\n\\font_sf_scale " << fontsSansScale
840 << "\n\\font_tt_scale " << fontsTypewriterScale
842 if (!fontsCJK.empty()) {
843 os << "\\font_cjk " << fontsCJK << '\n';
845 os << "\n\\graphics " << graphicsDriver << '\n';
846 os << "\\default_output_format " << defaultOutputFormat << '\n';
847 os << "\\bibtex_command " << bibtex_command << '\n';
848 os << "\\index_command " << index_command << '\n';
850 if (!float_placement.empty()) {
851 os << "\\float_placement " << float_placement << '\n';
853 os << "\\paperfontsize " << fontsize << '\n';
855 spacing().writeFile(os);
856 pdfoptions().writeFile(os);
858 os << "\\papersize " << string_papersize[papersize]
859 << "\n\\use_geometry " << convert<string>(use_geometry)
860 << "\n\\use_amsmath " << use_amsmath
861 << "\n\\use_esint " << use_esint
862 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
863 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
864 << "\n\\use_indices " << convert<string>(use_indices)
865 << "\n\\paperorientation " << string_orientation[orientation]
867 if (backgroundcolor != lyx::rgbFromHexName("#ffffff"))
868 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
870 BranchList::const_iterator it = branchlist().begin();
871 BranchList::const_iterator end = branchlist().end();
872 for (; it != end; ++it) {
873 os << "\\branch " << to_utf8(it->branch())
874 << "\n\\selected " << it->isSelected()
875 << "\n\\filename_suffix " << it->hasFilenameSuffix()
876 << "\n\\color " << lyx::X11hexname(it->color())
881 IndicesList::const_iterator iit = indiceslist().begin();
882 IndicesList::const_iterator iend = indiceslist().end();
883 for (; iit != iend; ++iit) {
884 os << "\\index " << to_utf8(iit->index())
885 << "\n\\shortcut " << to_utf8(iit->shortcut())
886 << "\n\\color " << lyx::X11hexname(iit->color())
891 if (!paperwidth.empty())
892 os << "\\paperwidth "
893 << VSpace(paperwidth).asLyXCommand() << '\n';
894 if (!paperheight.empty())
895 os << "\\paperheight "
896 << VSpace(paperheight).asLyXCommand() << '\n';
897 if (!leftmargin.empty())
898 os << "\\leftmargin "
899 << VSpace(leftmargin).asLyXCommand() << '\n';
900 if (!topmargin.empty())
902 << VSpace(topmargin).asLyXCommand() << '\n';
903 if (!rightmargin.empty())
904 os << "\\rightmargin "
905 << VSpace(rightmargin).asLyXCommand() << '\n';
906 if (!bottommargin.empty())
907 os << "\\bottommargin "
908 << VSpace(bottommargin).asLyXCommand() << '\n';
909 if (!headheight.empty())
910 os << "\\headheight "
911 << VSpace(headheight).asLyXCommand() << '\n';
912 if (!headsep.empty())
914 << VSpace(headsep).asLyXCommand() << '\n';
915 if (!footskip.empty())
917 << VSpace(footskip).asLyXCommand() << '\n';
918 if (!columnsep.empty())
920 << VSpace(columnsep).asLyXCommand() << '\n';
921 os << "\\secnumdepth " << secnumdepth
922 << "\n\\tocdepth " << tocdepth
923 << "\n\\paragraph_separation "
924 << string_paragraph_separation[paragraph_separation];
925 if (!paragraph_separation)
926 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
928 os << "\n\\defskip " << getDefSkip().asLyXCommand();
929 os << "\n\\quotes_language "
930 << string_quotes_language[quotes_language]
931 << "\n\\papercolumns " << columns
932 << "\n\\papersides " << sides
933 << "\n\\paperpagestyle " << pagestyle << '\n';
934 if (!listings_params.empty())
935 os << "\\listings_params \"" <<
936 InsetListingsParams(listings_params).encodedString() << "\"\n";
937 for (int i = 0; i < 4; ++i) {
938 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
939 if (user_defined_bullet(i).getFont() != -1) {
940 os << "\\bullet " << i << " "
941 << user_defined_bullet(i).getFont() << " "
942 << user_defined_bullet(i).getCharacter() << " "
943 << user_defined_bullet(i).getSize() << "\n";
947 os << "\\bulletLaTeX " << i << " \""
948 << lyx::to_ascii(user_defined_bullet(i).getText())
954 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
955 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
957 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
958 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
959 for (; a_it != a_end; ++a_it) {
960 if (a_it->second.used())
961 os << "\\author " << a_it->second << "\n";
963 os << "\\author " << Author() << "\n";
968 void BufferParams::validate(LaTeXFeatures & features) const
970 features.require(documentClass().requires());
973 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
974 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
975 LaTeXFeatures::isAvailable("xcolor");
977 switch (features.runparams().flavor) {
978 case OutputParams::LATEX:
980 features.require("ct-dvipost");
981 features.require("dvipost");
982 } else if (xcolorulem) {
983 features.require("ct-xcolor-ulem");
984 features.require("ulem");
985 features.require("xcolor");
987 features.require("ct-none");
990 case OutputParams::PDFLATEX:
991 case OutputParams::XETEX:
993 features.require("ct-xcolor-ulem");
994 features.require("ulem");
995 features.require("xcolor");
996 // improves color handling in PDF output
997 features.require("pdfcolmk");
999 features.require("ct-none");
1007 // Floats with 'Here definitely' as default setting.
1008 if (float_placement.find('H') != string::npos)
1009 features.require("float");
1011 // AMS Style is at document level
1012 if (use_amsmath == package_on
1013 || documentClass().provides("amsmath"))
1014 features.require("amsmath");
1015 if (use_esint == package_on)
1016 features.require("esint");
1018 // Document-level line spacing
1019 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1020 features.require("setspace");
1022 // the bullet shapes are buffer level not paragraph level
1023 // so they are tested here
1024 for (int i = 0; i < 4; ++i) {
1025 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1027 int const font = user_defined_bullet(i).getFont();
1029 int const c = user_defined_bullet(i).getCharacter();
1035 features.require("latexsym");
1037 } else if (font == 1) {
1038 features.require("amssymb");
1039 } else if (font >= 2 && font <= 5) {
1040 features.require("pifont");
1044 if (pdfoptions().use_hyperref) {
1045 features.require("hyperref");
1046 // due to interferences with babel and hyperref, the color package has to
1047 // be loaded after hyperref when hyperref is used with the colorlinks
1048 // option, see http://bugzilla.lyx.org/show_bug.cgi?id=5291
1049 if (pdfoptions().colorlinks)
1050 features.require("color");
1054 features.require("xetex");
1056 if (language->lang() == "vietnamese")
1057 features.require("vietnamese");
1058 else if (language->lang() == "japanese")
1059 features.require("japanese");
1063 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1064 TexRow & texrow) const
1066 os << "\\documentclass";
1068 DocumentClass const & tclass = documentClass();
1070 ostringstream clsoptions; // the document class options.
1072 if (tokenPos(tclass.opt_fontsize(),
1073 '|', fontsize) >= 0) {
1074 // only write if existing in list (and not default)
1075 clsoptions << fontsize << "pt,";
1078 // custom, A3, B3 and B4 paper sizes need geometry
1079 bool nonstandard_papersize = papersize == PAPER_B3
1080 || papersize == PAPER_B4
1081 || papersize == PAPER_A3
1082 || papersize == PAPER_CUSTOM;
1084 if (!use_geometry) {
1085 switch (papersize) {
1087 clsoptions << "a4paper,";
1089 case PAPER_USLETTER:
1090 clsoptions << "letterpaper,";
1093 clsoptions << "a5paper,";
1096 clsoptions << "b5paper,";
1098 case PAPER_USEXECUTIVE:
1099 clsoptions << "executivepaper,";
1102 clsoptions << "legalpaper,";
1114 if (sides != tclass.sides()) {
1117 clsoptions << "oneside,";
1120 clsoptions << "twoside,";
1126 if (columns != tclass.columns()) {
1128 clsoptions << "twocolumn,";
1130 clsoptions << "onecolumn,";
1134 && orientation == ORIENTATION_LANDSCAPE)
1135 clsoptions << "landscape,";
1137 // language should be a parameter to \documentclass
1138 if (language->babel() == "hebrew"
1139 && default_language->babel() != "hebrew")
1140 // This seems necessary
1141 features.useLanguage(default_language);
1143 ostringstream language_options;
1144 bool const use_babel = features.useBabel();
1146 language_options << features.getLanguages();
1147 if (!language->babel().empty()) {
1148 if (!language_options.str().empty())
1149 language_options << ',';
1150 language_options << language->babel();
1152 // if Vietnamese is used, babel must directly be loaded
1153 // with language options, not in the class options, see
1154 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1155 size_t viet = language_options.str().find("vietnam");
1156 // viet = string::npos when not found
1157 // the same is for all other languages that are not directly supported by
1158 // babel, but where LaTeX-packages add babel support.
1159 // this is currently the case for Latvian, Lithuanian, and Mongolian
1160 size_t latvian = language_options.str().find("latvian");
1161 size_t lithu = language_options.str().find("lithuanian");
1162 size_t mongo = language_options.str().find("mongolian");
1163 // if Japanese is used, babel must directly be loaded
1164 // with language options, not in the class options, see
1165 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1166 size_t japan = language_options.str().find("japanese");
1167 if (lyxrc.language_global_options && !language_options.str().empty()
1168 && viet == string::npos && japan == string::npos
1169 && latvian == string::npos && lithu == string::npos
1170 && mongo == string::npos)
1171 clsoptions << language_options.str() << ',';
1174 // the predefined options from the layout
1175 if (use_default_options && !tclass.options().empty())
1176 clsoptions << tclass.options() << ',';
1178 // the user-defined options
1179 if (!options.empty()) {
1180 clsoptions << options << ',';
1183 string strOptions(clsoptions.str());
1184 if (!strOptions.empty()) {
1185 strOptions = rtrim(strOptions, ",");
1187 os << '[' << from_utf8(strOptions) << ']';
1190 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1192 // end of \documentclass defs
1195 os << "\\usepackage{fontspec}\n";
1199 // font selection must be done before loading fontenc.sty
1200 string const fonts =
1201 loadFonts(fontsRoman, fontsSans,
1202 fontsTypewriter, fontsSC, fontsOSF,
1203 fontsSansScale, fontsTypewriterScale, useXetex);
1204 if (!fonts.empty()) {
1205 os << from_ascii(fonts);
1208 if (fontsDefaultFamily != "default")
1209 os << "\\renewcommand{\\familydefault}{\\"
1210 << from_ascii(fontsDefaultFamily) << "}\n";
1212 // set font encoding
1213 // this one is not per buffer
1214 // for arabic_arabi and farsi we also need to load the LAE and
1216 // XeTeX works without fontenc
1217 if (lyxrc.fontenc != "default" && language->lang() != "japanese"
1219 if (language->lang() == "arabic_arabi"
1220 || language->lang() == "farsi") {
1221 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1222 << ",LFE,LAE]{fontenc}\n";
1225 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1231 // handle inputenc etc.
1232 writeEncodingPreamble(os, features, texrow);
1234 if (!listings_params.empty() || features.isRequired("listings")) {
1235 os << "\\usepackage{listings}\n";
1238 if (!listings_params.empty()) {
1240 // do not test validity because listings_params is
1241 // supposed to be valid
1243 InsetListingsParams(listings_params).separatedParams(true);
1244 // we can't support all packages, but we should load the color package
1245 if (par.find("\\color", 0) != string::npos)
1246 features.require("color");
1247 os << from_utf8(par);
1248 // count the number of newlines
1249 for (size_t i = 0; i < par.size(); ++i)
1255 if (!tclass.provides("geometry")
1256 && (use_geometry || nonstandard_papersize)) {
1257 odocstringstream ods;
1258 if (!getGraphicsDriver("geometry").empty())
1259 ods << getGraphicsDriver("geometry");
1260 if (orientation == ORIENTATION_LANDSCAPE)
1261 ods << ",landscape";
1262 switch (papersize) {
1264 if (!paperwidth.empty())
1265 ods << ",paperwidth="
1266 << from_ascii(paperwidth);
1267 if (!paperheight.empty())
1268 ods << ",paperheight="
1269 << from_ascii(paperheight);
1271 case PAPER_USLETTER:
1272 ods << ",letterpaper";
1275 ods << ",legalpaper";
1277 case PAPER_USEXECUTIVE:
1278 ods << ",executivepaper";
1299 // default papersize ie PAPER_DEFAULT
1300 switch (lyxrc.default_papersize) {
1301 case PAPER_DEFAULT: // keep compiler happy
1302 case PAPER_USLETTER:
1303 ods << ",letterpaper";
1306 ods << ",legalpaper";
1308 case PAPER_USEXECUTIVE:
1309 ods << ",executivepaper";
1329 docstring const g_options = trim(ods.str(), ",");
1330 os << "\\usepackage";
1331 if (!g_options.empty())
1332 os << '[' << g_options << ']';
1333 os << "{geometry}\n";
1335 os << "\\geometry{verbose";
1336 if (!topmargin.empty())
1337 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1338 if (!bottommargin.empty())
1339 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1340 if (!leftmargin.empty())
1341 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1342 if (!rightmargin.empty())
1343 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1344 if (!headheight.empty())
1345 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1346 if (!headsep.empty())
1347 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1348 if (!footskip.empty())
1349 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1350 if (!columnsep.empty())
1351 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1354 } else if (orientation == ORIENTATION_LANDSCAPE) {
1355 features.require("papersize");
1358 if (tokenPos(tclass.opt_pagestyle(),
1359 '|', pagestyle) >= 0) {
1360 if (pagestyle == "fancy") {
1361 os << "\\usepackage{fancyhdr}\n";
1364 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1368 // only output when the background color is not white
1369 if (backgroundcolor != lyx::rgbFromHexName("#ffffff")) {
1370 // only require color here, the background color will be defined
1371 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1373 features.require("color");
1374 features.require("pagecolor");
1377 // Only if class has a ToC hierarchy
1378 if (tclass.hasTocLevels()) {
1379 if (secnumdepth != tclass.secnumdepth()) {
1380 os << "\\setcounter{secnumdepth}{"
1385 if (tocdepth != tclass.tocdepth()) {
1386 os << "\\setcounter{tocdepth}{"
1393 if (paragraph_separation) {
1394 // when skip separation
1395 switch (getDefSkip().kind()) {
1396 case VSpace::SMALLSKIP:
1397 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1399 case VSpace::MEDSKIP:
1400 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1402 case VSpace::BIGSKIP:
1403 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1405 case VSpace::LENGTH:
1406 os << "\\setlength{\\parskip}{"
1407 << from_utf8(getDefSkip().length().asLatexString())
1410 default: // should never happen // Then delete it.
1411 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1415 os << "\\setlength{\\parindent}{0pt}\n";
1418 // when separation by indentation
1419 // only output something when a width is given
1420 if (getIndentation().asLyXCommand() != "default") {
1421 os << "\\setlength{\\parindent}{"
1422 << from_utf8(getIndentation().asLatexCommand())
1428 // Now insert the LyX specific LaTeX commands...
1429 docstring lyxpreamble;
1431 // due to interferences with babel and hyperref, the color package has to
1432 // be loaded (when it is not already loaded) before babel when hyperref
1433 // is used with the colorlinks option, see
1434 // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1435 // we decided therefore to load color always before babel, see
1436 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1437 lyxpreamble += from_ascii(features.getColorOptions());
1439 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1441 && (features.isRequired("jurabib")
1442 || features.isRequired("hyperref")
1443 || features.isRequired("vietnamese")
1444 || features.isRequired("japanese") ) ) {
1446 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1447 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1450 // The optional packages;
1451 lyxpreamble += from_ascii(features.getPackages());
1453 // Additional Indices
1454 if (features.isRequired("splitidx")) {
1455 IndicesList::const_iterator iit = indiceslist().begin();
1456 IndicesList::const_iterator iend = indiceslist().end();
1457 for (; iit != iend; ++iit) {
1458 lyxpreamble += "\\newindex[";
1459 lyxpreamble += iit->index();
1460 lyxpreamble += "]{";
1461 lyxpreamble += iit->shortcut();
1462 lyxpreamble += "}\n";
1467 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1470 // * Hyperref manual: "Make sure it comes last of your loaded
1471 // packages, to give it a fighting chance of not being over-written,
1472 // since its job is to redefine many LaTeX commands."
1473 // * Email from Heiko Oberdiek: "It is usually better to load babel
1474 // before hyperref. Then hyperref has a chance to detect babel.
1475 // * Has to be loaded before the "LyX specific LaTeX commands" to
1476 // avoid errors with algorithm floats.
1477 // use hyperref explicitely when it is required
1478 if (features.isRequired("hyperref")) {
1479 odocstringstream oss;
1480 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1481 lyxpreamble += oss.str();
1484 // Will be surrounded by \makeatletter and \makeatother when not empty
1485 docstring atlyxpreamble;
1487 // Some macros LyX will need
1488 docstring tmppreamble(features.getMacros());
1490 if (!tmppreamble.empty())
1491 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1492 "LyX specific LaTeX commands.\n"
1493 + tmppreamble + '\n';
1495 // the text class specific preamble
1496 tmppreamble = features.getTClassPreamble();
1497 if (!tmppreamble.empty())
1498 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1499 "Textclass specific LaTeX commands.\n"
1500 + tmppreamble + '\n';
1502 /* the user-defined preamble */
1503 if (!containsOnly(preamble, " \n\t"))
1505 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1506 "User specified LaTeX commands.\n"
1507 + from_utf8(preamble) + '\n';
1509 // subfig loads internally the LaTeX package "caption". As
1510 // caption is a very popular package, users will load it in
1511 // the preamble. Therefore we must load subfig behind the
1512 // user-defined preamble and check if the caption package was
1513 // loaded or not. For the case that caption is loaded before
1514 // subfig, there is the subfig option "caption=false". This
1515 // option also works when a koma-script class is used and
1516 // koma's own caption commands are used instead of caption. We
1517 // use \PassOptionsToPackage here because the user could have
1518 // already loaded subfig in the preamble.
1519 if (features.isRequired("subfig")) {
1520 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1521 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1522 "\\usepackage{subfig}\n";
1525 // Itemize bullet settings need to be last in case the user
1526 // defines their own bullets that use a package included
1527 // in the user-defined preamble -- ARRae
1528 // Actually it has to be done much later than that
1529 // since some packages like frenchb make modifications
1530 // at \begin{document} time -- JMarc
1531 docstring bullets_def;
1532 for (int i = 0; i < 4; ++i) {
1533 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1534 if (bullets_def.empty())
1535 bullets_def += "\\AtBeginDocument{\n";
1536 bullets_def += " \\def\\labelitemi";
1538 // `i' is one less than the item to modify
1545 bullets_def += "ii";
1551 bullets_def += '{' +
1552 user_defined_bullet(i).getText()
1557 if (!bullets_def.empty())
1558 atlyxpreamble += bullets_def + "}\n\n";
1560 if (!atlyxpreamble.empty())
1561 lyxpreamble += "\n\\makeatletter\n"
1562 + atlyxpreamble + "\\makeatother\n\n";
1564 // We try to load babel late, in case it interferes with other packages.
1565 // Jurabib and Hyperref have to be called after babel, though.
1566 if (use_babel && !features.isRequired("jurabib")
1567 && !features.isRequired("hyperref")
1568 && !features.isRequired("vietnamese")
1569 && !features.isRequired("japanese")) {
1571 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1572 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1575 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1576 if (!i18npreamble.empty())
1577 lyxpreamble += i18npreamble + '\n';
1580 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1581 for (int j = 0; j != nlines; ++j) {
1587 // these packages (xunicode, for that matter) need to be loaded at least
1588 // after amsmath, amssymb, esint and the other packages that provide
1591 os << "\\usepackage{xunicode}\n";
1593 os << "\\usepackage{xltxtra}\n";
1600 void BufferParams::useClassDefaults()
1602 DocumentClass const & tclass = documentClass();
1604 sides = tclass.sides();
1605 columns = tclass.columns();
1606 pagestyle = tclass.pagestyle();
1607 use_default_options = true;
1608 // Only if class has a ToC hierarchy
1609 if (tclass.hasTocLevels()) {
1610 secnumdepth = tclass.secnumdepth();
1611 tocdepth = tclass.tocdepth();
1616 bool BufferParams::hasClassDefaults() const
1618 DocumentClass const & tclass = documentClass();
1620 return sides == tclass.sides()
1621 && columns == tclass.columns()
1622 && pagestyle == tclass.pagestyle()
1623 && use_default_options
1624 && secnumdepth == tclass.secnumdepth()
1625 && tocdepth == tclass.tocdepth();
1629 DocumentClass const & BufferParams::documentClass() const
1635 DocumentClass const * BufferParams::documentClassPtr() const {
1640 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1641 // evil, but this function is evil
1642 doc_class_ = const_cast<DocumentClass *>(tc);
1646 bool BufferParams::setBaseClass(string const & classname)
1648 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1649 LayoutFileList & bcl = LayoutFileList::get();
1650 if (!bcl.haveClass(classname)) {
1652 bformat(_("The document class %1$s could not be found. "
1653 "A default textclass with default layouts will be used. "
1654 "LyX might not be able to produce output unless a correct "
1655 "textclass is selected from the document settings dialog."),
1656 from_utf8(classname));
1657 frontend::Alert::error(_("Document class not found"), s);
1658 bcl.addEmptyClass(classname);
1661 bool const success = bcl[classname].load();
1664 bformat(_("The document class %1$s could not be loaded."),
1665 from_utf8(classname));
1666 frontend::Alert::error(_("Could not load class"), s);
1670 pimpl_->baseClass_ = classname;
1671 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1676 LayoutFile const * BufferParams::baseClass() const
1678 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1679 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1685 LayoutFileIndex const & BufferParams::baseClassID() const
1687 return pimpl_->baseClass_;
1691 void BufferParams::makeDocumentClass()
1696 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
1698 if (!local_layout.empty()) {
1699 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1700 docstring const msg = _("Error reading internal layout information");
1701 frontend::Alert::warning(_("Read Error"), msg);
1706 bool BufferParams::moduleCanBeAdded(string const & modName) const
1708 return layoutModules_.moduleCanBeAdded(modName, baseClass());
1712 bool BufferParams::addLayoutModule(string const & modName)
1714 LayoutModuleList::const_iterator it = layoutModules_.begin();
1715 LayoutModuleList::const_iterator end = layoutModules_.end();
1716 for (; it != end; it++)
1719 layoutModules_.push_back(modName);
1724 Font const BufferParams::getFont() const
1726 FontInfo f = documentClass().defaultfont();
1727 if (fontsDefaultFamily == "rmdefault")
1728 f.setFamily(ROMAN_FAMILY);
1729 else if (fontsDefaultFamily == "sfdefault")
1730 f.setFamily(SANS_FAMILY);
1731 else if (fontsDefaultFamily == "ttdefault")
1732 f.setFamily(TYPEWRITER_FAMILY);
1733 return Font(f, language);
1737 void BufferParams::readPreamble(Lexer & lex)
1739 if (lex.getString() != "\\begin_preamble")
1740 lyxerr << "Error (BufferParams::readPreamble):"
1741 "consistency check failed." << endl;
1743 preamble = lex.getLongString("\\end_preamble");
1747 void BufferParams::readLocalLayout(Lexer & lex)
1749 if (lex.getString() != "\\begin_local_layout")
1750 lyxerr << "Error (BufferParams::readLocalLayout):"
1751 "consistency check failed." << endl;
1753 local_layout = lex.getLongString("\\end_local_layout");
1757 void BufferParams::readLanguage(Lexer & lex)
1759 if (!lex.next()) return;
1761 string const tmptok = lex.getString();
1763 // check if tmptok is part of tex_babel in tex-defs.h
1764 language = languages.getLanguage(tmptok);
1766 // Language tmptok was not found
1767 language = default_language;
1768 lyxerr << "Warning: Setting language `"
1769 << tmptok << "' to `" << language->lang()
1775 void BufferParams::readGraphicsDriver(Lexer & lex)
1780 string const tmptok = lex.getString();
1781 // check if tmptok is part of tex_graphics in tex_defs.h
1784 string const test = tex_graphics[n++];
1786 if (test == tmptok) {
1787 graphicsDriver = tmptok;
1792 "Warning: graphics driver `$$Token' not recognized!\n"
1793 " Setting graphics driver to `default'.\n");
1794 graphicsDriver = "default";
1801 void BufferParams::readBullets(Lexer & lex)
1806 int const index = lex.getInteger();
1808 int temp_int = lex.getInteger();
1809 user_defined_bullet(index).setFont(temp_int);
1810 temp_bullet(index).setFont(temp_int);
1812 user_defined_bullet(index).setCharacter(temp_int);
1813 temp_bullet(index).setCharacter(temp_int);
1815 user_defined_bullet(index).setSize(temp_int);
1816 temp_bullet(index).setSize(temp_int);
1820 void BufferParams::readBulletsLaTeX(Lexer & lex)
1822 // The bullet class should be able to read this.
1825 int const index = lex.getInteger();
1827 docstring const temp_str = lex.getDocString();
1829 user_defined_bullet(index).setText(temp_str);
1830 temp_bullet(index).setText(temp_str);
1834 void BufferParams::readModules(Lexer & lex)
1836 if (!lex.eatLine()) {
1837 lyxerr << "Error (BufferParams::readModules):"
1838 "Unexpected end of input." << endl;
1842 string mod = lex.getString();
1843 if (mod == "\\end_modules")
1845 addLayoutModule(mod);
1851 void BufferParams::readRemovedModules(Lexer & lex)
1853 if (!lex.eatLine()) {
1854 lyxerr << "Error (BufferParams::readRemovedModules):"
1855 "Unexpected end of input." << endl;
1859 string mod = lex.getString();
1860 if (mod == "\\end_removed_modules")
1862 removedModules_.push_back(mod);
1865 // now we want to remove any removed modules that were previously
1866 // added. normally, that will be because default modules were added in
1867 // setBaseClass(), which gets called when \textclass is read at the
1868 // start of the read.
1869 list<string>::const_iterator rit = removedModules_.begin();
1870 list<string>::const_iterator const ren = removedModules_.end();
1871 for (; rit != ren; rit++) {
1872 LayoutModuleList::iterator const mit = layoutModules_.begin();
1873 LayoutModuleList::iterator const men = layoutModules_.end();
1874 LayoutModuleList::iterator found = find(mit, men, *rit);
1877 layoutModules_.erase(found);
1882 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1884 char real_papersize = papersize;
1885 if (real_papersize == PAPER_DEFAULT)
1886 real_papersize = lyxrc.default_papersize;
1888 switch (real_papersize) {
1890 // could be anything, so don't guess
1892 case PAPER_CUSTOM: {
1893 if (purpose == XDVI && !paperwidth.empty() &&
1894 !paperheight.empty()) {
1895 // heightxwidth<unit>
1896 string first = paperwidth;
1897 string second = paperheight;
1898 if (orientation == ORIENTATION_LANDSCAPE)
1901 return first.erase(first.length() - 2)
1913 // dvips and dvipdfm do not know this
1914 if (purpose == DVIPS || purpose == DVIPDFM)
1918 // dvipdfm does not know this
1919 if (purpose == DVIPDFM)
1923 // dvipdfm does not know this
1924 if (purpose == DVIPDFM)
1927 case PAPER_USEXECUTIVE:
1928 // dvipdfm does not know this
1929 if (purpose == DVIPDFM)
1934 case PAPER_USLETTER:
1936 if (purpose == XDVI)
1943 string const BufferParams::dvips_options() const
1948 && papersize == PAPER_CUSTOM
1949 && !lyxrc.print_paper_dimension_flag.empty()
1950 && !paperwidth.empty()
1951 && !paperheight.empty()) {
1952 // using a custom papersize
1953 result = lyxrc.print_paper_dimension_flag;
1954 result += ' ' + paperwidth;
1955 result += ',' + paperheight;
1957 string const paper_option = paperSizeName(DVIPS);
1958 if (!paper_option.empty() && (paper_option != "letter" ||
1959 orientation != ORIENTATION_LANDSCAPE)) {
1960 // dvips won't accept -t letter -t landscape.
1961 // In all other cases, include the paper size
1963 result = lyxrc.print_paper_flag;
1964 result += ' ' + paper_option;
1967 if (orientation == ORIENTATION_LANDSCAPE &&
1968 papersize != PAPER_CUSTOM)
1969 result += ' ' + lyxrc.print_landscape_flag;
1974 string BufferParams::babelCall(string const & lang_opts) const
1976 string lang_pack = lyxrc.language_package;
1977 if (lang_pack != "\\usepackage{babel}")
1979 // suppress the babel call when there is no babel language defined
1980 // for the document language in the lib/languages file and if no
1981 // other languages are used (lang_opts is then empty)
1982 if (lang_opts.empty())
1984 // If Vietnamese is used, babel must directly be loaded with the
1985 // language options, see
1986 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1987 size_t viet = lang_opts.find("vietnam");
1988 // viet = string::npos when not found
1989 // the same is for all other languages that are not directly supported by
1990 // babel, but where LaTeX-packages add babel support.
1991 // this is currently the case for Latvian, Lithuanian, and Mongolian
1992 size_t latvian = lang_opts.find("latvian");
1993 size_t lithu = lang_opts.find("lithuanian");
1994 size_t mongo = lang_opts.find("mongolian");
1995 // If Japanese is used, babel must directly be loaded with the
1996 // language options, see
1997 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1998 size_t japan = lang_opts.find("japanese");
1999 if (!lyxrc.language_global_options || viet != string::npos
2000 || japan != string::npos || latvian != string::npos
2001 || lithu != string::npos || mongo != string::npos)
2002 return "\\usepackage[" + lang_opts + "]{babel}";
2007 docstring BufferParams::getGraphicsDriver(string const & package) const
2011 if (package == "geometry") {
2012 if (graphicsDriver == "dvips"
2013 || graphicsDriver == "dvipdfm"
2014 || graphicsDriver == "pdftex"
2015 || graphicsDriver == "vtex")
2016 result = from_ascii(graphicsDriver);
2017 else if (graphicsDriver == "dvipdfmx")
2018 result = from_ascii("dvipdfm");
2025 void BufferParams::writeEncodingPreamble(odocstream & os,
2026 LaTeXFeatures & features, TexRow & texrow) const
2030 if (inputenc == "auto") {
2031 string const doc_encoding =
2032 language->encoding()->latexName();
2033 Encoding::Package const package =
2034 language->encoding()->package();
2036 // Create a list with all the input encodings used
2038 set<string> encodings =
2039 features.getEncodingSet(doc_encoding);
2041 // If the "japanese" package (i.e. pLaTeX) is used,
2042 // inputenc must be omitted.
2043 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2044 if (package == Encoding::japanese)
2045 features.require("japanese");
2047 if ((!encodings.empty() || package == Encoding::inputenc)
2048 && !features.isRequired("japanese")) {
2049 os << "\\usepackage[";
2050 set<string>::const_iterator it = encodings.begin();
2051 set<string>::const_iterator const end = encodings.end();
2053 os << from_ascii(*it);
2056 for (; it != end; ++it)
2057 os << ',' << from_ascii(*it);
2058 if (package == Encoding::inputenc) {
2059 if (!encodings.empty())
2061 os << from_ascii(doc_encoding);
2063 os << "]{inputenc}\n";
2066 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2067 if (language->encoding()->name() == "utf8-cjk"
2068 && LaTeXFeatures::isAvailable("CJKutf8"))
2069 os << "\\usepackage{CJKutf8}\n";
2071 os << "\\usepackage{CJK}\n";
2074 } else if (inputenc != "default") {
2075 switch (encoding().package()) {
2076 case Encoding::none:
2077 case Encoding::japanese:
2079 case Encoding::inputenc:
2080 // do not load inputenc if japanese is used
2081 if (features.isRequired("japanese"))
2083 os << "\\usepackage[" << from_ascii(inputenc)
2088 if (encoding().name() == "utf8-cjk"
2089 && LaTeXFeatures::isAvailable("CJKutf8"))
2090 os << "\\usepackage{CJKutf8}\n";
2092 os << "\\usepackage{CJK}\n";
2098 // The encoding "armscii8" (for Armenian) is only available when
2099 // the package "armtex" is loaded.
2100 if (language->encoding()->latexName() == "armscii8"
2101 || inputenc == "armscii8") {
2102 os << "\\usepackage{armtex}\n";
2108 string const BufferParams::parseFontName(string const & name) const
2110 string mangled = name;
2111 size_t const idx = mangled.find('[');
2112 if (idx == string::npos || idx == 0)
2115 return mangled.substr(0, idx - 1);
2119 string const BufferParams::loadFonts(string const & rm,
2120 string const & sf, string const & tt,
2121 bool const & sc, bool const & osf,
2122 int const & sfscale, int const & ttscale,
2123 bool const & xetex) const
2125 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2126 several packages have been replaced by others, that might not
2127 be installed on every system. We have to take care for that
2128 (see psnfss.pdf). We try to support all psnfss fonts as well
2129 as the fonts that have become de facto standard in the LaTeX
2130 world (e.g. Latin Modern). We do not support obsolete fonts
2131 (like PSLatex). In general, it should be possible to mix any
2132 rm font with any sf or tt font, respectively. (JSpitzm)
2134 -- separate math fonts.
2137 if (rm == "default" && sf == "default" && tt == "default")
2144 if (rm != "default")
2145 os << "\\setmainfont[Mapping=tex-text]{"
2146 << parseFontName(rm) << "}\n";
2147 if (sf != "default") {
2148 string const sans = parseFontName(sf);
2150 os << "\\setsansfont[Scale="
2151 << float(sfscale) / 100
2152 << ",Mapping=tex-text]{"
2155 os << "\\setsansfont[Mapping=tex-text]{"
2158 if (tt != "default") {
2159 string const mono = parseFontName(tt);
2161 os << "\\setmonofont[Scale="
2162 << float(sfscale) / 100
2166 os << "\\setmonofont[Mapping=tex-text]{"
2170 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2175 // Computer Modern (must be explicitely selectable -- there might be classes
2176 // that define a different default font!
2178 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2179 // osf for Computer Modern needs eco.sty
2181 os << "\\usepackage{eco}\n";
2183 // Latin Modern Roman
2184 else if (rm == "lmodern")
2185 os << "\\usepackage{lmodern}\n";
2187 else if (rm == "ae") {
2188 // not needed when using OT1 font encoding.
2189 if (lyxrc.fontenc != "default")
2190 os << "\\usepackage{ae,aecompl}\n";
2193 else if (rm == "times") {
2194 // try to load the best available package
2195 if (LaTeXFeatures::isAvailable("mathptmx"))
2196 os << "\\usepackage{mathptmx}\n";
2197 else if (LaTeXFeatures::isAvailable("mathptm"))
2198 os << "\\usepackage{mathptm}\n";
2200 os << "\\usepackage{times}\n";
2203 else if (rm == "palatino") {
2204 // try to load the best available package
2205 if (LaTeXFeatures::isAvailable("mathpazo")) {
2206 os << "\\usepackage";
2212 // "osf" includes "sc"!
2216 os << "{mathpazo}\n";
2218 else if (LaTeXFeatures::isAvailable("mathpple"))
2219 os << "\\usepackage{mathpple}\n";
2221 os << "\\usepackage{palatino}\n";
2224 else if (rm == "utopia") {
2225 // fourier supersedes utopia.sty, but does
2226 // not work with OT1 encoding.
2227 if (LaTeXFeatures::isAvailable("fourier")
2228 && lyxrc.fontenc != "default") {
2229 os << "\\usepackage";
2240 os << "{fourier}\n";
2243 os << "\\usepackage{utopia}\n";
2245 // Bera (complete fontset)
2246 else if (rm == "bera" && sf == "default" && tt == "default")
2247 os << "\\usepackage{bera}\n";
2249 else if (rm != "default")
2250 os << "\\usepackage" << "{" << rm << "}\n";
2253 // Helvetica, Bera Sans
2254 if (sf == "helvet" || sf == "berasans") {
2256 os << "\\usepackage[scaled=" << float(sfscale) / 100
2257 << "]{" << sf << "}\n";
2259 os << "\\usepackage{" << sf << "}\n";
2262 else if (sf == "avant")
2263 os << "\\usepackage{" << sf << "}\n";
2264 // Computer Modern, Latin Modern, CM Bright
2265 else if (sf != "default")
2266 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2268 // monospaced/typewriter
2269 // Courier, LuxiMono
2270 if (tt == "luximono" || tt == "beramono") {
2272 os << "\\usepackage[scaled=" << float(ttscale) / 100
2273 << "]{" << tt << "}\n";
2275 os << "\\usepackage{" << tt << "}\n";
2278 else if (tt == "courier" )
2279 os << "\\usepackage{" << tt << "}\n";
2280 // Computer Modern, Latin Modern, CM Bright
2281 else if (tt != "default")
2282 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2288 Encoding const & BufferParams::encoding() const
2291 return *(encodings.fromLaTeXName("utf8-plain"));
2292 if (inputenc == "auto" || inputenc == "default")
2293 return *language->encoding();
2294 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2297 LYXERR0("Unknown inputenc value `" << inputenc
2298 << "'. Using `auto' instead.");
2299 return *language->encoding();
2303 CiteEngine BufferParams::citeEngine() const
2305 // FIXME the class should provide the numerical/
2306 // authoryear choice
2307 if (documentClass().provides("natbib")
2308 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2309 return ENGINE_NATBIB_AUTHORYEAR;
2310 return cite_engine_;
2314 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2316 cite_engine_ = cite_engine;