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;
421 docstring BufferParams::B_(string const & l10n) const
423 LASSERT(language, /**/);
424 return getMessages(language->code()).get(l10n);
428 AuthorList & BufferParams::authors()
430 return pimpl_->authorlist;
434 AuthorList const & BufferParams::authors() const
436 return pimpl_->authorlist;
440 BranchList & BufferParams::branchlist()
442 return pimpl_->branchlist;
446 BranchList const & BufferParams::branchlist() const
448 return pimpl_->branchlist;
452 IndicesList & BufferParams::indiceslist()
454 return pimpl_->indiceslist;
458 IndicesList const & BufferParams::indiceslist() const
460 return pimpl_->indiceslist;
464 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
466 LASSERT(index < 4, /**/);
467 return pimpl_->temp_bullets[index];
471 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
473 LASSERT(index < 4, /**/);
474 return pimpl_->temp_bullets[index];
478 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
480 LASSERT(index < 4, /**/);
481 return pimpl_->user_defined_bullets[index];
485 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
487 LASSERT(index < 4, /**/);
488 return pimpl_->user_defined_bullets[index];
492 Spacing & BufferParams::spacing()
494 return pimpl_->spacing;
498 Spacing const & BufferParams::spacing() const
500 return pimpl_->spacing;
504 PDFOptions & BufferParams::pdfoptions()
506 return pimpl_->pdfoptions;
510 PDFOptions const & BufferParams::pdfoptions() const
512 return pimpl_->pdfoptions;
516 HSpace const & BufferParams::getIndentation() const
518 return pimpl_->indentation;
522 void BufferParams::setIndentation(HSpace const & indent)
524 pimpl_->indentation = indent;
528 VSpace const & BufferParams::getDefSkip() const
530 return pimpl_->defskip;
534 void BufferParams::setDefSkip(VSpace const & vs)
536 pimpl_->defskip = vs;
540 string BufferParams::readToken(Lexer & lex, string const & token,
541 FileName const & filepath)
543 if (token == "\\textclass") {
545 string const classname = lex.getString();
546 // if there exists a local layout file, ignore the system one
547 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
549 LayoutFileList & bcl = LayoutFileList::get();
550 if (tcp.empty() && !filepath.empty())
551 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
555 setBaseClass(classname);
556 // We assume that a tex class exists for local or unknown layouts so this warning
557 // will only be given for system layouts.
558 if (!baseClass()->isTeXClassAvailable()) {
559 docstring const desc =
560 translateIfPossible(from_utf8(baseClass()->description()));
561 docstring const prereqs = from_utf8(baseClass()->prerequisites());
562 docstring const msg =
563 bformat(_("The selected document class\n"
565 "requires external files that are not available.\n"
566 "The document class can still be used, but the\n"
567 "document cannot be compiled until the following\n"
568 "prerequisites are installed:\n"
570 "See section 3.1.2.2 of the User's Guide for\n"
571 "more information."), desc, prereqs);
572 frontend::Alert::warning(_("Document class not available"),
575 } else if (token == "\\begin_preamble") {
577 } else if (token == "\\begin_local_layout") {
578 readLocalLayout(lex);
579 } else if (token == "\\begin_modules") {
581 } else if (token == "\\begin_removed_modules") {
582 readRemovedModules(lex);
583 } else if (token == "\\begin_includeonly") {
584 readIncludeonly(lex);
585 } else if (token == "\\maintain_unincluded_children") {
586 lex >> maintain_unincluded_children;
587 } else if (token == "\\options") {
589 options = lex.getString();
590 } else if (token == "\\use_default_options") {
591 lex >> use_default_options;
592 } else if (token == "\\master") {
594 master = lex.getString();
595 } else if (token == "\\suppress_date") {
596 lex >> suppress_date;
597 } else if (token == "\\language") {
599 } else if (token == "\\inputencoding") {
601 } else if (token == "\\graphics") {
602 readGraphicsDriver(lex);
603 } else if (token == "\\default_output_format") {
604 lex >> defaultOutputFormat;
605 } else if (token == "\\bibtex_command") {
607 bibtex_command = lex.getString();
608 } else if (token == "\\index_command") {
610 index_command = lex.getString();
611 } else if (token == "\\fontencoding") {
613 fontenc = lex.getString();
614 } else if (token == "\\font_roman") {
616 fontsRoman = lex.getString();
617 } else if (token == "\\font_sans") {
619 fontsSans = lex.getString();
620 } else if (token == "\\font_typewriter") {
622 fontsTypewriter = lex.getString();
623 } else if (token == "\\font_default_family") {
624 lex >> fontsDefaultFamily;
625 } else if (token == "\\use_xetex") {
627 } else if (token == "\\font_sc") {
629 } else if (token == "\\font_osf") {
631 } else if (token == "\\font_sf_scale") {
632 lex >> fontsSansScale;
633 } else if (token == "\\font_tt_scale") {
634 lex >> fontsTypewriterScale;
635 } else if (token == "\\font_cjk") {
637 } else if (token == "\\paragraph_separation") {
640 paragraph_separation = parseptranslator().find(parsep);
641 } else if (token == "\\paragraph_indentation") {
643 string indentation = lex.getString();
644 pimpl_->indentation = HSpace(indentation);
645 } else if (token == "\\defskip") {
647 string defskip = lex.getString();
648 if (defskip == "defskip")
651 pimpl_->defskip = VSpace(defskip);
652 } else if (token == "\\quotes_language") {
655 quotes_language = quoteslangtranslator().find(quotes_lang);
656 } else if (token == "\\papersize") {
659 papersize = papersizetranslator().find(ppsize);
660 } else if (token == "\\use_geometry") {
662 } else if (token == "\\use_amsmath") {
665 use_amsmath = packagetranslator().find(use_ams);
666 } else if (token == "\\use_esint") {
669 use_esint = packagetranslator().find(useesint);
670 } else if (token == "\\use_mhchem") {
673 use_mhchem = packagetranslator().find(usemhchem);
674 } else if (token == "\\use_mathdots") {
677 use_mathdots = packagetranslator().find(usemathdots);
678 } else if (token == "\\cite_engine") {
681 cite_engine_ = citeenginetranslator().find(engine);
682 } else if (token == "\\use_bibtopic") {
684 } else if (token == "\\use_indices") {
686 } else if (token == "\\tracking_changes") {
688 } else if (token == "\\output_changes") {
689 lex >> outputChanges;
690 } else if (token == "\\branch") {
692 docstring branch = lex.getDocString();
693 branchlist().add(branch);
696 string const tok = lex.getString();
697 if (tok == "\\end_branch")
699 Branch * branch_ptr = branchlist().find(branch);
700 if (tok == "\\selected") {
703 branch_ptr->setSelected(lex.getInteger());
705 if (tok == "\\filename_suffix") {
708 branch_ptr->setFileNameSuffix(lex.getInteger());
710 if (tok == "\\color") {
712 string color = lex.getString();
714 branch_ptr->setColor(color);
715 // Update also the Color table:
717 color = lcolor.getX11Name(Color_background);
719 lcolor.setColor(to_utf8(branch), color);
722 } else if (token == "\\index") {
724 docstring index = lex.getDocString();
726 indiceslist().add(index);
729 string const tok = lex.getString();
730 if (tok == "\\end_index")
732 Index * index_ptr = indiceslist().find(index);
733 if (tok == "\\shortcut") {
735 shortcut = lex.getDocString();
737 index_ptr->setShortcut(shortcut);
739 if (tok == "\\color") {
741 string color = lex.getString();
743 index_ptr->setColor(color);
744 // Update also the Color table:
746 color = lcolor.getX11Name(Color_background);
748 if (!shortcut.empty())
749 lcolor.setColor(to_utf8(shortcut), color);
752 } else if (token == "\\author") {
754 istringstream ss(lex.getString());
757 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
758 } else if (token == "\\paperorientation") {
761 orientation = paperorientationtranslator().find(orient);
762 } else if (token == "\\backgroundcolor") {
764 backgroundcolor = lyx::rgbFromHexName(lex.getString());
765 isbackgroundcolor = true;
766 } else if (token == "\\fontcolor") {
768 fontcolor = lyx::rgbFromHexName(lex.getString());
770 } else if (token == "\\notefontcolor") {
772 string color = lex.getString();
773 notefontcolor = lyx::rgbFromHexName(color);
774 } else if (token == "\\boxbgcolor") {
776 string color = lex.getString();
777 boxbgcolor = lyx::rgbFromHexName(color);
778 } else if (token == "\\paperwidth") {
780 } else if (token == "\\paperheight") {
782 } else if (token == "\\leftmargin") {
784 } else if (token == "\\topmargin") {
786 } else if (token == "\\rightmargin") {
788 } else if (token == "\\bottommargin") {
790 } else if (token == "\\headheight") {
792 } else if (token == "\\headsep") {
794 } else if (token == "\\footskip") {
796 } else if (token == "\\columnsep") {
798 } else if (token == "\\paperfontsize") {
800 } else if (token == "\\papercolumns") {
802 } else if (token == "\\listings_params") {
805 listings_params = InsetListingsParams(par).params();
806 } else if (token == "\\papersides") {
809 sides = sidestranslator().find(psides);
810 } else if (token == "\\paperpagestyle") {
812 } else if (token == "\\bullet") {
814 } else if (token == "\\bulletLaTeX") {
815 readBulletsLaTeX(lex);
816 } else if (token == "\\secnumdepth") {
818 } else if (token == "\\tocdepth") {
820 } else if (token == "\\spacing") {
824 if (nspacing == "other") {
827 spacing().set(spacetranslator().find(nspacing), tmp_val);
828 } else if (token == "\\float_placement") {
829 lex >> float_placement;
831 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
832 string toktmp = pdfoptions().readToken(lex, token);
833 if (!toktmp.empty()) {
834 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
838 } else if (token == "\\html_math_output") {
841 html_math_output = static_cast<MathOutput>(temp);
842 } else if (token == "\\html_be_strict") {
843 lex >> html_be_strict;
844 } else if (token == "\\html_math_img_scale") {
845 lex >> html_math_img_scale;
846 } else if (token == "\\html_latex_start") {
848 html_latex_start = lex.getString();
849 } else if (token == "\\html_latex_end") {
851 html_latex_end = lex.getString();
852 } else if (token == "\\output_sync") {
854 } else if (token == "\\output_sync_macro") {
855 lex >> output_sync_macro;
857 lyxerr << "BufferParams::readToken(): Unknown token: " <<
866 void BufferParams::writeFile(ostream & os) const
868 // The top of the file is written by the buffer.
869 // Prints out the buffer info into the .lyx file given by file
872 os << "\\textclass " << baseClass()->name() << '\n';
875 if (!preamble.empty()) {
876 // remove '\n' from the end of preamble
877 string const tmppreamble = rtrim(preamble, "\n");
878 os << "\\begin_preamble\n"
880 << "\n\\end_preamble\n";
884 if (!options.empty()) {
885 os << "\\options " << options << '\n';
888 // use the class options defined in the layout?
889 os << "\\use_default_options "
890 << convert<string>(use_default_options) << "\n";
892 // the master document
893 if (!master.empty()) {
894 os << "\\master " << master << '\n';
898 if (!removedModules_.empty()) {
899 os << "\\begin_removed_modules" << '\n';
900 list<string>::const_iterator it = removedModules_.begin();
901 list<string>::const_iterator en = removedModules_.end();
902 for (; it != en; it++)
904 os << "\\end_removed_modules" << '\n';
908 if (!layoutModules_.empty()) {
909 os << "\\begin_modules" << '\n';
910 LayoutModuleList::const_iterator it = layoutModules_.begin();
911 LayoutModuleList::const_iterator en = layoutModules_.end();
912 for (; it != en; it++)
914 os << "\\end_modules" << '\n';
918 if (!includedChildren_.empty()) {
919 os << "\\begin_includeonly" << '\n';
920 list<string>::const_iterator it = includedChildren_.begin();
921 list<string>::const_iterator en = includedChildren_.end();
922 for (; it != en; it++)
924 os << "\\end_includeonly" << '\n';
926 os << "\\maintain_unincluded_children "
927 << convert<string>(maintain_unincluded_children) << '\n';
929 // local layout information
930 if (!local_layout.empty()) {
931 // remove '\n' from the end
932 string const tmplocal = rtrim(local_layout, "\n");
933 os << "\\begin_local_layout\n"
935 << "\n\\end_local_layout\n";
938 // then the text parameters
939 if (language != ignore_language)
940 os << "\\language " << language->lang() << '\n';
941 os << "\\inputencoding " << inputenc
942 << "\n\\fontencoding " << fontenc
943 << "\n\\font_roman " << fontsRoman
944 << "\n\\font_sans " << fontsSans
945 << "\n\\font_typewriter " << fontsTypewriter
946 << "\n\\font_default_family " << fontsDefaultFamily
947 << "\n\\use_xetex " << convert<string>(useXetex)
948 << "\n\\font_sc " << convert<string>(fontsSC)
949 << "\n\\font_osf " << convert<string>(fontsOSF)
950 << "\n\\font_sf_scale " << fontsSansScale
951 << "\n\\font_tt_scale " << fontsTypewriterScale
953 if (!fontsCJK.empty()) {
954 os << "\\font_cjk " << fontsCJK << '\n';
956 os << "\n\\graphics " << graphicsDriver << '\n';
957 os << "\\default_output_format " << defaultOutputFormat << '\n';
958 os << "\\output_sync " << output_sync << '\n';
959 if (!output_sync_macro.empty())
960 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
961 os << "\\bibtex_command " << bibtex_command << '\n';
962 os << "\\index_command " << index_command << '\n';
964 if (!float_placement.empty()) {
965 os << "\\float_placement " << float_placement << '\n';
967 os << "\\paperfontsize " << fontsize << '\n';
969 spacing().writeFile(os);
970 pdfoptions().writeFile(os);
972 os << "\\papersize " << string_papersize[papersize]
973 << "\n\\use_geometry " << convert<string>(use_geometry)
974 << "\n\\use_amsmath " << use_amsmath
975 << "\n\\use_esint " << use_esint
976 << "\n\\use_mhchem " << use_mhchem
977 << "\n\\use_mathdots " << use_mathdots
978 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
979 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
980 << "\n\\use_indices " << convert<string>(use_indices)
981 << "\n\\paperorientation " << string_orientation[orientation]
982 << "\n\\suppress_date " << convert<string>(suppress_date)
984 if (isbackgroundcolor == true)
985 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
986 if (isfontcolor == true)
987 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
988 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
989 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
990 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
991 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
993 BranchList::const_iterator it = branchlist().begin();
994 BranchList::const_iterator end = branchlist().end();
995 for (; it != end; ++it) {
996 os << "\\branch " << to_utf8(it->branch())
997 << "\n\\selected " << it->isSelected()
998 << "\n\\filename_suffix " << it->hasFileNameSuffix()
999 << "\n\\color " << lyx::X11hexname(it->color())
1004 IndicesList::const_iterator iit = indiceslist().begin();
1005 IndicesList::const_iterator iend = indiceslist().end();
1006 for (; iit != iend; ++iit) {
1007 os << "\\index " << to_utf8(iit->index())
1008 << "\n\\shortcut " << to_utf8(iit->shortcut())
1009 << "\n\\color " << lyx::X11hexname(iit->color())
1014 if (!paperwidth.empty())
1015 os << "\\paperwidth "
1016 << VSpace(paperwidth).asLyXCommand() << '\n';
1017 if (!paperheight.empty())
1018 os << "\\paperheight "
1019 << VSpace(paperheight).asLyXCommand() << '\n';
1020 if (!leftmargin.empty())
1021 os << "\\leftmargin "
1022 << VSpace(leftmargin).asLyXCommand() << '\n';
1023 if (!topmargin.empty())
1024 os << "\\topmargin "
1025 << VSpace(topmargin).asLyXCommand() << '\n';
1026 if (!rightmargin.empty())
1027 os << "\\rightmargin "
1028 << VSpace(rightmargin).asLyXCommand() << '\n';
1029 if (!bottommargin.empty())
1030 os << "\\bottommargin "
1031 << VSpace(bottommargin).asLyXCommand() << '\n';
1032 if (!headheight.empty())
1033 os << "\\headheight "
1034 << VSpace(headheight).asLyXCommand() << '\n';
1035 if (!headsep.empty())
1037 << VSpace(headsep).asLyXCommand() << '\n';
1038 if (!footskip.empty())
1040 << VSpace(footskip).asLyXCommand() << '\n';
1041 if (!columnsep.empty())
1042 os << "\\columnsep "
1043 << VSpace(columnsep).asLyXCommand() << '\n';
1044 os << "\\secnumdepth " << secnumdepth
1045 << "\n\\tocdepth " << tocdepth
1046 << "\n\\paragraph_separation "
1047 << string_paragraph_separation[paragraph_separation];
1048 if (!paragraph_separation)
1049 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1051 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1052 os << "\n\\quotes_language "
1053 << string_quotes_language[quotes_language]
1054 << "\n\\papercolumns " << columns
1055 << "\n\\papersides " << sides
1056 << "\n\\paperpagestyle " << pagestyle << '\n';
1057 if (!listings_params.empty())
1058 os << "\\listings_params \"" <<
1059 InsetListingsParams(listings_params).encodedString() << "\"\n";
1060 for (int i = 0; i < 4; ++i) {
1061 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1062 if (user_defined_bullet(i).getFont() != -1) {
1063 os << "\\bullet " << i << " "
1064 << user_defined_bullet(i).getFont() << " "
1065 << user_defined_bullet(i).getCharacter() << " "
1066 << user_defined_bullet(i).getSize() << "\n";
1070 os << "\\bulletLaTeX " << i << " \""
1071 << lyx::to_ascii(user_defined_bullet(i).getText())
1077 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1078 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1079 << "\\html_math_output " << html_math_output << '\n'
1080 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1082 if (html_math_img_scale != 1.0)
1083 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1084 if (!html_latex_start.empty())
1085 os << "\\html_latex_start " << html_latex_start << '\n';
1086 if (!html_latex_end.empty())
1087 os << "\\html_latex_end " << html_latex_end << '\n';
1089 os << pimpl_->authorlist;
1093 void BufferParams::validate(LaTeXFeatures & features) const
1095 features.require(documentClass().requires());
1097 if (outputChanges) {
1098 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1099 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1100 LaTeXFeatures::isAvailable("xcolor");
1102 switch (features.runparams().flavor) {
1103 case OutputParams::LATEX:
1105 features.require("ct-dvipost");
1106 features.require("dvipost");
1107 } else if (xcolorulem) {
1108 features.require("ct-xcolor-ulem");
1109 features.require("ulem");
1110 features.require("xcolor");
1112 features.require("ct-none");
1115 case OutputParams::PDFLATEX:
1116 case OutputParams::XETEX:
1118 features.require("ct-xcolor-ulem");
1119 features.require("ulem");
1120 features.require("xcolor");
1121 // improves color handling in PDF output
1122 features.require("pdfcolmk");
1124 features.require("ct-none");
1132 // Floats with 'Here definitely' as default setting.
1133 if (float_placement.find('H') != string::npos)
1134 features.require("float");
1136 // AMS Style is at document level
1137 if (use_amsmath == package_on
1138 || documentClass().provides("amsmath"))
1139 features.require("amsmath");
1140 if (use_esint == package_on)
1141 features.require("esint");
1142 if (use_mhchem == package_on)
1143 features.require("mhchem");
1144 if (use_mathdots == package_on)
1145 features.require("mathdots");
1147 // Document-level line spacing
1148 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1149 features.require("setspace");
1151 // the bullet shapes are buffer level not paragraph level
1152 // so they are tested here
1153 for (int i = 0; i < 4; ++i) {
1154 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1156 int const font = user_defined_bullet(i).getFont();
1158 int const c = user_defined_bullet(i).getCharacter();
1164 features.require("latexsym");
1166 } else if (font == 1) {
1167 features.require("amssymb");
1168 } else if (font >= 2 && font <= 5) {
1169 features.require("pifont");
1173 if (pdfoptions().use_hyperref) {
1174 features.require("hyperref");
1175 // due to interferences with babel and hyperref, the color package has to
1176 // be loaded after hyperref when hyperref is used with the colorlinks
1177 // option, see http://www.lyx.org/trac/ticket/5291
1178 if (pdfoptions().colorlinks)
1179 features.require("color");
1183 features.require("xetex");
1185 if (language->lang() == "vietnamese")
1186 features.require("vietnamese");
1187 else if (language->lang() == "japanese")
1188 features.require("japanese");
1192 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1193 TexRow & texrow, FileName const & filepath) const
1195 os << "\\documentclass";
1197 DocumentClass const & tclass = documentClass();
1199 ostringstream clsoptions; // the document class options.
1201 if (tokenPos(tclass.opt_fontsize(),
1202 '|', fontsize) >= 0) {
1203 // only write if existing in list (and not default)
1204 clsoptions << fontsize << "pt,";
1207 // all paper sizes except of A4, A5, B5 and the US sizes need the
1209 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1210 && papersize != PAPER_USLETTER
1211 && papersize != PAPER_USLEGAL
1212 && papersize != PAPER_USEXECUTIVE
1213 && papersize != PAPER_A4
1214 && papersize != PAPER_A5
1215 && papersize != PAPER_B5;
1217 if (!use_geometry) {
1218 switch (papersize) {
1220 clsoptions << "a4paper,";
1222 case PAPER_USLETTER:
1223 clsoptions << "letterpaper,";
1226 clsoptions << "a5paper,";
1229 clsoptions << "b5paper,";
1231 case PAPER_USEXECUTIVE:
1232 clsoptions << "executivepaper,";
1235 clsoptions << "legalpaper,";
1269 if (sides != tclass.sides()) {
1272 clsoptions << "oneside,";
1275 clsoptions << "twoside,";
1281 if (columns != tclass.columns()) {
1283 clsoptions << "twocolumn,";
1285 clsoptions << "onecolumn,";
1289 && orientation == ORIENTATION_LANDSCAPE)
1290 clsoptions << "landscape,";
1292 // language should be a parameter to \documentclass
1293 if (language->babel() == "hebrew"
1294 && default_language->babel() != "hebrew")
1295 // This seems necessary
1296 features.useLanguage(default_language);
1298 ostringstream language_options;
1299 bool const use_babel = features.useBabel() && !tclass.provides("babel");
1301 language_options << features.getLanguages();
1302 if (!language->babel().empty()) {
1303 if (!language_options.str().empty())
1304 language_options << ',';
1305 language_options << language->babel();
1307 // if Vietnamese is used, babel must directly be loaded
1308 // with language options, not in the class options, see
1309 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1310 size_t viet = language_options.str().find("vietnam");
1311 // viet = string::npos when not found
1312 // the same is for all other languages that are not directly supported by
1313 // babel, but where LaTeX-packages add babel support.
1314 // this is currently the case for Latvian, Lithuanian, Mongolian
1316 size_t latvian = language_options.str().find("latvian");
1317 size_t lithu = language_options.str().find("lithuanian");
1318 size_t mongo = language_options.str().find("mongolian");
1319 size_t turkmen = language_options.str().find("turkmen");
1320 // if Japanese is used, babel must directly be loaded
1321 // with language options, not in the class options, see
1322 // http://www.lyx.org/trac/ticket/4597#c4
1323 size_t japan = language_options.str().find("japanese");
1324 if (lyxrc.language_global_options && !language_options.str().empty()
1325 && viet == string::npos && japan == string::npos
1326 && latvian == string::npos && lithu == string::npos
1327 && mongo == string::npos && turkmen == string::npos)
1328 clsoptions << language_options.str() << ',';
1331 // the predefined options from the layout
1332 if (use_default_options && !tclass.options().empty())
1333 clsoptions << tclass.options() << ',';
1335 // the user-defined options
1336 if (!options.empty()) {
1337 clsoptions << options << ',';
1340 string strOptions(clsoptions.str());
1341 if (!strOptions.empty()) {
1342 strOptions = rtrim(strOptions, ",");
1344 os << '[' << from_utf8(strOptions) << ']';
1347 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1349 // end of \documentclass defs
1352 os << "\\usepackage{fontspec}\n";
1356 // font selection must be done before loading fontenc.sty
1357 string const fonts =
1358 loadFonts(fontsRoman, fontsSans,
1359 fontsTypewriter, fontsSC, fontsOSF,
1360 fontsSansScale, fontsTypewriterScale, useXetex);
1361 if (!fonts.empty()) {
1362 os << from_ascii(fonts);
1365 if (fontsDefaultFamily != "default")
1366 os << "\\renewcommand{\\familydefault}{\\"
1367 << from_ascii(fontsDefaultFamily) << "}\n";
1369 // set font encoding
1370 // for arabic_arabi and farsi we also need to load the LAE and
1372 // XeTeX works without fontenc
1373 if (font_encoding() != "default" && language->lang() != "japanese"
1374 && !useXetex && !tclass.provides("fontenc")) {
1375 size_t fars = language_options.str().find("farsi");
1376 size_t arab = language_options.str().find("arabic");
1377 if (language->lang() == "arabic_arabi"
1378 || language->lang() == "farsi" || fars != string::npos
1379 || arab != string::npos) {
1380 os << "\\usepackage[" << from_ascii(font_encoding())
1381 << ",LFE,LAE]{fontenc}\n";
1384 os << "\\usepackage[" << from_ascii(font_encoding())
1390 // handle inputenc etc.
1391 writeEncodingPreamble(os, features, texrow);
1394 if (!features.runparams().includeall && !includedChildren_.empty()) {
1395 os << "\\includeonly{";
1396 list<string>::const_iterator it = includedChildren_.begin();
1398 for (; it != includedChildren_.end() ; ++it) {
1399 string incfile = *it;
1400 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1401 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1403 if (!features.runparams().nice)
1405 // \includeonly doesn't want an extension
1406 incfile = changeExtension(incfile, string());
1407 incfile = support::latex_path(incfile);
1408 if (!incfile.empty()) {
1411 os << from_utf8(incfile);
1418 if (!listings_params.empty() || features.isRequired("listings")) {
1419 os << "\\usepackage{listings}\n";
1422 if (!listings_params.empty()) {
1424 // do not test validity because listings_params is
1425 // supposed to be valid
1427 InsetListingsParams(listings_params).separatedParams(true);
1428 // we can't support all packages, but we should load the color package
1429 if (par.find("\\color", 0) != string::npos)
1430 features.require("color");
1431 os << from_utf8(par);
1432 // count the number of newlines
1433 for (size_t i = 0; i < par.size(); ++i)
1439 if (!tclass.provides("geometry")
1440 && (use_geometry || nonstandard_papersize)) {
1441 odocstringstream ods;
1442 if (!getGraphicsDriver("geometry").empty())
1443 ods << getGraphicsDriver("geometry");
1444 if (orientation == ORIENTATION_LANDSCAPE)
1445 ods << ",landscape";
1446 switch (papersize) {
1448 if (!paperwidth.empty())
1449 ods << ",paperwidth="
1450 << from_ascii(paperwidth);
1451 if (!paperheight.empty())
1452 ods << ",paperheight="
1453 << from_ascii(paperheight);
1455 case PAPER_USLETTER:
1456 ods << ",letterpaper";
1459 ods << ",legalpaper";
1461 case PAPER_USEXECUTIVE:
1462 ods << ",executivepaper";
1549 // default papersize ie PAPER_DEFAULT
1550 switch (lyxrc.default_papersize) {
1551 case PAPER_DEFAULT: // keep compiler happy
1552 case PAPER_USLETTER:
1553 ods << ",letterpaper";
1556 ods << ",legalpaper";
1558 case PAPER_USEXECUTIVE:
1559 ods << ",executivepaper";
1601 docstring const g_options = trim(ods.str(), ",");
1602 os << "\\usepackage";
1603 if (!g_options.empty())
1604 os << '[' << g_options << ']';
1605 os << "{geometry}\n";
1607 // output this only if use_geometry is true
1609 os << "\\geometry{verbose";
1610 if (!topmargin.empty())
1611 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1612 if (!bottommargin.empty())
1613 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1614 if (!leftmargin.empty())
1615 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1616 if (!rightmargin.empty())
1617 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1618 if (!headheight.empty())
1619 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1620 if (!headsep.empty())
1621 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1622 if (!footskip.empty())
1623 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1624 if (!columnsep.empty())
1625 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1629 } else if (orientation == ORIENTATION_LANDSCAPE
1630 || papersize != PAPER_DEFAULT) {
1631 features.require("papersize");
1634 if (tokenPos(tclass.opt_pagestyle(),
1635 '|', pagestyle) >= 0) {
1636 if (pagestyle == "fancy") {
1637 os << "\\usepackage{fancyhdr}\n";
1640 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1644 // only output when the background color is not default
1645 if (isbackgroundcolor == true) {
1646 // only require color here, the background color will be defined
1647 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1649 features.require("color");
1650 features.require("pagecolor");
1653 // only output when the font color is not default
1654 if (isfontcolor == true) {
1655 // only require color here, the font color will be defined
1656 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1658 features.require("color");
1659 features.require("fontcolor");
1662 // Only if class has a ToC hierarchy
1663 if (tclass.hasTocLevels()) {
1664 if (secnumdepth != tclass.secnumdepth()) {
1665 os << "\\setcounter{secnumdepth}{"
1670 if (tocdepth != tclass.tocdepth()) {
1671 os << "\\setcounter{tocdepth}{"
1678 if (paragraph_separation) {
1679 // when skip separation
1680 switch (getDefSkip().kind()) {
1681 case VSpace::SMALLSKIP:
1682 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1684 case VSpace::MEDSKIP:
1685 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1687 case VSpace::BIGSKIP:
1688 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1690 case VSpace::LENGTH:
1691 os << "\\setlength{\\parskip}{"
1692 << from_utf8(getDefSkip().length().asLatexString())
1695 default: // should never happen // Then delete it.
1696 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1700 os << "\\setlength{\\parindent}{0pt}\n";
1703 // when separation by indentation
1704 // only output something when a width is given
1705 if (getIndentation().asLyXCommand() != "default") {
1706 os << "\\setlength{\\parindent}{"
1707 << from_utf8(getIndentation().asLatexCommand())
1713 // Now insert the LyX specific LaTeX commands...
1714 docstring lyxpreamble;
1717 if (!output_sync_macro.empty())
1718 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1719 else if (features.runparams().flavor == OutputParams::LATEX)
1720 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1721 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1722 lyxpreamble += "\\synctex=-1\n";
1725 // due to interferences with babel and hyperref, the color package has to
1726 // be loaded (when it is not already loaded) before babel when hyperref
1727 // is used with the colorlinks option, see
1728 // http://www.lyx.org/trac/ticket/5291
1729 // we decided therefore to load color always before babel, see
1730 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1731 lyxpreamble += from_ascii(features.getColorOptions());
1733 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1735 && (features.isRequired("jurabib")
1736 || features.isRequired("hyperref")
1737 || features.isRequired("vietnamese")
1738 || features.isRequired("japanese") ) ) {
1740 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1741 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1744 // The optional packages;
1745 lyxpreamble += from_ascii(features.getPackages());
1747 // Additional Indices
1748 if (features.isRequired("splitidx")) {
1749 IndicesList::const_iterator iit = indiceslist().begin();
1750 IndicesList::const_iterator iend = indiceslist().end();
1751 for (; iit != iend; ++iit) {
1752 lyxpreamble += "\\newindex[";
1753 lyxpreamble += iit->index();
1754 lyxpreamble += "]{";
1755 lyxpreamble += iit->shortcut();
1756 lyxpreamble += "}\n";
1761 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1764 // * Hyperref manual: "Make sure it comes last of your loaded
1765 // packages, to give it a fighting chance of not being over-written,
1766 // since its job is to redefine many LaTeX commands."
1767 // * Email from Heiko Oberdiek: "It is usually better to load babel
1768 // before hyperref. Then hyperref has a chance to detect babel.
1769 // * Has to be loaded before the "LyX specific LaTeX commands" to
1770 // avoid errors with algorithm floats.
1771 // use hyperref explicitly if it is required
1772 if (features.isRequired("hyperref")) {
1773 // pass what we have to stream here, since we need
1774 // to access the stream itself in PDFOptions.
1778 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1780 OutputParams tmp_params = features.runparams();
1781 lines += pdfoptions().writeLaTeX(tmp_params, os,
1782 documentClass().provides("hyperref"));
1783 texrow.newlines(lines);
1784 // set back for the rest
1785 lyxpreamble.clear();
1786 } else if (features.isRequired("nameref"))
1787 // hyperref loads this automatically
1788 lyxpreamble += "\\usepackage{nameref}\n";
1790 // Will be surrounded by \makeatletter and \makeatother when not empty
1791 docstring atlyxpreamble;
1793 // Some macros LyX will need
1794 docstring tmppreamble(features.getMacros());
1796 if (!tmppreamble.empty())
1797 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1798 "LyX specific LaTeX commands.\n"
1799 + tmppreamble + '\n';
1801 // the text class specific preamble
1802 tmppreamble = features.getTClassPreamble();
1803 if (!tmppreamble.empty())
1804 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1805 "Textclass specific LaTeX commands.\n"
1806 + tmppreamble + '\n';
1808 // suppress date if selected
1809 // use \@ifundefined because we cannot be sure that every document class
1810 // has a \date command
1812 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1814 /* the user-defined preamble */
1815 if (!containsOnly(preamble, " \n\t"))
1817 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1818 "User specified LaTeX commands.\n"
1819 + from_utf8(preamble) + '\n';
1821 // subfig loads internally the LaTeX package "caption". As
1822 // caption is a very popular package, users will load it in
1823 // the preamble. Therefore we must load subfig behind the
1824 // user-defined preamble and check if the caption package was
1825 // loaded or not. For the case that caption is loaded before
1826 // subfig, there is the subfig option "caption=false". This
1827 // option also works when a koma-script class is used and
1828 // koma's own caption commands are used instead of caption. We
1829 // use \PassOptionsToPackage here because the user could have
1830 // already loaded subfig in the preamble.
1831 if (features.isRequired("subfig")) {
1832 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1833 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1834 "\\usepackage{subfig}\n";
1837 // Itemize bullet settings need to be last in case the user
1838 // defines their own bullets that use a package included
1839 // in the user-defined preamble -- ARRae
1840 // Actually it has to be done much later than that
1841 // since some packages like frenchb make modifications
1842 // at \begin{document} time -- JMarc
1843 docstring bullets_def;
1844 for (int i = 0; i < 4; ++i) {
1845 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1846 if (bullets_def.empty())
1847 bullets_def += "\\AtBeginDocument{\n";
1848 bullets_def += " \\def\\labelitemi";
1850 // `i' is one less than the item to modify
1857 bullets_def += "ii";
1863 bullets_def += '{' +
1864 user_defined_bullet(i).getText()
1869 if (!bullets_def.empty())
1870 atlyxpreamble += bullets_def + "}\n\n";
1872 if (!atlyxpreamble.empty())
1873 lyxpreamble += "\n\\makeatletter\n"
1874 + atlyxpreamble + "\\makeatother\n\n";
1876 // We try to load babel late, in case it interferes with other packages.
1877 // Jurabib and Hyperref have to be called after babel, though.
1878 if (use_babel && !features.isRequired("jurabib")
1879 && !features.isRequired("hyperref")
1880 && !features.isRequired("vietnamese")
1881 && !features.isRequired("japanese")) {
1883 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1884 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1887 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1888 if (!i18npreamble.empty())
1889 lyxpreamble += i18npreamble + '\n';
1892 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1893 texrow.newlines(nlines);
1897 // these packages (xunicode, for that matter) need to be loaded at least
1898 // after amsmath, amssymb, esint and the other packages that provide
1901 os << "\\usepackage{xunicode}\n";
1903 os << "\\usepackage{xltxtra}\n";
1910 void BufferParams::useClassDefaults()
1912 DocumentClass const & tclass = documentClass();
1914 sides = tclass.sides();
1915 columns = tclass.columns();
1916 pagestyle = tclass.pagestyle();
1917 use_default_options = true;
1918 // Only if class has a ToC hierarchy
1919 if (tclass.hasTocLevels()) {
1920 secnumdepth = tclass.secnumdepth();
1921 tocdepth = tclass.tocdepth();
1926 bool BufferParams::hasClassDefaults() const
1928 DocumentClass const & tclass = documentClass();
1930 return sides == tclass.sides()
1931 && columns == tclass.columns()
1932 && pagestyle == tclass.pagestyle()
1933 && use_default_options
1934 && secnumdepth == tclass.secnumdepth()
1935 && tocdepth == tclass.tocdepth();
1939 DocumentClass const & BufferParams::documentClass() const
1945 DocumentClass const * BufferParams::documentClassPtr() const {
1950 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1951 // evil, but this function is evil
1952 doc_class_ = const_cast<DocumentClass *>(tc);
1956 bool BufferParams::setBaseClass(string const & classname)
1958 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1959 LayoutFileList & bcl = LayoutFileList::get();
1960 if (!bcl.haveClass(classname)) {
1962 bformat(_("The layout file:\n"
1964 "could not be found. A default textclass with default\n"
1965 "layouts will be used. LyX will not be able to produce\n"
1967 from_utf8(classname));
1968 frontend::Alert::error(_("Document class not found"), s);
1969 bcl.addEmptyClass(classname);
1972 bool const success = bcl[classname].load();
1975 bformat(_("Due to some error in it, the layout file:\n"
1977 "could not be loaded. A default textclass with default\n"
1978 "layouts will be used. LyX will not be able to produce\n"
1980 from_utf8(classname));
1981 frontend::Alert::error(_("Could not load class"), s);
1982 bcl.addEmptyClass(classname);
1985 pimpl_->baseClass_ = classname;
1986 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1991 LayoutFile const * BufferParams::baseClass() const
1993 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1994 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2000 LayoutFileIndex const & BufferParams::baseClassID() const
2002 return pimpl_->baseClass_;
2006 void BufferParams::makeDocumentClass()
2011 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
2013 if (!local_layout.empty()) {
2014 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
2015 docstring const msg = _("Error reading internal layout information");
2016 frontend::Alert::warning(_("Read Error"), msg);
2022 bool BufferParams::moduleCanBeAdded(string const & modName) const
2024 return layoutModules_.moduleCanBeAdded(modName, baseClass());
2028 bool BufferParams::addLayoutModule(string const & modName)
2030 LayoutModuleList::const_iterator it = layoutModules_.begin();
2031 LayoutModuleList::const_iterator end = layoutModules_.end();
2032 for (; it != end; it++)
2035 layoutModules_.push_back(modName);
2040 Font const BufferParams::getFont() const
2042 FontInfo f = documentClass().defaultfont();
2043 if (fontsDefaultFamily == "rmdefault")
2044 f.setFamily(ROMAN_FAMILY);
2045 else if (fontsDefaultFamily == "sfdefault")
2046 f.setFamily(SANS_FAMILY);
2047 else if (fontsDefaultFamily == "ttdefault")
2048 f.setFamily(TYPEWRITER_FAMILY);
2049 return Font(f, language);
2053 void BufferParams::readPreamble(Lexer & lex)
2055 if (lex.getString() != "\\begin_preamble")
2056 lyxerr << "Error (BufferParams::readPreamble):"
2057 "consistency check failed." << endl;
2059 preamble = lex.getLongString("\\end_preamble");
2063 void BufferParams::readLocalLayout(Lexer & lex)
2065 if (lex.getString() != "\\begin_local_layout")
2066 lyxerr << "Error (BufferParams::readLocalLayout):"
2067 "consistency check failed." << endl;
2069 local_layout = lex.getLongString("\\end_local_layout");
2073 void BufferParams::readLanguage(Lexer & lex)
2075 if (!lex.next()) return;
2077 string const tmptok = lex.getString();
2079 // check if tmptok is part of tex_babel in tex-defs.h
2080 language = languages.getLanguage(tmptok);
2082 // Language tmptok was not found
2083 language = default_language;
2084 lyxerr << "Warning: Setting language `"
2085 << tmptok << "' to `" << language->lang()
2091 void BufferParams::readGraphicsDriver(Lexer & lex)
2096 string const tmptok = lex.getString();
2097 // check if tmptok is part of tex_graphics in tex_defs.h
2100 string const test = tex_graphics[n++];
2102 if (test == tmptok) {
2103 graphicsDriver = tmptok;
2108 "Warning: graphics driver `$$Token' not recognized!\n"
2109 " Setting graphics driver to `default'.\n");
2110 graphicsDriver = "default";
2117 void BufferParams::readBullets(Lexer & lex)
2122 int const index = lex.getInteger();
2124 int temp_int = lex.getInteger();
2125 user_defined_bullet(index).setFont(temp_int);
2126 temp_bullet(index).setFont(temp_int);
2128 user_defined_bullet(index).setCharacter(temp_int);
2129 temp_bullet(index).setCharacter(temp_int);
2131 user_defined_bullet(index).setSize(temp_int);
2132 temp_bullet(index).setSize(temp_int);
2136 void BufferParams::readBulletsLaTeX(Lexer & lex)
2138 // The bullet class should be able to read this.
2141 int const index = lex.getInteger();
2143 docstring const temp_str = lex.getDocString();
2145 user_defined_bullet(index).setText(temp_str);
2146 temp_bullet(index).setText(temp_str);
2150 void BufferParams::readModules(Lexer & lex)
2152 if (!lex.eatLine()) {
2153 lyxerr << "Error (BufferParams::readModules):"
2154 "Unexpected end of input." << endl;
2158 string mod = lex.getString();
2159 if (mod == "\\end_modules")
2161 addLayoutModule(mod);
2167 void BufferParams::readRemovedModules(Lexer & lex)
2169 if (!lex.eatLine()) {
2170 lyxerr << "Error (BufferParams::readRemovedModules):"
2171 "Unexpected end of input." << endl;
2175 string mod = lex.getString();
2176 if (mod == "\\end_removed_modules")
2178 removedModules_.push_back(mod);
2181 // now we want to remove any removed modules that were previously
2182 // added. normally, that will be because default modules were added in
2183 // setBaseClass(), which gets called when \textclass is read at the
2184 // start of the read.
2185 list<string>::const_iterator rit = removedModules_.begin();
2186 list<string>::const_iterator const ren = removedModules_.end();
2187 for (; rit != ren; rit++) {
2188 LayoutModuleList::iterator const mit = layoutModules_.begin();
2189 LayoutModuleList::iterator const men = layoutModules_.end();
2190 LayoutModuleList::iterator found = find(mit, men, *rit);
2193 layoutModules_.erase(found);
2198 void BufferParams::readIncludeonly(Lexer & lex)
2200 if (!lex.eatLine()) {
2201 lyxerr << "Error (BufferParams::readIncludeonly):"
2202 "Unexpected end of input." << endl;
2206 string child = lex.getString();
2207 if (child == "\\end_includeonly")
2209 includedChildren_.push_back(child);
2215 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2217 char real_papersize = papersize;
2218 if (real_papersize == PAPER_DEFAULT)
2219 real_papersize = lyxrc.default_papersize;
2221 switch (real_papersize) {
2223 // could be anything, so don't guess
2225 case PAPER_CUSTOM: {
2226 if (purpose == XDVI && !paperwidth.empty() &&
2227 !paperheight.empty()) {
2228 // heightxwidth<unit>
2229 string first = paperwidth;
2230 string second = paperheight;
2231 if (orientation == ORIENTATION_LANDSCAPE)
2234 return first.erase(first.length() - 2)
2240 // dvips and dvipdfm do not know this
2241 if (purpose == DVIPS || purpose == DVIPDFM)
2245 if (purpose == DVIPS || purpose == DVIPDFM)
2249 if (purpose == DVIPS || purpose == DVIPDFM)
2259 if (purpose == DVIPS || purpose == DVIPDFM)
2263 if (purpose == DVIPS || purpose == DVIPDFM)
2267 if (purpose == DVIPS || purpose == DVIPDFM)
2271 if (purpose == DVIPS || purpose == DVIPDFM)
2275 if (purpose == DVIPS || purpose == DVIPDFM)
2279 // dvipdfm does not know this
2280 if (purpose == DVIPDFM)
2284 if (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)
2340 if (purpose == DVIPS || purpose == DVIPDFM)
2344 if (purpose == DVIPS || purpose == DVIPDFM)
2347 case PAPER_USEXECUTIVE:
2348 // dvipdfm does not know this
2349 if (purpose == DVIPDFM)
2354 case PAPER_USLETTER:
2356 if (purpose == XDVI)
2363 string const BufferParams::dvips_options() const
2368 && papersize == PAPER_CUSTOM
2369 && !lyxrc.print_paper_dimension_flag.empty()
2370 && !paperwidth.empty()
2371 && !paperheight.empty()) {
2372 // using a custom papersize
2373 result = lyxrc.print_paper_dimension_flag;
2374 result += ' ' + paperwidth;
2375 result += ',' + paperheight;
2377 string const paper_option = paperSizeName(DVIPS);
2378 if (!paper_option.empty() && (paper_option != "letter" ||
2379 orientation != ORIENTATION_LANDSCAPE)) {
2380 // dvips won't accept -t letter -t landscape.
2381 // In all other cases, include the paper size
2383 result = lyxrc.print_paper_flag;
2384 result += ' ' + paper_option;
2387 if (orientation == ORIENTATION_LANDSCAPE &&
2388 papersize != PAPER_CUSTOM)
2389 result += ' ' + lyxrc.print_landscape_flag;
2394 string const BufferParams::font_encoding() const
2396 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2400 string BufferParams::babelCall(string const & lang_opts) const
2402 string lang_pack = lyxrc.language_package;
2403 if (lang_pack != "\\usepackage{babel}")
2405 // suppress the babel call when there is no babel language defined
2406 // for the document language in the lib/languages file and if no
2407 // other languages are used (lang_opts is then empty)
2408 if (lang_opts.empty())
2410 // If Vietnamese is used, babel must directly be loaded with the
2411 // language options, see
2412 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2413 size_t viet = lang_opts.find("vietnam");
2414 // viet = string::npos when not found
2415 // the same is for all other languages that are not directly supported by
2416 // babel, but where LaTeX-packages add babel support.
2417 // this is currently the case for Latvian, Lithuanian, Mongolian
2419 size_t latvian = lang_opts.find("latvian");
2420 size_t lithu = lang_opts.find("lithuanian");
2421 size_t mongo = lang_opts.find("mongolian");
2422 size_t turkmen = lang_opts.find("turkmen");
2423 // If Japanese is used, babel must directly be loaded with the
2424 // language options, see
2425 // http://www.lyx.org/trac/ticket/4597#c4
2426 size_t japan = lang_opts.find("japanese");
2427 if (!lyxrc.language_global_options || viet != string::npos
2428 || japan != string::npos || latvian != string::npos
2429 || lithu != string::npos || mongo != string::npos
2430 || turkmen != string::npos)
2431 return "\\usepackage[" + lang_opts + "]{babel}";
2436 docstring BufferParams::getGraphicsDriver(string const & package) const
2440 if (package == "geometry") {
2441 if (graphicsDriver == "dvips"
2442 || graphicsDriver == "dvipdfm"
2443 || graphicsDriver == "pdftex"
2444 || graphicsDriver == "vtex")
2445 result = from_ascii(graphicsDriver);
2446 else if (graphicsDriver == "dvipdfmx")
2447 result = from_ascii("dvipdfm");
2454 void BufferParams::writeEncodingPreamble(odocstream & os,
2455 LaTeXFeatures & features, TexRow & texrow) const
2459 if (inputenc == "auto") {
2460 string const doc_encoding =
2461 language->encoding()->latexName();
2462 Encoding::Package const package =
2463 language->encoding()->package();
2465 // Create a list with all the input encodings used
2467 set<string> encodings =
2468 features.getEncodingSet(doc_encoding);
2470 // If the "japanese" package (i.e. pLaTeX) is used,
2471 // inputenc must be omitted.
2472 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2473 if (package == Encoding::japanese)
2474 features.require("japanese");
2476 if ((!encodings.empty() || package == Encoding::inputenc)
2477 && !features.isRequired("japanese")) {
2478 os << "\\usepackage[";
2479 set<string>::const_iterator it = encodings.begin();
2480 set<string>::const_iterator const end = encodings.end();
2482 os << from_ascii(*it);
2485 for (; it != end; ++it)
2486 os << ',' << from_ascii(*it);
2487 if (package == Encoding::inputenc) {
2488 if (!encodings.empty())
2490 os << from_ascii(doc_encoding);
2492 os << "]{inputenc}\n";
2495 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2496 if (language->encoding()->name() == "utf8-cjk"
2497 && LaTeXFeatures::isAvailable("CJKutf8"))
2498 os << "\\usepackage{CJKutf8}\n";
2500 os << "\\usepackage{CJK}\n";
2503 } else if (inputenc != "default") {
2504 switch (encoding().package()) {
2505 case Encoding::none:
2506 case Encoding::japanese:
2508 case Encoding::inputenc:
2509 // do not load inputenc if japanese is used
2510 if (features.isRequired("japanese"))
2512 os << "\\usepackage[" << from_ascii(inputenc)
2517 if (encoding().name() == "utf8-cjk"
2518 && LaTeXFeatures::isAvailable("CJKutf8"))
2519 os << "\\usepackage{CJKutf8}\n";
2521 os << "\\usepackage{CJK}\n";
2527 // The encoding "armscii8" (for Armenian) is only available when
2528 // the package "armtex" is loaded.
2529 if (language->encoding()->latexName() == "armscii8"
2530 || inputenc == "armscii8") {
2531 os << "\\usepackage{armtex}\n";
2537 string const BufferParams::parseFontName(string const & name) const
2539 string mangled = name;
2540 size_t const idx = mangled.find('[');
2541 if (idx == string::npos || idx == 0)
2544 return mangled.substr(0, idx - 1);
2548 string const BufferParams::loadFonts(string const & rm,
2549 string const & sf, string const & tt,
2550 bool const & sc, bool const & osf,
2551 int const & sfscale, int const & ttscale,
2552 bool const & xetex) const
2554 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2555 several packages have been replaced by others, that might not
2556 be installed on every system. We have to take care for that
2557 (see psnfss.pdf). We try to support all psnfss fonts as well
2558 as the fonts that have become de facto standard in the LaTeX
2559 world (e.g. Latin Modern). We do not support obsolete fonts
2560 (like PSLatex). In general, it should be possible to mix any
2561 rm font with any sf or tt font, respectively. (JSpitzm)
2563 -- separate math fonts.
2566 if (rm == "default" && sf == "default" && tt == "default")
2573 if (rm != "default")
2574 os << "\\setmainfont[Mapping=tex-text]{"
2575 << parseFontName(rm) << "}\n";
2576 if (sf != "default") {
2577 string const sans = parseFontName(sf);
2579 os << "\\setsansfont[Scale="
2580 << float(sfscale) / 100
2581 << ",Mapping=tex-text]{"
2584 os << "\\setsansfont[Mapping=tex-text]{"
2587 if (tt != "default") {
2588 string const mono = parseFontName(tt);
2590 os << "\\setmonofont[Scale="
2591 << float(sfscale) / 100
2595 os << "\\setmonofont[Mapping=tex-text]{"
2599 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2604 // Computer Modern (must be explicitly selectable -- there might be classes
2605 // that define a different default font!
2607 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2608 // osf for Computer Modern needs eco.sty
2610 os << "\\usepackage{eco}\n";
2612 // Latin Modern Roman
2613 else if (rm == "lmodern")
2614 os << "\\usepackage{lmodern}\n";
2616 else if (rm == "ae") {
2617 // not needed when using OT1 font encoding.
2618 if (font_encoding() != "default")
2619 os << "\\usepackage{ae,aecompl}\n";
2622 else if (rm == "times") {
2623 // try to load the best available package
2624 if (LaTeXFeatures::isAvailable("mathptmx"))
2625 os << "\\usepackage{mathptmx}\n";
2626 else if (LaTeXFeatures::isAvailable("mathptm"))
2627 os << "\\usepackage{mathptm}\n";
2629 os << "\\usepackage{times}\n";
2632 else if (rm == "palatino") {
2633 // try to load the best available package
2634 if (LaTeXFeatures::isAvailable("mathpazo")) {
2635 os << "\\usepackage";
2641 // "osf" includes "sc"!
2645 os << "{mathpazo}\n";
2647 else if (LaTeXFeatures::isAvailable("mathpple"))
2648 os << "\\usepackage{mathpple}\n";
2650 os << "\\usepackage{palatino}\n";
2653 else if (rm == "utopia") {
2654 // fourier supersedes utopia.sty, but does
2655 // not work with OT1 encoding.
2656 if (LaTeXFeatures::isAvailable("fourier")
2657 && font_encoding() != "default") {
2658 os << "\\usepackage";
2669 os << "{fourier}\n";
2672 os << "\\usepackage{utopia}\n";
2674 // Bera (complete fontset)
2675 else if (rm == "bera" && sf == "default" && tt == "default")
2676 os << "\\usepackage{bera}\n";
2678 else if (rm != "default")
2679 os << "\\usepackage" << "{" << rm << "}\n";
2682 // Helvetica, Bera Sans
2683 if (sf == "helvet" || sf == "berasans") {
2685 os << "\\usepackage[scaled=" << float(sfscale) / 100
2686 << "]{" << sf << "}\n";
2688 os << "\\usepackage{" << sf << "}\n";
2691 else if (sf == "avant")
2692 os << "\\usepackage{" << sf << "}\n";
2693 // Computer Modern, Latin Modern, CM Bright
2694 else if (sf != "default")
2695 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2697 // monospaced/typewriter
2698 // Courier, LuxiMono
2699 if (tt == "luximono" || tt == "beramono") {
2701 os << "\\usepackage[scaled=" << float(ttscale) / 100
2702 << "]{" << tt << "}\n";
2704 os << "\\usepackage{" << tt << "}\n";
2707 else if (tt == "courier" )
2708 os << "\\usepackage{" << tt << "}\n";
2709 // Computer Modern, Latin Modern, CM Bright
2710 else if (tt != "default")
2711 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2717 Encoding const & BufferParams::encoding() const
2720 return *(encodings.fromLaTeXName("utf8-plain"));
2721 if (inputenc == "auto" || inputenc == "default")
2722 return *language->encoding();
2723 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2726 LYXERR0("Unknown inputenc value `" << inputenc
2727 << "'. Using `auto' instead.");
2728 return *language->encoding();
2732 CiteEngine BufferParams::citeEngine() const
2734 // FIXME the class should provide the numerical/
2735 // authoryear choice
2736 if (documentClass().provides("natbib")
2737 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2738 return ENGINE_NATBIB_AUTHORYEAR;
2739 return cite_engine_;
2743 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2745 cite_engine_ = cite_engine;