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 pimpl_->defskip = vs;
541 string BufferParams::readToken(Lexer & lex, string const & token,
542 FileName const & filepath)
544 if (token == "\\textclass") {
546 string const classname = lex.getString();
547 // if there exists a local layout file, ignore the system one
548 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
550 LayoutFileList & bcl = LayoutFileList::get();
551 if (tcp.empty() && !filepath.empty())
552 tcp = bcl.addLocalLayout(classname, filepath.absFileName());
556 setBaseClass(classname);
557 // We assume that a tex class exists for local or unknown layouts so this warning
558 // will only be given for system layouts.
559 if (!baseClass()->isTeXClassAvailable()) {
560 docstring const desc =
561 translateIfPossible(from_utf8(baseClass()->description()));
562 docstring const prereqs = from_utf8(baseClass()->prerequisites());
563 docstring const msg =
564 bformat(_("The selected document class\n"
566 "requires external files that are not available.\n"
567 "The document class can still be used, but the\n"
568 "document cannot be compiled until the following\n"
569 "prerequisites are installed:\n"
571 "See section 3.1.2.2 of the User's Guide for\n"
572 "more information."), desc, prereqs);
573 frontend::Alert::warning(_("Document class not available"),
576 } else if (token == "\\begin_preamble") {
578 } else if (token == "\\begin_local_layout") {
579 readLocalLayout(lex);
580 } else if (token == "\\begin_modules") {
582 } else if (token == "\\begin_removed_modules") {
583 readRemovedModules(lex);
584 } else if (token == "\\begin_includeonly") {
585 readIncludeonly(lex);
586 } else if (token == "\\maintain_unincluded_children") {
587 lex >> maintain_unincluded_children;
588 } else if (token == "\\options") {
590 options = lex.getString();
591 } else if (token == "\\use_default_options") {
592 lex >> use_default_options;
593 } else if (token == "\\master") {
595 master = lex.getString();
596 } else if (token == "\\suppress_date") {
597 lex >> suppress_date;
598 } else if (token == "\\language") {
600 } else if (token == "\\inputencoding") {
602 } else if (token == "\\graphics") {
603 readGraphicsDriver(lex);
604 } else if (token == "\\default_output_format") {
605 lex >> defaultOutputFormat;
606 } else if (token == "\\bibtex_command") {
608 bibtex_command = lex.getString();
609 } else if (token == "\\index_command") {
611 index_command = lex.getString();
612 } else if (token == "\\fontencoding") {
614 fontenc = lex.getString();
615 } else if (token == "\\font_roman") {
617 fontsRoman = lex.getString();
618 } else if (token == "\\font_sans") {
620 fontsSans = lex.getString();
621 } else if (token == "\\font_typewriter") {
623 fontsTypewriter = lex.getString();
624 } else if (token == "\\font_default_family") {
625 lex >> fontsDefaultFamily;
626 } else if (token == "\\use_xetex") {
628 } else if (token == "\\font_sc") {
630 } else if (token == "\\font_osf") {
632 } else if (token == "\\font_sf_scale") {
633 lex >> fontsSansScale;
634 } else if (token == "\\font_tt_scale") {
635 lex >> fontsTypewriterScale;
636 } else if (token == "\\font_cjk") {
638 } else if (token == "\\paragraph_separation") {
641 paragraph_separation = parseptranslator().find(parsep);
642 } else if (token == "\\paragraph_indentation") {
644 string indentation = lex.getString();
645 pimpl_->indentation = HSpace(indentation);
646 } else if (token == "\\defskip") {
648 string const defskip = lex.getString();
649 pimpl_->defskip = VSpace(defskip);
650 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
652 pimpl_->defskip = VSpace(VSpace::MEDSKIP);
653 } else if (token == "\\quotes_language") {
656 quotes_language = quoteslangtranslator().find(quotes_lang);
657 } else if (token == "\\papersize") {
660 papersize = papersizetranslator().find(ppsize);
661 } else if (token == "\\use_geometry") {
663 } else if (token == "\\use_amsmath") {
666 use_amsmath = packagetranslator().find(use_ams);
667 } else if (token == "\\use_esint") {
670 use_esint = packagetranslator().find(useesint);
671 } else if (token == "\\use_mhchem") {
674 use_mhchem = packagetranslator().find(usemhchem);
675 } else if (token == "\\use_mathdots") {
678 use_mathdots = packagetranslator().find(usemathdots);
679 } else if (token == "\\cite_engine") {
682 cite_engine_ = citeenginetranslator().find(engine);
683 } else if (token == "\\use_bibtopic") {
685 } else if (token == "\\use_indices") {
687 } else if (token == "\\tracking_changes") {
689 } else if (token == "\\output_changes") {
690 lex >> outputChanges;
691 } else if (token == "\\branch") {
693 docstring branch = lex.getDocString();
694 branchlist().add(branch);
697 string const tok = lex.getString();
698 if (tok == "\\end_branch")
700 Branch * branch_ptr = branchlist().find(branch);
701 if (tok == "\\selected") {
704 branch_ptr->setSelected(lex.getInteger());
706 if (tok == "\\filename_suffix") {
709 branch_ptr->setFileNameSuffix(lex.getInteger());
711 if (tok == "\\color") {
713 string color = lex.getString();
715 branch_ptr->setColor(color);
716 // Update also the Color table:
718 color = lcolor.getX11Name(Color_background);
720 lcolor.setColor(to_utf8(branch), color);
723 } else if (token == "\\index") {
725 docstring index = lex.getDocString();
727 indiceslist().add(index);
730 string const tok = lex.getString();
731 if (tok == "\\end_index")
733 Index * index_ptr = indiceslist().find(index);
734 if (tok == "\\shortcut") {
736 shortcut = lex.getDocString();
738 index_ptr->setShortcut(shortcut);
740 if (tok == "\\color") {
742 string color = lex.getString();
744 index_ptr->setColor(color);
745 // Update also the Color table:
747 color = lcolor.getX11Name(Color_background);
749 if (!shortcut.empty())
750 lcolor.setColor(to_utf8(shortcut), color);
753 } else if (token == "\\author") {
755 istringstream ss(lex.getString());
758 author_map[a.buffer_id()] = pimpl_->authorlist.record(a);
759 } else if (token == "\\paperorientation") {
762 orientation = paperorientationtranslator().find(orient);
763 } else if (token == "\\backgroundcolor") {
765 backgroundcolor = lyx::rgbFromHexName(lex.getString());
766 isbackgroundcolor = true;
767 } else if (token == "\\fontcolor") {
769 fontcolor = lyx::rgbFromHexName(lex.getString());
771 } else if (token == "\\notefontcolor") {
773 string color = lex.getString();
774 notefontcolor = lyx::rgbFromHexName(color);
775 } else if (token == "\\boxbgcolor") {
777 string color = lex.getString();
778 boxbgcolor = lyx::rgbFromHexName(color);
779 } else if (token == "\\paperwidth") {
781 } else if (token == "\\paperheight") {
783 } else if (token == "\\leftmargin") {
785 } else if (token == "\\topmargin") {
787 } else if (token == "\\rightmargin") {
789 } else if (token == "\\bottommargin") {
791 } else if (token == "\\headheight") {
793 } else if (token == "\\headsep") {
795 } else if (token == "\\footskip") {
797 } else if (token == "\\columnsep") {
799 } else if (token == "\\paperfontsize") {
801 } else if (token == "\\papercolumns") {
803 } else if (token == "\\listings_params") {
806 listings_params = InsetListingsParams(par).params();
807 } else if (token == "\\papersides") {
810 sides = sidestranslator().find(psides);
811 } else if (token == "\\paperpagestyle") {
813 } else if (token == "\\bullet") {
815 } else if (token == "\\bulletLaTeX") {
816 readBulletsLaTeX(lex);
817 } else if (token == "\\secnumdepth") {
819 } else if (token == "\\tocdepth") {
821 } else if (token == "\\spacing") {
825 if (nspacing == "other") {
828 spacing().set(spacetranslator().find(nspacing), tmp_val);
829 } else if (token == "\\float_placement") {
830 lex >> float_placement;
832 } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
833 string toktmp = pdfoptions().readToken(lex, token);
834 if (!toktmp.empty()) {
835 lyxerr << "PDFOptions::readToken(): Unknown token: " <<
839 } else if (token == "\\html_math_output") {
842 html_math_output = static_cast<MathOutput>(temp);
843 } else if (token == "\\html_be_strict") {
844 lex >> html_be_strict;
845 } else if (token == "\\html_math_img_scale") {
846 lex >> html_math_img_scale;
847 } else if (token == "\\html_latex_start") {
849 html_latex_start = lex.getString();
850 } else if (token == "\\html_latex_end") {
852 html_latex_end = lex.getString();
853 } else if (token == "\\output_sync") {
855 } else if (token == "\\output_sync_macro") {
856 lex >> output_sync_macro;
857 } else if (token == "\\use_refstyle") {
860 lyxerr << "BufferParams::readToken(): Unknown token: " <<
869 void BufferParams::writeFile(ostream & os) const
871 // The top of the file is written by the buffer.
872 // Prints out the buffer info into the .lyx file given by file
875 os << "\\textclass " << baseClass()->name() << '\n';
878 if (!preamble.empty()) {
879 // remove '\n' from the end of preamble
880 string const tmppreamble = rtrim(preamble, "\n");
881 os << "\\begin_preamble\n"
883 << "\n\\end_preamble\n";
887 if (!options.empty()) {
888 os << "\\options " << options << '\n';
891 // use the class options defined in the layout?
892 os << "\\use_default_options "
893 << convert<string>(use_default_options) << "\n";
895 // the master document
896 if (!master.empty()) {
897 os << "\\master " << master << '\n';
901 if (!removedModules_.empty()) {
902 os << "\\begin_removed_modules" << '\n';
903 list<string>::const_iterator it = removedModules_.begin();
904 list<string>::const_iterator en = removedModules_.end();
905 for (; it != en; it++)
907 os << "\\end_removed_modules" << '\n';
911 if (!layoutModules_.empty()) {
912 os << "\\begin_modules" << '\n';
913 LayoutModuleList::const_iterator it = layoutModules_.begin();
914 LayoutModuleList::const_iterator en = layoutModules_.end();
915 for (; it != en; it++)
917 os << "\\end_modules" << '\n';
921 if (!includedChildren_.empty()) {
922 os << "\\begin_includeonly" << '\n';
923 list<string>::const_iterator it = includedChildren_.begin();
924 list<string>::const_iterator en = includedChildren_.end();
925 for (; it != en; it++)
927 os << "\\end_includeonly" << '\n';
929 os << "\\maintain_unincluded_children "
930 << convert<string>(maintain_unincluded_children) << '\n';
932 // local layout information
933 if (!local_layout.empty()) {
934 // remove '\n' from the end
935 string const tmplocal = rtrim(local_layout, "\n");
936 os << "\\begin_local_layout\n"
938 << "\n\\end_local_layout\n";
941 // then the text parameters
942 if (language != ignore_language)
943 os << "\\language " << language->lang() << '\n';
944 os << "\\inputencoding " << inputenc
945 << "\n\\fontencoding " << fontenc
946 << "\n\\font_roman " << fontsRoman
947 << "\n\\font_sans " << fontsSans
948 << "\n\\font_typewriter " << fontsTypewriter
949 << "\n\\font_default_family " << fontsDefaultFamily
950 << "\n\\use_xetex " << convert<string>(useXetex)
951 << "\n\\font_sc " << convert<string>(fontsSC)
952 << "\n\\font_osf " << convert<string>(fontsOSF)
953 << "\n\\font_sf_scale " << fontsSansScale
954 << "\n\\font_tt_scale " << fontsTypewriterScale
956 if (!fontsCJK.empty()) {
957 os << "\\font_cjk " << fontsCJK << '\n';
959 os << "\n\\graphics " << graphicsDriver << '\n';
960 os << "\\default_output_format " << defaultOutputFormat << '\n';
961 os << "\\output_sync " << output_sync << '\n';
962 if (!output_sync_macro.empty())
963 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
964 os << "\\bibtex_command " << bibtex_command << '\n';
965 os << "\\index_command " << index_command << '\n';
967 if (!float_placement.empty()) {
968 os << "\\float_placement " << float_placement << '\n';
970 os << "\\paperfontsize " << fontsize << '\n';
972 spacing().writeFile(os);
973 pdfoptions().writeFile(os);
975 os << "\\papersize " << string_papersize[papersize]
976 << "\n\\use_geometry " << convert<string>(use_geometry)
977 << "\n\\use_amsmath " << use_amsmath
978 << "\n\\use_esint " << use_esint
979 << "\n\\use_mhchem " << use_mhchem
980 << "\n\\use_mathdots " << use_mathdots
981 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
982 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
983 << "\n\\use_indices " << convert<string>(use_indices)
984 << "\n\\paperorientation " << string_orientation[orientation]
985 << "\n\\suppress_date " << convert<string>(suppress_date)
986 << "\n\\use_refstyle " << use_refstyle
988 if (isbackgroundcolor == true)
989 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
990 if (isfontcolor == true)
991 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
992 if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
993 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
994 if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
995 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
997 BranchList::const_iterator it = branchlist().begin();
998 BranchList::const_iterator end = branchlist().end();
999 for (; it != end; ++it) {
1000 os << "\\branch " << to_utf8(it->branch())
1001 << "\n\\selected " << it->isSelected()
1002 << "\n\\filename_suffix " << it->hasFileNameSuffix()
1003 << "\n\\color " << lyx::X11hexname(it->color())
1008 IndicesList::const_iterator iit = indiceslist().begin();
1009 IndicesList::const_iterator iend = indiceslist().end();
1010 for (; iit != iend; ++iit) {
1011 os << "\\index " << to_utf8(iit->index())
1012 << "\n\\shortcut " << to_utf8(iit->shortcut())
1013 << "\n\\color " << lyx::X11hexname(iit->color())
1018 if (!paperwidth.empty())
1019 os << "\\paperwidth "
1020 << VSpace(paperwidth).asLyXCommand() << '\n';
1021 if (!paperheight.empty())
1022 os << "\\paperheight "
1023 << VSpace(paperheight).asLyXCommand() << '\n';
1024 if (!leftmargin.empty())
1025 os << "\\leftmargin "
1026 << VSpace(leftmargin).asLyXCommand() << '\n';
1027 if (!topmargin.empty())
1028 os << "\\topmargin "
1029 << VSpace(topmargin).asLyXCommand() << '\n';
1030 if (!rightmargin.empty())
1031 os << "\\rightmargin "
1032 << VSpace(rightmargin).asLyXCommand() << '\n';
1033 if (!bottommargin.empty())
1034 os << "\\bottommargin "
1035 << VSpace(bottommargin).asLyXCommand() << '\n';
1036 if (!headheight.empty())
1037 os << "\\headheight "
1038 << VSpace(headheight).asLyXCommand() << '\n';
1039 if (!headsep.empty())
1041 << VSpace(headsep).asLyXCommand() << '\n';
1042 if (!footskip.empty())
1044 << VSpace(footskip).asLyXCommand() << '\n';
1045 if (!columnsep.empty())
1046 os << "\\columnsep "
1047 << VSpace(columnsep).asLyXCommand() << '\n';
1048 os << "\\secnumdepth " << secnumdepth
1049 << "\n\\tocdepth " << tocdepth
1050 << "\n\\paragraph_separation "
1051 << string_paragraph_separation[paragraph_separation];
1052 if (!paragraph_separation)
1053 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1055 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1056 os << "\n\\quotes_language "
1057 << string_quotes_language[quotes_language]
1058 << "\n\\papercolumns " << columns
1059 << "\n\\papersides " << sides
1060 << "\n\\paperpagestyle " << pagestyle << '\n';
1061 if (!listings_params.empty())
1062 os << "\\listings_params \"" <<
1063 InsetListingsParams(listings_params).encodedString() << "\"\n";
1064 for (int i = 0; i < 4; ++i) {
1065 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1066 if (user_defined_bullet(i).getFont() != -1) {
1067 os << "\\bullet " << i << " "
1068 << user_defined_bullet(i).getFont() << " "
1069 << user_defined_bullet(i).getCharacter() << " "
1070 << user_defined_bullet(i).getSize() << "\n";
1074 os << "\\bulletLaTeX " << i << " \""
1075 << lyx::to_ascii(user_defined_bullet(i).getText())
1081 os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1082 << "\\output_changes " << convert<string>(outputChanges) << '\n'
1083 << "\\html_math_output " << html_math_output << '\n'
1084 << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1086 if (html_math_img_scale != 1.0)
1087 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1088 if (!html_latex_start.empty())
1089 os << "\\html_latex_start " << html_latex_start << '\n';
1090 if (!html_latex_end.empty())
1091 os << "\\html_latex_end " << html_latex_end << '\n';
1093 os << pimpl_->authorlist;
1097 void BufferParams::validate(LaTeXFeatures & features) const
1099 features.require(documentClass().requires());
1101 if (outputChanges) {
1102 bool dvipost = LaTeXFeatures::isAvailable("dvipost");
1103 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1104 LaTeXFeatures::isAvailable("xcolor");
1106 switch (features.runparams().flavor) {
1107 case OutputParams::LATEX:
1109 features.require("ct-dvipost");
1110 features.require("dvipost");
1111 } else if (xcolorulem) {
1112 features.require("ct-xcolor-ulem");
1113 features.require("ulem");
1114 features.require("xcolor");
1116 features.require("ct-none");
1119 case OutputParams::PDFLATEX:
1120 case OutputParams::XETEX:
1122 features.require("ct-xcolor-ulem");
1123 features.require("ulem");
1124 features.require("xcolor");
1125 // improves color handling in PDF output
1126 features.require("pdfcolmk");
1128 features.require("ct-none");
1136 // Floats with 'Here definitely' as default setting.
1137 if (float_placement.find('H') != string::npos)
1138 features.require("float");
1140 // AMS Style is at document level
1141 if (use_amsmath == package_on
1142 || documentClass().provides("amsmath"))
1143 features.require("amsmath");
1144 if (use_esint == package_on)
1145 features.require("esint");
1146 if (use_mhchem == package_on)
1147 features.require("mhchem");
1148 if (use_mathdots == package_on)
1149 features.require("mathdots");
1151 // Document-level line spacing
1152 if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1153 features.require("setspace");
1155 // the bullet shapes are buffer level not paragraph level
1156 // so they are tested here
1157 for (int i = 0; i < 4; ++i) {
1158 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i])
1160 int const font = user_defined_bullet(i).getFont();
1162 int const c = user_defined_bullet(i).getCharacter();
1168 features.require("latexsym");
1170 } else if (font == 1) {
1171 features.require("amssymb");
1172 } else if (font >= 2 && font <= 5) {
1173 features.require("pifont");
1177 if (pdfoptions().use_hyperref) {
1178 features.require("hyperref");
1179 // due to interferences with babel and hyperref, the color package has to
1180 // be loaded after hyperref when hyperref is used with the colorlinks
1181 // option, see http://www.lyx.org/trac/ticket/5291
1182 if (pdfoptions().colorlinks)
1183 features.require("color");
1187 features.require("xetex");
1189 if (language->lang() == "vietnamese")
1190 features.require("vietnamese");
1191 else if (language->lang() == "japanese")
1192 features.require("japanese");
1196 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1197 TexRow & texrow, FileName const & filepath) const
1199 os << "\\documentclass";
1201 DocumentClass const & tclass = documentClass();
1203 ostringstream clsoptions; // the document class options.
1205 if (tokenPos(tclass.opt_fontsize(),
1206 '|', fontsize) >= 0) {
1207 // only write if existing in list (and not default)
1208 clsoptions << fontsize << "pt,";
1211 // all paper sizes except of A4, A5, B5 and the US sizes need the
1213 bool nonstandard_papersize = papersize != PAPER_DEFAULT
1214 && papersize != PAPER_USLETTER
1215 && papersize != PAPER_USLEGAL
1216 && papersize != PAPER_USEXECUTIVE
1217 && papersize != PAPER_A4
1218 && papersize != PAPER_A5
1219 && papersize != PAPER_B5;
1221 if (!use_geometry) {
1222 switch (papersize) {
1224 clsoptions << "a4paper,";
1226 case PAPER_USLETTER:
1227 clsoptions << "letterpaper,";
1230 clsoptions << "a5paper,";
1233 clsoptions << "b5paper,";
1235 case PAPER_USEXECUTIVE:
1236 clsoptions << "executivepaper,";
1239 clsoptions << "legalpaper,";
1273 if (sides != tclass.sides()) {
1276 clsoptions << "oneside,";
1279 clsoptions << "twoside,";
1285 if (columns != tclass.columns()) {
1287 clsoptions << "twocolumn,";
1289 clsoptions << "onecolumn,";
1293 && orientation == ORIENTATION_LANDSCAPE)
1294 clsoptions << "landscape,";
1296 // language should be a parameter to \documentclass
1297 if (language->babel() == "hebrew"
1298 && default_language->babel() != "hebrew")
1299 // This seems necessary
1300 features.useLanguage(default_language);
1302 ostringstream language_options;
1303 bool const use_babel = features.useBabel() && !tclass.provides("babel");
1305 language_options << features.getLanguages();
1306 if (!language->babel().empty()) {
1307 if (!language_options.str().empty())
1308 language_options << ',';
1309 language_options << language->babel();
1311 // if Vietnamese is used, babel must directly be loaded
1312 // with language options, not in the class options, see
1313 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1314 size_t viet = language_options.str().find("vietnam");
1315 // viet = string::npos when not found
1316 // the same is for all other languages that are not directly supported by
1317 // babel, but where LaTeX-packages add babel support.
1318 // this is currently the case for Latvian, Lithuanian, Mongolian
1320 size_t latvian = language_options.str().find("latvian");
1321 size_t lithu = language_options.str().find("lithuanian");
1322 size_t mongo = language_options.str().find("mongolian");
1323 size_t turkmen = language_options.str().find("turkmen");
1324 // if Japanese is used, babel must directly be loaded
1325 // with language options, not in the class options, see
1326 // http://www.lyx.org/trac/ticket/4597#c4
1327 size_t japan = language_options.str().find("japanese");
1328 if (lyxrc.language_global_options && !language_options.str().empty()
1329 && viet == string::npos && japan == string::npos
1330 && latvian == string::npos && lithu == string::npos
1331 && mongo == string::npos && turkmen == string::npos)
1332 clsoptions << language_options.str() << ',';
1335 // the predefined options from the layout
1336 if (use_default_options && !tclass.options().empty())
1337 clsoptions << tclass.options() << ',';
1339 // the user-defined options
1340 if (!options.empty()) {
1341 clsoptions << options << ',';
1344 string strOptions(clsoptions.str());
1345 if (!strOptions.empty()) {
1346 strOptions = rtrim(strOptions, ",");
1348 os << '[' << from_utf8(strOptions) << ']';
1351 os << '{' << from_ascii(tclass.latexname()) << "}\n";
1353 // end of \documentclass defs
1356 os << "\\usepackage{fontspec}\n";
1360 // font selection must be done before loading fontenc.sty
1361 string const fonts =
1362 loadFonts(fontsRoman, fontsSans,
1363 fontsTypewriter, fontsSC, fontsOSF,
1364 fontsSansScale, fontsTypewriterScale, useXetex);
1365 if (!fonts.empty()) {
1366 os << from_ascii(fonts);
1369 if (fontsDefaultFamily != "default")
1370 os << "\\renewcommand{\\familydefault}{\\"
1371 << from_ascii(fontsDefaultFamily) << "}\n";
1373 // set font encoding
1374 // for arabic_arabi and farsi we also need to load the LAE and
1376 // XeTeX works without fontenc
1377 if (font_encoding() != "default" && language->lang() != "japanese"
1378 && !useXetex && !tclass.provides("fontenc")) {
1379 size_t fars = language_options.str().find("farsi");
1380 size_t arab = language_options.str().find("arabic");
1381 if (language->lang() == "arabic_arabi"
1382 || language->lang() == "farsi" || fars != string::npos
1383 || arab != string::npos) {
1384 os << "\\usepackage[" << from_ascii(font_encoding())
1385 << ",LFE,LAE]{fontenc}\n";
1388 os << "\\usepackage[" << from_ascii(font_encoding())
1394 // handle inputenc etc.
1395 writeEncodingPreamble(os, features, texrow);
1398 if (!features.runparams().includeall && !includedChildren_.empty()) {
1399 os << "\\includeonly{";
1400 list<string>::const_iterator it = includedChildren_.begin();
1402 for (; it != includedChildren_.end() ; ++it) {
1403 string incfile = *it;
1404 FileName inc = makeAbsPath(incfile, filepath.absFileName());
1405 string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1407 if (!features.runparams().nice)
1409 // \includeonly doesn't want an extension
1410 incfile = changeExtension(incfile, string());
1411 incfile = support::latex_path(incfile);
1412 if (!incfile.empty()) {
1415 os << from_utf8(incfile);
1422 if (!listings_params.empty() || features.isRequired("listings")) {
1423 os << "\\usepackage{listings}\n";
1426 if (!listings_params.empty()) {
1428 // do not test validity because listings_params is
1429 // supposed to be valid
1431 InsetListingsParams(listings_params).separatedParams(true);
1432 // we can't support all packages, but we should load the color package
1433 if (par.find("\\color", 0) != string::npos)
1434 features.require("color");
1435 os << from_utf8(par);
1436 // count the number of newlines
1437 for (size_t i = 0; i < par.size(); ++i)
1443 if (!tclass.provides("geometry")
1444 && (use_geometry || nonstandard_papersize)) {
1445 odocstringstream ods;
1446 if (!getGraphicsDriver("geometry").empty())
1447 ods << getGraphicsDriver("geometry");
1448 if (orientation == ORIENTATION_LANDSCAPE)
1449 ods << ",landscape";
1450 switch (papersize) {
1452 if (!paperwidth.empty())
1453 ods << ",paperwidth="
1454 << from_ascii(paperwidth);
1455 if (!paperheight.empty())
1456 ods << ",paperheight="
1457 << from_ascii(paperheight);
1459 case PAPER_USLETTER:
1460 ods << ",letterpaper";
1463 ods << ",legalpaper";
1465 case PAPER_USEXECUTIVE:
1466 ods << ",executivepaper";
1553 // default papersize ie PAPER_DEFAULT
1554 switch (lyxrc.default_papersize) {
1555 case PAPER_DEFAULT: // keep compiler happy
1556 case PAPER_USLETTER:
1557 ods << ",letterpaper";
1560 ods << ",legalpaper";
1562 case PAPER_USEXECUTIVE:
1563 ods << ",executivepaper";
1605 docstring const g_options = trim(ods.str(), ",");
1606 os << "\\usepackage";
1607 if (!g_options.empty())
1608 os << '[' << g_options << ']';
1609 os << "{geometry}\n";
1611 // output this only if use_geometry is true
1613 os << "\\geometry{verbose";
1614 if (!topmargin.empty())
1615 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1616 if (!bottommargin.empty())
1617 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1618 if (!leftmargin.empty())
1619 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1620 if (!rightmargin.empty())
1621 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1622 if (!headheight.empty())
1623 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1624 if (!headsep.empty())
1625 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1626 if (!footskip.empty())
1627 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1628 if (!columnsep.empty())
1629 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1633 } else if (orientation == ORIENTATION_LANDSCAPE
1634 || papersize != PAPER_DEFAULT) {
1635 features.require("papersize");
1638 if (tokenPos(tclass.opt_pagestyle(),
1639 '|', pagestyle) >= 0) {
1640 if (pagestyle == "fancy") {
1641 os << "\\usepackage{fancyhdr}\n";
1644 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1648 // only output when the background color is not default
1649 if (isbackgroundcolor == true) {
1650 // only require color here, the background color will be defined
1651 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1653 features.require("color");
1654 features.require("pagecolor");
1657 // only output when the font color is not default
1658 if (isfontcolor == true) {
1659 // only require color here, the font color will be defined
1660 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1662 features.require("color");
1663 features.require("fontcolor");
1666 // Only if class has a ToC hierarchy
1667 if (tclass.hasTocLevels()) {
1668 if (secnumdepth != tclass.secnumdepth()) {
1669 os << "\\setcounter{secnumdepth}{"
1674 if (tocdepth != tclass.tocdepth()) {
1675 os << "\\setcounter{tocdepth}{"
1682 if (paragraph_separation) {
1683 // when skip separation
1684 switch (getDefSkip().kind()) {
1685 case VSpace::SMALLSKIP:
1686 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1688 case VSpace::MEDSKIP:
1689 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1691 case VSpace::BIGSKIP:
1692 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1694 case VSpace::LENGTH:
1695 os << "\\setlength{\\parskip}{"
1696 << from_utf8(getDefSkip().length().asLatexString())
1699 default: // should never happen // Then delete it.
1700 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1704 os << "\\setlength{\\parindent}{0pt}\n";
1707 // when separation by indentation
1708 // only output something when a width is given
1709 if (getIndentation().asLyXCommand() != "default") {
1710 os << "\\setlength{\\parindent}{"
1711 << from_utf8(getIndentation().asLatexCommand())
1717 // Now insert the LyX specific LaTeX commands...
1718 docstring lyxpreamble;
1721 if (!output_sync_macro.empty())
1722 lyxpreamble += from_utf8(output_sync_macro) +"\n";
1723 else if (features.runparams().flavor == OutputParams::LATEX)
1724 lyxpreamble += "\\usepackage[active]{srcltx}\n";
1725 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1726 lyxpreamble += "\\synctex=-1\n";
1729 // due to interferences with babel and hyperref, the color package has to
1730 // be loaded (when it is not already loaded) before babel when hyperref
1731 // is used with the colorlinks option, see
1732 // http://www.lyx.org/trac/ticket/5291
1733 // we decided therefore to load color always before babel, see
1734 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1735 lyxpreamble += from_ascii(features.getColorOptions());
1737 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1739 && (features.isRequired("jurabib")
1740 || features.isRequired("hyperref")
1741 || features.isRequired("vietnamese")
1742 || features.isRequired("japanese") ) ) {
1744 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1745 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1748 // The optional packages;
1749 lyxpreamble += from_ascii(features.getPackages());
1751 // Additional Indices
1752 if (features.isRequired("splitidx")) {
1753 IndicesList::const_iterator iit = indiceslist().begin();
1754 IndicesList::const_iterator iend = indiceslist().end();
1755 for (; iit != iend; ++iit) {
1756 lyxpreamble += "\\newindex[";
1757 lyxpreamble += iit->index();
1758 lyxpreamble += "]{";
1759 lyxpreamble += iit->shortcut();
1760 lyxpreamble += "}\n";
1765 lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1768 // * Hyperref manual: "Make sure it comes last of your loaded
1769 // packages, to give it a fighting chance of not being over-written,
1770 // since its job is to redefine many LaTeX commands."
1771 // * Email from Heiko Oberdiek: "It is usually better to load babel
1772 // before hyperref. Then hyperref has a chance to detect babel.
1773 // * Has to be loaded before the "LyX specific LaTeX commands" to
1774 // avoid errors with algorithm floats.
1775 // use hyperref explicitly if it is required
1776 if (features.isRequired("hyperref")) {
1777 // pass what we have to stream here, since we need
1778 // to access the stream itself in PDFOptions.
1782 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1784 OutputParams tmp_params = features.runparams();
1785 lines += pdfoptions().writeLaTeX(tmp_params, os,
1786 documentClass().provides("hyperref"));
1787 texrow.newlines(lines);
1788 // set back for the rest
1789 lyxpreamble.clear();
1790 } else if (features.isRequired("nameref"))
1791 // hyperref loads this automatically
1792 lyxpreamble += "\\usepackage{nameref}\n";
1794 // Will be surrounded by \makeatletter and \makeatother when not empty
1795 docstring atlyxpreamble;
1797 // Some macros LyX will need
1798 docstring tmppreamble(features.getMacros());
1800 if (!tmppreamble.empty())
1801 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1802 "LyX specific LaTeX commands.\n"
1803 + tmppreamble + '\n';
1805 // the text class specific preamble
1806 tmppreamble = features.getTClassPreamble();
1807 if (!tmppreamble.empty())
1808 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1809 "Textclass specific LaTeX commands.\n"
1810 + tmppreamble + '\n';
1812 // suppress date if selected
1813 // use \@ifundefined because we cannot be sure that every document class
1814 // has a \date command
1816 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1818 /* the user-defined preamble */
1819 if (!containsOnly(preamble, " \n\t"))
1821 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1822 "User specified LaTeX commands.\n"
1823 + from_utf8(preamble) + '\n';
1825 // subfig loads internally the LaTeX package "caption". As
1826 // caption is a very popular package, users will load it in
1827 // the preamble. Therefore we must load subfig behind the
1828 // user-defined preamble and check if the caption package was
1829 // loaded or not. For the case that caption is loaded before
1830 // subfig, there is the subfig option "caption=false". This
1831 // option also works when a koma-script class is used and
1832 // koma's own caption commands are used instead of caption. We
1833 // use \PassOptionsToPackage here because the user could have
1834 // already loaded subfig in the preamble.
1835 if (features.isRequired("subfig")) {
1836 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1837 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1838 "\\usepackage{subfig}\n";
1841 // Itemize bullet settings need to be last in case the user
1842 // defines their own bullets that use a package included
1843 // in the user-defined preamble -- ARRae
1844 // Actually it has to be done much later than that
1845 // since some packages like frenchb make modifications
1846 // at \begin{document} time -- JMarc
1847 docstring bullets_def;
1848 for (int i = 0; i < 4; ++i) {
1849 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1850 if (bullets_def.empty())
1851 bullets_def += "\\AtBeginDocument{\n";
1852 bullets_def += " \\def\\labelitemi";
1854 // `i' is one less than the item to modify
1861 bullets_def += "ii";
1867 bullets_def += '{' +
1868 user_defined_bullet(i).getText()
1873 if (!bullets_def.empty())
1874 atlyxpreamble += bullets_def + "}\n\n";
1876 if (!atlyxpreamble.empty())
1877 lyxpreamble += "\n\\makeatletter\n"
1878 + atlyxpreamble + "\\makeatother\n\n";
1880 // We try to load babel late, in case it interferes with other packages.
1881 // Jurabib and Hyperref have to be called after babel, though.
1882 if (use_babel && !features.isRequired("jurabib")
1883 && !features.isRequired("hyperref")
1884 && !features.isRequired("vietnamese")
1885 && !features.isRequired("japanese")) {
1887 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1888 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1891 docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1892 if (!i18npreamble.empty())
1893 lyxpreamble += i18npreamble + '\n';
1896 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1897 texrow.newlines(nlines);
1901 // these packages (xunicode, for that matter) need to be loaded at least
1902 // after amsmath, amssymb, esint and the other packages that provide
1905 os << "\\usepackage{xunicode}\n";
1907 os << "\\usepackage{xltxtra}\n";
1914 void BufferParams::useClassDefaults()
1916 DocumentClass const & tclass = documentClass();
1918 sides = tclass.sides();
1919 columns = tclass.columns();
1920 pagestyle = tclass.pagestyle();
1921 use_default_options = true;
1922 // Only if class has a ToC hierarchy
1923 if (tclass.hasTocLevels()) {
1924 secnumdepth = tclass.secnumdepth();
1925 tocdepth = tclass.tocdepth();
1930 bool BufferParams::hasClassDefaults() const
1932 DocumentClass const & tclass = documentClass();
1934 return sides == tclass.sides()
1935 && columns == tclass.columns()
1936 && pagestyle == tclass.pagestyle()
1937 && use_default_options
1938 && secnumdepth == tclass.secnumdepth()
1939 && tocdepth == tclass.tocdepth();
1943 DocumentClass const & BufferParams::documentClass() const
1949 DocumentClass const * BufferParams::documentClassPtr() const
1955 void BufferParams::setDocumentClass(DocumentClass const * const tc)
1957 // evil, but this function is evil
1958 doc_class_ = const_cast<DocumentClass *>(tc);
1962 bool BufferParams::setBaseClass(string const & classname)
1964 LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1965 LayoutFileList & bcl = LayoutFileList::get();
1966 if (!bcl.haveClass(classname)) {
1968 bformat(_("The layout file:\n"
1970 "could not be found. 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(_("Document class not found"), s);
1975 bcl.addEmptyClass(classname);
1978 bool const success = bcl[classname].load();
1981 bformat(_("Due to some error in it, the layout file:\n"
1983 "could not be loaded. A default textclass with default\n"
1984 "layouts will be used. LyX will not be able to produce\n"
1986 from_utf8(classname));
1987 frontend::Alert::error(_("Could not load class"), s);
1988 bcl.addEmptyClass(classname);
1991 pimpl_->baseClass_ = classname;
1992 layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1997 LayoutFile const * BufferParams::baseClass() const
1999 if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2000 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2006 LayoutFileIndex const & BufferParams::baseClassID() const
2008 return pimpl_->baseClass_;
2012 void BufferParams::makeDocumentClass()
2017 doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
2019 if (!local_layout.empty()) {
2020 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
2021 docstring const msg = _("Error reading internal layout information");
2022 frontend::Alert::warning(_("Read Error"), msg);
2028 bool BufferParams::moduleCanBeAdded(string const & modName) const
2030 return layoutModules_.moduleCanBeAdded(modName, baseClass());
2034 bool BufferParams::addLayoutModule(string const & modName)
2036 LayoutModuleList::const_iterator it = layoutModules_.begin();
2037 LayoutModuleList::const_iterator end = layoutModules_.end();
2038 for (; it != end; it++)
2041 layoutModules_.push_back(modName);
2046 Font const BufferParams::getFont() const
2048 FontInfo f = documentClass().defaultfont();
2049 if (fontsDefaultFamily == "rmdefault")
2050 f.setFamily(ROMAN_FAMILY);
2051 else if (fontsDefaultFamily == "sfdefault")
2052 f.setFamily(SANS_FAMILY);
2053 else if (fontsDefaultFamily == "ttdefault")
2054 f.setFamily(TYPEWRITER_FAMILY);
2055 return Font(f, language);
2059 void BufferParams::readPreamble(Lexer & lex)
2061 if (lex.getString() != "\\begin_preamble")
2062 lyxerr << "Error (BufferParams::readPreamble):"
2063 "consistency check failed." << endl;
2065 preamble = lex.getLongString("\\end_preamble");
2069 void BufferParams::readLocalLayout(Lexer & lex)
2071 if (lex.getString() != "\\begin_local_layout")
2072 lyxerr << "Error (BufferParams::readLocalLayout):"
2073 "consistency check failed." << endl;
2075 local_layout = lex.getLongString("\\end_local_layout");
2079 void BufferParams::readLanguage(Lexer & lex)
2081 if (!lex.next()) return;
2083 string const tmptok = lex.getString();
2085 // check if tmptok is part of tex_babel in tex-defs.h
2086 language = languages.getLanguage(tmptok);
2088 // Language tmptok was not found
2089 language = default_language;
2090 lyxerr << "Warning: Setting language `"
2091 << tmptok << "' to `" << language->lang()
2097 void BufferParams::readGraphicsDriver(Lexer & lex)
2102 string const tmptok = lex.getString();
2103 // check if tmptok is part of tex_graphics in tex_defs.h
2106 string const test = tex_graphics[n++];
2108 if (test == tmptok) {
2109 graphicsDriver = tmptok;
2114 "Warning: graphics driver `$$Token' not recognized!\n"
2115 " Setting graphics driver to `default'.\n");
2116 graphicsDriver = "default";
2123 void BufferParams::readBullets(Lexer & lex)
2128 int const index = lex.getInteger();
2130 int temp_int = lex.getInteger();
2131 user_defined_bullet(index).setFont(temp_int);
2132 temp_bullet(index).setFont(temp_int);
2134 user_defined_bullet(index).setCharacter(temp_int);
2135 temp_bullet(index).setCharacter(temp_int);
2137 user_defined_bullet(index).setSize(temp_int);
2138 temp_bullet(index).setSize(temp_int);
2142 void BufferParams::readBulletsLaTeX(Lexer & lex)
2144 // The bullet class should be able to read this.
2147 int const index = lex.getInteger();
2149 docstring const temp_str = lex.getDocString();
2151 user_defined_bullet(index).setText(temp_str);
2152 temp_bullet(index).setText(temp_str);
2156 void BufferParams::readModules(Lexer & lex)
2158 if (!lex.eatLine()) {
2159 lyxerr << "Error (BufferParams::readModules):"
2160 "Unexpected end of input." << endl;
2164 string mod = lex.getString();
2165 if (mod == "\\end_modules")
2167 addLayoutModule(mod);
2173 void BufferParams::readRemovedModules(Lexer & lex)
2175 if (!lex.eatLine()) {
2176 lyxerr << "Error (BufferParams::readRemovedModules):"
2177 "Unexpected end of input." << endl;
2181 string mod = lex.getString();
2182 if (mod == "\\end_removed_modules")
2184 removedModules_.push_back(mod);
2187 // now we want to remove any removed modules that were previously
2188 // added. normally, that will be because default modules were added in
2189 // setBaseClass(), which gets called when \textclass is read at the
2190 // start of the read.
2191 list<string>::const_iterator rit = removedModules_.begin();
2192 list<string>::const_iterator const ren = removedModules_.end();
2193 for (; rit != ren; rit++) {
2194 LayoutModuleList::iterator const mit = layoutModules_.begin();
2195 LayoutModuleList::iterator const men = layoutModules_.end();
2196 LayoutModuleList::iterator found = find(mit, men, *rit);
2199 layoutModules_.erase(found);
2204 void BufferParams::readIncludeonly(Lexer & lex)
2206 if (!lex.eatLine()) {
2207 lyxerr << "Error (BufferParams::readIncludeonly):"
2208 "Unexpected end of input." << endl;
2212 string child = lex.getString();
2213 if (child == "\\end_includeonly")
2215 includedChildren_.push_back(child);
2221 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2223 char real_papersize = papersize;
2224 if (real_papersize == PAPER_DEFAULT)
2225 real_papersize = lyxrc.default_papersize;
2227 switch (real_papersize) {
2229 // could be anything, so don't guess
2231 case PAPER_CUSTOM: {
2232 if (purpose == XDVI && !paperwidth.empty() &&
2233 !paperheight.empty()) {
2234 // heightxwidth<unit>
2235 string first = paperwidth;
2236 string second = paperheight;
2237 if (orientation == ORIENTATION_LANDSCAPE)
2240 return first.erase(first.length() - 2)
2246 // dvips and dvipdfm do not know this
2247 if (purpose == DVIPS || purpose == DVIPDFM)
2251 if (purpose == DVIPS || purpose == DVIPDFM)
2255 if (purpose == DVIPS || purpose == DVIPDFM)
2265 if (purpose == DVIPS || purpose == DVIPDFM)
2269 if (purpose == DVIPS || purpose == DVIPDFM)
2273 if (purpose == DVIPS || purpose == DVIPDFM)
2277 if (purpose == DVIPS || purpose == DVIPDFM)
2281 if (purpose == DVIPS || purpose == DVIPDFM)
2285 // dvipdfm does not know this
2286 if (purpose == DVIPDFM)
2290 if (purpose == DVIPDFM)
2294 if (purpose == DVIPS || purpose == DVIPDFM)
2298 if (purpose == DVIPS || purpose == DVIPDFM)
2302 if (purpose == DVIPS || purpose == DVIPDFM)
2306 if (purpose == DVIPS || purpose == DVIPDFM)
2310 if (purpose == DVIPS || purpose == DVIPDFM)
2314 if (purpose == DVIPS || purpose == DVIPDFM)
2318 if (purpose == DVIPS || purpose == DVIPDFM)
2322 if (purpose == DVIPS || purpose == DVIPDFM)
2326 if (purpose == DVIPS || purpose == DVIPDFM)
2330 if (purpose == DVIPS || purpose == DVIPDFM)
2334 if (purpose == DVIPS || purpose == DVIPDFM)
2338 if (purpose == DVIPS || purpose == DVIPDFM)
2342 if (purpose == DVIPS || purpose == DVIPDFM)
2346 if (purpose == DVIPS || purpose == DVIPDFM)
2350 if (purpose == DVIPS || purpose == DVIPDFM)
2353 case PAPER_USEXECUTIVE:
2354 // dvipdfm does not know this
2355 if (purpose == DVIPDFM)
2360 case PAPER_USLETTER:
2362 if (purpose == XDVI)
2369 string const BufferParams::dvips_options() const
2374 && papersize == PAPER_CUSTOM
2375 && !lyxrc.print_paper_dimension_flag.empty()
2376 && !paperwidth.empty()
2377 && !paperheight.empty()) {
2378 // using a custom papersize
2379 result = lyxrc.print_paper_dimension_flag;
2380 result += ' ' + paperwidth;
2381 result += ',' + paperheight;
2383 string const paper_option = paperSizeName(DVIPS);
2384 if (!paper_option.empty() && (paper_option != "letter" ||
2385 orientation != ORIENTATION_LANDSCAPE)) {
2386 // dvips won't accept -t letter -t landscape.
2387 // In all other cases, include the paper size
2389 result = lyxrc.print_paper_flag;
2390 result += ' ' + paper_option;
2393 if (orientation == ORIENTATION_LANDSCAPE &&
2394 papersize != PAPER_CUSTOM)
2395 result += ' ' + lyxrc.print_landscape_flag;
2400 string const BufferParams::font_encoding() const
2402 return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2406 string BufferParams::babelCall(string const & lang_opts) const
2408 string lang_pack = lyxrc.language_package;
2409 if (lang_pack != "\\usepackage{babel}")
2411 // suppress the babel call when there is no babel language defined
2412 // for the document language in the lib/languages file and if no
2413 // other languages are used (lang_opts is then empty)
2414 if (lang_opts.empty())
2416 // If Vietnamese is used, babel must directly be loaded with the
2417 // language options, see
2418 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2419 size_t viet = lang_opts.find("vietnam");
2420 // viet = string::npos when not found
2421 // the same is for all other languages that are not directly supported by
2422 // babel, but where LaTeX-packages add babel support.
2423 // this is currently the case for Latvian, Lithuanian, Mongolian
2425 size_t latvian = lang_opts.find("latvian");
2426 size_t lithu = lang_opts.find("lithuanian");
2427 size_t mongo = lang_opts.find("mongolian");
2428 size_t turkmen = lang_opts.find("turkmen");
2429 // If Japanese is used, babel must directly be loaded with the
2430 // language options, see
2431 // http://www.lyx.org/trac/ticket/4597#c4
2432 size_t japan = lang_opts.find("japanese");
2433 if (!lyxrc.language_global_options || viet != string::npos
2434 || japan != string::npos || latvian != string::npos
2435 || lithu != string::npos || mongo != string::npos
2436 || turkmen != string::npos)
2437 return "\\usepackage[" + lang_opts + "]{babel}";
2442 docstring BufferParams::getGraphicsDriver(string const & package) const
2446 if (package == "geometry") {
2447 if (graphicsDriver == "dvips"
2448 || graphicsDriver == "dvipdfm"
2449 || graphicsDriver == "pdftex"
2450 || graphicsDriver == "vtex")
2451 result = from_ascii(graphicsDriver);
2452 else if (graphicsDriver == "dvipdfmx")
2453 result = from_ascii("dvipdfm");
2460 void BufferParams::writeEncodingPreamble(odocstream & os,
2461 LaTeXFeatures & features, TexRow & texrow) const
2465 if (inputenc == "auto") {
2466 string const doc_encoding =
2467 language->encoding()->latexName();
2468 Encoding::Package const package =
2469 language->encoding()->package();
2471 // Create a list with all the input encodings used
2473 set<string> encodings =
2474 features.getEncodingSet(doc_encoding);
2476 // If the "japanese" package (i.e. pLaTeX) is used,
2477 // inputenc must be omitted.
2478 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2479 if (package == Encoding::japanese)
2480 features.require("japanese");
2482 if ((!encodings.empty() || package == Encoding::inputenc)
2483 && !features.isRequired("japanese")) {
2484 os << "\\usepackage[";
2485 set<string>::const_iterator it = encodings.begin();
2486 set<string>::const_iterator const end = encodings.end();
2488 os << from_ascii(*it);
2491 for (; it != end; ++it)
2492 os << ',' << from_ascii(*it);
2493 if (package == Encoding::inputenc) {
2494 if (!encodings.empty())
2496 os << from_ascii(doc_encoding);
2498 os << "]{inputenc}\n";
2501 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2502 if (language->encoding()->name() == "utf8-cjk"
2503 && LaTeXFeatures::isAvailable("CJKutf8"))
2504 os << "\\usepackage{CJKutf8}\n";
2506 os << "\\usepackage{CJK}\n";
2509 } else if (inputenc != "default") {
2510 switch (encoding().package()) {
2511 case Encoding::none:
2512 case Encoding::japanese:
2514 case Encoding::inputenc:
2515 // do not load inputenc if japanese is used
2516 if (features.isRequired("japanese"))
2518 os << "\\usepackage[" << from_ascii(inputenc)
2523 if (encoding().name() == "utf8-cjk"
2524 && LaTeXFeatures::isAvailable("CJKutf8"))
2525 os << "\\usepackage{CJKutf8}\n";
2527 os << "\\usepackage{CJK}\n";
2533 // The encoding "armscii8" (for Armenian) is only available when
2534 // the package "armtex" is loaded.
2535 if (language->encoding()->latexName() == "armscii8"
2536 || inputenc == "armscii8") {
2537 os << "\\usepackage{armtex}\n";
2543 string const BufferParams::parseFontName(string const & name) const
2545 string mangled = name;
2546 size_t const idx = mangled.find('[');
2547 if (idx == string::npos || idx == 0)
2550 return mangled.substr(0, idx - 1);
2554 string const BufferParams::loadFonts(string const & rm,
2555 string const & sf, string const & tt,
2556 bool const & sc, bool const & osf,
2557 int const & sfscale, int const & ttscale,
2558 bool const & xetex) const
2560 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2561 several packages have been replaced by others, that might not
2562 be installed on every system. We have to take care for that
2563 (see psnfss.pdf). We try to support all psnfss fonts as well
2564 as the fonts that have become de facto standard in the LaTeX
2565 world (e.g. Latin Modern). We do not support obsolete fonts
2566 (like PSLatex). In general, it should be possible to mix any
2567 rm font with any sf or tt font, respectively. (JSpitzm)
2569 -- separate math fonts.
2572 if (rm == "default" && sf == "default" && tt == "default")
2579 if (rm != "default")
2580 os << "\\setmainfont[Mapping=tex-text]{"
2581 << parseFontName(rm) << "}\n";
2582 if (sf != "default") {
2583 string const sans = parseFontName(sf);
2585 os << "\\setsansfont[Scale="
2586 << float(sfscale) / 100
2587 << ",Mapping=tex-text]{"
2590 os << "\\setsansfont[Mapping=tex-text]{"
2593 if (tt != "default") {
2594 string const mono = parseFontName(tt);
2596 os << "\\setmonofont[Scale="
2597 << float(sfscale) / 100
2601 os << "\\setmonofont[Mapping=tex-text]{"
2605 os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2610 // Computer Modern (must be explicitly selectable -- there might be classes
2611 // that define a different default font!
2613 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2614 // osf for Computer Modern needs eco.sty
2616 os << "\\usepackage{eco}\n";
2618 // Latin Modern Roman
2619 else if (rm == "lmodern")
2620 os << "\\usepackage{lmodern}\n";
2622 else if (rm == "ae") {
2623 // not needed when using OT1 font encoding.
2624 if (font_encoding() != "default")
2625 os << "\\usepackage{ae,aecompl}\n";
2628 else if (rm == "times") {
2629 // try to load the best available package
2630 if (LaTeXFeatures::isAvailable("mathptmx"))
2631 os << "\\usepackage{mathptmx}\n";
2632 else if (LaTeXFeatures::isAvailable("mathptm"))
2633 os << "\\usepackage{mathptm}\n";
2635 os << "\\usepackage{times}\n";
2638 else if (rm == "palatino") {
2639 // try to load the best available package
2640 if (LaTeXFeatures::isAvailable("mathpazo")) {
2641 os << "\\usepackage";
2647 // "osf" includes "sc"!
2651 os << "{mathpazo}\n";
2653 else if (LaTeXFeatures::isAvailable("mathpple"))
2654 os << "\\usepackage{mathpple}\n";
2656 os << "\\usepackage{palatino}\n";
2659 else if (rm == "utopia") {
2660 // fourier supersedes utopia.sty, but does
2661 // not work with OT1 encoding.
2662 if (LaTeXFeatures::isAvailable("fourier")
2663 && font_encoding() != "default") {
2664 os << "\\usepackage";
2675 os << "{fourier}\n";
2678 os << "\\usepackage{utopia}\n";
2680 // Bera (complete fontset)
2681 else if (rm == "bera" && sf == "default" && tt == "default")
2682 os << "\\usepackage{bera}\n";
2684 else if (rm != "default")
2685 os << "\\usepackage" << "{" << rm << "}\n";
2688 // Helvetica, Bera Sans
2689 if (sf == "helvet" || sf == "berasans") {
2691 os << "\\usepackage[scaled=" << float(sfscale) / 100
2692 << "]{" << sf << "}\n";
2694 os << "\\usepackage{" << sf << "}\n";
2697 else if (sf == "avant")
2698 os << "\\usepackage{" << sf << "}\n";
2699 // Computer Modern, Latin Modern, CM Bright
2700 else if (sf != "default")
2701 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2703 // monospaced/typewriter
2704 // Courier, LuxiMono
2705 if (tt == "luximono" || tt == "beramono") {
2707 os << "\\usepackage[scaled=" << float(ttscale) / 100
2708 << "]{" << tt << "}\n";
2710 os << "\\usepackage{" << tt << "}\n";
2713 else if (tt == "courier" )
2714 os << "\\usepackage{" << tt << "}\n";
2715 // Computer Modern, Latin Modern, CM Bright
2716 else if (tt != "default")
2717 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2723 Encoding const & BufferParams::encoding() const
2726 return *(encodings.fromLaTeXName("utf8-plain"));
2727 if (inputenc == "auto" || inputenc == "default")
2728 return *language->encoding();
2729 Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2732 LYXERR0("Unknown inputenc value `" << inputenc
2733 << "'. Using `auto' instead.");
2734 return *language->encoding();
2738 CiteEngine BufferParams::citeEngine() const
2740 // FIXME the class should provide the numerical/
2741 // authoryear choice
2742 if (documentClass().provides("natbib")
2743 && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2744 return ENGINE_NATBIB_AUTHORYEAR;
2745 return cite_engine_;
2749 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2751 cite_engine_ = cite_engine;