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 cite_engine_ = ENGINE_BASIC;
367 use_bibtopic = false;
369 trackChanges = false;
370 outputChanges = false;
371 use_default_options = true;
372 maintain_unincluded_children = false;
375 language = default_language;
377 fontsRoman = "default";
378 fontsSans = "default";
379 fontsTypewriter = "default";
380 fontsDefaultFamily = "default";
384 fontsSansScale = 100;
385 fontsTypewriterScale = 100;
387 graphicsDriver = "default";
388 defaultOutputFormat = "default";
389 bibtex_command = "default";
390 index_command = "default";
393 listings_params = string();
394 pagestyle = "default";
395 suppress_date = false;
396 // no color is the default (white)
397 backgroundcolor = lyx::rgbFromHexName("#ffffff");
398 isbackgroundcolor = false;
399 // no color is the default (black)
400 fontcolor = lyx::rgbFromHexName("#000000");
402 // light gray is the default font color for greyed-out notes
403 notefontcolor = lyx::rgbFromHexName("#cccccc");
404 boxbgcolor = lyx::rgbFromHexName("#ff0000");
405 compressed = lyxrc.save_compressed;
406 for (int iter = 0; iter < 4; ++iter) {
407 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
408 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
411 indiceslist().addDefault(B_("Index"));
412 html_be_strict = false;
413 html_math_output = MathML;
414 html_math_img_scale = 1.0;
420 docstring BufferParams::B_(string const & l10n) const
422 LASSERT(language, /**/);
423 return getMessages(language->code()).get(l10n);
427 AuthorList & BufferParams::authors()
429 return pimpl_->authorlist;
433 AuthorList const & BufferParams::authors() const
435 return pimpl_->authorlist;
439 BranchList & BufferParams::branchlist()
441 return pimpl_->branchlist;
445 BranchList const & BufferParams::branchlist() const
447 return pimpl_->branchlist;
451 IndicesList & BufferParams::indiceslist()
453 return pimpl_->indiceslist;
457 IndicesList const & BufferParams::indiceslist() const
459 return pimpl_->indiceslist;
463 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
465 LASSERT(index < 4, /**/);
466 return pimpl_->temp_bullets[index];
470 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
472 LASSERT(index < 4, /**/);
473 return pimpl_->temp_bullets[index];
477 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
479 LASSERT(index < 4, /**/);
480 return pimpl_->user_defined_bullets[index];
484 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
486 LASSERT(index < 4, /**/);
487 return pimpl_->user_defined_bullets[index];
491 Spacing & BufferParams::spacing()
493 return pimpl_->spacing;
497 Spacing const & BufferParams::spacing() const
499 return pimpl_->spacing;
503 PDFOptions & BufferParams::pdfoptions()
505 return pimpl_->pdfoptions;
509 PDFOptions const & BufferParams::pdfoptions() const
511 return pimpl_->pdfoptions;
515 HSpace const & BufferParams::getIndentation() const
517 return pimpl_->indentation;
521 void BufferParams::setIndentation(HSpace const & indent)
523 pimpl_->indentation = indent;
527 VSpace const & BufferParams::getDefSkip() const
529 return pimpl_->defskip;
533 void BufferParams::setDefSkip(VSpace const & vs)
535 pimpl_->defskip = vs;
539 string BufferParams::readToken(Lexer & lex, string const & token,
540 FileName const & filepath)
542 if (token == "\\textclass") {
544 string const classname = lex.getString();
545 // if there exists a local layout file, ignore the system one
546 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
548 LayoutFileList & bcl = LayoutFileList::get();
549 if (tcp.empty() && !filepath.empty())
550 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
554 setBaseClass(classname);
555 // We assume that a tex class exists for local or unknown layouts so this warning
556 // will only be given for system layouts.
557 if (!baseClass()->isTeXClassAvailable()) {
558 docstring const desc =
559 translateIfPossible(from_utf8(baseClass()->description()));
560 docstring const prereqs = from_utf8(baseClass()->prerequisites());
561 docstring const msg =
562 bformat(_("The selected document class\n"
564 "requires external files that are not available.\n"
565 "The document class can still be used, but the\n"
566 "document cannot be compiled until the following\n"
567 "prerequisites are installed:\n"
569 "See section 3.1.2.2 of the User's Guide for\n"
570 "more information."), desc, prereqs);
571 frontend::Alert::warning(_("Document class not available"),
574 } else if (token == "\\begin_preamble") {
576 } else if (token == "\\begin_local_layout") {
577 readLocalLayout(lex);
578 } else if (token == "\\begin_modules") {
580 } else if (token == "\\begin_removed_modules") {
581 readRemovedModules(lex);
582 } else if (token == "\\begin_includeonly") {
583 readIncludeonly(lex);
584 } else if (token == "\\maintain_unincluded_children") {
585 lex >> maintain_unincluded_children;
586 } else if (token == "\\options") {
588 options = lex.getString();
589 } else if (token == "\\use_default_options") {
590 lex >> use_default_options;
591 } else if (token == "\\master") {
593 master = lex.getString();
594 } else if (token == "\\suppress_date") {
595 lex >> suppress_date;
596 } else if (token == "\\language") {
598 } else if (token == "\\inputencoding") {
600 } else if (token == "\\graphics") {
601 readGraphicsDriver(lex);
602 } else if (token == "\\default_output_format") {
603 lex >> defaultOutputFormat;
604 } else if (token == "\\bibtex_command") {
606 bibtex_command = lex.getString();
607 } else if (token == "\\index_command") {
609 index_command = lex.getString();
610 } else if (token == "\\fontencoding") {
612 fontenc = lex.getString();
613 } else if (token == "\\font_roman") {
615 fontsRoman = lex.getString();
616 } else if (token == "\\font_sans") {
618 fontsSans = lex.getString();
619 } else if (token == "\\font_typewriter") {
621 fontsTypewriter = lex.getString();
622 } else if (token == "\\font_default_family") {
623 lex >> fontsDefaultFamily;
624 } else if (token == "\\use_xetex") {
626 } else if (token == "\\font_sc") {
628 } else if (token == "\\font_osf") {
630 } else if (token == "\\font_sf_scale") {
631 lex >> fontsSansScale;
632 } else if (token == "\\font_tt_scale") {
633 lex >> fontsTypewriterScale;
634 } else if (token == "\\font_cjk") {
636 } else if (token == "\\paragraph_separation") {
639 paragraph_separation = parseptranslator().find(parsep);
640 } else if (token == "\\paragraph_indentation") {
642 string indentation = lex.getString();
643 pimpl_->indentation = HSpace(indentation);
644 } else if (token == "\\defskip") {
646 string defskip = lex.getString();
647 if (defskip == "defskip")
650 pimpl_->defskip = VSpace(defskip);
651 } else if (token == "\\quotes_language") {
654 quotes_language = quoteslangtranslator().find(quotes_lang);
655 } else if (token == "\\papersize") {
658 papersize = papersizetranslator().find(ppsize);
659 } else if (token == "\\use_geometry") {
661 } else if (token == "\\use_amsmath") {
664 use_amsmath = packagetranslator().find(use_ams);
665 } else if (token == "\\use_esint") {
668 use_esint = packagetranslator().find(useesint);
669 } else if (token == "\\use_mhchem") {
672 use_mhchem = packagetranslator().find(usemhchem);
673 } else if (token == "\\cite_engine") {
676 cite_engine_ = citeenginetranslator().find(engine);
677 } else if (token == "\\use_bibtopic") {
679 } else if (token == "\\use_indices") {
681 } else if (token == "\\tracking_changes") {
683 } else if (token == "\\output_changes") {
684 lex >> outputChanges;
685 } else if (token == "\\branch") {
687 docstring branch = lex.getDocString();
688 branchlist().add(branch);
691 string const tok = lex.getString();
692 if (tok == "\\end_branch")
694 Branch * branch_ptr = branchlist().find(branch);
695 if (tok == "\\selected") {
698 branch_ptr->setSelected(lex.getInteger());
700 if (tok == "\\filename_suffix") {
703 branch_ptr->setFileNameSuffix(lex.getInteger());
705 if (tok == "\\color") {
707 string color = lex.getString();
709 branch_ptr->setColor(color);
710 // Update also the Color table:
712 color = lcolor.getX11Name(Color_background);
714 lcolor.setColor(to_utf8(branch), color);
717 } else if (token == "\\index") {
719 docstring index = lex.getDocString();
721 indiceslist().add(index);
724 string const tok = lex.getString();
725 if (tok == "\\end_index")
727 Index * index_ptr = indiceslist().find(index);
728 if (tok == "\\shortcut") {
730 shortcut = lex.getDocString();
732 index_ptr->setShortcut(shortcut);
734 if (tok == "\\color") {
736 string color = lex.getString();
738 index_ptr->setColor(color);
739 // Update also the Color table:
741 color = lcolor.getX11Name(Color_background);
743 if (!shortcut.empty())
744 lcolor.setColor(to_utf8(shortcut), color);
747 } else if (token == "\\author") {
749 istringstream ss(lex.getString());
752 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
753 } else if (token == "\\paperorientation") {
756 orientation = paperorientationtranslator().find(orient);
757 } else if (token == "\\backgroundcolor") {
759 backgroundcolor = lyx::rgbFromHexName(lex.getString());
760 isbackgroundcolor = true;
761 } else if (token == "\\fontcolor") {
763 fontcolor = lyx::rgbFromHexName(lex.getString());
765 } else if (token == "\\notefontcolor") {
767 string color = lex.getString();
768 notefontcolor = lyx::rgbFromHexName(color);
769 } else if (token == "\\boxbgcolor") {
771 string color = lex.getString();
772 boxbgcolor = lyx::rgbFromHexName(color);
773 } else if (token == "\\paperwidth") {
775 } else if (token == "\\paperheight") {
777 } else if (token == "\\leftmargin") {
779 } else if (token == "\\topmargin") {
781 } else if (token == "\\rightmargin") {
783 } else if (token == "\\bottommargin") {
785 } else if (token == "\\headheight") {
787 } else if (token == "\\headsep") {
789 } else if (token == "\\footskip") {
791 } else if (token == "\\columnsep") {
793 } else if (token == "\\paperfontsize") {
795 } else if (token == "\\papercolumns") {
797 } else if (token == "\\listings_params") {
800 listings_params = InsetListingsParams(par).params();
801 } else if (token == "\\papersides") {
804 sides = sidestranslator().find(psides);
805 } else if (token == "\\paperpagestyle") {
807 } else if (token == "\\bullet") {
809 } else if (token == "\\bulletLaTeX") {
810 readBulletsLaTeX(lex);
811 } else if (token == "\\secnumdepth") {
813 } else if (token == "\\tocdepth") {
815 } else if (token == "\\spacing") {
819 if (nspacing == "other") {
822 spacing().set(spacetranslator().find(nspacing), tmp_val);
823 } else if (token == "\\float_placement") {
824 lex >> float_placement;
826 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
827 string toktmp = pdfoptions().readToken(lex, token);
828 if (!toktmp.empty()) {
829 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
833 } else if (token == "\\html_math_output") {
836 html_math_output = static_cast<MathOutput>(temp);
837 } else if (token == "\\html_be_strict") {
838 lex >> html_be_strict;
839 } else if (token == "\\html_math_img_scale") {
840 lex >> html_math_img_scale;
841 } else if (token == "\\html_latex_start") {
843 html_latex_start = lex.getString();
844 } else if (token == "\\html_latex_end") {
846 html_latex_end = lex.getString();
847 } else if (token == "\\output_sync") {
849 } else if (token == "\\output_sync_macro") {
850 lex >> output_sync_macro;
852 lyxerr << "BufferParams::readToken(): Unknown token: " <<
861 void BufferParams::writeFile(ostream & os) const
863 // The top of the file is written by the buffer.
864 // Prints out the buffer info into the .lyx file given by file
867 os << "\\textclass " << baseClass()->name() << '\n';
870 if (!preamble.empty()) {
871 // remove '\n' from the end of preamble
872 string const tmppreamble = rtrim(preamble, "\n");
873 os << "\\begin_preamble\n"
875 << "\n\\end_preamble\n";
879 if (!options.empty()) {
880 os << "\\options " << options << '\n';
883 // use the class options defined in the layout?
884 os << "\\use_default_options "
885 << convert<string>(use_default_options) << "\n";
887 // the master document
888 if (!master.empty()) {
889 os << "\\master " << master << '\n';
893 if (!removedModules_.empty()) {
894 os << "\\begin_removed_modules" << '\n';
895 list<string>::const_iterator it = removedModules_.begin();
896 list<string>::const_iterator en = removedModules_.end();
897 for (; it != en; it++)
899 os << "\\end_removed_modules" << '\n';
903 if (!layoutModules_.empty()) {
904 os << "\\begin_modules" << '\n';
905 LayoutModuleList::const_iterator it = layoutModules_.begin();
906 LayoutModuleList::const_iterator en = layoutModules_.end();
907 for (; it != en; it++)
909 os << "\\end_modules" << '\n';
913 if (!includedChildren_.empty()) {
914 os << "\\begin_includeonly" << '\n';
915 list<string>::const_iterator it = includedChildren_.begin();
916 list<string>::const_iterator en = includedChildren_.end();
917 for (; it != en; it++)
919 os << "\\end_includeonly" << '\n';
921 os << "\\maintain_unincluded_children "
922 << convert<string>(maintain_unincluded_children) << '\n';
924 // local layout information
925 if (!local_layout.empty()) {
926 // remove '\n' from the end
927 string const tmplocal = rtrim(local_layout, "\n");
928 os << "\\begin_local_layout\n"
930 << "\n\\end_local_layout\n";
933 // then the text parameters
934 if (language != ignore_language)
935 os << "\\language " << language->lang() << '\n';
936 os << "\\inputencoding " << inputenc
937 << "\n\\fontencoding " << fontenc
938 << "\n\\font_roman " << fontsRoman
939 << "\n\\font_sans " << fontsSans
940 << "\n\\font_typewriter " << fontsTypewriter
941 << "\n\\font_default_family " << fontsDefaultFamily
942 << "\n\\use_xetex " << convert<string>(useXetex)
943 << "\n\\font_sc " << convert<string>(fontsSC)
944 << "\n\\font_osf " << convert<string>(fontsOSF)
945 << "\n\\font_sf_scale " << fontsSansScale
946 << "\n\\font_tt_scale " << fontsTypewriterScale
948 if (!fontsCJK.empty()) {
949 os << "\\font_cjk " << fontsCJK << '\n';
951 os << "\n\\graphics " << graphicsDriver << '\n';
952 os << "\\default_output_format " << defaultOutputFormat << '\n';
953 os << "\\output_sync " << output_sync << '\n';
954 if (!output_sync_macro.empty())
955 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
956 os << "\\bibtex_command " << bibtex_command << '\n';
957 os << "\\index_command " << index_command << '\n';
959 if (!float_placement.empty()) {
960 os << "\\float_placement " << float_placement << '\n';
962 os << "\\paperfontsize " << fontsize << '\n';
964 spacing().writeFile(os);
965 pdfoptions().writeFile(os);
967 os << "\\papersize " << string_papersize[papersize]
968 << "\n\\use_geometry " << convert<string>(use_geometry)
969 << "\n\\use_amsmath " << use_amsmath
970 << "\n\\use_esint " << use_esint
971 << "\n\\use_mhchem " << use_mhchem
972 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
973 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
974 << "\n\\use_indices " << convert<string>(use_indices)
975 << "\n\\paperorientation " << string_orientation[orientation]
976 << "\n\\suppress_date " << convert<string>(suppress_date)
978 if (isbackgroundcolor == true)
979 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
980 if (isfontcolor == true)
981 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
982 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
983 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
984 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
985 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
987 BranchList::const_iterator it = branchlist().begin();
988 BranchList::const_iterator end = branchlist().end();
989 for (; it != end; ++it) {
990 os << "\\branch " << to_utf8(it->branch())
991 << "\n\\selected " << it->isSelected()
992 << "\n\\filename_suffix " << it->hasFileNameSuffix()
993 << "\n\\color " << lyx::X11hexname(it->color())
998 IndicesList::const_iterator iit = indiceslist().begin();
999 IndicesList::const_iterator iend = indiceslist().end();
1000 for (; iit != iend; ++iit) {
1001 os << "\\index " << to_utf8(iit->index())
1002 << "\n\\shortcut " << to_utf8(iit->shortcut())
1003 << "\n\\color " << lyx::X11hexname(iit->color())
1008 if (!paperwidth.empty())
1009 os << "\\paperwidth "
1010 << VSpace(paperwidth).asLyXCommand() << '\n';
1011 if (!paperheight.empty())
1012 os << "\\paperheight "
1013 << VSpace(paperheight).asLyXCommand() << '\n';
1014 if (!leftmargin.empty())
1015 os << "\\leftmargin "
1016 << VSpace(leftmargin).asLyXCommand() << '\n';
1017 if (!topmargin.empty())
1018 os << "\\topmargin "
1019 << VSpace(topmargin).asLyXCommand() << '\n';
1020 if (!rightmargin.empty())
1021 os << "\\rightmargin "
1022 << VSpace(rightmargin).asLyXCommand() << '\n';
1023 if (!bottommargin.empty())
1024 os << "\\bottommargin "
1025 << VSpace(bottommargin).asLyXCommand() << '\n';
1026 if (!headheight.empty())
1027 os << "\\headheight "
1028 << VSpace(headheight).asLyXCommand() << '\n';
1029 if (!headsep.empty())
1031 << VSpace(headsep).asLyXCommand() << '\n';
1032 if (!footskip.empty())
1034 << VSpace(footskip).asLyXCommand() << '\n';
1035 if (!columnsep.empty())
1036 os << "\\columnsep "
1037 << VSpace(columnsep).asLyXCommand() << '\n';
1038 os << "\\secnumdepth " << secnumdepth
1039 << "\n\\tocdepth " << tocdepth
1040 << "\n\\paragraph_separation "
1041 << string_paragraph_separation[paragraph_separation];
1042 if (!paragraph_separation)
1043 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1045 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1046 os << "\n\\quotes_language "
1047 << string_quotes_language[quotes_language]
1048 << "\n\\papercolumns " << columns
1049 << "\n\\papersides " << sides
1050 << "\n\\paperpagestyle " << pagestyle << '\n';
1051 if (!listings_params.empty())
1052 os << "\\listings_params \"" <<
1053 InsetListingsParams(listings_params).encodedString() << "\"\n";
1054 for (int i = 0; i < 4; ++i) {
1055 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1056 if (user_defined_bullet(i).getFont() != -1) {
1057 os << "\\bullet " << i << " "
1058 << user_defined_bullet(i).getFont() << " "
1059 << user_defined_bullet(i).getCharacter() << " "
1060 << user_defined_bullet(i).getSize() << "\n";
1064 os << "\\bulletLaTeX " << i << " \""
1065 << lyx::to_ascii(user_defined_bullet(i).getText())
1071 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1072 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1073 << "\\html_math_output " << html_math_output << '\n'
1074 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1076 if (html_math_img_scale != 1.0)
1077 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1078 if (!html_latex_start.empty())
1079 os << "\\html_latex_start " << html_latex_start << '\n';
1080 if (!html_latex_end.empty())
1081 os << "\\html_latex_end " << html_latex_end << '\n';
1083 os << pimpl_->authorlist;
1087 void BufferParams::validate(LaTeXFeatures & features) const
1089 features.require(documentClass().requires());
1091 if (outputChanges) {
1092 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1093 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1094 LaTeXFeatures::isAvailable("xcolor");
1096 switch (features.runparams().flavor) {
1097 case OutputParams::LATEX:
1099 features.require("ct-dvipost");
1100 features.require("dvipost");
1101 } else if (xcolorulem) {
1102 features.require("ct-xcolor-ulem");
1103 features.require("ulem");
1104 features.require("xcolor");
1106 features.require("ct-none");
1109 case OutputParams::PDFLATEX:
1110 case OutputParams::XETEX:
1112 features.require("ct-xcolor-ulem");
1113 features.require("ulem");
1114 features.require("xcolor");
1115 // improves color handling in PDF output
1116 features.require("pdfcolmk");
1118 features.require("ct-none");
1126 // Floats with 'Here definitely' as default setting.
1127 if (float_placement.find('H') != string::npos)
1128 features.require("float");
1130 // AMS Style is at document level
1131 if (use_amsmath == package_on
1132 || documentClass().provides("amsmath"))
1133 features.require("amsmath");
1134 if (use_esint == package_on)
1135 features.require("esint");
1136 if (use_mhchem == package_on)
1137 features.require("mhchem");
1139 // Document-level line spacing
1140 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1141 features.require("setspace");
1143 // the bullet shapes are buffer level not paragraph level
1144 // so they are tested here
1145 for (int i = 0; i < 4; ++i) {
1146 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1148 int const font = user_defined_bullet(i).getFont();
1150 int const c = user_defined_bullet(i).getCharacter();
1156 features.require("latexsym");
1158 } else if (font == 1) {
1159 features.require("amssymb");
1160 } else if (font >= 2 && font <= 5) {
1161 features.require("pifont");
1165 if (pdfoptions().use_hyperref) {
1166 features.require("hyperref");
1167 // due to interferences with babel and hyperref, the color package has to
1168 // be loaded after hyperref when hyperref is used with the colorlinks
1169 // option, see http://www.lyx.org/trac/ticket/5291
1170 if (pdfoptions().colorlinks)
1171 features.require("color");
1175 features.require("xetex");
1177 if (language->lang() == "vietnamese")
1178 features.require("vietnamese");
1179 else if (language->lang() == "japanese")
1180 features.require("japanese");
1184 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1185 TexRow & texrow, FileName const & filepath) const
1187 os << "\\documentclass";
1189 DocumentClass const & tclass = documentClass();
1191 ostringstream clsoptions; // the document class options.
1193 if (tokenPos(tclass.opt_fontsize(),
1194 '|', fontsize) >= 0) {
1195 // only write if existing in list (and not default)
1196 clsoptions << fontsize << "pt,";
1199 // all paper sizes except of A4, A5, B5 and the US sizes need the
1201 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1202 && papersize != PAPER_USLETTER
1203 && papersize != PAPER_USLEGAL
1204 && papersize != PAPER_USEXECUTIVE
1205 && papersize != PAPER_A4
1206 && papersize != PAPER_A5
1207 && papersize != PAPER_B5;
1209 if (!use_geometry) {
1210 switch (papersize) {
1212 clsoptions << "a4paper,";
1214 case PAPER_USLETTER:
1215 clsoptions << "letterpaper,";
1218 clsoptions << "a5paper,";
1221 clsoptions << "b5paper,";
1223 case PAPER_USEXECUTIVE:
1224 clsoptions << "executivepaper,";
1227 clsoptions << "legalpaper,";
1261 if (sides != tclass.sides()) {
1264 clsoptions << "oneside,";
1267 clsoptions << "twoside,";
1273 if (columns != tclass.columns()) {
1275 clsoptions << "twocolumn,";
1277 clsoptions << "onecolumn,";
1281 && orientation == ORIENTATION_LANDSCAPE)
1282 clsoptions << "landscape,";
1284 // language should be a parameter to \documentclass
1285 if (language->babel() == "hebrew"
1286 && default_language->babel() != "hebrew")
1287 // This seems necessary
1288 features.useLanguage(default_language);
1290 ostringstream language_options;
1291 bool const use_babel = features.useBabel() && !tclass.provides("babel");
1293 language_options << features.getLanguages();
1294 if (!language->babel().empty()) {
1295 if (!language_options.str().empty())
1296 language_options << ',';
1297 language_options << language->babel();
1299 // if Vietnamese is used, babel must directly be loaded
1300 // with language options, not in the class options, see
1301 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1302 size_t viet = language_options.str().find("vietnam");
1303 // viet = string::npos when not found
1304 // the same is for all other languages that are not directly supported by
1305 // babel, but where LaTeX-packages add babel support.
1306 // this is currently the case for Latvian, Lithuanian, Mongolian
1308 size_t latvian = language_options.str().find("latvian");
1309 size_t lithu = language_options.str().find("lithuanian");
1310 size_t mongo = language_options.str().find("mongolian");
1311 size_t turkmen = language_options.str().find("turkmen");
1312 // if Japanese is used, babel must directly be loaded
1313 // with language options, not in the class options, see
1314 // http://www.lyx.org/trac/ticket/4597#c4
1315 size_t japan = language_options.str().find("japanese");
1316 if (lyxrc.language_global_options && !language_options.str().empty()
1317 && viet == string::npos && japan == string::npos
1318 && latvian == string::npos && lithu == string::npos
1319 && mongo == string::npos && turkmen == string::npos)
1320 clsoptions << language_options.str() << ',';
1323 // the predefined options from the layout
1324 if (use_default_options && !tclass.options().empty())
1325 clsoptions << tclass.options() << ',';
1327 // the user-defined options
1328 if (!options.empty()) {
1329 clsoptions << options << ',';
1332 string strOptions(clsoptions.str());
1333 if (!strOptions.empty()) {
1334 strOptions = rtrim(strOptions, ",");
1336 os << '[' << from_utf8(strOptions) << ']';
1339 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1341 // end of \documentclass defs
1344 os << "\\usepackage{fontspec}\n";
1348 // font selection must be done before loading fontenc.sty
1349 string const fonts =
1350 loadFonts(fontsRoman, fontsSans,
1351 fontsTypewriter, fontsSC, fontsOSF,
1352 fontsSansScale, fontsTypewriterScale, useXetex);
1353 if (!fonts.empty()) {
1354 os << from_ascii(fonts);
1357 if (fontsDefaultFamily != "default")
1358 os << "\\renewcommand{\\familydefault}{\\"
1359 << from_ascii(fontsDefaultFamily) << "}\n";
1361 // set font encoding
1362 // for arabic_arabi and farsi we also need to load the LAE and
1364 // XeTeX works without fontenc
1365 if (font_encoding() != "default" && language->lang() != "japanese"
1366 && !useXetex && !tclass.provides("fontenc")) {
1367 size_t fars = language_options.str().find("farsi");
1368 size_t arab = language_options.str().find("arabic");
1369 if (language->lang() == "arabic_arabi"
1370 || language->lang() == "farsi" || fars != string::npos
1371 || arab != string::npos) {
1372 os << "\\usepackage[" << from_ascii(font_encoding())
1373 << ",LFE,LAE]{fontenc}\n";
1376 os << "\\usepackage[" << from_ascii(font_encoding())
1382 // handle inputenc etc.
1383 writeEncodingPreamble(os, features, texrow);
1386 if (!features.runparams().includeall && !includedChildren_.empty()) {
1387 os << "\\includeonly{";
1388 list<string>::const_iterator it = includedChildren_.begin();
1390 for (; it != includedChildren_.end() ; ++it) {
1391 string incfile = *it;
1392 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1393 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1395 if (!features.runparams().nice)
1397 // \includeonly doesn't want an extension
1398 incfile = changeExtension(incfile, string());
1399 incfile = support::latex_path(incfile);
1400 if (!incfile.empty()) {
1403 os << from_utf8(incfile);
1410 if (!listings_params.empty() || features.isRequired("listings")) {
1411 os << "\\usepackage{listings}\n";
1414 if (!listings_params.empty()) {
1416 // do not test validity because listings_params is
1417 // supposed to be valid
1419 InsetListingsParams(listings_params).separatedParams(true);
1420 // we can't support all packages, but we should load the color package
1421 if (par.find("\\color", 0) != string::npos)
1422 features.require("color");
1423 os << from_utf8(par);
1424 // count the number of newlines
1425 for (size_t i = 0; i < par.size(); ++i)
1431 if (!tclass.provides("geometry")
1432 && (use_geometry || nonstandard_papersize)) {
1433 odocstringstream ods;
1434 if (!getGraphicsDriver("geometry").empty())
1435 ods << getGraphicsDriver("geometry");
1436 if (orientation == ORIENTATION_LANDSCAPE)
1437 ods << ",landscape";
1438 switch (papersize) {
1440 if (!paperwidth.empty())
1441 ods << ",paperwidth="
1442 << from_ascii(paperwidth);
1443 if (!paperheight.empty())
1444 ods << ",paperheight="
1445 << from_ascii(paperheight);
1447 case PAPER_USLETTER:
1448 ods << ",letterpaper";
1451 ods << ",legalpaper";
1453 case PAPER_USEXECUTIVE:
1454 ods << ",executivepaper";
1541 // default papersize ie PAPER_DEFAULT
1542 switch (lyxrc.default_papersize) {
1543 case PAPER_DEFAULT: // keep compiler happy
1544 case PAPER_USLETTER:
1545 ods << ",letterpaper";
1548 ods << ",legalpaper";
1550 case PAPER_USEXECUTIVE:
1551 ods << ",executivepaper";
1593 docstring const g_options = trim(ods.str(), ",");
1594 os << "\\usepackage";
1595 if (!g_options.empty())
1596 os << '[' << g_options << ']';
1597 os << "{geometry}\n";
1599 // output this only if use_geometry is true
1601 os << "\\geometry{verbose";
1602 if (!topmargin.empty())
1603 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1604 if (!bottommargin.empty())
1605 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1606 if (!leftmargin.empty())
1607 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1608 if (!rightmargin.empty())
1609 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1610 if (!headheight.empty())
1611 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1612 if (!headsep.empty())
1613 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1614 if (!footskip.empty())
1615 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1616 if (!columnsep.empty())
1617 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1621 } else if (orientation == ORIENTATION_LANDSCAPE
1622 || papersize != PAPER_DEFAULT) {
1623 features.require("papersize");
1626 if (tokenPos(tclass.opt_pagestyle(),
1627 '|', pagestyle) >= 0) {
1628 if (pagestyle == "fancy") {
1629 os << "\\usepackage{fancyhdr}\n";
1632 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1636 // only output when the background color is not default
1637 if (isbackgroundcolor == true) {
1638 // only require color here, the background color will be defined
1639 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1641 features.require("color");
1642 features.require("pagecolor");
1645 // only output when the font color is not default
1646 if (isfontcolor == true) {
1647 // only require color here, the font color will be defined
1648 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1650 features.require("color");
1651 features.require("fontcolor");
1654 // Only if class has a ToC hierarchy
1655 if (tclass.hasTocLevels()) {
1656 if (secnumdepth != tclass.secnumdepth()) {
1657 os << "\\setcounter{secnumdepth}{"
1662 if (tocdepth != tclass.tocdepth()) {
1663 os << "\\setcounter{tocdepth}{"
1670 if (paragraph_separation) {
1671 // when skip separation
1672 switch (getDefSkip().kind()) {
1673 case VSpace::SMALLSKIP:
1674 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1676 case VSpace::MEDSKIP:
1677 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1679 case VSpace::BIGSKIP:
1680 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1682 case VSpace::LENGTH:
1683 os << "\\setlength{\\parskip}{"
1684 << from_utf8(getDefSkip().length().asLatexString())
1687 default: // should never happen // Then delete it.
1688 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1692 os << "\\setlength{\\parindent}{0pt}\n";
1695 // when separation by indentation
1696 // only output something when a width is given
1697 if (getIndentation().asLyXCommand() != "default") {
1698 os << "\\setlength{\\parindent}{"
1699 << from_utf8(getIndentation().asLatexCommand())
1705 // Now insert the LyX specific LaTeX commands...
1706 docstring lyxpreamble;
1709 if (!output_sync_macro.empty())
1710 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1711 else if (features.runparams().flavor == OutputParams::LATEX)
1712 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1713 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1714 lyxpreamble += "\\synctex=-1\n";
1717 // due to interferences with babel and hyperref, the color package has to
1718 // be loaded (when it is not already loaded) before babel when hyperref
1719 // is used with the colorlinks option, see
1720 // http://www.lyx.org/trac/ticket/5291
1721 // we decided therefore to load color always before babel, see
1722 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1723 lyxpreamble += from_ascii(features.getColorOptions());
1725 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1727 && (features.isRequired("jurabib")
1728 || features.isRequired("hyperref")
1729 || features.isRequired("vietnamese")
1730 || features.isRequired("japanese") ) ) {
1732 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1733 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1736 // The optional packages;
1737 lyxpreamble += from_ascii(features.getPackages());
1739 // Additional Indices
1740 if (features.isRequired("splitidx")) {
1741 IndicesList::const_iterator iit = indiceslist().begin();
1742 IndicesList::const_iterator iend = indiceslist().end();
1743 for (; iit != iend; ++iit) {
1744 lyxpreamble += "\\newindex[";
1745 lyxpreamble += iit->index();
1746 lyxpreamble += "]{";
1747 lyxpreamble += iit->shortcut();
1748 lyxpreamble += "}\n";
1753 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1756 // * Hyperref manual: "Make sure it comes last of your loaded
1757 // packages, to give it a fighting chance of not being over-written,
1758 // since its job is to redefine many LaTeX commands."
1759 // * Email from Heiko Oberdiek: "It is usually better to load babel
1760 // before hyperref. Then hyperref has a chance to detect babel.
1761 // * Has to be loaded before the "LyX specific LaTeX commands" to
1762 // avoid errors with algorithm floats.
1763 // use hyperref explicitly if it is required
1764 if (features.isRequired("hyperref")) {
1765 // pass what we have to stream here, since we need
1766 // to access the stream itself in PDFOptions.
1770 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1772 OutputParams tmp_params = features.runparams();
1773 lines += pdfoptions().writeLaTeX(tmp_params, os,
1774 documentClass().provides("hyperref"));
1775 texrow.newlines(lines);
1776 // set back for the rest
1777 lyxpreamble.clear();
1778 } else if (features.isRequired("nameref"))
1779 // hyperref loads this automatically
1780 lyxpreamble += "\\usepackage{nameref}\n";
1782 // Will be surrounded by \makeatletter and \makeatother when not empty
1783 docstring atlyxpreamble;
1785 // Some macros LyX will need
1786 docstring tmppreamble(features.getMacros());
1788 if (!tmppreamble.empty())
1789 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1790 "LyX specific LaTeX commands.\n"
1791 + tmppreamble + '\n';
1793 // the text class specific preamble
1794 tmppreamble = features.getTClassPreamble();
1795 if (!tmppreamble.empty())
1796 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1797 "Textclass specific LaTeX commands.\n"
1798 + tmppreamble + '\n';
1800 // suppress date if selected
1801 // use \@ifundefined because we cannot be sure that every document class
1802 // has a \date command
1804 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1806 /* the user-defined preamble */
1807 if (!containsOnly(preamble, " \n\t"))
1809 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1810 "User specified LaTeX commands.\n"
1811 + from_utf8(preamble) + '\n';
1813 // subfig loads internally the LaTeX package "caption". As
1814 // caption is a very popular package, users will load it in
1815 // the preamble. Therefore we must load subfig behind the
1816 // user-defined preamble and check if the caption package was
1817 // loaded or not. For the case that caption is loaded before
1818 // subfig, there is the subfig option "caption=false". This
1819 // option also works when a koma-script class is used and
1820 // koma's own caption commands are used instead of caption. We
1821 // use \PassOptionsToPackage here because the user could have
1822 // already loaded subfig in the preamble.
1823 if (features.isRequired("subfig")) {
1824 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1825 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1826 "\\usepackage{subfig}\n";
1829 // Itemize bullet settings need to be last in case the user
1830 // defines their own bullets that use a package included
1831 // in the user-defined preamble -- ARRae
1832 // Actually it has to be done much later than that
1833 // since some packages like frenchb make modifications
1834 // at \begin{document} time -- JMarc
1835 docstring bullets_def;
1836 for (int i = 0; i < 4; ++i) {
1837 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1838 if (bullets_def.empty())
1839 bullets_def += "\\AtBeginDocument{\n";
1840 bullets_def += " \\def\\labelitemi";
1842 // `i' is one less than the item to modify
1849 bullets_def += "ii";
1855 bullets_def += '{' +
1856 user_defined_bullet(i).getText()
1861 if (!bullets_def.empty())
1862 atlyxpreamble += bullets_def + "}\n\n";
1864 if (!atlyxpreamble.empty())
1865 lyxpreamble += "\n\\makeatletter\n"
1866 + atlyxpreamble + "\\makeatother\n\n";
1868 // We try to load babel late, in case it interferes with other packages.
1869 // Jurabib and Hyperref have to be called after babel, though.
1870 if (use_babel && !features.isRequired("jurabib")
1871 && !features.isRequired("hyperref")
1872 && !features.isRequired("vietnamese")
1873 && !features.isRequired("japanese")) {
1875 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1876 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1879 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1880 if (!i18npreamble.empty())
1881 lyxpreamble += i18npreamble + '\n';
1884 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1885 texrow.newlines(nlines);
1889 // these packages (xunicode, for that matter) need to be loaded at least
1890 // after amsmath, amssymb, esint and the other packages that provide
1893 os << "\\usepackage{xunicode}\n";
1895 os << "\\usepackage{xltxtra}\n";
1902 void BufferParams::useClassDefaults()
1904 DocumentClass const & tclass = documentClass();
1906 sides = tclass.sides();
1907 columns = tclass.columns();
1908 pagestyle = tclass.pagestyle();
1909 use_default_options = true;
1910 // Only if class has a ToC hierarchy
1911 if (tclass.hasTocLevels()) {
1912 secnumdepth = tclass.secnumdepth();
1913 tocdepth = tclass.tocdepth();
1918 bool BufferParams::hasClassDefaults() const
1920 DocumentClass const & tclass = documentClass();
1922 return sides == tclass.sides()
1923 && columns == tclass.columns()
1924 && pagestyle == tclass.pagestyle()
1925 && use_default_options
1926 && secnumdepth == tclass.secnumdepth()
1927 && tocdepth == tclass.tocdepth();
1931 DocumentClass const & BufferParams::documentClass() const
1937 DocumentClass const * BufferParams::documentClassPtr() const {
1942 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1943 // evil, but this function is evil
1944 doc_class_ = const_cast<DocumentClass *>(tc);
1948 bool BufferParams::setBaseClass(string const & classname)
1950 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1951 LayoutFileList & bcl = LayoutFileList::get();
1952 if (!bcl.haveClass(classname)) {
1954 bformat(_("The layout file:\n"
1956 "could not be found. A default textclass with default\n"
1957 "layouts will be used. LyX will not be able to produce\n"
1959 from_utf8(classname));
1960 frontend::Alert::error(_("Document class not found"), s);
1961 bcl.addEmptyClass(classname);
1964 bool const success = bcl[classname].load();
1967 bformat(_("Due to some error in it, the layout file:\n"
1969 "could not be loaded. A default textclass with default\n"
1970 "layouts will be used. LyX will not be able to produce\n"
1972 from_utf8(classname));
1973 frontend::Alert::error(_("Could not load class"), s);
1974 bcl.addEmptyClass(classname);
1977 pimpl_->baseClass_ = classname;
1978 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1983 LayoutFile const * BufferParams::baseClass() const
1985 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1986 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1992 LayoutFileIndex const & BufferParams::baseClassID() const
1994 return pimpl_->baseClass_;
1998 void BufferParams::makeDocumentClass()
2003 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
2005 if (!local_layout.empty()) {
2006 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
2007 docstring const msg = _("Error reading internal layout information");
2008 frontend::Alert::warning(_("Read Error"), msg);
2014 bool BufferParams::moduleCanBeAdded(string const & modName) const
2016 return layoutModules_.moduleCanBeAdded(modName, baseClass());
2020 bool BufferParams::addLayoutModule(string const & modName)
2022 LayoutModuleList::const_iterator it = layoutModules_.begin();
2023 LayoutModuleList::const_iterator end = layoutModules_.end();
2024 for (; it != end; it++)
2027 layoutModules_.push_back(modName);
2032 Font const BufferParams::getFont() const
2034 FontInfo f = documentClass().defaultfont();
2035 if (fontsDefaultFamily == "rmdefault")
2036 f.setFamily(ROMAN_FAMILY);
2037 else if (fontsDefaultFamily == "sfdefault")
2038 f.setFamily(SANS_FAMILY);
2039 else if (fontsDefaultFamily == "ttdefault")
2040 f.setFamily(TYPEWRITER_FAMILY);
2041 return Font(f, language);
2045 void BufferParams::readPreamble(Lexer & lex)
2047 if (lex.getString() != "\\begin_preamble")
2048 lyxerr << "Error (BufferParams::readPreamble):"
2049 "consistency check failed." << endl;
2051 preamble = lex.getLongString("\\end_preamble");
2055 void BufferParams::readLocalLayout(Lexer & lex)
2057 if (lex.getString() != "\\begin_local_layout")
2058 lyxerr << "Error (BufferParams::readLocalLayout):"
2059 "consistency check failed." << endl;
2061 local_layout = lex.getLongString("\\end_local_layout");
2065 void BufferParams::readLanguage(Lexer & lex)
2067 if (!lex.next()) return;
2069 string const tmptok = lex.getString();
2071 // check if tmptok is part of tex_babel in tex-defs.h
2072 language = languages.getLanguage(tmptok);
2074 // Language tmptok was not found
2075 language = default_language;
2076 lyxerr << "Warning: Setting language `"
2077 << tmptok << "' to `" << language->lang()
2083 void BufferParams::readGraphicsDriver(Lexer & lex)
2088 string const tmptok = lex.getString();
2089 // check if tmptok is part of tex_graphics in tex_defs.h
2092 string const test = tex_graphics[n++];
2094 if (test == tmptok) {
2095 graphicsDriver = tmptok;
2100 "Warning: graphics driver `$$Token' not recognized!\n"
2101 " Setting graphics driver to `default'.\n");
2102 graphicsDriver = "default";
2109 void BufferParams::readBullets(Lexer & lex)
2114 int const index = lex.getInteger();
2116 int temp_int = lex.getInteger();
2117 user_defined_bullet(index).setFont(temp_int);
2118 temp_bullet(index).setFont(temp_int);
2120 user_defined_bullet(index).setCharacter(temp_int);
2121 temp_bullet(index).setCharacter(temp_int);
2123 user_defined_bullet(index).setSize(temp_int);
2124 temp_bullet(index).setSize(temp_int);
2128 void BufferParams::readBulletsLaTeX(Lexer & lex)
2130 // The bullet class should be able to read this.
2133 int const index = lex.getInteger();
2135 docstring const temp_str = lex.getDocString();
2137 user_defined_bullet(index).setText(temp_str);
2138 temp_bullet(index).setText(temp_str);
2142 void BufferParams::readModules(Lexer & lex)
2144 if (!lex.eatLine()) {
2145 lyxerr << "Error (BufferParams::readModules):"
2146 "Unexpected end of input." << endl;
2150 string mod = lex.getString();
2151 if (mod == "\\end_modules")
2153 addLayoutModule(mod);
2159 void BufferParams::readRemovedModules(Lexer & lex)
2161 if (!lex.eatLine()) {
2162 lyxerr << "Error (BufferParams::readRemovedModules):"
2163 "Unexpected end of input." << endl;
2167 string mod = lex.getString();
2168 if (mod == "\\end_removed_modules")
2170 removedModules_.push_back(mod);
2173 // now we want to remove any removed modules that were previously
2174 // added. normally, that will be because default modules were added in
2175 // setBaseClass(), which gets called when \textclass is read at the
2176 // start of the read.
2177 list<string>::const_iterator rit = removedModules_.begin();
2178 list<string>::const_iterator const ren = removedModules_.end();
2179 for (; rit != ren; rit++) {
2180 LayoutModuleList::iterator const mit = layoutModules_.begin();
2181 LayoutModuleList::iterator const men = layoutModules_.end();
2182 LayoutModuleList::iterator found = find(mit, men, *rit);
2185 layoutModules_.erase(found);
2190 void BufferParams::readIncludeonly(Lexer & lex)
2192 if (!lex.eatLine()) {
2193 lyxerr << "Error (BufferParams::readIncludeonly):"
2194 "Unexpected end of input." << endl;
2198 string child = lex.getString();
2199 if (child == "\\end_includeonly")
2201 includedChildren_.push_back(child);
2207 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2209 char real_papersize = papersize;
2210 if (real_papersize == PAPER_DEFAULT)
2211 real_papersize = lyxrc.default_papersize;
2213 switch (real_papersize) {
2215 // could be anything, so don't guess
2217 case PAPER_CUSTOM: {
2218 if (purpose == XDVI && !paperwidth.empty() &&
2219 !paperheight.empty()) {
2220 // heightxwidth<unit>
2221 string first = paperwidth;
2222 string second = paperheight;
2223 if (orientation == ORIENTATION_LANDSCAPE)
2226 return first.erase(first.length() - 2)
2232 // dvips and dvipdfm do not know this
2233 if (purpose == DVIPS || purpose == DVIPDFM)
2237 if (purpose == DVIPS || purpose == DVIPDFM)
2241 if (purpose == DVIPS || purpose == DVIPDFM)
2251 if (purpose == DVIPS || purpose == DVIPDFM)
2255 if (purpose == DVIPS || purpose == DVIPDFM)
2259 if (purpose == DVIPS || purpose == DVIPDFM)
2263 if (purpose == DVIPS || purpose == DVIPDFM)
2267 if (purpose == DVIPS || purpose == DVIPDFM)
2271 // dvipdfm does not know this
2272 if (purpose == DVIPDFM)
2276 if (purpose == DVIPDFM)
2280 if (purpose == DVIPS || purpose == DVIPDFM)
2284 if (purpose == DVIPS || purpose == DVIPDFM)
2288 if (purpose == DVIPS || purpose == DVIPDFM)
2292 if (purpose == DVIPS || purpose == DVIPDFM)
2296 if (purpose == DVIPS || purpose == DVIPDFM)
2300 if (purpose == DVIPS || purpose == DVIPDFM)
2304 if (purpose == DVIPS || purpose == DVIPDFM)
2308 if (purpose == DVIPS || purpose == DVIPDFM)
2312 if (purpose == DVIPS || purpose == DVIPDFM)
2316 if (purpose == DVIPS || purpose == DVIPDFM)
2320 if (purpose == DVIPS || purpose == DVIPDFM)
2324 if (purpose == DVIPS || purpose == DVIPDFM)
2328 if (purpose == DVIPS || purpose == DVIPDFM)
2332 if (purpose == DVIPS || purpose == DVIPDFM)
2336 if (purpose == DVIPS || purpose == DVIPDFM)
2339 case PAPER_USEXECUTIVE:
2340 // dvipdfm does not know this
2341 if (purpose == DVIPDFM)
2346 case PAPER_USLETTER:
2348 if (purpose == XDVI)
2355 string const BufferParams::dvips_options() const
2360 && papersize == PAPER_CUSTOM
2361 && !lyxrc.print_paper_dimension_flag.empty()
2362 && !paperwidth.empty()
2363 && !paperheight.empty()) {
2364 // using a custom papersize
2365 result = lyxrc.print_paper_dimension_flag;
2366 result += ' ' + paperwidth;
2367 result += ',' + paperheight;
2369 string const paper_option = paperSizeName(DVIPS);
2370 if (!paper_option.empty() && (paper_option != "letter" ||
2371 orientation != ORIENTATION_LANDSCAPE)) {
2372 // dvips won't accept -t letter -t landscape.
2373 // In all other cases, include the paper size
2375 result = lyxrc.print_paper_flag;
2376 result += ' ' + paper_option;
2379 if (orientation == ORIENTATION_LANDSCAPE &&
2380 papersize != PAPER_CUSTOM)
2381 result += ' ' + lyxrc.print_landscape_flag;
2386 string const BufferParams::font_encoding() const
2388 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2392 string BufferParams::babelCall(string const & lang_opts) const
2394 string lang_pack = lyxrc.language_package;
2395 if (lang_pack != "\\usepackage{babel}")
2397 // suppress the babel call when there is no babel language defined
2398 // for the document language in the lib/languages file and if no
2399 // other languages are used (lang_opts is then empty)
2400 if (lang_opts.empty())
2402 // If Vietnamese is used, babel must directly be loaded with the
2403 // language options, see
2404 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2405 size_t viet = lang_opts.find("vietnam");
2406 // viet = string::npos when not found
2407 // the same is for all other languages that are not directly supported by
2408 // babel, but where LaTeX-packages add babel support.
2409 // this is currently the case for Latvian, Lithuanian, Mongolian
2411 size_t latvian = lang_opts.find("latvian");
2412 size_t lithu = lang_opts.find("lithuanian");
2413 size_t mongo = lang_opts.find("mongolian");
2414 size_t turkmen = lang_opts.find("turkmen");
2415 // If Japanese is used, babel must directly be loaded with the
2416 // language options, see
2417 // http://www.lyx.org/trac/ticket/4597#c4
2418 size_t japan = lang_opts.find("japanese");
2419 if (!lyxrc.language_global_options || viet != string::npos
2420 || japan != string::npos || latvian != string::npos
2421 || lithu != string::npos || mongo != string::npos
2422 || turkmen != string::npos)
2423 return "\\usepackage[" + lang_opts + "]{babel}";
2428 docstring BufferParams::getGraphicsDriver(string const & package) const
2432 if (package == "geometry") {
2433 if (graphicsDriver == "dvips"
2434 || graphicsDriver == "dvipdfm"
2435 || graphicsDriver == "pdftex"
2436 || graphicsDriver == "vtex")
2437 result = from_ascii(graphicsDriver);
2438 else if (graphicsDriver == "dvipdfmx")
2439 result = from_ascii("dvipdfm");
2446 void BufferParams::writeEncodingPreamble(odocstream & os,
2447 LaTeXFeatures & features, TexRow & texrow) const
2451 if (inputenc == "auto") {
2452 string const doc_encoding =
2453 language->encoding()->latexName();
2454 Encoding::Package const package =
2455 language->encoding()->package();
2457 // Create a list with all the input encodings used
2459 set<string> encodings =
2460 features.getEncodingSet(doc_encoding);
2462 // If the "japanese" package (i.e. pLaTeX) is used,
2463 // inputenc must be omitted.
2464 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2465 if (package == Encoding::japanese)
2466 features.require("japanese");
2468 if ((!encodings.empty() || package == Encoding::inputenc)
2469 && !features.isRequired("japanese")) {
2470 os << "\\usepackage[";
2471 set<string>::const_iterator it = encodings.begin();
2472 set<string>::const_iterator const end = encodings.end();
2474 os << from_ascii(*it);
2477 for (; it != end; ++it)
2478 os << ',' << from_ascii(*it);
2479 if (package == Encoding::inputenc) {
2480 if (!encodings.empty())
2482 os << from_ascii(doc_encoding);
2484 os << "]{inputenc}\n";
2487 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2488 if (language->encoding()->name() == "utf8-cjk"
2489 && LaTeXFeatures::isAvailable("CJKutf8"))
2490 os << "\\usepackage{CJKutf8}\n";
2492 os << "\\usepackage{CJK}\n";
2495 } else if (inputenc != "default") {
2496 switch (encoding().package()) {
2497 case Encoding::none:
2498 case Encoding::japanese:
2500 case Encoding::inputenc:
2501 // do not load inputenc if japanese is used
2502 if (features.isRequired("japanese"))
2504 os << "\\usepackage[" << from_ascii(inputenc)
2509 if (encoding().name() == "utf8-cjk"
2510 && LaTeXFeatures::isAvailable("CJKutf8"))
2511 os << "\\usepackage{CJKutf8}\n";
2513 os << "\\usepackage{CJK}\n";
2519 // The encoding "armscii8" (for Armenian) is only available when
2520 // the package "armtex" is loaded.
2521 if (language->encoding()->latexName() == "armscii8"
2522 || inputenc == "armscii8") {
2523 os << "\\usepackage{armtex}\n";
2529 string const BufferParams::parseFontName(string const & name) const
2531 string mangled = name;
2532 size_t const idx = mangled.find('[');
2533 if (idx == string::npos || idx == 0)
2536 return mangled.substr(0, idx - 1);
2540 string const BufferParams::loadFonts(string const & rm,
2541 string const & sf, string const & tt,
2542 bool const & sc, bool const & osf,
2543 int const & sfscale, int const & ttscale,
2544 bool const & xetex) const
2546 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2547 several packages have been replaced by others, that might not
2548 be installed on every system. We have to take care for that
2549 (see psnfss.pdf). We try to support all psnfss fonts as well
2550 as the fonts that have become de facto standard in the LaTeX
2551 world (e.g. Latin Modern). We do not support obsolete fonts
2552 (like PSLatex). In general, it should be possible to mix any
2553 rm font with any sf or tt font, respectively. (JSpitzm)
2555 -- separate math fonts.
2558 if (rm == "default" && sf == "default" && tt == "default")
2565 if (rm != "default")
2566 os << "\\setmainfont[Mapping=tex-text]{"
2567 << parseFontName(rm) << "}\n";
2568 if (sf != "default") {
2569 string const sans = parseFontName(sf);
2571 os << "\\setsansfont[Scale="
2572 << float(sfscale) / 100
2573 << ",Mapping=tex-text]{"
2576 os << "\\setsansfont[Mapping=tex-text]{"
2579 if (tt != "default") {
2580 string const mono = parseFontName(tt);
2582 os << "\\setmonofont[Scale="
2583 << float(sfscale) / 100
2587 os << "\\setmonofont[Mapping=tex-text]{"
2591 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2596 // Computer Modern (must be explicitly selectable -- there might be classes
2597 // that define a different default font!
2599 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2600 // osf for Computer Modern needs eco.sty
2602 os << "\\usepackage{eco}\n";
2604 // Latin Modern Roman
2605 else if (rm == "lmodern")
2606 os << "\\usepackage{lmodern}\n";
2608 else if (rm == "ae") {
2609 // not needed when using OT1 font encoding.
2610 if (font_encoding() != "default")
2611 os << "\\usepackage{ae,aecompl}\n";
2614 else if (rm == "times") {
2615 // try to load the best available package
2616 if (LaTeXFeatures::isAvailable("mathptmx"))
2617 os << "\\usepackage{mathptmx}\n";
2618 else if (LaTeXFeatures::isAvailable("mathptm"))
2619 os << "\\usepackage{mathptm}\n";
2621 os << "\\usepackage{times}\n";
2624 else if (rm == "palatino") {
2625 // try to load the best available package
2626 if (LaTeXFeatures::isAvailable("mathpazo")) {
2627 os << "\\usepackage";
2633 // "osf" includes "sc"!
2637 os << "{mathpazo}\n";
2639 else if (LaTeXFeatures::isAvailable("mathpple"))
2640 os << "\\usepackage{mathpple}\n";
2642 os << "\\usepackage{palatino}\n";
2645 else if (rm == "utopia") {
2646 // fourier supersedes utopia.sty, but does
2647 // not work with OT1 encoding.
2648 if (LaTeXFeatures::isAvailable("fourier")
2649 && font_encoding() != "default") {
2650 os << "\\usepackage";
2661 os << "{fourier}\n";
2664 os << "\\usepackage{utopia}\n";
2666 // Bera (complete fontset)
2667 else if (rm == "bera" && sf == "default" && tt == "default")
2668 os << "\\usepackage{bera}\n";
2670 else if (rm != "default")
2671 os << "\\usepackage" << "{" << rm << "}\n";
2674 // Helvetica, Bera Sans
2675 if (sf == "helvet" || sf == "berasans") {
2677 os << "\\usepackage[scaled=" << float(sfscale) / 100
2678 << "]{" << sf << "}\n";
2680 os << "\\usepackage{" << sf << "}\n";
2683 else if (sf == "avant")
2684 os << "\\usepackage{" << sf << "}\n";
2685 // Computer Modern, Latin Modern, CM Bright
2686 else if (sf != "default")
2687 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2689 // monospaced/typewriter
2690 // Courier, LuxiMono
2691 if (tt == "luximono" || tt == "beramono") {
2693 os << "\\usepackage[scaled=" << float(ttscale) / 100
2694 << "]{" << tt << "}\n";
2696 os << "\\usepackage{" << tt << "}\n";
2699 else if (tt == "courier" )
2700 os << "\\usepackage{" << tt << "}\n";
2701 // Computer Modern, Latin Modern, CM Bright
2702 else if (tt != "default")
2703 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2709 Encoding const & BufferParams::encoding() const
2712 return *(encodings.fromLaTeXName("utf8-plain"));
2713 if (inputenc == "auto" || inputenc == "default")
2714 return *language->encoding();
2715 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2718 LYXERR0("Unknown inputenc value `" << inputenc
2719 << "'. Using `auto' instead.");
2720 return *language->encoding();
2724 CiteEngine BufferParams::citeEngine() const
2726 // FIXME the class should provide the numerical/
2727 // authoryear choice
2728 if (documentClass().provides("natbib")
2729 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2730 return ENGINE_NATBIB_AUTHORYEAR;
2731 return cite_engine_;
2735 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2737 cite_engine_ = cite_engine;