2 * \file BufferParams.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Alfredo Braunstein
7 * \author Lars Gullik Bjønnes
8 * \author Jean-Marc Lasgouttes
10 * \author André Pönitz
11 * \author Martin Vermeer
13 * Full author contact details are available in file CREDITS.
18 #include "BufferParams.h"
21 #include "LayoutFile.h"
22 #include "BranchList.h"
23 #include "buffer_funcs.h"
29 #include "IndicesList.h"
31 #include "LaTeXFeatures.h"
32 #include "ModuleList.h"
36 #include "OutputParams.h"
40 #include "PDFOptions.h"
42 #include "frontends/alert.h"
44 #include "insets/InsetListingsParams.h"
46 #include "support/convert.h"
47 #include "support/debug.h"
48 #include "support/docstream.h"
49 #include "support/FileName.h"
50 #include "support/filetools.h"
51 #include "support/gettext.h"
52 #include "support/Messages.h"
53 #include "support/Translator.h"
54 #include "support/lstrings.h"
60 using namespace lyx::support;
63 static char const * const string_paragraph_separation[] = {
68 static char const * const string_quotes_language[] = {
69 "english", "swedish", "german", "polish", "french", "danish", ""
73 static char const * const string_papersize[] = {
74 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
75 "a0paper", "a1paper", "a2paper", "a3paper", "a4paper", "a5paper",
76 "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
77 "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
78 "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
83 static char const * const string_orientation[] = {
84 "portrait", "landscape", ""
88 static char const * const string_footnotekinds[] = {
89 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
93 static char const * const tex_graphics[] = {
94 "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
95 "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
96 "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
97 "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
108 // Paragraph separation
109 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
112 ParSepTranslator const init_parseptranslator()
114 ParSepTranslator translator
115 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
116 translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
121 ParSepTranslator const & parseptranslator()
123 static ParSepTranslator translator = init_parseptranslator();
129 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
132 QuotesLangTranslator const init_quoteslangtranslator()
134 QuotesLangTranslator translator
135 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
136 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
137 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
138 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
139 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
140 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
145 QuotesLangTranslator const & quoteslangtranslator()
147 static QuotesLangTranslator translator = init_quoteslangtranslator();
153 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
156 static PaperSizeTranslator initPaperSizeTranslator()
158 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
159 translator.addPair(string_papersize[1], PAPER_CUSTOM);
160 translator.addPair(string_papersize[2], PAPER_USLETTER);
161 translator.addPair(string_papersize[3], PAPER_USLEGAL);
162 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
163 translator.addPair(string_papersize[5], PAPER_A0);
164 translator.addPair(string_papersize[6], PAPER_A1);
165 translator.addPair(string_papersize[7], PAPER_A2);
166 translator.addPair(string_papersize[8], PAPER_A3);
167 translator.addPair(string_papersize[9], PAPER_A4);
168 translator.addPair(string_papersize[10], PAPER_A5);
169 translator.addPair(string_papersize[11], PAPER_A6);
170 translator.addPair(string_papersize[12], PAPER_B0);
171 translator.addPair(string_papersize[13], PAPER_B1);
172 translator.addPair(string_papersize[14], PAPER_B2);
173 translator.addPair(string_papersize[15], PAPER_B3);
174 translator.addPair(string_papersize[16], PAPER_B4);
175 translator.addPair(string_papersize[17], PAPER_B5);
176 translator.addPair(string_papersize[18], PAPER_B6);
177 translator.addPair(string_papersize[19], PAPER_C0);
178 translator.addPair(string_papersize[20], PAPER_C1);
179 translator.addPair(string_papersize[21], PAPER_C2);
180 translator.addPair(string_papersize[22], PAPER_C3);
181 translator.addPair(string_papersize[23], PAPER_C4);
182 translator.addPair(string_papersize[24], PAPER_C5);
183 translator.addPair(string_papersize[25], PAPER_C6);
184 translator.addPair(string_papersize[26], PAPER_JISB0);
185 translator.addPair(string_papersize[27], PAPER_JISB1);
186 translator.addPair(string_papersize[28], PAPER_JISB2);
187 translator.addPair(string_papersize[29], PAPER_JISB3);
188 translator.addPair(string_papersize[30], PAPER_JISB4);
189 translator.addPair(string_papersize[31], PAPER_JISB5);
190 translator.addPair(string_papersize[32], PAPER_JISB6);
195 PaperSizeTranslator const & papersizetranslator()
197 static PaperSizeTranslator translator = initPaperSizeTranslator();
203 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
206 PaperOrientationTranslator const init_paperorientationtranslator()
208 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
209 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
214 PaperOrientationTranslator const & paperorientationtranslator()
216 static PaperOrientationTranslator translator = init_paperorientationtranslator();
222 typedef Translator<int, PageSides> SidesTranslator;
225 SidesTranslator const init_sidestranslator()
227 SidesTranslator translator(1, OneSide);
228 translator.addPair(2, TwoSides);
233 SidesTranslator const & sidestranslator()
235 static SidesTranslator translator = init_sidestranslator();
241 typedef Translator<int, BufferParams::Package> PackageTranslator;
244 PackageTranslator const init_packagetranslator()
246 PackageTranslator translator(0, BufferParams::package_off);
247 translator.addPair(1, BufferParams::package_auto);
248 translator.addPair(2, BufferParams::package_on);
253 PackageTranslator const & packagetranslator()
255 static PackageTranslator translator = init_packagetranslator();
261 typedef Translator<string, CiteEngine> CiteEngineTranslator;
264 CiteEngineTranslator const init_citeenginetranslator()
266 CiteEngineTranslator translator("basic", ENGINE_BASIC);
267 translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
268 translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
269 translator.addPair("jurabib", ENGINE_JURABIB);
274 CiteEngineTranslator const & citeenginetranslator()
276 static CiteEngineTranslator translator = init_citeenginetranslator();
282 typedef Translator<string, Spacing::Space> SpaceTranslator;
285 SpaceTranslator const init_spacetranslator()
287 SpaceTranslator translator("default", Spacing::Default);
288 translator.addPair("single", Spacing::Single);
289 translator.addPair("onehalf", Spacing::Onehalf);
290 translator.addPair("double", Spacing::Double);
291 translator.addPair("other", Spacing::Other);
296 SpaceTranslator const & spacetranslator()
298 static SpaceTranslator translator = init_spacetranslator();
305 class BufferParams::Impl
310 AuthorList authorlist;
311 BranchList branchlist;
312 Bullet temp_bullets[4];
313 Bullet user_defined_bullets[4];
314 IndicesList indiceslist;
316 /** This is the amount of space used for paragraph_separation "skip",
317 * and for detached paragraphs in "indented" documents.
321 PDFOptions pdfoptions;
322 LayoutFileIndex baseClass_;
326 BufferParams::Impl::Impl()
327 : defskip(VSpace::MEDSKIP), baseClass_(string(""))
329 // set initial author
331 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
336 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
340 return new BufferParams::Impl(*ptr);
344 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
350 BufferParams::BufferParams()
353 setBaseClass(defaultBaseclass());
355 paragraph_separation = ParagraphIndentSeparation;
356 quotes_language = InsetQuotes::EnglishQuotes;
357 fontsize = "default";
360 papersize = PAPER_DEFAULT;
361 orientation = ORIENTATION_PORTRAIT;
362 use_geometry = false;
363 use_amsmath = package_auto;
364 use_esint = package_auto;
365 use_mhchem = package_auto;
366 use_mathdots = package_auto;
367 cite_engine_ = ENGINE_BASIC;
368 use_bibtopic = false;
370 trackChanges = false;
371 outputChanges = false;
372 use_default_options = true;
373 maintain_unincluded_children = false;
376 language = default_language;
378 fontsRoman = "default";
379 fontsSans = "default";
380 fontsTypewriter = "default";
381 fontsDefaultFamily = "default";
385 fontsSansScale = 100;
386 fontsTypewriterScale = 100;
388 graphicsDriver = "default";
389 defaultOutputFormat = "default";
390 bibtex_command = "default";
391 index_command = "default";
394 listings_params = string();
395 pagestyle = "default";
396 suppress_date = false;
397 // no color is the default (white)
398 backgroundcolor = lyx::rgbFromHexName("#ffffff");
399 isbackgroundcolor = false;
400 // no color is the default (black)
401 fontcolor = lyx::rgbFromHexName("#000000");
403 // light gray is the default font color for greyed-out notes
404 notefontcolor = lyx::rgbFromHexName("#cccccc");
405 boxbgcolor = lyx::rgbFromHexName("#ff0000");
406 compressed = lyxrc.save_compressed;
407 for (int iter = 0; iter < 4; ++iter) {
408 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
409 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
412 indiceslist().addDefault(B_("Index"));
413 html_be_strict = false;
414 html_math_output = MathML;
415 html_math_img_scale = 1.0;
422 docstring BufferParams::B_(string const & l10n) const
424 LASSERT(language, /**/);
425 return getMessages(language->code()).get(l10n);
429 AuthorList & BufferParams::authors()
431 return pimpl_->authorlist;
435 AuthorList const & BufferParams::authors() const
437 return pimpl_->authorlist;
441 BranchList & BufferParams::branchlist()
443 return pimpl_->branchlist;
447 BranchList const & BufferParams::branchlist() const
449 return pimpl_->branchlist;
453 IndicesList & BufferParams::indiceslist()
455 return pimpl_->indiceslist;
459 IndicesList const & BufferParams::indiceslist() const
461 return pimpl_->indiceslist;
465 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
467 LASSERT(index < 4, /**/);
468 return pimpl_->temp_bullets[index];
472 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
474 LASSERT(index < 4, /**/);
475 return pimpl_->temp_bullets[index];
479 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
481 LASSERT(index < 4, /**/);
482 return pimpl_->user_defined_bullets[index];
486 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
488 LASSERT(index < 4, /**/);
489 return pimpl_->user_defined_bullets[index];
493 Spacing & BufferParams::spacing()
495 return pimpl_->spacing;
499 Spacing const & BufferParams::spacing() const
501 return pimpl_->spacing;
505 PDFOptions & BufferParams::pdfoptions()
507 return pimpl_->pdfoptions;
511 PDFOptions const & BufferParams::pdfoptions() const
513 return pimpl_->pdfoptions;
517 HSpace const & BufferParams::getIndentation() const
519 return pimpl_->indentation;
523 void BufferParams::setIndentation(HSpace const & indent)
525 pimpl_->indentation = indent;
529 VSpace const & BufferParams::getDefSkip() const
531 return pimpl_->defskip;
535 void BufferParams::setDefSkip(VSpace const & vs)
537 // DEFSKIP will cause an infinite loop
538 LASSERT(vs.kind() != VSpace::DEFSKIP, return);
539 pimpl_->defskip = vs;
543 string BufferParams::readToken(Lexer & lex, string const & token,
544 FileName const & filepath)
546 if (token == "\\textclass") {
548 string const classname = lex.getString();
549 // if there exists a local layout file, ignore the system one
550 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
552 LayoutFileList & bcl = LayoutFileList::get();
553 if (tcp.empty() && !filepath.empty())
554 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
558 setBaseClass(classname);
559 // We assume that a tex class exists for local or unknown layouts so this warning
560 // will only be given for system layouts.
561 if (!baseClass()->isTeXClassAvailable()) {
562 docstring const desc =
563 translateIfPossible(from_utf8(baseClass()->description()));
564 docstring const prereqs = from_utf8(baseClass()->prerequisites());
565 docstring const msg =
566 bformat(_("The selected document class\n"
568 "requires external files that are not available.\n"
569 "The document class can still be used, but the\n"
570 "document cannot be compiled until the following\n"
571 "prerequisites are installed:\n"
573 "See section 3.1.2.2 of the User's Guide for\n"
574 "more information."), desc, prereqs);
575 frontend::Alert::warning(_("Document class not available"),
578 } else if (token == "\\begin_preamble") {
580 } else if (token == "\\begin_local_layout") {
581 readLocalLayout(lex);
582 } else if (token == "\\begin_modules") {
584 } else if (token == "\\begin_removed_modules") {
585 readRemovedModules(lex);
586 } else if (token == "\\begin_includeonly") {
587 readIncludeonly(lex);
588 } else if (token == "\\maintain_unincluded_children") {
589 lex >> maintain_unincluded_children;
590 } else if (token == "\\options") {
592 options = lex.getString();
593 } else if (token == "\\use_default_options") {
594 lex >> use_default_options;
595 } else if (token == "\\master") {
597 master = lex.getString();
598 } else if (token == "\\suppress_date") {
599 lex >> suppress_date;
600 } else if (token == "\\language") {
602 } else if (token == "\\inputencoding") {
604 } else if (token == "\\graphics") {
605 readGraphicsDriver(lex);
606 } else if (token == "\\default_output_format") {
607 lex >> defaultOutputFormat;
608 } else if (token == "\\bibtex_command") {
610 bibtex_command = lex.getString();
611 } else if (token == "\\index_command") {
613 index_command = lex.getString();
614 } else if (token == "\\fontencoding") {
616 fontenc = lex.getString();
617 } else if (token == "\\font_roman") {
619 fontsRoman = lex.getString();
620 } else if (token == "\\font_sans") {
622 fontsSans = lex.getString();
623 } else if (token == "\\font_typewriter") {
625 fontsTypewriter = lex.getString();
626 } else if (token == "\\font_default_family") {
627 lex >> fontsDefaultFamily;
628 } else if (token == "\\use_xetex") {
630 } else if (token == "\\font_sc") {
632 } else if (token == "\\font_osf") {
634 } else if (token == "\\font_sf_scale") {
635 lex >> fontsSansScale;
636 } else if (token == "\\font_tt_scale") {
637 lex >> fontsTypewriterScale;
638 } else if (token == "\\font_cjk") {
640 } else if (token == "\\paragraph_separation") {
643 paragraph_separation = parseptranslator().find(parsep);
644 } else if (token == "\\paragraph_indentation") {
646 string indentation = lex.getString();
647 pimpl_->indentation = HSpace(indentation);
648 } else if (token == "\\defskip") {
650 string const defskip = lex.getString();
651 pimpl_->defskip = VSpace(defskip);
652 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
654 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
655 } else if (token == "\\quotes_language") {
658 quotes_language = quoteslangtranslator().find(quotes_lang);
659 } else if (token == "\\papersize") {
662 papersize = papersizetranslator().find(ppsize);
663 } else if (token == "\\use_geometry") {
665 } else if (token == "\\use_amsmath") {
668 use_amsmath = packagetranslator().find(use_ams);
669 } else if (token == "\\use_esint") {
672 use_esint = packagetranslator().find(useesint);
673 } else if (token == "\\use_mhchem") {
676 use_mhchem = packagetranslator().find(usemhchem);
677 } else if (token == "\\use_mathdots") {
680 use_mathdots = packagetranslator().find(usemathdots);
681 } else if (token == "\\cite_engine") {
684 cite_engine_ = citeenginetranslator().find(engine);
685 } else if (token == "\\use_bibtopic") {
687 } else if (token == "\\use_indices") {
689 } else if (token == "\\tracking_changes") {
691 } else if (token == "\\output_changes") {
692 lex >> outputChanges;
693 } else if (token == "\\branch") {
695 docstring branch = lex.getDocString();
696 branchlist().add(branch);
699 string const tok = lex.getString();
700 if (tok == "\\end_branch")
702 Branch * branch_ptr = branchlist().find(branch);
703 if (tok == "\\selected") {
706 branch_ptr->setSelected(lex.getInteger());
708 if (tok == "\\filename_suffix") {
711 branch_ptr->setFileNameSuffix(lex.getInteger());
713 if (tok == "\\color") {
715 string color = lex.getString();
717 branch_ptr->setColor(color);
718 // Update also the Color table:
720 color = lcolor.getX11Name(Color_background);
722 lcolor.setColor(to_utf8(branch), color);
725 } else if (token == "\\index") {
727 docstring index = lex.getDocString();
729 indiceslist().add(index);
732 string const tok = lex.getString();
733 if (tok == "\\end_index")
735 Index * index_ptr = indiceslist().find(index);
736 if (tok == "\\shortcut") {
738 shortcut = lex.getDocString();
740 index_ptr->setShortcut(shortcut);
742 if (tok == "\\color") {
744 string color = lex.getString();
746 index_ptr->setColor(color);
747 // Update also the Color table:
749 color = lcolor.getX11Name(Color_background);
751 if (!shortcut.empty())
752 lcolor.setColor(to_utf8(shortcut), color);
755 } else if (token == "\\author") {
757 istringstream ss(lex.getString());
760 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
761 } else if (token == "\\paperorientation") {
764 orientation = paperorientationtranslator().find(orient);
765 } else if (token == "\\backgroundcolor") {
767 backgroundcolor = lyx::rgbFromHexName(lex.getString());
768 isbackgroundcolor = true;
769 } else if (token == "\\fontcolor") {
771 fontcolor = lyx::rgbFromHexName(lex.getString());
773 } else if (token == "\\notefontcolor") {
775 string color = lex.getString();
776 notefontcolor = lyx::rgbFromHexName(color);
777 } else if (token == "\\boxbgcolor") {
779 string color = lex.getString();
780 boxbgcolor = lyx::rgbFromHexName(color);
781 } else if (token == "\\paperwidth") {
783 } else if (token == "\\paperheight") {
785 } else if (token == "\\leftmargin") {
787 } else if (token == "\\topmargin") {
789 } else if (token == "\\rightmargin") {
791 } else if (token == "\\bottommargin") {
793 } else if (token == "\\headheight") {
795 } else if (token == "\\headsep") {
797 } else if (token == "\\footskip") {
799 } else if (token == "\\columnsep") {
801 } else if (token == "\\paperfontsize") {
803 } else if (token == "\\papercolumns") {
805 } else if (token == "\\listings_params") {
808 listings_params = InsetListingsParams(par).params();
809 } else if (token == "\\papersides") {
812 sides = sidestranslator().find(psides);
813 } else if (token == "\\paperpagestyle") {
815 } else if (token == "\\bullet") {
817 } else if (token == "\\bulletLaTeX") {
818 readBulletsLaTeX(lex);
819 } else if (token == "\\secnumdepth") {
821 } else if (token == "\\tocdepth") {
823 } else if (token == "\\spacing") {
827 if (nspacing == "other") {
830 spacing().set(spacetranslator().find(nspacing), tmp_val);
831 } else if (token == "\\float_placement") {
832 lex >> float_placement;
834 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
835 string toktmp = pdfoptions().readToken(lex, token);
836 if (!toktmp.empty()) {
837 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
841 } else if (token == "\\html_math_output") {
844 html_math_output = static_cast<MathOutput>(temp);
845 } else if (token == "\\html_be_strict") {
846 lex >> html_be_strict;
847 } else if (token == "\\html_math_img_scale") {
848 lex >> html_math_img_scale;
849 } else if (token == "\\html_latex_start") {
851 html_latex_start = lex.getString();
852 } else if (token == "\\html_latex_end") {
854 html_latex_end = lex.getString();
855 } else if (token == "\\output_sync") {
857 } else if (token == "\\output_sync_macro") {
858 lex >> output_sync_macro;
859 } else if (token == "\\use_refstyle") {
862 lyxerr << "BufferParams::readToken(): Unknown token: " <<
871 void BufferParams::writeFile(ostream & os) const
873 // The top of the file is written by the buffer.
874 // Prints out the buffer info into the .lyx file given by file
877 os << "\\textclass " << baseClass()->name() << '\n';
880 if (!preamble.empty()) {
881 // remove '\n' from the end of preamble
882 string const tmppreamble = rtrim(preamble, "\n");
883 os << "\\begin_preamble\n"
885 << "\n\\end_preamble\n";
889 if (!options.empty()) {
890 os << "\\options " << options << '\n';
893 // use the class options defined in the layout?
894 os << "\\use_default_options "
895 << convert<string>(use_default_options) << "\n";
897 // the master document
898 if (!master.empty()) {
899 os << "\\master " << master << '\n';
903 if (!removedModules_.empty()) {
904 os << "\\begin_removed_modules" << '\n';
905 list<string>::const_iterator it = removedModules_.begin();
906 list<string>::const_iterator en = removedModules_.end();
907 for (; it != en; it++)
909 os << "\\end_removed_modules" << '\n';
913 if (!layoutModules_.empty()) {
914 os << "\\begin_modules" << '\n';
915 LayoutModuleList::const_iterator it = layoutModules_.begin();
916 LayoutModuleList::const_iterator en = layoutModules_.end();
917 for (; it != en; it++)
919 os << "\\end_modules" << '\n';
923 if (!includedChildren_.empty()) {
924 os << "\\begin_includeonly" << '\n';
925 list<string>::const_iterator it = includedChildren_.begin();
926 list<string>::const_iterator en = includedChildren_.end();
927 for (; it != en; it++)
929 os << "\\end_includeonly" << '\n';
931 os << "\\maintain_unincluded_children "
932 << convert<string>(maintain_unincluded_children) << '\n';
934 // local layout information
935 if (!local_layout.empty()) {
936 // remove '\n' from the end
937 string const tmplocal = rtrim(local_layout, "\n");
938 os << "\\begin_local_layout\n"
940 << "\n\\end_local_layout\n";
943 // then the text parameters
944 if (language != ignore_language)
945 os << "\\language " << language->lang() << '\n';
946 os << "\\inputencoding " << inputenc
947 << "\n\\fontencoding " << fontenc
948 << "\n\\font_roman " << fontsRoman
949 << "\n\\font_sans " << fontsSans
950 << "\n\\font_typewriter " << fontsTypewriter
951 << "\n\\font_default_family " << fontsDefaultFamily
952 << "\n\\use_xetex " << convert<string>(useXetex)
953 << "\n\\font_sc " << convert<string>(fontsSC)
954 << "\n\\font_osf " << convert<string>(fontsOSF)
955 << "\n\\font_sf_scale " << fontsSansScale
956 << "\n\\font_tt_scale " << fontsTypewriterScale
958 if (!fontsCJK.empty()) {
959 os << "\\font_cjk " << fontsCJK << '\n';
961 os << "\n\\graphics " << graphicsDriver << '\n';
962 os << "\\default_output_format " << defaultOutputFormat << '\n';
963 os << "\\output_sync " << output_sync << '\n';
964 if (!output_sync_macro.empty())
965 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
966 os << "\\bibtex_command " << bibtex_command << '\n';
967 os << "\\index_command " << index_command << '\n';
969 if (!float_placement.empty()) {
970 os << "\\float_placement " << float_placement << '\n';
972 os << "\\paperfontsize " << fontsize << '\n';
974 spacing().writeFile(os);
975 pdfoptions().writeFile(os);
977 os << "\\papersize " << string_papersize[papersize]
978 << "\n\\use_geometry " << convert<string>(use_geometry)
979 << "\n\\use_amsmath " << use_amsmath
980 << "\n\\use_esint " << use_esint
981 << "\n\\use_mhchem " << use_mhchem
982 << "\n\\use_mathdots " << use_mathdots
983 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
984 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
985 << "\n\\use_indices " << convert<string>(use_indices)
986 << "\n\\paperorientation " << string_orientation[orientation]
987 << "\n\\suppress_date " << convert<string>(suppress_date)
988 << "\n\\use_refstyle " << use_refstyle
990 if (isbackgroundcolor == true)
991 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
992 if (isfontcolor == true)
993 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
994 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
995 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
996 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
997 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
999 BranchList::const_iterator it = branchlist().begin();
1000 BranchList::const_iterator end = branchlist().end();
1001 for (; it != end; ++it) {
1002 os << "\\branch " << to_utf8(it->branch())
1003 << "\n\\selected " << it->isSelected()
1004 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1005 << "\n\\color " << lyx::X11hexname(it->color())
1010 IndicesList::const_iterator iit = indiceslist().begin();
1011 IndicesList::const_iterator iend = indiceslist().end();
1012 for (; iit != iend; ++iit) {
1013 os << "\\index " << to_utf8(iit->index())
1014 << "\n\\shortcut " << to_utf8(iit->shortcut())
1015 << "\n\\color " << lyx::X11hexname(iit->color())
1020 if (!paperwidth.empty())
1021 os << "\\paperwidth "
1022 << VSpace(paperwidth).asLyXCommand() << '\n';
1023 if (!paperheight.empty())
1024 os << "\\paperheight "
1025 << VSpace(paperheight).asLyXCommand() << '\n';
1026 if (!leftmargin.empty())
1027 os << "\\leftmargin "
1028 << VSpace(leftmargin).asLyXCommand() << '\n';
1029 if (!topmargin.empty())
1030 os << "\\topmargin "
1031 << VSpace(topmargin).asLyXCommand() << '\n';
1032 if (!rightmargin.empty())
1033 os << "\\rightmargin "
1034 << VSpace(rightmargin).asLyXCommand() << '\n';
1035 if (!bottommargin.empty())
1036 os << "\\bottommargin "
1037 << VSpace(bottommargin).asLyXCommand() << '\n';
1038 if (!headheight.empty())
1039 os << "\\headheight "
1040 << VSpace(headheight).asLyXCommand() << '\n';
1041 if (!headsep.empty())
1043 << VSpace(headsep).asLyXCommand() << '\n';
1044 if (!footskip.empty())
1046 << VSpace(footskip).asLyXCommand() << '\n';
1047 if (!columnsep.empty())
1048 os << "\\columnsep "
1049 << VSpace(columnsep).asLyXCommand() << '\n';
1050 os << "\\secnumdepth " << secnumdepth
1051 << "\n\\tocdepth " << tocdepth
1052 << "\n\\paragraph_separation "
1053 << string_paragraph_separation[paragraph_separation];
1054 if (!paragraph_separation)
1055 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1057 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1058 os << "\n\\quotes_language "
1059 << string_quotes_language[quotes_language]
1060 << "\n\\papercolumns " << columns
1061 << "\n\\papersides " << sides
1062 << "\n\\paperpagestyle " << pagestyle << '\n';
1063 if (!listings_params.empty())
1064 os << "\\listings_params \"" <<
1065 InsetListingsParams(listings_params).encodedString() << "\"\n";
1066 for (int i = 0; i < 4; ++i) {
1067 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1068 if (user_defined_bullet(i).getFont() != -1) {
1069 os << "\\bullet " << i << " "
1070 << user_defined_bullet(i).getFont() << " "
1071 << user_defined_bullet(i).getCharacter() << " "
1072 << user_defined_bullet(i).getSize() << "\n";
1076 os << "\\bulletLaTeX " << i << " \""
1077 << lyx::to_ascii(user_defined_bullet(i).getText())
1083 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1084 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1085 << "\\html_math_output " << html_math_output << '\n'
1086 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1088 if (html_math_img_scale != 1.0)
1089 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1090 if (!html_latex_start.empty())
1091 os << "\\html_latex_start " << html_latex_start << '\n';
1092 if (!html_latex_end.empty())
1093 os << "\\html_latex_end " << html_latex_end << '\n';
1095 os << pimpl_->authorlist;
1099 void BufferParams::validate(LaTeXFeatures & features) const
1101 features.require(documentClass().requires());
1103 if (outputChanges) {
1104 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1105 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1106 LaTeXFeatures::isAvailable("xcolor");
1108 switch (features.runparams().flavor) {
1109 case OutputParams::LATEX:
1111 features.require("ct-dvipost");
1112 features.require("dvipost");
1113 } else if (xcolorulem) {
1114 features.require("ct-xcolor-ulem");
1115 features.require("ulem");
1116 features.require("xcolor");
1118 features.require("ct-none");
1121 case OutputParams::PDFLATEX:
1122 case OutputParams::XETEX:
1124 features.require("ct-xcolor-ulem");
1125 features.require("ulem");
1126 features.require("xcolor");
1127 // improves color handling in PDF output
1128 features.require("pdfcolmk");
1130 features.require("ct-none");
1138 // Floats with 'Here definitely' as default setting.
1139 if (float_placement.find('H') != string::npos)
1140 features.require("float");
1142 // AMS Style is at document level
1143 if (use_amsmath == package_on
1144 || documentClass().provides("amsmath"))
1145 features.require("amsmath");
1146 if (use_esint == package_on)
1147 features.require("esint");
1148 if (use_mhchem == package_on)
1149 features.require("mhchem");
1150 if (use_mathdots == package_on)
1151 features.require("mathdots");
1153 // Document-level line spacing
1154 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1155 features.require("setspace");
1157 // the bullet shapes are buffer level not paragraph level
1158 // so they are tested here
1159 for (int i = 0; i < 4; ++i) {
1160 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1162 int const font = user_defined_bullet(i).getFont();
1164 int const c = user_defined_bullet(i).getCharacter();
1170 features.require("latexsym");
1172 } else if (font == 1) {
1173 features.require("amssymb");
1174 } else if (font >= 2 && font <= 5) {
1175 features.require("pifont");
1179 if (pdfoptions().use_hyperref) {
1180 features.require("hyperref");
1181 // due to interferences with babel and hyperref, the color package has to
1182 // be loaded after hyperref when hyperref is used with the colorlinks
1183 // option, see http://www.lyx.org/trac/ticket/5291
1184 if (pdfoptions().colorlinks)
1185 features.require("color");
1189 features.require("xetex");
1191 if (language->lang() == "vietnamese")
1192 features.require("vietnamese");
1193 else if (language->lang() == "japanese")
1194 features.require("japanese");
1198 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1199 TexRow & texrow, FileName const & filepath) const
1201 os << "\\documentclass";
1203 DocumentClass const & tclass = documentClass();
1205 ostringstream clsoptions; // the document class options.
1207 if (tokenPos(tclass.opt_fontsize(),
1208 '|', fontsize) >= 0) {
1209 // only write if existing in list (and not default)
1210 clsoptions << fontsize << "pt,";
1213 // all paper sizes except of A4, A5, B5 and the US sizes need the
1215 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1216 && papersize != PAPER_USLETTER
1217 && papersize != PAPER_USLEGAL
1218 && papersize != PAPER_USEXECUTIVE
1219 && papersize != PAPER_A4
1220 && papersize != PAPER_A5
1221 && papersize != PAPER_B5;
1223 if (!use_geometry) {
1224 switch (papersize) {
1226 clsoptions << "a4paper,";
1228 case PAPER_USLETTER:
1229 clsoptions << "letterpaper,";
1232 clsoptions << "a5paper,";
1235 clsoptions << "b5paper,";
1237 case PAPER_USEXECUTIVE:
1238 clsoptions << "executivepaper,";
1241 clsoptions << "legalpaper,";
1275 if (sides != tclass.sides()) {
1278 clsoptions << "oneside,";
1281 clsoptions << "twoside,";
1287 if (columns != tclass.columns()) {
1289 clsoptions << "twocolumn,";
1291 clsoptions << "onecolumn,";
1295 && orientation == ORIENTATION_LANDSCAPE)
1296 clsoptions << "landscape,";
1298 // language should be a parameter to \documentclass
1299 if (language->babel() == "hebrew"
1300 && default_language->babel() != "hebrew")
1301 // This seems necessary
1302 features.useLanguage(default_language);
1304 ostringstream language_options;
1305 bool const use_babel = features.useBabel() && !tclass.provides("babel");
1307 language_options << features.getLanguages();
1308 if (!language->babel().empty()) {
1309 if (!language_options.str().empty())
1310 language_options << ',';
1311 language_options << language->babel();
1313 if (lyxrc.language_global_options
1314 && !features.needBabelLangOptions())
1315 clsoptions << language_options.str() << ',';
1318 // the predefined options from the layout
1319 if (use_default_options && !tclass.options().empty())
1320 clsoptions << tclass.options() << ',';
1322 // the user-defined options
1323 if (!options.empty()) {
1324 clsoptions << options << ',';
1327 string strOptions(clsoptions.str());
1328 if (!strOptions.empty()) {
1329 strOptions = rtrim(strOptions, ",");
1331 os << '[' << from_utf8(strOptions) << ']';
1334 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1336 // end of \documentclass defs
1339 os << "\\usepackage{fontspec}\n";
1343 // font selection must be done before loading fontenc.sty
1344 string const fonts =
1345 loadFonts(fontsRoman, fontsSans,
1346 fontsTypewriter, fontsSC, fontsOSF,
1347 fontsSansScale, fontsTypewriterScale, useXetex);
1348 if (!fonts.empty()) {
1349 os << from_ascii(fonts);
1352 if (fontsDefaultFamily != "default")
1353 os << "\\renewcommand{\\familydefault}{\\"
1354 << from_ascii(fontsDefaultFamily) << "}\n";
1356 // set font encoding
1357 // for arabic_arabi and farsi we also need to load the LAE and
1359 // XeTeX works without fontenc
1360 if (font_encoding() != "default" && language->lang() != "japanese"
1361 && !useXetex && !tclass.provides("fontenc")) {
1362 size_t fars = language_options.str().find("farsi");
1363 size_t arab = language_options.str().find("arabic");
1364 if (language->lang() == "arabic_arabi"
1365 || language->lang() == "farsi" || fars != string::npos
1366 || arab != string::npos) {
1367 os << "\\usepackage[" << from_ascii(font_encoding())
1368 << ",LFE,LAE]{fontenc}\n";
1371 os << "\\usepackage[" << from_ascii(font_encoding())
1377 // handle inputenc etc.
1378 writeEncodingPreamble(os, features, texrow);
1381 if (!features.runparams().includeall && !includedChildren_.empty()) {
1382 os << "\\includeonly{";
1383 list<string>::const_iterator it = includedChildren_.begin();
1385 for (; it != includedChildren_.end() ; ++it) {
1386 string incfile = *it;
1387 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1388 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1390 if (!features.runparams().nice)
1392 // \includeonly doesn't want an extension
1393 incfile = changeExtension(incfile, string());
1394 incfile = support::latex_path(incfile);
1395 if (!incfile.empty()) {
1398 os << from_utf8(incfile);
1405 if (!listings_params.empty() || features.isRequired("listings")) {
1406 os << "\\usepackage{listings}\n";
1409 if (!listings_params.empty()) {
1411 // do not test validity because listings_params is
1412 // supposed to be valid
1414 InsetListingsParams(listings_params).separatedParams(true);
1415 // we can't support all packages, but we should load the color package
1416 if (par.find("\\color", 0) != string::npos)
1417 features.require("color");
1418 os << from_utf8(par);
1419 // count the number of newlines
1420 for (size_t i = 0; i < par.size(); ++i)
1426 if (!tclass.provides("geometry")
1427 && (use_geometry || nonstandard_papersize)) {
1428 odocstringstream ods;
1429 if (!getGraphicsDriver("geometry").empty())
1430 ods << getGraphicsDriver("geometry");
1431 if (orientation == ORIENTATION_LANDSCAPE)
1432 ods << ",landscape";
1433 switch (papersize) {
1435 if (!paperwidth.empty())
1436 ods << ",paperwidth="
1437 << from_ascii(paperwidth);
1438 if (!paperheight.empty())
1439 ods << ",paperheight="
1440 << from_ascii(paperheight);
1442 case PAPER_USLETTER:
1443 ods << ",letterpaper";
1446 ods << ",legalpaper";
1448 case PAPER_USEXECUTIVE:
1449 ods << ",executivepaper";
1536 // default papersize ie PAPER_DEFAULT
1537 switch (lyxrc.default_papersize) {
1538 case PAPER_DEFAULT: // keep compiler happy
1539 case PAPER_USLETTER:
1540 ods << ",letterpaper";
1543 ods << ",legalpaper";
1545 case PAPER_USEXECUTIVE:
1546 ods << ",executivepaper";
1588 docstring const g_options = trim(ods.str(), ",");
1589 os << "\\usepackage";
1590 if (!g_options.empty())
1591 os << '[' << g_options << ']';
1592 os << "{geometry}\n";
1594 // output this only if use_geometry is true
1596 os << "\\geometry{verbose";
1597 if (!topmargin.empty())
1598 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1599 if (!bottommargin.empty())
1600 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1601 if (!leftmargin.empty())
1602 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1603 if (!rightmargin.empty())
1604 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1605 if (!headheight.empty())
1606 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1607 if (!headsep.empty())
1608 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1609 if (!footskip.empty())
1610 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1611 if (!columnsep.empty())
1612 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1616 } else if (orientation == ORIENTATION_LANDSCAPE
1617 || papersize != PAPER_DEFAULT) {
1618 features.require("papersize");
1621 if (tokenPos(tclass.opt_pagestyle(),
1622 '|', pagestyle) >= 0) {
1623 if (pagestyle == "fancy") {
1624 os << "\\usepackage{fancyhdr}\n";
1627 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1631 // only output when the background color is not default
1632 if (isbackgroundcolor == true) {
1633 // only require color here, the background color will be defined
1634 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1636 features.require("color");
1637 features.require("pagecolor");
1640 // only output when the font color is not default
1641 if (isfontcolor == true) {
1642 // only require color here, the font color will be defined
1643 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1645 features.require("color");
1646 features.require("fontcolor");
1649 // Only if class has a ToC hierarchy
1650 if (tclass.hasTocLevels()) {
1651 if (secnumdepth != tclass.secnumdepth()) {
1652 os << "\\setcounter{secnumdepth}{"
1657 if (tocdepth != tclass.tocdepth()) {
1658 os << "\\setcounter{tocdepth}{"
1665 if (paragraph_separation) {
1666 // when skip separation
1667 switch (getDefSkip().kind()) {
1668 case VSpace::SMALLSKIP:
1669 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1671 case VSpace::MEDSKIP:
1672 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1674 case VSpace::BIGSKIP:
1675 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1677 case VSpace::LENGTH:
1678 os << "\\setlength{\\parskip}{"
1679 << from_utf8(getDefSkip().length().asLatexString())
1682 default: // should never happen // Then delete it.
1683 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1687 os << "\\setlength{\\parindent}{0pt}\n";
1690 // when separation by indentation
1691 // only output something when a width is given
1692 if (getIndentation().asLyXCommand() != "default") {
1693 os << "\\setlength{\\parindent}{"
1694 << from_utf8(getIndentation().asLatexCommand())
1700 // Now insert the LyX specific LaTeX commands...
1701 docstring lyxpreamble;
1704 if (!output_sync_macro.empty())
1705 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1706 else if (features.runparams().flavor == OutputParams::LATEX)
1707 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1708 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1709 lyxpreamble += "\\synctex=-1\n";
1712 // due to interferences with babel and hyperref, the color package has to
1713 // be loaded (when it is not already loaded) before babel when hyperref
1714 // is used with the colorlinks option, see
1715 // http://www.lyx.org/trac/ticket/5291
1716 // we decided therefore to load color always before babel, see
1717 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1718 lyxpreamble += from_ascii(features.getColorOptions());
1720 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1722 && (features.isRequired("jurabib")
1723 || features.isRequired("hyperref")
1724 || features.isRequired("vietnamese")
1725 || features.isRequired("japanese") ) ) {
1727 lyxpreamble += from_utf8(features.getBabelPresettings());
1728 lyxpreamble += from_utf8(babelCall(language_options.str(),
1729 features.needBabelLangOptions())) + '\n';
1730 lyxpreamble += from_utf8(features.getBabelPostsettings());
1733 // The optional packages;
1734 lyxpreamble += from_ascii(features.getPackages());
1736 // Additional Indices
1737 if (features.isRequired("splitidx")) {
1738 IndicesList::const_iterator iit = indiceslist().begin();
1739 IndicesList::const_iterator iend = indiceslist().end();
1740 for (; iit != iend; ++iit) {
1741 lyxpreamble += "\\newindex[";
1742 lyxpreamble += iit->index();
1743 lyxpreamble += "]{";
1744 lyxpreamble += iit->shortcut();
1745 lyxpreamble += "}\n";
1750 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1753 // * Hyperref manual: "Make sure it comes last of your loaded
1754 // packages, to give it a fighting chance of not being over-written,
1755 // since its job is to redefine many LaTeX commands."
1756 // * Email from Heiko Oberdiek: "It is usually better to load babel
1757 // before hyperref. Then hyperref has a chance to detect babel.
1758 // * Has to be loaded before the "LyX specific LaTeX commands" to
1759 // avoid errors with algorithm floats.
1760 // use hyperref explicitly if it is required
1761 if (features.isRequired("hyperref")) {
1762 // pass what we have to stream here, since we need
1763 // to access the stream itself in PDFOptions.
1767 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1769 OutputParams tmp_params = features.runparams();
1770 lines += pdfoptions().writeLaTeX(tmp_params, os,
1771 documentClass().provides("hyperref"));
1772 texrow.newlines(lines);
1773 // set back for the rest
1774 lyxpreamble.clear();
1775 } else if (features.isRequired("nameref"))
1776 // hyperref loads this automatically
1777 lyxpreamble += "\\usepackage{nameref}\n";
1779 // Will be surrounded by \makeatletter and \makeatother when not empty
1780 docstring atlyxpreamble;
1782 // Some macros LyX will need
1783 docstring tmppreamble(features.getMacros());
1785 if (!tmppreamble.empty())
1786 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1787 "LyX specific LaTeX commands.\n"
1788 + tmppreamble + '\n';
1790 // the text class specific preamble
1791 tmppreamble = features.getTClassPreamble();
1792 if (!tmppreamble.empty())
1793 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1794 "Textclass specific LaTeX commands.\n"
1795 + tmppreamble + '\n';
1797 // suppress date if selected
1798 // use \@ifundefined because we cannot be sure that every document class
1799 // has a \date command
1801 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1803 /* the user-defined preamble */
1804 if (!containsOnly(preamble, " \n\t"))
1806 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1807 "User specified LaTeX commands.\n"
1808 + from_utf8(preamble) + '\n';
1810 // subfig loads internally the LaTeX package "caption". As
1811 // caption is a very popular package, users will load it in
1812 // the preamble. Therefore we must load subfig behind the
1813 // user-defined preamble and check if the caption package was
1814 // loaded or not. For the case that caption is loaded before
1815 // subfig, there is the subfig option "caption=false". This
1816 // option also works when a koma-script class is used and
1817 // koma's own caption commands are used instead of caption. We
1818 // use \PassOptionsToPackage here because the user could have
1819 // already loaded subfig in the preamble.
1820 if (features.isRequired("subfig")) {
1821 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1822 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1823 "\\usepackage{subfig}\n";
1826 // Itemize bullet settings need to be last in case the user
1827 // defines their own bullets that use a package included
1828 // in the user-defined preamble -- ARRae
1829 // Actually it has to be done much later than that
1830 // since some packages like frenchb make modifications
1831 // at \begin{document} time -- JMarc
1832 docstring bullets_def;
1833 for (int i = 0; i < 4; ++i) {
1834 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1835 if (bullets_def.empty())
1836 bullets_def += "\\AtBeginDocument{\n";
1837 bullets_def += " \\def\\labelitemi";
1839 // `i' is one less than the item to modify
1846 bullets_def += "ii";
1852 bullets_def += '{' +
1853 user_defined_bullet(i).getText()
1858 if (!bullets_def.empty())
1859 atlyxpreamble += bullets_def + "}\n\n";
1861 if (!atlyxpreamble.empty())
1862 lyxpreamble += "\n\\makeatletter\n"
1863 + atlyxpreamble + "\\makeatother\n\n";
1865 // We try to load babel late, in case it interferes with other packages.
1866 // Jurabib and Hyperref have to be called after babel, though.
1867 if (use_babel && !features.isRequired("jurabib")
1868 && !features.isRequired("hyperref")
1869 && !features.isRequired("vietnamese")
1870 && !features.isRequired("japanese")) {
1872 lyxpreamble += from_utf8(features.getBabelPresettings());
1873 lyxpreamble += from_utf8(babelCall(language_options.str(),
1874 features.needBabelLangOptions())) + '\n';
1875 lyxpreamble += from_utf8(features.getBabelPostsettings());
1878 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1879 if (!i18npreamble.empty())
1880 lyxpreamble += i18npreamble + '\n';
1883 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1884 texrow.newlines(nlines);
1888 // these packages (xunicode, for that matter) need to be loaded at least
1889 // after amsmath, amssymb, esint and the other packages that provide
1892 os << "\\usepackage{xunicode}\n";
1894 os << "\\usepackage{xltxtra}\n";
1901 void BufferParams::useClassDefaults()
1903 DocumentClass const & tclass = documentClass();
1905 sides = tclass.sides();
1906 columns = tclass.columns();
1907 pagestyle = tclass.pagestyle();
1908 use_default_options = true;
1909 // Only if class has a ToC hierarchy
1910 if (tclass.hasTocLevels()) {
1911 secnumdepth = tclass.secnumdepth();
1912 tocdepth = tclass.tocdepth();
1917 bool BufferParams::hasClassDefaults() const
1919 DocumentClass const & tclass = documentClass();
1921 return sides == tclass.sides()
1922 && columns == tclass.columns()
1923 && pagestyle == tclass.pagestyle()
1924 && use_default_options
1925 && secnumdepth == tclass.secnumdepth()
1926 && tocdepth == tclass.tocdepth();
1930 DocumentClass const & BufferParams::documentClass() const
1936 DocumentClass const * BufferParams::documentClassPtr() const
1942 void BufferParams::setDocumentClass(DocumentClass const * const tc)
1944 // evil, but this function is evil
1945 doc_class_ = const_cast<DocumentClass *>(tc);
1949 bool BufferParams::setBaseClass(string const & classname)
1951 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1952 LayoutFileList & bcl = LayoutFileList::get();
1953 if (!bcl.haveClass(classname)) {
1955 bformat(_("The layout file:\n"
1957 "could not be found. A default textclass with default\n"
1958 "layouts will be used. LyX will not be able to produce\n"
1960 from_utf8(classname));
1961 frontend::Alert::error(_("Document class not found"), s);
1962 bcl.addEmptyClass(classname);
1965 bool const success = bcl[classname].load();
1968 bformat(_("Due to some error in it, the layout file:\n"
1970 "could not be loaded. A default textclass with default\n"
1971 "layouts will be used. LyX will not be able to produce\n"
1973 from_utf8(classname));
1974 frontend::Alert::error(_("Could not load class"), s);
1975 bcl.addEmptyClass(classname);
1978 pimpl_->baseClass_ = classname;
1979 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1984 LayoutFile const * BufferParams::baseClass() const
1986 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1987 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1993 LayoutFileIndex const & BufferParams::baseClassID() const
1995 return pimpl_->baseClass_;
1999 void BufferParams::makeDocumentClass()
2004 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
2006 if (!local_layout.empty()) {
2007 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
2008 docstring const msg = _("Error reading internal layout information");
2009 frontend::Alert::warning(_("Read Error"), msg);
2015 bool BufferParams::moduleCanBeAdded(string const & modName) const
2017 return layoutModules_.moduleCanBeAdded(modName, baseClass());
2021 bool BufferParams::addLayoutModule(string const & modName)
2023 LayoutModuleList::const_iterator it = layoutModules_.begin();
2024 LayoutModuleList::const_iterator end = layoutModules_.end();
2025 for (; it != end; it++)
2028 layoutModules_.push_back(modName);
2033 Font const BufferParams::getFont() const
2035 FontInfo f = documentClass().defaultfont();
2036 if (fontsDefaultFamily == "rmdefault")
2037 f.setFamily(ROMAN_FAMILY);
2038 else if (fontsDefaultFamily == "sfdefault")
2039 f.setFamily(SANS_FAMILY);
2040 else if (fontsDefaultFamily == "ttdefault")
2041 f.setFamily(TYPEWRITER_FAMILY);
2042 return Font(f, language);
2046 void BufferParams::readPreamble(Lexer & lex)
2048 if (lex.getString() != "\\begin_preamble")
2049 lyxerr << "Error (BufferParams::readPreamble):"
2050 "consistency check failed." << endl;
2052 preamble = lex.getLongString("\\end_preamble");
2056 void BufferParams::readLocalLayout(Lexer & lex)
2058 if (lex.getString() != "\\begin_local_layout")
2059 lyxerr << "Error (BufferParams::readLocalLayout):"
2060 "consistency check failed." << endl;
2062 local_layout = lex.getLongString("\\end_local_layout");
2066 void BufferParams::readLanguage(Lexer & lex)
2068 if (!lex.next()) return;
2070 string const tmptok = lex.getString();
2072 // check if tmptok is part of tex_babel in tex-defs.h
2073 language = languages.getLanguage(tmptok);
2075 // Language tmptok was not found
2076 language = default_language;
2077 lyxerr << "Warning: Setting language `"
2078 << tmptok << "' to `" << language->lang()
2084 void BufferParams::readGraphicsDriver(Lexer & lex)
2089 string const tmptok = lex.getString();
2090 // check if tmptok is part of tex_graphics in tex_defs.h
2093 string const test = tex_graphics[n++];
2095 if (test == tmptok) {
2096 graphicsDriver = tmptok;
2101 "Warning: graphics driver `$$Token' not recognized!\n"
2102 " Setting graphics driver to `default'.\n");
2103 graphicsDriver = "default";
2110 void BufferParams::readBullets(Lexer & lex)
2115 int const index = lex.getInteger();
2117 int temp_int = lex.getInteger();
2118 user_defined_bullet(index).setFont(temp_int);
2119 temp_bullet(index).setFont(temp_int);
2121 user_defined_bullet(index).setCharacter(temp_int);
2122 temp_bullet(index).setCharacter(temp_int);
2124 user_defined_bullet(index).setSize(temp_int);
2125 temp_bullet(index).setSize(temp_int);
2129 void BufferParams::readBulletsLaTeX(Lexer & lex)
2131 // The bullet class should be able to read this.
2134 int const index = lex.getInteger();
2136 docstring const temp_str = lex.getDocString();
2138 user_defined_bullet(index).setText(temp_str);
2139 temp_bullet(index).setText(temp_str);
2143 void BufferParams::readModules(Lexer & lex)
2145 if (!lex.eatLine()) {
2146 lyxerr << "Error (BufferParams::readModules):"
2147 "Unexpected end of input." << endl;
2151 string mod = lex.getString();
2152 if (mod == "\\end_modules")
2154 addLayoutModule(mod);
2160 void BufferParams::readRemovedModules(Lexer & lex)
2162 if (!lex.eatLine()) {
2163 lyxerr << "Error (BufferParams::readRemovedModules):"
2164 "Unexpected end of input." << endl;
2168 string mod = lex.getString();
2169 if (mod == "\\end_removed_modules")
2171 removedModules_.push_back(mod);
2174 // now we want to remove any removed modules that were previously
2175 // added. normally, that will be because default modules were added in
2176 // setBaseClass(), which gets called when \textclass is read at the
2177 // start of the read.
2178 list<string>::const_iterator rit = removedModules_.begin();
2179 list<string>::const_iterator const ren = removedModules_.end();
2180 for (; rit != ren; rit++) {
2181 LayoutModuleList::iterator const mit = layoutModules_.begin();
2182 LayoutModuleList::iterator const men = layoutModules_.end();
2183 LayoutModuleList::iterator found = find(mit, men, *rit);
2186 layoutModules_.erase(found);
2191 void BufferParams::readIncludeonly(Lexer & lex)
2193 if (!lex.eatLine()) {
2194 lyxerr << "Error (BufferParams::readIncludeonly):"
2195 "Unexpected end of input." << endl;
2199 string child = lex.getString();
2200 if (child == "\\end_includeonly")
2202 includedChildren_.push_back(child);
2208 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2210 char real_papersize = papersize;
2211 if (real_papersize == PAPER_DEFAULT)
2212 real_papersize = lyxrc.default_papersize;
2214 switch (real_papersize) {
2216 // could be anything, so don't guess
2218 case PAPER_CUSTOM: {
2219 if (purpose == XDVI && !paperwidth.empty() &&
2220 !paperheight.empty()) {
2221 // heightxwidth<unit>
2222 string first = paperwidth;
2223 string second = paperheight;
2224 if (orientation == ORIENTATION_LANDSCAPE)
2227 return first.erase(first.length() - 2)
2233 // dvips and dvipdfm do not know this
2234 if (purpose == DVIPS || purpose == DVIPDFM)
2238 if (purpose == DVIPS || purpose == DVIPDFM)
2242 if (purpose == DVIPS || purpose == DVIPDFM)
2252 if (purpose == DVIPS || purpose == DVIPDFM)
2256 if (purpose == DVIPS || purpose == DVIPDFM)
2260 if (purpose == DVIPS || purpose == DVIPDFM)
2264 if (purpose == DVIPS || purpose == DVIPDFM)
2268 if (purpose == DVIPS || purpose == DVIPDFM)
2272 // dvipdfm does not know this
2273 if (purpose == DVIPDFM)
2277 if (purpose == DVIPDFM)
2281 if (purpose == DVIPS || purpose == DVIPDFM)
2285 if (purpose == DVIPS || purpose == DVIPDFM)
2289 if (purpose == DVIPS || purpose == DVIPDFM)
2293 if (purpose == DVIPS || purpose == DVIPDFM)
2297 if (purpose == DVIPS || purpose == DVIPDFM)
2301 if (purpose == DVIPS || purpose == DVIPDFM)
2305 if (purpose == DVIPS || purpose == DVIPDFM)
2309 if (purpose == DVIPS || purpose == DVIPDFM)
2313 if (purpose == DVIPS || purpose == DVIPDFM)
2317 if (purpose == DVIPS || purpose == DVIPDFM)
2321 if (purpose == DVIPS || purpose == DVIPDFM)
2325 if (purpose == DVIPS || purpose == DVIPDFM)
2329 if (purpose == DVIPS || purpose == DVIPDFM)
2333 if (purpose == DVIPS || purpose == DVIPDFM)
2337 if (purpose == DVIPS || purpose == DVIPDFM)
2340 case PAPER_USEXECUTIVE:
2341 // dvipdfm does not know this
2342 if (purpose == DVIPDFM)
2347 case PAPER_USLETTER:
2349 if (purpose == XDVI)
2356 string const BufferParams::dvips_options() const
2361 && papersize == PAPER_CUSTOM
2362 && !lyxrc.print_paper_dimension_flag.empty()
2363 && !paperwidth.empty()
2364 && !paperheight.empty()) {
2365 // using a custom papersize
2366 result = lyxrc.print_paper_dimension_flag;
2367 result += ' ' + paperwidth;
2368 result += ',' + paperheight;
2370 string const paper_option = paperSizeName(DVIPS);
2371 if (!paper_option.empty() && (paper_option != "letter" ||
2372 orientation != ORIENTATION_LANDSCAPE)) {
2373 // dvips won't accept -t letter -t landscape.
2374 // In all other cases, include the paper size
2376 result = lyxrc.print_paper_flag;
2377 result += ' ' + paper_option;
2380 if (orientation == ORIENTATION_LANDSCAPE &&
2381 papersize != PAPER_CUSTOM)
2382 result += ' ' + lyxrc.print_landscape_flag;
2387 string const BufferParams::font_encoding() const
2389 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2393 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2395 string lang_pack = lyxrc.language_package;
2396 if (lang_pack != "\\usepackage{babel}")
2398 // suppress the babel call if there is no BabelName defined
2399 // for the document language in the lib/languages file and if no
2400 // other languages are used (lang_opts is then empty)
2401 if (lang_opts.empty())
2403 // either a specific language (AsBabelOptions setting in
2404 // lib/languages) or the prefs require the languages to
2405 // be submitted to babel itself (not the class).
2407 return "\\usepackage[" + lang_opts + "]{babel}";
2412 docstring BufferParams::getGraphicsDriver(string const & package) const
2416 if (package == "geometry") {
2417 if (graphicsDriver == "dvips"
2418 || graphicsDriver == "dvipdfm"
2419 || graphicsDriver == "pdftex"
2420 || graphicsDriver == "vtex")
2421 result = from_ascii(graphicsDriver);
2422 else if (graphicsDriver == "dvipdfmx")
2423 result = from_ascii("dvipdfm");
2430 void BufferParams::writeEncodingPreamble(odocstream & os,
2431 LaTeXFeatures & features, TexRow & texrow) const
2435 if (inputenc == "auto") {
2436 string const doc_encoding =
2437 language->encoding()->latexName();
2438 Encoding::Package const package =
2439 language->encoding()->package();
2441 // Create a list with all the input encodings used
2443 set<string> encodings =
2444 features.getEncodingSet(doc_encoding);
2446 // If the "japanese" package (i.e. pLaTeX) is used,
2447 // inputenc must be omitted.
2448 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2449 if (package == Encoding::japanese)
2450 features.require("japanese");
2452 if ((!encodings.empty() || package == Encoding::inputenc)
2453 && !features.isRequired("japanese")) {
2454 os << "\\usepackage[";
2455 set<string>::const_iterator it = encodings.begin();
2456 set<string>::const_iterator const end = encodings.end();
2458 os << from_ascii(*it);
2461 for (; it != end; ++it)
2462 os << ',' << from_ascii(*it);
2463 if (package == Encoding::inputenc) {
2464 if (!encodings.empty())
2466 os << from_ascii(doc_encoding);
2468 os << "]{inputenc}\n";
2471 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2472 if (language->encoding()->name() == "utf8-cjk"
2473 && LaTeXFeatures::isAvailable("CJKutf8"))
2474 os << "\\usepackage{CJKutf8}\n";
2476 os << "\\usepackage{CJK}\n";
2479 } else if (inputenc != "default") {
2480 switch (encoding().package()) {
2481 case Encoding::none:
2482 case Encoding::japanese:
2484 case Encoding::inputenc:
2485 // do not load inputenc if japanese is used
2486 if (features.isRequired("japanese"))
2488 os << "\\usepackage[" << from_ascii(inputenc)
2493 if (encoding().name() == "utf8-cjk"
2494 && LaTeXFeatures::isAvailable("CJKutf8"))
2495 os << "\\usepackage{CJKutf8}\n";
2497 os << "\\usepackage{CJK}\n";
2503 // The encoding "armscii8" (for Armenian) is only available when
2504 // the package "armtex" is loaded.
2505 if (language->encoding()->latexName() == "armscii8"
2506 || inputenc == "armscii8") {
2507 os << "\\usepackage{armtex}\n";
2513 string const BufferParams::parseFontName(string const & name) const
2515 string mangled = name;
2516 size_t const idx = mangled.find('[');
2517 if (idx == string::npos || idx == 0)
2520 return mangled.substr(0, idx - 1);
2524 string const BufferParams::loadFonts(string const & rm,
2525 string const & sf, string const & tt,
2526 bool const & sc, bool const & osf,
2527 int const & sfscale, int const & ttscale,
2528 bool const & xetex) const
2530 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2531 several packages have been replaced by others, that might not
2532 be installed on every system. We have to take care for that
2533 (see psnfss.pdf). We try to support all psnfss fonts as well
2534 as the fonts that have become de facto standard in the LaTeX
2535 world (e.g. Latin Modern). We do not support obsolete fonts
2536 (like PSLatex). In general, it should be possible to mix any
2537 rm font with any sf or tt font, respectively. (JSpitzm)
2539 -- separate math fonts.
2542 if (rm == "default" && sf == "default" && tt == "default")
2549 if (rm != "default")
2550 os << "\\setmainfont[Mapping=tex-text]{"
2551 << parseFontName(rm) << "}\n";
2552 if (sf != "default") {
2553 string const sans = parseFontName(sf);
2555 os << "\\setsansfont[Scale="
2556 << float(sfscale) / 100
2557 << ",Mapping=tex-text]{"
2560 os << "\\setsansfont[Mapping=tex-text]{"
2563 if (tt != "default") {
2564 string const mono = parseFontName(tt);
2566 os << "\\setmonofont[Scale="
2567 << float(sfscale) / 100
2571 os << "\\setmonofont[Mapping=tex-text]{"
2575 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2580 // Computer Modern (must be explicitly selectable -- there might be classes
2581 // that define a different default font!
2583 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2584 // osf for Computer Modern needs eco.sty
2586 os << "\\usepackage{eco}\n";
2588 // Latin Modern Roman
2589 else if (rm == "lmodern")
2590 os << "\\usepackage{lmodern}\n";
2592 else if (rm == "ae") {
2593 // not needed when using OT1 font encoding.
2594 if (font_encoding() != "default")
2595 os << "\\usepackage{ae,aecompl}\n";
2598 else if (rm == "times") {
2599 // try to load the best available package
2600 if (LaTeXFeatures::isAvailable("mathptmx"))
2601 os << "\\usepackage{mathptmx}\n";
2602 else if (LaTeXFeatures::isAvailable("mathptm"))
2603 os << "\\usepackage{mathptm}\n";
2605 os << "\\usepackage{times}\n";
2608 else if (rm == "palatino") {
2609 // try to load the best available package
2610 if (LaTeXFeatures::isAvailable("mathpazo")) {
2611 os << "\\usepackage";
2617 // "osf" includes "sc"!
2621 os << "{mathpazo}\n";
2623 else if (LaTeXFeatures::isAvailable("mathpple"))
2624 os << "\\usepackage{mathpple}\n";
2626 os << "\\usepackage{palatino}\n";
2629 else if (rm == "utopia") {
2630 // fourier supersedes utopia.sty, but does
2631 // not work with OT1 encoding.
2632 if (LaTeXFeatures::isAvailable("fourier")
2633 && font_encoding() != "default") {
2634 os << "\\usepackage";
2645 os << "{fourier}\n";
2648 os << "\\usepackage{utopia}\n";
2650 // Bera (complete fontset)
2651 else if (rm == "bera" && sf == "default" && tt == "default")
2652 os << "\\usepackage{bera}\n";
2654 else if (rm != "default")
2655 os << "\\usepackage" << "{" << rm << "}\n";
2658 // Helvetica, Bera Sans
2659 if (sf == "helvet" || sf == "berasans") {
2661 os << "\\usepackage[scaled=" << float(sfscale) / 100
2662 << "]{" << sf << "}\n";
2664 os << "\\usepackage{" << sf << "}\n";
2667 else if (sf == "avant")
2668 os << "\\usepackage{" << sf << "}\n";
2669 // Computer Modern, Latin Modern, CM Bright
2670 else if (sf != "default")
2671 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2673 // monospaced/typewriter
2674 // Courier, LuxiMono
2675 if (tt == "luximono" || tt == "beramono") {
2677 os << "\\usepackage[scaled=" << float(ttscale) / 100
2678 << "]{" << tt << "}\n";
2680 os << "\\usepackage{" << tt << "}\n";
2683 else if (tt == "courier" )
2684 os << "\\usepackage{" << tt << "}\n";
2685 // Computer Modern, Latin Modern, CM Bright
2686 else if (tt != "default")
2687 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2693 Encoding const & BufferParams::encoding() const
2696 return *(encodings.fromLaTeXName("utf8-plain"));
2697 if (inputenc == "auto" || inputenc == "default")
2698 return *language->encoding();
2699 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2702 LYXERR0("Unknown inputenc value `" << inputenc
2703 << "'. Using `auto' instead.");
2704 return *language->encoding();
2708 CiteEngine BufferParams::citeEngine() const
2710 // FIXME the class should provide the numerical/
2711 // authoryear choice
2712 if (documentClass().provides("natbib")
2713 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2714 return ENGINE_NATBIB_AUTHORYEAR;
2715 return cite_engine_;
2719 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2721 cite_engine_ = cite_engine;