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 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
76 "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
77 "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
78 "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
83 static char const * const string_orientation[] = {
84 "portrait", "landscape", ""
88 static char const * const string_footnotekinds[] = {
89 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
93 static char const * const tex_graphics[] = {
94 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
95 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
96 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
97 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
108 // Paragraph separation
109 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
112 ParSepTranslator const init_parseptranslator()
114 ParSepTranslator translator
115 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
116 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
121 ParSepTranslator const & parseptranslator()
123 static ParSepTranslator translator = init_parseptranslator();
129 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
132 QuotesLangTranslator const init_quoteslangtranslator()
134 QuotesLangTranslator translator
135 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
136 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
137 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
138 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
139 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
140 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
145 QuotesLangTranslator const & quoteslangtranslator()
147 static QuotesLangTranslator translator = init_quoteslangtranslator();
153 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
156 static PaperSizeTranslator initPaperSizeTranslator()
158 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
159 translator.addPair(string_papersize[1], PAPER_CUSTOM);
160 translator.addPair(string_papersize[2], PAPER_USLETTER);
161 translator.addPair(string_papersize[3], PAPER_USLEGAL);
162 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
163 translator.addPair(string_papersize[5], PAPER_A0);
164 translator.addPair(string_papersize[6], PAPER_A1);
165 translator.addPair(string_papersize[7], PAPER_A2);
166 translator.addPair(string_papersize[8], PAPER_A3);
167 translator.addPair(string_papersize[9], PAPER_A4);
168 translator.addPair(string_papersize[10], PAPER_A5);
169 translator.addPair(string_papersize[11], PAPER_A6);
170 translator.addPair(string_papersize[12], PAPER_B0);
171 translator.addPair(string_papersize[13], PAPER_B1);
172 translator.addPair(string_papersize[14], PAPER_B2);
173 translator.addPair(string_papersize[15], PAPER_B3);
174 translator.addPair(string_papersize[16], PAPER_B4);
175 translator.addPair(string_papersize[17], PAPER_B5);
176 translator.addPair(string_papersize[18], PAPER_B6);
177 translator.addPair(string_papersize[19], PAPER_C0);
178 translator.addPair(string_papersize[20], PAPER_C1);
179 translator.addPair(string_papersize[21], PAPER_C2);
180 translator.addPair(string_papersize[22], PAPER_C3);
181 translator.addPair(string_papersize[23], PAPER_C4);
182 translator.addPair(string_papersize[24], PAPER_C5);
183 translator.addPair(string_papersize[25], PAPER_C6);
184 translator.addPair(string_papersize[26], PAPER_JISB0);
185 translator.addPair(string_papersize[27], PAPER_JISB1);
186 translator.addPair(string_papersize[28], PAPER_JISB2);
187 translator.addPair(string_papersize[29], PAPER_JISB3);
188 translator.addPair(string_papersize[30], PAPER_JISB4);
189 translator.addPair(string_papersize[31], PAPER_JISB5);
190 translator.addPair(string_papersize[32], PAPER_JISB6);
195 PaperSizeTranslator const & papersizetranslator()
197 static PaperSizeTranslator translator = initPaperSizeTranslator();
203 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
206 PaperOrientationTranslator const init_paperorientationtranslator()
208 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
209 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
214 PaperOrientationTranslator const & paperorientationtranslator()
216 static PaperOrientationTranslator translator = init_paperorientationtranslator();
222 typedef Translator<int, PageSides> SidesTranslator;
225 SidesTranslator const init_sidestranslator()
227 SidesTranslator translator(1, OneSide);
228 translator.addPair(2, TwoSides);
233 SidesTranslator const & sidestranslator()
235 static SidesTranslator translator = init_sidestranslator();
241 typedef Translator<int, BufferParams::Package> PackageTranslator;
244 PackageTranslator const init_packagetranslator()
246 PackageTranslator translator(0, BufferParams::package_off);
247 translator.addPair(1, BufferParams::package_auto);
248 translator.addPair(2, BufferParams::package_on);
253 PackageTranslator const & packagetranslator()
255 static PackageTranslator translator = init_packagetranslator();
261 typedef Translator<string, CiteEngine> CiteEngineTranslator;
264 CiteEngineTranslator const init_citeenginetranslator()
266 CiteEngineTranslator translator("basic", ENGINE_BASIC);
267 translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
268 translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
269 translator.addPair("jurabib", ENGINE_JURABIB);
274 CiteEngineTranslator const & citeenginetranslator()
276 static CiteEngineTranslator translator = init_citeenginetranslator();
282 typedef Translator<string, Spacing::Space> SpaceTranslator;
285 SpaceTranslator const init_spacetranslator()
287 SpaceTranslator translator("default", Spacing::Default);
288 translator.addPair("single", Spacing::Single);
289 translator.addPair("onehalf", Spacing::Onehalf);
290 translator.addPair("double", Spacing::Double);
291 translator.addPair("other", Spacing::Other);
296 SpaceTranslator const & spacetranslator()
298 static SpaceTranslator translator = init_spacetranslator();
305 class BufferParams::Impl
310 AuthorList authorlist;
311 BranchList branchlist;
312 Bullet temp_bullets[4];
313 Bullet user_defined_bullets[4];
314 IndicesList indiceslist;
316 /** This is the amount of space used for paragraph_separation "skip",
317 * and for detached paragraphs in "indented" documents.
321 PDFOptions pdfoptions;
322 LayoutFileIndex baseClass_;
326 BufferParams::Impl::Impl()
327 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
329 // set initial author
331 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
336 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
340 return new BufferParams::Impl(*ptr);
344 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
350 BufferParams::BufferParams()
353 setBaseClass(defaultBaseclass());
355 paragraph_separation = ParagraphIndentSeparation;
356 quotes_language = InsetQuotes::EnglishQuotes;
357 fontsize = "default";
360 papersize = PAPER_DEFAULT;
361 orientation = ORIENTATION_PORTRAIT;
362 use_geometry = false;
363 use_amsmath = package_auto;
364 use_esint = package_auto;
365 use_mhchem = package_auto;
366 use_mathdots = package_auto;
367 cite_engine_ = ENGINE_BASIC;
368 use_bibtopic = false;
370 trackChanges = false;
371 outputChanges = false;
372 use_default_options = true;
373 maintain_unincluded_children = false;
376 language = default_language;
378 fontsRoman = "default";
379 fontsSans = "default";
380 fontsTypewriter = "default";
381 fontsDefaultFamily = "default";
385 fontsSansScale = 100;
386 fontsTypewriterScale = 100;
388 graphicsDriver = "default";
389 defaultOutputFormat = "default";
390 bibtex_command = "default";
391 index_command = "default";
394 listings_params = string();
395 pagestyle = "default";
396 suppress_date = false;
397 // no color is the default (white)
398 backgroundcolor = lyx::rgbFromHexName("#ffffff");
399 isbackgroundcolor = false;
400 // no color is the default (black)
401 fontcolor = lyx::rgbFromHexName("#000000");
403 // light gray is the default font color for greyed-out notes
404 notefontcolor = lyx::rgbFromHexName("#cccccc");
405 boxbgcolor = lyx::rgbFromHexName("#ff0000");
406 compressed = lyxrc.save_compressed;
407 for (int iter = 0; iter < 4; ++iter) {
408 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
409 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
412 indiceslist().addDefault(B_("Index"));
413 html_be_strict = false;
414 html_math_output = MathML;
415 html_math_img_scale = 1.0;
422 docstring BufferParams::B_(string const & l10n) const
424 LASSERT(language, /**/);
425 return getMessages(language->code()).get(l10n);
429 AuthorList & BufferParams::authors()
431 return pimpl_->authorlist;
435 AuthorList const & BufferParams::authors() const
437 return pimpl_->authorlist;
441 BranchList & BufferParams::branchlist()
443 return pimpl_->branchlist;
447 BranchList const & BufferParams::branchlist() const
449 return pimpl_->branchlist;
453 IndicesList & BufferParams::indiceslist()
455 return pimpl_->indiceslist;
459 IndicesList const & BufferParams::indiceslist() const
461 return pimpl_->indiceslist;
465 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
467 LASSERT(index < 4, /**/);
468 return pimpl_->temp_bullets[index];
472 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
474 LASSERT(index < 4, /**/);
475 return pimpl_->temp_bullets[index];
479 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
481 LASSERT(index < 4, /**/);
482 return pimpl_->user_defined_bullets[index];
486 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
488 LASSERT(index < 4, /**/);
489 return pimpl_->user_defined_bullets[index];
493 Spacing & BufferParams::spacing()
495 return pimpl_->spacing;
499 Spacing const & BufferParams::spacing() const
501 return pimpl_->spacing;
505 PDFOptions & BufferParams::pdfoptions()
507 return pimpl_->pdfoptions;
511 PDFOptions const & BufferParams::pdfoptions() const
513 return pimpl_->pdfoptions;
517 HSpace const & BufferParams::getIndentation() const
519 return pimpl_->indentation;
523 void BufferParams::setIndentation(HSpace const & indent)
525 pimpl_->indentation = indent;
529 VSpace const & BufferParams::getDefSkip() const
531 return pimpl_->defskip;
535 void BufferParams::setDefSkip(VSpace const & vs)
537 // DEFSKIP will cause an infinite loop
538 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
539 pimpl_->defskip = vs;
543 string BufferParams::readToken(Lexer & lex, string const & token,
544 FileName const & filepath)
546 if (token == "\\textclass") {
548 string const classname = lex.getString();
549 // if there exists a local layout file, ignore the system one
550 // NOTE: in this case, the textclass (.cls file) is assumed to
553 LayoutFileList & bcl = LayoutFileList::get();
554 if (tcp.empty() && !filepath.empty())
555 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
559 setBaseClass(classname);
560 // We assume that a tex class exists for local or unknown
561 // layouts so this warning, will only be given for system layouts.
562 if (!baseClass()->isTeXClassAvailable()) {
563 docstring const desc =
564 translateIfPossible(from_utf8(baseClass()->description()));
565 docstring const prereqs =
566 from_utf8(baseClass()->prerequisites());
567 docstring const msg =
568 bformat(_("The selected document class\n"
570 "requires external files that are not available.\n"
571 "The document class can still be used, but the\n"
572 "document cannot be compiled until the following\n"
573 "prerequisites are installed:\n"
575 "See section 3.1.2.2 of the User's Guide for\n"
576 "more information."), desc, prereqs);
577 frontend::Alert::warning(_("Document class not available"),
580 } else if (token == "\\begin_preamble") {
582 } else if (token == "\\begin_local_layout") {
583 readLocalLayout(lex);
584 } else if (token == "\\begin_modules") {
586 } else if (token == "\\begin_removed_modules") {
587 readRemovedModules(lex);
588 } else if (token == "\\begin_includeonly") {
589 readIncludeonly(lex);
590 } else if (token == "\\maintain_unincluded_children") {
591 lex >> maintain_unincluded_children;
592 } else if (token == "\\options") {
594 options = lex.getString();
595 } else if (token == "\\use_default_options") {
596 lex >> use_default_options;
597 } else if (token == "\\master") {
599 master = lex.getString();
600 } else if (token == "\\suppress_date") {
601 lex >> suppress_date;
602 } else if (token == "\\language") {
604 } else if (token == "\\inputencoding") {
606 } else if (token == "\\graphics") {
607 readGraphicsDriver(lex);
608 } else if (token == "\\default_output_format") {
609 lex >> defaultOutputFormat;
610 } else if (token == "\\bibtex_command") {
612 bibtex_command = lex.getString();
613 } else if (token == "\\index_command") {
615 index_command = lex.getString();
616 } else if (token == "\\fontencoding") {
618 fontenc = lex.getString();
619 } else if (token == "\\font_roman") {
621 fontsRoman = lex.getString();
622 } else if (token == "\\font_sans") {
624 fontsSans = lex.getString();
625 } else if (token == "\\font_typewriter") {
627 fontsTypewriter = lex.getString();
628 } else if (token == "\\font_default_family") {
629 lex >> fontsDefaultFamily;
630 } else if (token == "\\use_xetex") {
632 } else if (token == "\\font_sc") {
634 } else if (token == "\\font_osf") {
636 } else if (token == "\\font_sf_scale") {
637 lex >> fontsSansScale;
638 } else if (token == "\\font_tt_scale") {
639 lex >> fontsTypewriterScale;
640 } else if (token == "\\font_cjk") {
642 } else if (token == "\\paragraph_separation") {
645 paragraph_separation = parseptranslator().find(parsep);
646 } else if (token == "\\paragraph_indentation") {
648 string indentation = lex.getString();
649 pimpl_->indentation = HSpace(indentation);
650 } else if (token == "\\defskip") {
652 string const defskip = lex.getString();
653 pimpl_->defskip = VSpace(defskip);
654 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
656 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
657 } else if (token == "\\quotes_language") {
660 quotes_language = quoteslangtranslator().find(quotes_lang);
661 } else if (token == "\\papersize") {
664 papersize = papersizetranslator().find(ppsize);
665 } else if (token == "\\use_geometry") {
667 } else if (token == "\\use_amsmath") {
670 use_amsmath = packagetranslator().find(use_ams);
671 } else if (token == "\\use_esint") {
674 use_esint = packagetranslator().find(useesint);
675 } else if (token == "\\use_mhchem") {
678 use_mhchem = packagetranslator().find(usemhchem);
679 } else if (token == "\\use_mathdots") {
682 use_mathdots = packagetranslator().find(usemathdots);
683 } else if (token == "\\cite_engine") {
686 cite_engine_ = citeenginetranslator().find(engine);
687 } else if (token == "\\use_bibtopic") {
689 } else if (token == "\\use_indices") {
691 } else if (token == "\\tracking_changes") {
693 } else if (token == "\\output_changes") {
694 lex >> outputChanges;
695 } else if (token == "\\branch") {
697 docstring branch = lex.getDocString();
698 branchlist().add(branch);
701 string const tok = lex.getString();
702 if (tok == "\\end_branch")
704 Branch * branch_ptr = branchlist().find(branch);
705 if (tok == "\\selected") {
708 branch_ptr->setSelected(lex.getInteger());
710 if (tok == "\\filename_suffix") {
713 branch_ptr->setFileNameSuffix(lex.getInteger());
715 if (tok == "\\color") {
717 string color = lex.getString();
719 branch_ptr->setColor(color);
720 // Update also the Color table:
722 color = lcolor.getX11Name(Color_background);
724 lcolor.setColor(to_utf8(branch), color);
727 } else if (token == "\\index") {
729 docstring index = lex.getDocString();
731 indiceslist().add(index);
734 string const tok = lex.getString();
735 if (tok == "\\end_index")
737 Index * index_ptr = indiceslist().find(index);
738 if (tok == "\\shortcut") {
740 shortcut = lex.getDocString();
742 index_ptr->setShortcut(shortcut);
744 if (tok == "\\color") {
746 string color = lex.getString();
748 index_ptr->setColor(color);
749 // Update also the Color table:
751 color = lcolor.getX11Name(Color_background);
753 if (!shortcut.empty())
754 lcolor.setColor(to_utf8(shortcut), color);
757 } else if (token == "\\author") {
759 istringstream ss(lex.getString());
762 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
763 } else if (token == "\\paperorientation") {
766 orientation = paperorientationtranslator().find(orient);
767 } else if (token == "\\backgroundcolor") {
769 backgroundcolor = lyx::rgbFromHexName(lex.getString());
770 isbackgroundcolor = true;
771 } else if (token == "\\fontcolor") {
773 fontcolor = lyx::rgbFromHexName(lex.getString());
775 } else if (token == "\\notefontcolor") {
777 string color = lex.getString();
778 notefontcolor = lyx::rgbFromHexName(color);
779 } else if (token == "\\boxbgcolor") {
781 string color = lex.getString();
782 boxbgcolor = lyx::rgbFromHexName(color);
783 } else if (token == "\\paperwidth") {
785 } else if (token == "\\paperheight") {
787 } else if (token == "\\leftmargin") {
789 } else if (token == "\\topmargin") {
791 } else if (token == "\\rightmargin") {
793 } else if (token == "\\bottommargin") {
795 } else if (token == "\\headheight") {
797 } else if (token == "\\headsep") {
799 } else if (token == "\\footskip") {
801 } else if (token == "\\columnsep") {
803 } else if (token == "\\paperfontsize") {
805 } else if (token == "\\papercolumns") {
807 } else if (token == "\\listings_params") {
810 listings_params = InsetListingsParams(par).params();
811 } else if (token == "\\papersides") {
814 sides = sidestranslator().find(psides);
815 } else if (token == "\\paperpagestyle") {
817 } else if (token == "\\bullet") {
819 } else if (token == "\\bulletLaTeX") {
820 readBulletsLaTeX(lex);
821 } else if (token == "\\secnumdepth") {
823 } else if (token == "\\tocdepth") {
825 } else if (token == "\\spacing") {
829 if (nspacing == "other") {
832 spacing().set(spacetranslator().find(nspacing), tmp_val);
833 } else if (token == "\\float_placement") {
834 lex >> float_placement;
836 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
837 string toktmp = pdfoptions().readToken(lex, token);
838 if (!toktmp.empty()) {
839 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
843 } else if (token == "\\html_math_output") {
846 html_math_output = static_cast<MathOutput>(temp);
847 } else if (token == "\\html_be_strict") {
848 lex >> html_be_strict;
849 } else if (token == "\\html_math_img_scale") {
850 lex >> html_math_img_scale;
851 } else if (token == "\\html_latex_start") {
853 html_latex_start = lex.getString();
854 } else if (token == "\\html_latex_end") {
856 html_latex_end = lex.getString();
857 } else if (token == "\\output_sync") {
859 } else if (token == "\\output_sync_macro") {
860 lex >> output_sync_macro;
861 } else if (token == "\\use_refstyle") {
864 lyxerr << "BufferParams::readToken(): Unknown token: " <<
873 void BufferParams::writeFile(ostream & os) const
875 // The top of the file is written by the buffer.
876 // Prints out the buffer info into the .lyx file given by file
879 os << "\\textclass " << baseClass()->name() << '\n';
882 if (!preamble.empty()) {
883 // remove '\n' from the end of preamble
884 string const tmppreamble = rtrim(preamble, "\n");
885 os << "\\begin_preamble\n"
887 << "\n\\end_preamble\n";
891 if (!options.empty()) {
892 os << "\\options " << options << '\n';
895 // use the class options defined in the layout?
896 os << "\\use_default_options "
897 << convert<string>(use_default_options) << "\n";
899 // the master document
900 if (!master.empty()) {
901 os << "\\master " << master << '\n';
905 if (!removedModules_.empty()) {
906 os << "\\begin_removed_modules" << '\n';
907 list<string>::const_iterator it = removedModules_.begin();
908 list<string>::const_iterator en = removedModules_.end();
909 for (; it != en; it++)
911 os << "\\end_removed_modules" << '\n';
915 if (!layoutModules_.empty()) {
916 os << "\\begin_modules" << '\n';
917 LayoutModuleList::const_iterator it = layoutModules_.begin();
918 LayoutModuleList::const_iterator en = layoutModules_.end();
919 for (; it != en; it++)
921 os << "\\end_modules" << '\n';
925 if (!includedChildren_.empty()) {
926 os << "\\begin_includeonly" << '\n';
927 list<string>::const_iterator it = includedChildren_.begin();
928 list<string>::const_iterator en = includedChildren_.end();
929 for (; it != en; it++)
931 os << "\\end_includeonly" << '\n';
933 os << "\\maintain_unincluded_children "
934 << convert<string>(maintain_unincluded_children) << '\n';
936 // local layout information
937 if (!local_layout.empty()) {
938 // remove '\n' from the end
939 string const tmplocal = rtrim(local_layout, "\n");
940 os << "\\begin_local_layout\n"
942 << "\n\\end_local_layout\n";
945 // then the text parameters
946 if (language != ignore_language)
947 os << "\\language " << language->lang() << '\n';
948 os << "\\inputencoding " << inputenc
949 << "\n\\fontencoding " << fontenc
950 << "\n\\font_roman " << fontsRoman
951 << "\n\\font_sans " << fontsSans
952 << "\n\\font_typewriter " << fontsTypewriter
953 << "\n\\font_default_family " << fontsDefaultFamily
954 << "\n\\use_xetex " << convert<string>(useXetex)
955 << "\n\\font_sc " << convert<string>(fontsSC)
956 << "\n\\font_osf " << convert<string>(fontsOSF)
957 << "\n\\font_sf_scale " << fontsSansScale
958 << "\n\\font_tt_scale " << fontsTypewriterScale
960 if (!fontsCJK.empty()) {
961 os << "\\font_cjk " << fontsCJK << '\n';
963 os << "\n\\graphics " << graphicsDriver << '\n';
964 os << "\\default_output_format " << defaultOutputFormat << '\n';
965 os << "\\output_sync " << output_sync << '\n';
966 if (!output_sync_macro.empty())
967 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
968 os << "\\bibtex_command " << bibtex_command << '\n';
969 os << "\\index_command " << index_command << '\n';
971 if (!float_placement.empty()) {
972 os << "\\float_placement " << float_placement << '\n';
974 os << "\\paperfontsize " << fontsize << '\n';
976 spacing().writeFile(os);
977 pdfoptions().writeFile(os);
979 os << "\\papersize " << string_papersize[papersize]
980 << "\n\\use_geometry " << convert<string>(use_geometry)
981 << "\n\\use_amsmath " << use_amsmath
982 << "\n\\use_esint " << use_esint
983 << "\n\\use_mhchem " << use_mhchem
984 << "\n\\use_mathdots " << use_mathdots
985 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
986 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
987 << "\n\\use_indices " << convert<string>(use_indices)
988 << "\n\\paperorientation " << string_orientation[orientation]
989 << "\n\\suppress_date " << convert<string>(suppress_date)
990 << "\n\\use_refstyle " << use_refstyle
992 if (isbackgroundcolor == true)
993 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
994 if (isfontcolor == true)
995 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
996 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
997 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
998 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
999 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1001 BranchList::const_iterator it = branchlist().begin();
1002 BranchList::const_iterator end = branchlist().end();
1003 for (; it != end; ++it) {
1004 os << "\\branch " << to_utf8(it->branch())
1005 << "\n\\selected " << it->isSelected()
1006 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1007 << "\n\\color " << lyx::X11hexname(it->color())
1012 IndicesList::const_iterator iit = indiceslist().begin();
1013 IndicesList::const_iterator iend = indiceslist().end();
1014 for (; iit != iend; ++iit) {
1015 os << "\\index " << to_utf8(iit->index())
1016 << "\n\\shortcut " << to_utf8(iit->shortcut())
1017 << "\n\\color " << lyx::X11hexname(iit->color())
1022 if (!paperwidth.empty())
1023 os << "\\paperwidth "
1024 << VSpace(paperwidth).asLyXCommand() << '\n';
1025 if (!paperheight.empty())
1026 os << "\\paperheight "
1027 << VSpace(paperheight).asLyXCommand() << '\n';
1028 if (!leftmargin.empty())
1029 os << "\\leftmargin "
1030 << VSpace(leftmargin).asLyXCommand() << '\n';
1031 if (!topmargin.empty())
1032 os << "\\topmargin "
1033 << VSpace(topmargin).asLyXCommand() << '\n';
1034 if (!rightmargin.empty())
1035 os << "\\rightmargin "
1036 << VSpace(rightmargin).asLyXCommand() << '\n';
1037 if (!bottommargin.empty())
1038 os << "\\bottommargin "
1039 << VSpace(bottommargin).asLyXCommand() << '\n';
1040 if (!headheight.empty())
1041 os << "\\headheight "
1042 << VSpace(headheight).asLyXCommand() << '\n';
1043 if (!headsep.empty())
1045 << VSpace(headsep).asLyXCommand() << '\n';
1046 if (!footskip.empty())
1048 << VSpace(footskip).asLyXCommand() << '\n';
1049 if (!columnsep.empty())
1050 os << "\\columnsep "
1051 << VSpace(columnsep).asLyXCommand() << '\n';
1052 os << "\\secnumdepth " << secnumdepth
1053 << "\n\\tocdepth " << tocdepth
1054 << "\n\\paragraph_separation "
1055 << string_paragraph_separation[paragraph_separation];
1056 if (!paragraph_separation)
1057 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1059 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1060 os << "\n\\quotes_language "
1061 << string_quotes_language[quotes_language]
1062 << "\n\\papercolumns " << columns
1063 << "\n\\papersides " << sides
1064 << "\n\\paperpagestyle " << pagestyle << '\n';
1065 if (!listings_params.empty())
1066 os << "\\listings_params \"" <<
1067 InsetListingsParams(listings_params).encodedString() << "\"\n";
1068 for (int i = 0; i < 4; ++i) {
1069 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1070 if (user_defined_bullet(i).getFont() != -1) {
1071 os << "\\bullet " << i << " "
1072 << user_defined_bullet(i).getFont() << " "
1073 << user_defined_bullet(i).getCharacter() << " "
1074 << user_defined_bullet(i).getSize() << "\n";
1078 os << "\\bulletLaTeX " << i << " \""
1079 << lyx::to_ascii(user_defined_bullet(i).getText())
1085 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1086 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1087 << "\\html_math_output " << html_math_output << '\n'
1088 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1090 if (html_math_img_scale != 1.0)
1091 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1092 if (!html_latex_start.empty())
1093 os << "\\html_latex_start " << html_latex_start << '\n';
1094 if (!html_latex_end.empty())
1095 os << "\\html_latex_end " << html_latex_end << '\n';
1097 os << pimpl_->authorlist;
1101 void BufferParams::validate(LaTeXFeatures & features) const
1103 features.require(documentClass().requires());
1105 if (outputChanges) {
1106 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1107 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1108 LaTeXFeatures::isAvailable("xcolor");
1110 switch (features.runparams().flavor) {
1111 case OutputParams::LATEX:
1113 features.require("ct-dvipost");
1114 features.require("dvipost");
1115 } else if (xcolorulem) {
1116 features.require("ct-xcolor-ulem");
1117 features.require("ulem");
1118 features.require("xcolor");
1120 features.require("ct-none");
1123 case OutputParams::PDFLATEX:
1124 case OutputParams::XETEX:
1126 features.require("ct-xcolor-ulem");
1127 features.require("ulem");
1128 features.require("xcolor");
1129 // improves color handling in PDF output
1130 features.require("pdfcolmk");
1132 features.require("ct-none");
1140 // Floats with 'Here definitely' as default setting.
1141 if (float_placement.find('H') != string::npos)
1142 features.require("float");
1144 // AMS Style is at document level
1145 if (use_amsmath == package_on
1146 || documentClass().provides("amsmath"))
1147 features.require("amsmath");
1148 if (use_esint == package_on)
1149 features.require("esint");
1150 if (use_mhchem == package_on)
1151 features.require("mhchem");
1152 if (use_mathdots == package_on)
1153 features.require("mathdots");
1155 // Document-level line spacing
1156 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1157 features.require("setspace");
1159 // the bullet shapes are buffer level not paragraph level
1160 // so they are tested here
1161 for (int i = 0; i < 4; ++i) {
1162 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1164 int const font = user_defined_bullet(i).getFont();
1166 int const c = user_defined_bullet(i).getCharacter();
1172 features.require("latexsym");
1174 } else if (font == 1) {
1175 features.require("amssymb");
1176 } else if (font >= 2 && font <= 5) {
1177 features.require("pifont");
1181 if (pdfoptions().use_hyperref) {
1182 features.require("hyperref");
1183 // due to interferences with babel and hyperref, the color package has to
1184 // be loaded after hyperref when hyperref is used with the colorlinks
1185 // option, see http://www.lyx.org/trac/ticket/5291
1186 if (pdfoptions().colorlinks)
1187 features.require("color");
1191 features.require("xetex");
1193 if (language->lang() == "vietnamese")
1194 features.require("vietnamese");
1195 else if (language->lang() == "japanese")
1196 features.require("japanese");
1200 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1201 TexRow & texrow, FileName const & filepath) const
1203 os << "\\documentclass";
1205 DocumentClass const & tclass = documentClass();
1207 ostringstream clsoptions; // the document class options.
1209 if (tokenPos(tclass.opt_fontsize(),
1210 '|', fontsize) >= 0) {
1211 // only write if existing in list (and not default)
1212 clsoptions << fontsize << "pt,";
1215 // all paper sizes except of A4, A5, B5 and the US sizes need the
1217 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1218 && papersize != PAPER_USLETTER
1219 && papersize != PAPER_USLEGAL
1220 && papersize != PAPER_USEXECUTIVE
1221 && papersize != PAPER_A4
1222 && papersize != PAPER_A5
1223 && papersize != PAPER_B5;
1225 if (!use_geometry) {
1226 switch (papersize) {
1228 clsoptions << "a4paper,";
1230 case PAPER_USLETTER:
1231 clsoptions << "letterpaper,";
1234 clsoptions << "a5paper,";
1237 clsoptions << "b5paper,";
1239 case PAPER_USEXECUTIVE:
1240 clsoptions << "executivepaper,";
1243 clsoptions << "legalpaper,";
1277 if (sides != tclass.sides()) {
1280 clsoptions << "oneside,";
1283 clsoptions << "twoside,";
1289 if (columns != tclass.columns()) {
1291 clsoptions << "twocolumn,";
1293 clsoptions << "onecolumn,";
1297 && orientation == ORIENTATION_LANDSCAPE)
1298 clsoptions << "landscape,";
1300 // language should be a parameter to \documentclass
1301 if (language->babel() == "hebrew"
1302 && default_language->babel() != "hebrew")
1303 // This seems necessary
1304 features.useLanguage(default_language);
1306 ostringstream language_options;
1307 bool const use_babel = features.useBabel() && !tclass.provides("babel");
1309 language_options << features.getLanguages();
1310 if (!language->babel().empty()) {
1311 if (!language_options.str().empty())
1312 language_options << ',';
1313 language_options << language->babel();
1315 if (lyxrc.language_global_options
1316 && !features.needBabelLangOptions())
1317 clsoptions << language_options.str() << ',';
1320 // the predefined options from the layout
1321 if (use_default_options && !tclass.options().empty())
1322 clsoptions << tclass.options() << ',';
1324 // the user-defined options
1325 if (!options.empty()) {
1326 clsoptions << options << ',';
1329 string strOptions(clsoptions.str());
1330 if (!strOptions.empty()) {
1331 strOptions = rtrim(strOptions, ",");
1333 os << '[' << from_utf8(strOptions) << ']';
1336 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1338 // end of \documentclass defs
1341 os << "\\usepackage{fontspec}\n";
1345 // font selection must be done before loading fontenc.sty
1346 string const fonts =
1347 loadFonts(fontsRoman, fontsSans,
1348 fontsTypewriter, fontsSC, fontsOSF,
1349 fontsSansScale, fontsTypewriterScale, useXetex);
1350 if (!fonts.empty()) {
1351 os << from_ascii(fonts);
1354 if (fontsDefaultFamily != "default")
1355 os << "\\renewcommand{\\familydefault}{\\"
1356 << from_ascii(fontsDefaultFamily) << "}\n";
1358 // set font encoding
1359 // for arabic_arabi and farsi we also need to load the LAE and
1361 // XeTeX works without fontenc
1362 if (font_encoding() != "default" && language->lang() != "japanese"
1363 && !useXetex && !tclass.provides("fontenc")) {
1364 size_t fars = language_options.str().find("farsi");
1365 size_t arab = language_options.str().find("arabic");
1366 if (language->lang() == "arabic_arabi"
1367 || language->lang() == "farsi" || fars != string::npos
1368 || arab != string::npos) {
1369 os << "\\usepackage[" << from_ascii(font_encoding())
1370 << ",LFE,LAE]{fontenc}\n";
1373 os << "\\usepackage[" << from_ascii(font_encoding())
1379 // handle inputenc etc.
1380 writeEncodingPreamble(os, features, texrow);
1383 if (!features.runparams().includeall && !includedChildren_.empty()) {
1384 os << "\\includeonly{";
1385 list<string>::const_iterator it = includedChildren_.begin();
1387 for (; it != includedChildren_.end() ; ++it) {
1388 string incfile = *it;
1389 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1390 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1392 if (!features.runparams().nice)
1394 // \includeonly doesn't want an extension
1395 incfile = changeExtension(incfile, string());
1396 incfile = support::latex_path(incfile);
1397 if (!incfile.empty()) {
1400 os << from_utf8(incfile);
1407 if (!listings_params.empty() || features.isRequired("listings")) {
1408 os << "\\usepackage{listings}\n";
1411 if (!listings_params.empty()) {
1413 // do not test validity because listings_params is
1414 // supposed to be valid
1416 InsetListingsParams(listings_params).separatedParams(true);
1417 // we can't support all packages, but we should load the color package
1418 if (par.find("\\color", 0) != string::npos)
1419 features.require("color");
1420 os << from_utf8(par);
1421 // count the number of newlines
1422 for (size_t i = 0; i < par.size(); ++i)
1428 if (!tclass.provides("geometry")
1429 && (use_geometry || nonstandard_papersize)) {
1430 odocstringstream ods;
1431 if (!getGraphicsDriver("geometry").empty())
1432 ods << getGraphicsDriver("geometry");
1433 if (orientation == ORIENTATION_LANDSCAPE)
1434 ods << ",landscape";
1435 switch (papersize) {
1437 if (!paperwidth.empty())
1438 ods << ",paperwidth="
1439 << from_ascii(paperwidth);
1440 if (!paperheight.empty())
1441 ods << ",paperheight="
1442 << from_ascii(paperheight);
1444 case PAPER_USLETTER:
1445 ods << ",letterpaper";
1448 ods << ",legalpaper";
1450 case PAPER_USEXECUTIVE:
1451 ods << ",executivepaper";
1538 // default papersize ie PAPER_DEFAULT
1539 switch (lyxrc.default_papersize) {
1540 case PAPER_DEFAULT: // keep compiler happy
1541 case PAPER_USLETTER:
1542 ods << ",letterpaper";
1545 ods << ",legalpaper";
1547 case PAPER_USEXECUTIVE:
1548 ods << ",executivepaper";
1590 docstring const g_options = trim(ods.str(), ",");
1591 os << "\\usepackage";
1592 if (!g_options.empty())
1593 os << '[' << g_options << ']';
1594 os << "{geometry}\n";
1596 // output this only if use_geometry is true
1598 os << "\\geometry{verbose";
1599 if (!topmargin.empty())
1600 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1601 if (!bottommargin.empty())
1602 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1603 if (!leftmargin.empty())
1604 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1605 if (!rightmargin.empty())
1606 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1607 if (!headheight.empty())
1608 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1609 if (!headsep.empty())
1610 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1611 if (!footskip.empty())
1612 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1613 if (!columnsep.empty())
1614 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1618 } else if (orientation == ORIENTATION_LANDSCAPE
1619 || papersize != PAPER_DEFAULT) {
1620 features.require("papersize");
1623 if (tokenPos(tclass.opt_pagestyle(),
1624 '|', pagestyle) >= 0) {
1625 if (pagestyle == "fancy") {
1626 os << "\\usepackage{fancyhdr}\n";
1629 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1633 // only output when the background color is not default
1634 if (isbackgroundcolor == true) {
1635 // only require color here, the background color will be defined
1636 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1638 features.require("color");
1639 features.require("pagecolor");
1642 // only output when the font color is not default
1643 if (isfontcolor == true) {
1644 // only require color here, the font color will be defined
1645 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1647 features.require("color");
1648 features.require("fontcolor");
1651 // Only if class has a ToC hierarchy
1652 if (tclass.hasTocLevels()) {
1653 if (secnumdepth != tclass.secnumdepth()) {
1654 os << "\\setcounter{secnumdepth}{"
1659 if (tocdepth != tclass.tocdepth()) {
1660 os << "\\setcounter{tocdepth}{"
1667 if (paragraph_separation) {
1668 // when skip separation
1669 switch (getDefSkip().kind()) {
1670 case VSpace::SMALLSKIP:
1671 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1673 case VSpace::MEDSKIP:
1674 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1676 case VSpace::BIGSKIP:
1677 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1679 case VSpace::LENGTH:
1680 os << "\\setlength{\\parskip}{"
1681 << from_utf8(getDefSkip().length().asLatexString())
1684 default: // should never happen // Then delete it.
1685 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1689 os << "\\setlength{\\parindent}{0pt}\n";
1692 // when separation by indentation
1693 // only output something when a width is given
1694 if (getIndentation().asLyXCommand() != "default") {
1695 os << "\\setlength{\\parindent}{"
1696 << from_utf8(getIndentation().asLatexCommand())
1702 // Now insert the LyX specific LaTeX commands...
1703 docstring lyxpreamble;
1706 if (!output_sync_macro.empty())
1707 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1708 else if (features.runparams().flavor == OutputParams::LATEX)
1709 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1710 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1711 lyxpreamble += "\\synctex=-1\n";
1714 // due to interferences with babel and hyperref, the color package has to
1715 // be loaded (when it is not already loaded) before babel when hyperref
1716 // is used with the colorlinks option, see
1717 // http://www.lyx.org/trac/ticket/5291
1718 // we decided therefore to load color always before babel, see
1719 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1720 lyxpreamble += from_ascii(features.getColorOptions());
1722 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1724 && (features.isRequired("jurabib")
1725 || features.isRequired("hyperref")
1726 || features.isRequired("vietnamese")
1727 || features.isRequired("japanese") ) ) {
1729 lyxpreamble += from_utf8(features.getBabelPresettings());
1730 lyxpreamble += from_utf8(babelCall(language_options.str(),
1731 features.needBabelLangOptions())) + '\n';
1732 lyxpreamble += from_utf8(features.getBabelPostsettings());
1735 // The optional packages;
1736 lyxpreamble += from_ascii(features.getPackages());
1738 // Additional Indices
1739 if (features.isRequired("splitidx")) {
1740 IndicesList::const_iterator iit = indiceslist().begin();
1741 IndicesList::const_iterator iend = indiceslist().end();
1742 for (; iit != iend; ++iit) {
1743 lyxpreamble += "\\newindex[";
1744 lyxpreamble += iit->index();
1745 lyxpreamble += "]{";
1746 lyxpreamble += iit->shortcut();
1747 lyxpreamble += "}\n";
1752 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1755 // * Hyperref manual: "Make sure it comes last of your loaded
1756 // packages, to give it a fighting chance of not being over-written,
1757 // since its job is to redefine many LaTeX commands."
1758 // * Email from Heiko Oberdiek: "It is usually better to load babel
1759 // before hyperref. Then hyperref has a chance to detect babel.
1760 // * Has to be loaded before the "LyX specific LaTeX commands" to
1761 // avoid errors with algorithm floats.
1762 // use hyperref explicitly if it is required
1763 if (features.isRequired("hyperref")) {
1764 // pass what we have to stream here, since we need
1765 // to access the stream itself in PDFOptions.
1769 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1771 OutputParams tmp_params = features.runparams();
1772 lines += pdfoptions().writeLaTeX(tmp_params, os,
1773 documentClass().provides("hyperref"));
1774 texrow.newlines(lines);
1775 // set back for the rest
1776 lyxpreamble.clear();
1777 } else if (features.isRequired("nameref"))
1778 // hyperref loads this automatically
1779 lyxpreamble += "\\usepackage{nameref}\n";
1781 // Will be surrounded by \makeatletter and \makeatother when not empty
1782 docstring atlyxpreamble;
1784 // Some macros LyX will need
1785 docstring tmppreamble(features.getMacros());
1787 if (!tmppreamble.empty())
1788 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1789 "LyX specific LaTeX commands.\n"
1790 + tmppreamble + '\n';
1792 // the text class specific preamble
1793 tmppreamble = features.getTClassPreamble();
1794 if (!tmppreamble.empty())
1795 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1796 "Textclass specific LaTeX commands.\n"
1797 + tmppreamble + '\n';
1799 // suppress date if selected
1800 // use \@ifundefined because we cannot be sure that every document class
1801 // has a \date command
1803 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1805 /* the user-defined preamble */
1806 if (!containsOnly(preamble, " \n\t"))
1808 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1809 "User specified LaTeX commands.\n"
1810 + from_utf8(preamble) + '\n';
1812 // subfig loads internally the LaTeX package "caption". As
1813 // caption is a very popular package, users will load it in
1814 // the preamble. Therefore we must load subfig behind the
1815 // user-defined preamble and check if the caption package was
1816 // loaded or not. For the case that caption is loaded before
1817 // subfig, there is the subfig option "caption=false". This
1818 // option also works when a koma-script class is used and
1819 // koma's own caption commands are used instead of caption. We
1820 // use \PassOptionsToPackage here because the user could have
1821 // already loaded subfig in the preamble.
1822 if (features.isRequired("subfig")) {
1823 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1824 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1825 "\\usepackage{subfig}\n";
1828 // Itemize bullet settings need to be last in case the user
1829 // defines their own bullets that use a package included
1830 // in the user-defined preamble -- ARRae
1831 // Actually it has to be done much later than that
1832 // since some packages like frenchb make modifications
1833 // at \begin{document} time -- JMarc
1834 docstring bullets_def;
1835 for (int i = 0; i < 4; ++i) {
1836 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1837 if (bullets_def.empty())
1838 bullets_def += "\\AtBeginDocument{\n";
1839 bullets_def += " \\def\\labelitemi";
1841 // `i' is one less than the item to modify
1848 bullets_def += "ii";
1854 bullets_def += '{' +
1855 user_defined_bullet(i).getText()
1860 if (!bullets_def.empty())
1861 atlyxpreamble += bullets_def + "}\n\n";
1863 if (!atlyxpreamble.empty())
1864 lyxpreamble += "\n\\makeatletter\n"
1865 + atlyxpreamble + "\\makeatother\n\n";
1867 // We try to load babel late, in case it interferes with other packages.
1868 // Jurabib and Hyperref have to be called after babel, though.
1869 if (use_babel && !features.isRequired("jurabib")
1870 && !features.isRequired("hyperref")
1871 && !features.isRequired("vietnamese")
1872 && !features.isRequired("japanese")) {
1874 lyxpreamble += from_utf8(features.getBabelPresettings());
1875 lyxpreamble += from_utf8(babelCall(language_options.str(),
1876 features.needBabelLangOptions())) + '\n';
1877 lyxpreamble += from_utf8(features.getBabelPostsettings());
1880 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1881 if (!i18npreamble.empty())
1882 lyxpreamble += i18npreamble + '\n';
1885 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1886 texrow.newlines(nlines);
1890 // these packages (xunicode, for that matter) need to be loaded at least
1891 // after amsmath, amssymb, esint and the other packages that provide
1894 os << "\\usepackage{xunicode}\n";
1896 os << "\\usepackage{xltxtra}\n";
1903 void BufferParams::useClassDefaults()
1905 DocumentClass const & tclass = documentClass();
1907 sides = tclass.sides();
1908 columns = tclass.columns();
1909 pagestyle = tclass.pagestyle();
1910 use_default_options = true;
1911 // Only if class has a ToC hierarchy
1912 if (tclass.hasTocLevels()) {
1913 secnumdepth = tclass.secnumdepth();
1914 tocdepth = tclass.tocdepth();
1919 bool BufferParams::hasClassDefaults() const
1921 DocumentClass const & tclass = documentClass();
1923 return sides == tclass.sides()
1924 && columns == tclass.columns()
1925 && pagestyle == tclass.pagestyle()
1926 && use_default_options
1927 && secnumdepth == tclass.secnumdepth()
1928 && tocdepth == tclass.tocdepth();
1932 DocumentClass const & BufferParams::documentClass() const
1938 DocumentClass const * BufferParams::documentClassPtr() const
1944 void BufferParams::setDocumentClass(DocumentClass const * const tc)
1946 // evil, but this function is evil
1947 doc_class_ = const_cast<DocumentClass *>(tc);
1951 bool BufferParams::setBaseClass(string const & classname)
1953 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1954 LayoutFileList & bcl = LayoutFileList::get();
1955 if (!bcl.haveClass(classname)) {
1957 bformat(_("The layout file:\n"
1959 "could not be found. A default textclass with default\n"
1960 "layouts will be used. LyX will not be able to produce\n"
1962 from_utf8(classname));
1963 frontend::Alert::error(_("Document class not found"), s);
1964 bcl.addEmptyClass(classname);
1967 bool const success = bcl[classname].load();
1970 bformat(_("Due to some error in it, the layout file:\n"
1972 "could not be loaded. A default textclass with default\n"
1973 "layouts will be used. LyX will not be able to produce\n"
1975 from_utf8(classname));
1976 frontend::Alert::error(_("Could not load class"), s);
1977 bcl.addEmptyClass(classname);
1980 pimpl_->baseClass_ = classname;
1981 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1986 LayoutFile const * BufferParams::baseClass() const
1988 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1989 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1995 LayoutFileIndex const & BufferParams::baseClassID() const
1997 return pimpl_->baseClass_;
2001 void BufferParams::makeDocumentClass()
2006 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
2008 if (!local_layout.empty()) {
2009 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
2010 docstring const msg = _("Error reading internal layout information");
2011 frontend::Alert::warning(_("Read Error"), msg);
2017 bool BufferParams::moduleCanBeAdded(string const & modName) const
2019 return layoutModules_.moduleCanBeAdded(modName, baseClass());
2023 bool BufferParams::addLayoutModule(string const & modName)
2025 LayoutModuleList::const_iterator it = layoutModules_.begin();
2026 LayoutModuleList::const_iterator end = layoutModules_.end();
2027 for (; it != end; it++)
2030 layoutModules_.push_back(modName);
2035 Font const BufferParams::getFont() const
2037 FontInfo f = documentClass().defaultfont();
2038 if (fontsDefaultFamily == "rmdefault")
2039 f.setFamily(ROMAN_FAMILY);
2040 else if (fontsDefaultFamily == "sfdefault")
2041 f.setFamily(SANS_FAMILY);
2042 else if (fontsDefaultFamily == "ttdefault")
2043 f.setFamily(TYPEWRITER_FAMILY);
2044 return Font(f, language);
2048 void BufferParams::readPreamble(Lexer & lex)
2050 if (lex.getString() != "\\begin_preamble")
2051 lyxerr << "Error (BufferParams::readPreamble):"
2052 "consistency check failed." << endl;
2054 preamble = lex.getLongString("\\end_preamble");
2058 void BufferParams::readLocalLayout(Lexer & lex)
2060 if (lex.getString() != "\\begin_local_layout")
2061 lyxerr << "Error (BufferParams::readLocalLayout):"
2062 "consistency check failed." << endl;
2064 local_layout = lex.getLongString("\\end_local_layout");
2068 void BufferParams::readLanguage(Lexer & lex)
2070 if (!lex.next()) return;
2072 string const tmptok = lex.getString();
2074 // check if tmptok is part of tex_babel in tex-defs.h
2075 language = languages.getLanguage(tmptok);
2077 // Language tmptok was not found
2078 language = default_language;
2079 lyxerr << "Warning: Setting language `"
2080 << tmptok << "' to `" << language->lang()
2086 void BufferParams::readGraphicsDriver(Lexer & lex)
2091 string const tmptok = lex.getString();
2092 // check if tmptok is part of tex_graphics in tex_defs.h
2095 string const test = tex_graphics[n++];
2097 if (test == tmptok) {
2098 graphicsDriver = tmptok;
2103 "Warning: graphics driver `$$Token' not recognized!\n"
2104 " Setting graphics driver to `default'.\n");
2105 graphicsDriver = "default";
2112 void BufferParams::readBullets(Lexer & lex)
2117 int const index = lex.getInteger();
2119 int temp_int = lex.getInteger();
2120 user_defined_bullet(index).setFont(temp_int);
2121 temp_bullet(index).setFont(temp_int);
2123 user_defined_bullet(index).setCharacter(temp_int);
2124 temp_bullet(index).setCharacter(temp_int);
2126 user_defined_bullet(index).setSize(temp_int);
2127 temp_bullet(index).setSize(temp_int);
2131 void BufferParams::readBulletsLaTeX(Lexer & lex)
2133 // The bullet class should be able to read this.
2136 int const index = lex.getInteger();
2138 docstring const temp_str = lex.getDocString();
2140 user_defined_bullet(index).setText(temp_str);
2141 temp_bullet(index).setText(temp_str);
2145 void BufferParams::readModules(Lexer & lex)
2147 if (!lex.eatLine()) {
2148 lyxerr << "Error (BufferParams::readModules):"
2149 "Unexpected end of input." << endl;
2153 string mod = lex.getString();
2154 if (mod == "\\end_modules")
2156 addLayoutModule(mod);
2162 void BufferParams::readRemovedModules(Lexer & lex)
2164 if (!lex.eatLine()) {
2165 lyxerr << "Error (BufferParams::readRemovedModules):"
2166 "Unexpected end of input." << endl;
2170 string mod = lex.getString();
2171 if (mod == "\\end_removed_modules")
2173 removedModules_.push_back(mod);
2176 // now we want to remove any removed modules that were previously
2177 // added. normally, that will be because default modules were added in
2178 // setBaseClass(), which gets called when \textclass is read at the
2179 // start of the read.
2180 list<string>::const_iterator rit = removedModules_.begin();
2181 list<string>::const_iterator const ren = removedModules_.end();
2182 for (; rit != ren; rit++) {
2183 LayoutModuleList::iterator const mit = layoutModules_.begin();
2184 LayoutModuleList::iterator const men = layoutModules_.end();
2185 LayoutModuleList::iterator found = find(mit, men, *rit);
2188 layoutModules_.erase(found);
2193 void BufferParams::readIncludeonly(Lexer & lex)
2195 if (!lex.eatLine()) {
2196 lyxerr << "Error (BufferParams::readIncludeonly):"
2197 "Unexpected end of input." << endl;
2201 string child = lex.getString();
2202 if (child == "\\end_includeonly")
2204 includedChildren_.push_back(child);
2210 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2212 char real_papersize = papersize;
2213 if (real_papersize == PAPER_DEFAULT)
2214 real_papersize = lyxrc.default_papersize;
2216 switch (real_papersize) {
2218 // could be anything, so don't guess
2220 case PAPER_CUSTOM: {
2221 if (purpose == XDVI && !paperwidth.empty() &&
2222 !paperheight.empty()) {
2223 // heightxwidth<unit>
2224 string first = paperwidth;
2225 string second = paperheight;
2226 if (orientation == ORIENTATION_LANDSCAPE)
2229 return first.erase(first.length() - 2)
2235 // dvips and dvipdfm do not know this
2236 if (purpose == DVIPS || purpose == DVIPDFM)
2240 if (purpose == DVIPS || purpose == DVIPDFM)
2244 if (purpose == DVIPS || purpose == DVIPDFM)
2254 if (purpose == DVIPS || purpose == DVIPDFM)
2258 if (purpose == DVIPS || purpose == DVIPDFM)
2262 if (purpose == DVIPS || purpose == DVIPDFM)
2266 if (purpose == DVIPS || purpose == DVIPDFM)
2270 if (purpose == DVIPS || purpose == DVIPDFM)
2274 // dvipdfm does not know this
2275 if (purpose == DVIPDFM)
2279 if (purpose == DVIPDFM)
2283 if (purpose == DVIPS || purpose == DVIPDFM)
2287 if (purpose == DVIPS || purpose == DVIPDFM)
2291 if (purpose == DVIPS || purpose == DVIPDFM)
2295 if (purpose == DVIPS || purpose == DVIPDFM)
2299 if (purpose == DVIPS || purpose == DVIPDFM)
2303 if (purpose == DVIPS || purpose == DVIPDFM)
2307 if (purpose == DVIPS || purpose == DVIPDFM)
2311 if (purpose == DVIPS || purpose == DVIPDFM)
2315 if (purpose == DVIPS || purpose == DVIPDFM)
2319 if (purpose == DVIPS || purpose == DVIPDFM)
2323 if (purpose == DVIPS || purpose == DVIPDFM)
2327 if (purpose == DVIPS || purpose == DVIPDFM)
2331 if (purpose == DVIPS || purpose == DVIPDFM)
2335 if (purpose == DVIPS || purpose == DVIPDFM)
2339 if (purpose == DVIPS || purpose == DVIPDFM)
2342 case PAPER_USEXECUTIVE:
2343 // dvipdfm does not know this
2344 if (purpose == DVIPDFM)
2349 case PAPER_USLETTER:
2351 if (purpose == XDVI)
2358 string const BufferParams::dvips_options() const
2363 && papersize == PAPER_CUSTOM
2364 && !lyxrc.print_paper_dimension_flag.empty()
2365 && !paperwidth.empty()
2366 && !paperheight.empty()) {
2367 // using a custom papersize
2368 result = lyxrc.print_paper_dimension_flag;
2369 result += ' ' + paperwidth;
2370 result += ',' + paperheight;
2372 string const paper_option = paperSizeName(DVIPS);
2373 if (!paper_option.empty() && (paper_option != "letter" ||
2374 orientation != ORIENTATION_LANDSCAPE)) {
2375 // dvips won't accept -t letter -t landscape.
2376 // In all other cases, include the paper size
2378 result = lyxrc.print_paper_flag;
2379 result += ' ' + paper_option;
2382 if (orientation == ORIENTATION_LANDSCAPE &&
2383 papersize != PAPER_CUSTOM)
2384 result += ' ' + lyxrc.print_landscape_flag;
2389 string const BufferParams::font_encoding() const
2391 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2395 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2397 if (lyxrc.language_package_selection == LyXRC::LP_CUSTOM)
2398 return lyxrc.language_custom_package;
2399 // suppress the babel call if there is no BabelName defined
2400 // for the document language in the lib/languages file and if no
2401 // other languages are used (lang_opts is then empty)
2402 if (lang_opts.empty())
2404 // either a specific language (AsBabelOptions setting in
2405 // lib/languages) or the prefs require the languages to
2406 // be submitted to babel itself (not the class).
2408 return "\\usepackage[" + lang_opts + "]{babel}";
2409 return "\\usepackage{babel}";
2413 docstring BufferParams::getGraphicsDriver(string const & package) const
2417 if (package == "geometry") {
2418 if (graphicsDriver == "dvips"
2419 || graphicsDriver == "dvipdfm"
2420 || graphicsDriver == "pdftex"
2421 || graphicsDriver == "vtex")
2422 result = from_ascii(graphicsDriver);
2423 else if (graphicsDriver == "dvipdfmx")
2424 result = from_ascii("dvipdfm");
2431 void BufferParams::writeEncodingPreamble(odocstream & os,
2432 LaTeXFeatures & features, TexRow & texrow) const
2436 if (inputenc == "auto") {
2437 string const doc_encoding =
2438 language->encoding()->latexName();
2439 Encoding::Package const package =
2440 language->encoding()->package();
2442 // Create a list with all the input encodings used
2444 set<string> encodings =
2445 features.getEncodingSet(doc_encoding);
2447 // If the "japanese" package (i.e. pLaTeX) is used,
2448 // inputenc must be omitted.
2449 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2450 if (package == Encoding::japanese)
2451 features.require("japanese");
2453 if ((!encodings.empty() || package == Encoding::inputenc)
2454 && !features.isRequired("japanese")) {
2455 os << "\\usepackage[";
2456 set<string>::const_iterator it = encodings.begin();
2457 set<string>::const_iterator const end = encodings.end();
2459 os << from_ascii(*it);
2462 for (; it != end; ++it)
2463 os << ',' << from_ascii(*it);
2464 if (package == Encoding::inputenc) {
2465 if (!encodings.empty())
2467 os << from_ascii(doc_encoding);
2469 os << "]{inputenc}\n";
2472 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2473 if (language->encoding()->name() == "utf8-cjk"
2474 && LaTeXFeatures::isAvailable("CJKutf8"))
2475 os << "\\usepackage{CJKutf8}\n";
2477 os << "\\usepackage{CJK}\n";
2480 } else if (inputenc != "default") {
2481 switch (encoding().package()) {
2482 case Encoding::none:
2483 case Encoding::japanese:
2485 case Encoding::inputenc:
2486 // do not load inputenc if japanese is used
2487 if (features.isRequired("japanese"))
2489 os << "\\usepackage[" << from_ascii(inputenc)
2494 if (encoding().name() == "utf8-cjk"
2495 && LaTeXFeatures::isAvailable("CJKutf8"))
2496 os << "\\usepackage{CJKutf8}\n";
2498 os << "\\usepackage{CJK}\n";
2504 // The encoding "armscii8" (for Armenian) is only available when
2505 // the package "armtex" is loaded.
2506 if (language->encoding()->latexName() == "armscii8"
2507 || inputenc == "armscii8") {
2508 os << "\\usepackage{armtex}\n";
2514 string const BufferParams::parseFontName(string const & name) const
2516 string mangled = name;
2517 size_t const idx = mangled.find('[');
2518 if (idx == string::npos || idx == 0)
2521 return mangled.substr(0, idx - 1);
2525 string const BufferParams::loadFonts(string const & rm,
2526 string const & sf, string const & tt,
2527 bool const & sc, bool const & osf,
2528 int const & sfscale, int const & ttscale,
2529 bool const & xetex) const
2531 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2532 several packages have been replaced by others, that might not
2533 be installed on every system. We have to take care for that
2534 (see psnfss.pdf). We try to support all psnfss fonts as well
2535 as the fonts that have become de facto standard in the LaTeX
2536 world (e.g. Latin Modern). We do not support obsolete fonts
2537 (like PSLatex). In general, it should be possible to mix any
2538 rm font with any sf or tt font, respectively. (JSpitzm)
2540 -- separate math fonts.
2543 if (rm == "default" && sf == "default" && tt == "default")
2550 if (rm != "default") {
2551 os << "\\setmainfont[Mapping=tex-text";
2553 os << ",Numbers=OldStyle";
2554 os << "]{" << parseFontName(rm) << "}\n";
2556 if (sf != "default") {
2557 string const sans = parseFontName(sf);
2559 os << "\\setsansfont[Scale="
2560 << float(sfscale) / 100
2561 << ",Mapping=tex-text]{"
2564 os << "\\setsansfont[Mapping=tex-text]{"
2567 if (tt != "default") {
2568 string const mono = parseFontName(tt);
2570 os << "\\setmonofont[Scale="
2571 << float(sfscale) / 100
2575 os << "\\setmonofont[Mapping=tex-text]{"
2582 // Computer Modern (must be explicitly selectable -- there might be classes
2583 // that define a different default font!
2585 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2586 // osf for Computer Modern needs eco.sty
2588 os << "\\usepackage{eco}\n";
2590 // Latin Modern Roman
2591 else if (rm == "lmodern")
2592 os << "\\usepackage{lmodern}\n";
2594 else if (rm == "ae") {
2595 // not needed when using OT1 font encoding.
2596 if (font_encoding() != "default")
2597 os << "\\usepackage{ae,aecompl}\n";
2600 else if (rm == "times") {
2601 // try to load the best available package
2602 if (LaTeXFeatures::isAvailable("mathptmx"))
2603 os << "\\usepackage{mathptmx}\n";
2604 else if (LaTeXFeatures::isAvailable("mathptm"))
2605 os << "\\usepackage{mathptm}\n";
2607 os << "\\usepackage{times}\n";
2610 else if (rm == "palatino") {
2611 // try to load the best available package
2612 if (LaTeXFeatures::isAvailable("mathpazo")) {
2613 os << "\\usepackage";
2619 // "osf" includes "sc"!
2623 os << "{mathpazo}\n";
2625 else if (LaTeXFeatures::isAvailable("mathpple"))
2626 os << "\\usepackage{mathpple}\n";
2628 os << "\\usepackage{palatino}\n";
2631 else if (rm == "utopia") {
2632 // fourier supersedes utopia.sty, but does
2633 // not work with OT1 encoding.
2634 if (LaTeXFeatures::isAvailable("fourier")
2635 && font_encoding() != "default") {
2636 os << "\\usepackage";
2647 os << "{fourier}\n";
2650 os << "\\usepackage{utopia}\n";
2652 // Bera (complete fontset)
2653 else if (rm == "bera" && sf == "default" && tt == "default")
2654 os << "\\usepackage{bera}\n";
2656 else if (rm != "default")
2657 os << "\\usepackage" << "{" << rm << "}\n";
2660 // Helvetica, Bera Sans
2661 if (sf == "helvet" || sf == "berasans") {
2663 os << "\\usepackage[scaled=" << float(sfscale) / 100
2664 << "]{" << sf << "}\n";
2666 os << "\\usepackage{" << sf << "}\n";
2669 else if (sf == "avant")
2670 os << "\\usepackage{" << sf << "}\n";
2671 // Computer Modern, Latin Modern, CM Bright
2672 else if (sf != "default")
2673 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2675 // monospaced/typewriter
2676 // Courier, LuxiMono
2677 if (tt == "luximono" || tt == "beramono") {
2679 os << "\\usepackage[scaled=" << float(ttscale) / 100
2680 << "]{" << tt << "}\n";
2682 os << "\\usepackage{" << tt << "}\n";
2685 else if (tt == "courier" )
2686 os << "\\usepackage{" << tt << "}\n";
2687 // Computer Modern, Latin Modern, CM Bright
2688 else if (tt != "default")
2689 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2695 Encoding const & BufferParams::encoding() const
2698 return *(encodings.fromLaTeXName("utf8-plain"));
2699 if (inputenc == "auto" || inputenc == "default")
2700 return *language->encoding();
2701 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2704 LYXERR0("Unknown inputenc value `" << inputenc
2705 << "'. Using `auto' instead.");
2706 return *language->encoding();
2710 CiteEngine BufferParams::citeEngine() const
2712 // FIXME the class should provide the numerical/
2713 // authoryear choice
2714 if (documentClass().provides("natbib")
2715 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2716 return ENGINE_NATBIB_AUTHORYEAR;
2717 return cite_engine_;
2721 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2723 cite_engine_ = cite_engine;