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"
28 #include "LaTeXFeatures.h"
29 #include "ModuleList.h"
33 #include "OutputParams.h"
37 #include "PDFOptions.h"
39 #include "frontends/alert.h"
41 #include "insets/InsetListingsParams.h"
43 #include "support/convert.h"
44 #include "support/debug.h"
45 #include "support/docstream.h"
46 #include "support/FileName.h"
47 #include "support/filetools.h"
48 #include "support/gettext.h"
49 #include "support/Messages.h"
50 #include "support/Translator.h"
51 #include "support/lstrings.h"
57 using namespace lyx::support
;
60 static char const * const string_paragraph_separation
[] = {
65 static char const * const string_quotes_language
[] = {
66 "english", "swedish", "german", "polish", "french", "danish", ""
70 static char const * const string_papersize
[] = {
71 "default", "custom", "letterpaper", "legalpaper", "executivepaper",
72 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
76 static char const * const string_orientation
[] = {
77 "portrait", "landscape", ""
81 static char const * const string_footnotekinds
[] = {
82 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
86 static char const * const tex_graphics
[] = {
87 "default", "dvips", "dvitops", "emtex",
88 "ln", "oztex", "textures", "none", ""
97 // Paragraph separation
98 typedef Translator
<string
, BufferParams::ParagraphSeparation
> ParSepTranslator
;
101 ParSepTranslator
const init_parseptranslator()
103 ParSepTranslator translator
104 (string_paragraph_separation
[0], BufferParams::ParagraphIndentSeparation
);
105 translator
.addPair(string_paragraph_separation
[1], BufferParams::ParagraphSkipSeparation
);
110 ParSepTranslator
const & parseptranslator()
112 static ParSepTranslator translator
= init_parseptranslator();
118 typedef Translator
<string
, InsetQuotes::QuoteLanguage
> QuotesLangTranslator
;
121 QuotesLangTranslator
const init_quoteslangtranslator()
123 QuotesLangTranslator translator
124 (string_quotes_language
[0], InsetQuotes::EnglishQuotes
);
125 translator
.addPair(string_quotes_language
[1], InsetQuotes::SwedishQuotes
);
126 translator
.addPair(string_quotes_language
[2], InsetQuotes::GermanQuotes
);
127 translator
.addPair(string_quotes_language
[3], InsetQuotes::PolishQuotes
);
128 translator
.addPair(string_quotes_language
[4], InsetQuotes::FrenchQuotes
);
129 translator
.addPair(string_quotes_language
[5], InsetQuotes::DanishQuotes
);
134 QuotesLangTranslator
const & quoteslangtranslator()
136 static QuotesLangTranslator translator
= init_quoteslangtranslator();
142 typedef Translator
<string
, PAPER_SIZE
> PaperSizeTranslator
;
145 static PaperSizeTranslator
initPaperSizeTranslator()
147 PaperSizeTranslator
translator(string_papersize
[0], PAPER_DEFAULT
);
148 translator
.addPair(string_papersize
[1], PAPER_CUSTOM
);
149 translator
.addPair(string_papersize
[2], PAPER_USLETTER
);
150 translator
.addPair(string_papersize
[3], PAPER_USLEGAL
);
151 translator
.addPair(string_papersize
[4], PAPER_USEXECUTIVE
);
152 translator
.addPair(string_papersize
[5], PAPER_A3
);
153 translator
.addPair(string_papersize
[6], PAPER_A4
);
154 translator
.addPair(string_papersize
[7], PAPER_A5
);
155 translator
.addPair(string_papersize
[8], PAPER_B3
);
156 translator
.addPair(string_papersize
[9], PAPER_B4
);
157 translator
.addPair(string_papersize
[10], PAPER_B5
);
162 PaperSizeTranslator
const & papersizetranslator()
164 static PaperSizeTranslator translator
= initPaperSizeTranslator();
170 typedef Translator
<string
, PAPER_ORIENTATION
> PaperOrientationTranslator
;
173 PaperOrientationTranslator
const init_paperorientationtranslator()
175 PaperOrientationTranslator
translator(string_orientation
[0], ORIENTATION_PORTRAIT
);
176 translator
.addPair(string_orientation
[1], ORIENTATION_LANDSCAPE
);
181 PaperOrientationTranslator
const & paperorientationtranslator()
183 static PaperOrientationTranslator translator
= init_paperorientationtranslator();
189 typedef Translator
<int, PageSides
> SidesTranslator
;
192 SidesTranslator
const init_sidestranslator()
194 SidesTranslator
translator(1, OneSide
);
195 translator
.addPair(2, TwoSides
);
200 SidesTranslator
const & sidestranslator()
202 static SidesTranslator translator
= init_sidestranslator();
208 typedef Translator
<int, BufferParams::Package
> PackageTranslator
;
211 PackageTranslator
const init_packagetranslator()
213 PackageTranslator
translator(0, BufferParams::package_off
);
214 translator
.addPair(1, BufferParams::package_auto
);
215 translator
.addPair(2, BufferParams::package_on
);
220 PackageTranslator
const & packagetranslator()
222 static PackageTranslator translator
= init_packagetranslator();
228 typedef Translator
<string
, CiteEngine
> CiteEngineTranslator
;
231 CiteEngineTranslator
const init_citeenginetranslator()
233 CiteEngineTranslator
translator("basic", ENGINE_BASIC
);
234 translator
.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL
);
235 translator
.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR
);
236 translator
.addPair("jurabib", ENGINE_JURABIB
);
241 CiteEngineTranslator
const & citeenginetranslator()
243 static CiteEngineTranslator translator
= init_citeenginetranslator();
249 typedef Translator
<string
, Spacing::Space
> SpaceTranslator
;
252 SpaceTranslator
const init_spacetranslator()
254 SpaceTranslator
translator("default", Spacing::Default
);
255 translator
.addPair("single", Spacing::Single
);
256 translator
.addPair("onehalf", Spacing::Onehalf
);
257 translator
.addPair("double", Spacing::Double
);
258 translator
.addPair("other", Spacing::Other
);
263 SpaceTranslator
const & spacetranslator()
265 static SpaceTranslator translator
= init_spacetranslator();
273 class BufferParams::Impl
278 AuthorList authorlist
;
279 BranchList branchlist
;
280 Bullet temp_bullets
[4];
281 Bullet user_defined_bullets
[4];
283 /** This is the amount of space used for paragraph_separation "skip",
284 * and for detached paragraphs in "indented" documents.
287 PDFOptions pdfoptions
;
288 LayoutFileIndex baseClass_
;
292 BufferParams::Impl::Impl()
293 : defskip(VSpace::MEDSKIP
), baseClass_(string(""))
295 // set initial author
297 authorlist
.record(Author(from_utf8(lyxrc
.user_name
), from_utf8(lyxrc
.user_email
)));
302 BufferParams::MemoryTraits::clone(BufferParams::Impl
const * ptr
)
306 return new BufferParams::Impl(*ptr
);
310 void BufferParams::MemoryTraits::destroy(BufferParams::Impl
* ptr
)
316 BufferParams::BufferParams()
319 setBaseClass(defaultBaseclass());
321 paragraph_separation
= ParagraphIndentSeparation
;
322 quotes_language
= InsetQuotes::EnglishQuotes
;
323 fontsize
= "default";
326 papersize
= PAPER_DEFAULT
;
327 orientation
= ORIENTATION_PORTRAIT
;
328 use_geometry
= false;
329 use_amsmath
= package_auto
;
330 use_esint
= package_auto
;
331 cite_engine_
= ENGINE_BASIC
;
332 use_bibtopic
= false;
333 trackChanges
= false;
334 outputChanges
= false;
337 language
= default_language
;
338 fontsRoman
= "default";
339 fontsSans
= "default";
340 fontsTypewriter
= "default";
341 fontsDefaultFamily
= "default";
344 fontsSansScale
= 100;
345 fontsTypewriterScale
= 100;
347 graphicsDriver
= "default";
350 listings_params
= string();
351 pagestyle
= "default";
353 for (int iter
= 0; iter
< 4; ++iter
) {
354 user_defined_bullet(iter
) = ITEMIZE_DEFAULTS
[iter
];
355 temp_bullet(iter
) = ITEMIZE_DEFAULTS
[iter
];
360 docstring
BufferParams::B_(string
const & l10n
) const
362 LASSERT(language
, /**/);
363 return getMessages(language
->code()).get(l10n
);
367 AuthorList
& BufferParams::authors()
369 return pimpl_
->authorlist
;
373 AuthorList
const & BufferParams::authors() const
375 return pimpl_
->authorlist
;
379 BranchList
& BufferParams::branchlist()
381 return pimpl_
->branchlist
;
385 BranchList
const & BufferParams::branchlist() const
387 return pimpl_
->branchlist
;
391 Bullet
& BufferParams::temp_bullet(lyx::size_type
const index
)
393 LASSERT(index
< 4, /**/);
394 return pimpl_
->temp_bullets
[index
];
398 Bullet
const & BufferParams::temp_bullet(lyx::size_type
const index
) const
400 LASSERT(index
< 4, /**/);
401 return pimpl_
->temp_bullets
[index
];
405 Bullet
& BufferParams::user_defined_bullet(lyx::size_type
const index
)
407 LASSERT(index
< 4, /**/);
408 return pimpl_
->user_defined_bullets
[index
];
412 Bullet
const & BufferParams::user_defined_bullet(lyx::size_type
const index
) const
414 LASSERT(index
< 4, /**/);
415 return pimpl_
->user_defined_bullets
[index
];
419 Spacing
& BufferParams::spacing()
421 return pimpl_
->spacing
;
425 Spacing
const & BufferParams::spacing() const
427 return pimpl_
->spacing
;
431 PDFOptions
& BufferParams::pdfoptions()
433 return pimpl_
->pdfoptions
;
437 PDFOptions
const & BufferParams::pdfoptions() const
439 return pimpl_
->pdfoptions
;
443 VSpace
const & BufferParams::getDefSkip() const
445 return pimpl_
->defskip
;
449 void BufferParams::setDefSkip(VSpace
const & vs
)
451 pimpl_
->defskip
= vs
;
455 string
BufferParams::readToken(Lexer
& lex
, string
const & token
,
456 FileName
const & filepath
)
458 if (token
== "\\textclass") {
460 string
const classname
= lex
.getString();
461 // if there exists a local layout file, ignore the system one
462 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
464 LayoutFileList
& bcl
= LayoutFileList::get();
465 if (tcp
.empty() && !filepath
.empty())
466 tcp
= bcl
.addLocalLayout(classname
, filepath
.absFilename());
470 setBaseClass(classname
);
471 // We assume that a tex class exists for local or unknown layouts so this warning
472 // will only be given for system layouts.
473 if (!baseClass()->isTeXClassAvailable()) {
474 docstring
const msg
=
475 bformat(_("The layout file requested by this document,\n"
477 "is not usable. This is probably because a LaTeX\n"
478 "class or style file required by it is not\n"
479 "available. See the Customization documentation\n"
480 "for more information.\n"), from_utf8(classname
));
481 frontend::Alert::warning(_("Document class not available"),
482 msg
+ _("LyX will not be able to produce output."));
484 } else if (token
== "\\begin_preamble") {
486 } else if (token
== "\\begin_local_layout") {
487 readLocalLayout(lex
);
488 } else if (token
== "\\begin_modules") {
490 } else if (token
== "\\options") {
492 options
= lex
.getString();
493 } else if (token
== "\\master") {
495 master
= lex
.getString();
496 } else if (token
== "\\language") {
498 } else if (token
== "\\inputencoding") {
500 } else if (token
== "\\graphics") {
501 readGraphicsDriver(lex
);
502 } else if (token
== "\\font_roman") {
504 } else if (token
== "\\font_sans") {
506 } else if (token
== "\\font_typewriter") {
507 lex
>> fontsTypewriter
;
508 } else if (token
== "\\font_default_family") {
509 lex
>> fontsDefaultFamily
;
510 } else if (token
== "\\font_sc") {
512 } else if (token
== "\\font_osf") {
514 } else if (token
== "\\font_sf_scale") {
515 lex
>> fontsSansScale
;
516 } else if (token
== "\\font_tt_scale") {
517 lex
>> fontsTypewriterScale
;
518 } else if (token
== "\\font_cjk") {
520 } else if (token
== "\\paragraph_separation") {
523 paragraph_separation
= parseptranslator().find(parsep
);
524 } else if (token
== "\\defskip") {
526 string defskip
= lex
.getString();
527 if (defskip
== "defskip")
530 pimpl_
->defskip
= VSpace(defskip
);
531 } else if (token
== "\\quotes_language") {
534 quotes_language
= quoteslangtranslator().find(quotes_lang
);
535 } else if (token
== "\\papersize") {
538 papersize
= papersizetranslator().find(ppsize
);
539 } else if (token
== "\\use_geometry") {
541 } else if (token
== "\\use_amsmath") {
544 use_amsmath
= packagetranslator().find(use_ams
);
545 } else if (token
== "\\use_esint") {
548 use_esint
= packagetranslator().find(useesint
);
549 } else if (token
== "\\cite_engine") {
552 cite_engine_
= citeenginetranslator().find(engine
);
553 } else if (token
== "\\use_bibtopic") {
555 } else if (token
== "\\tracking_changes") {
557 } else if (token
== "\\output_changes") {
558 lex
>> outputChanges
;
559 } else if (token
== "\\branch") {
561 docstring branch
= lex
.getDocString();
562 branchlist().add(branch
);
565 string
const tok
= lex
.getString();
566 if (tok
== "\\end_branch")
568 Branch
* branch_ptr
= branchlist().find(branch
);
569 if (tok
== "\\selected") {
572 branch_ptr
->setSelected(lex
.getInteger());
574 // not yet operational
575 if (tok
== "\\color") {
577 string color
= lex
.getString();
579 branch_ptr
->setColor(color
);
580 // Update also the Color table:
582 color
= lcolor
.getX11Name(Color_background
);
584 lcolor
.setColor(to_utf8(branch
), color
);
588 } else if (token
== "\\author") {
590 istringstream
ss(lex
.getString());
593 author_map
.push_back(pimpl_
->authorlist
.record(a
));
594 } else if (token
== "\\paperorientation") {
597 orientation
= paperorientationtranslator().find(orient
);
598 } else if (token
== "\\paperwidth") {
600 } else if (token
== "\\paperheight") {
602 } else if (token
== "\\leftmargin") {
604 } else if (token
== "\\topmargin") {
606 } else if (token
== "\\rightmargin") {
608 } else if (token
== "\\bottommargin") {
610 } else if (token
== "\\headheight") {
612 } else if (token
== "\\headsep") {
614 } else if (token
== "\\footskip") {
616 } else if (token
== "\\columnsep") {
618 } else if (token
== "\\paperfontsize") {
620 } else if (token
== "\\papercolumns") {
622 } else if (token
== "\\listings_params") {
625 listings_params
= InsetListingsParams(par
).params();
626 } else if (token
== "\\papersides") {
629 sides
= sidestranslator().find(psides
);
630 } else if (token
== "\\paperpagestyle") {
632 } else if (token
== "\\bullet") {
634 } else if (token
== "\\bulletLaTeX") {
635 readBulletsLaTeX(lex
);
636 } else if (token
== "\\secnumdepth") {
638 } else if (token
== "\\tocdepth") {
640 } else if (token
== "\\spacing") {
644 if (nspacing
== "other") {
647 spacing().set(spacetranslator().find(nspacing
), tmp_val
);
648 } else if (token
== "\\float_placement") {
649 lex
>> float_placement
;
651 } else if (prefixIs(token
, "\\pdf_") || token
== "\\use_hyperref") {
652 string toktmp
= pdfoptions().readToken(lex
, token
);
653 if (!toktmp
.empty()) {
654 lyxerr
<< "PDFOptions::readToken(): Unknown token: " <<
659 lyxerr
<< "BufferParams::readToken(): Unknown token: " <<
668 void BufferParams::writeFile(ostream
& os
) const
670 // The top of the file is written by the buffer.
671 // Prints out the buffer info into the .lyx file given by file
674 os
<< "\\textclass " << baseClass()->name() << '\n';
677 if (!preamble
.empty()) {
678 // remove '\n' from the end of preamble
679 string
const tmppreamble
= rtrim(preamble
, "\n");
680 os
<< "\\begin_preamble\n"
682 << "\n\\end_preamble\n";
686 if (!options
.empty()) {
687 os
<< "\\options " << options
<< '\n';
690 // the master document
691 if (!master
.empty()) {
692 os
<< "\\master " << master
<< '\n';
696 if (!layoutModules_
.empty()) {
697 os
<< "\\begin_modules" << '\n';
698 LayoutModuleList::const_iterator it
= layoutModules_
.begin();
699 for (; it
!= layoutModules_
.end(); it
++)
701 os
<< "\\end_modules" << '\n';
704 // local layout information
705 if (!local_layout
.empty()) {
706 // remove '\n' from the end
707 string
const tmplocal
= rtrim(local_layout
, "\n");
708 os
<< "\\begin_local_layout\n"
710 << "\n\\end_local_layout\n";
713 // then the text parameters
714 if (language
!= ignore_language
)
715 os
<< "\\language " << language
->lang() << '\n';
716 os
<< "\\inputencoding " << inputenc
717 << "\n\\font_roman " << fontsRoman
718 << "\n\\font_sans " << fontsSans
719 << "\n\\font_typewriter " << fontsTypewriter
720 << "\n\\font_default_family " << fontsDefaultFamily
721 << "\n\\font_sc " << convert
<string
>(fontsSC
)
722 << "\n\\font_osf " << convert
<string
>(fontsOSF
)
723 << "\n\\font_sf_scale " << fontsSansScale
724 << "\n\\font_tt_scale " << fontsTypewriterScale
726 if (!fontsCJK
.empty()) {
727 os
<< "\\font_cjk " << fontsCJK
<< '\n';
729 os
<< "\n\\graphics " << graphicsDriver
<< '\n';
731 if (!float_placement
.empty()) {
732 os
<< "\\float_placement " << float_placement
<< '\n';
734 os
<< "\\paperfontsize " << fontsize
<< '\n';
736 spacing().writeFile(os
);
737 pdfoptions().writeFile(os
);
739 os
<< "\\papersize " << string_papersize
[papersize
]
740 << "\n\\use_geometry " << convert
<string
>(use_geometry
)
741 << "\n\\use_amsmath " << use_amsmath
742 << "\n\\use_esint " << use_esint
743 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_
)
744 << "\n\\use_bibtopic " << convert
<string
>(use_bibtopic
)
745 << "\n\\paperorientation " << string_orientation
[orientation
]
748 BranchList::const_iterator it
= branchlist().begin();
749 BranchList::const_iterator end
= branchlist().end();
750 for (; it
!= end
; ++it
) {
751 os
<< "\\branch " << to_utf8(it
->getBranch())
752 << "\n\\selected " << it
->getSelected()
753 << "\n\\color " << lyx::X11hexname(it
->getColor())
758 if (!paperwidth
.empty())
759 os
<< "\\paperwidth "
760 << VSpace(paperwidth
).asLyXCommand() << '\n';
761 if (!paperheight
.empty())
762 os
<< "\\paperheight "
763 << VSpace(paperheight
).asLyXCommand() << '\n';
764 if (!leftmargin
.empty())
765 os
<< "\\leftmargin "
766 << VSpace(leftmargin
).asLyXCommand() << '\n';
767 if (!topmargin
.empty())
769 << VSpace(topmargin
).asLyXCommand() << '\n';
770 if (!rightmargin
.empty())
771 os
<< "\\rightmargin "
772 << VSpace(rightmargin
).asLyXCommand() << '\n';
773 if (!bottommargin
.empty())
774 os
<< "\\bottommargin "
775 << VSpace(bottommargin
).asLyXCommand() << '\n';
776 if (!headheight
.empty())
777 os
<< "\\headheight "
778 << VSpace(headheight
).asLyXCommand() << '\n';
779 if (!headsep
.empty())
781 << VSpace(headsep
).asLyXCommand() << '\n';
782 if (!footskip
.empty())
784 << VSpace(footskip
).asLyXCommand() << '\n';
785 if (!columnsep
.empty())
787 << VSpace(columnsep
).asLyXCommand() << '\n';
788 os
<< "\\secnumdepth " << secnumdepth
789 << "\n\\tocdepth " << tocdepth
790 << "\n\\paragraph_separation "
791 << string_paragraph_separation
[paragraph_separation
]
792 << "\n\\defskip " << getDefSkip().asLyXCommand()
793 << "\n\\quotes_language "
794 << string_quotes_language
[quotes_language
]
795 << "\n\\papercolumns " << columns
796 << "\n\\papersides " << sides
797 << "\n\\paperpagestyle " << pagestyle
<< '\n';
798 if (!listings_params
.empty())
799 os
<< "\\listings_params \"" <<
800 InsetListingsParams(listings_params
).encodedString() << "\"\n";
801 for (int i
= 0; i
< 4; ++i
) {
802 if (user_defined_bullet(i
) != ITEMIZE_DEFAULTS
[i
]) {
803 if (user_defined_bullet(i
).getFont() != -1) {
804 os
<< "\\bullet " << i
<< " "
805 << user_defined_bullet(i
).getFont() << " "
806 << user_defined_bullet(i
).getCharacter() << " "
807 << user_defined_bullet(i
).getSize() << "\n";
811 os
<< "\\bulletLaTeX " << i
<< " \""
812 << lyx::to_ascii(user_defined_bullet(i
).getText())
818 os
<< "\\tracking_changes " << convert
<string
>(trackChanges
) << "\n";
819 os
<< "\\output_changes " << convert
<string
>(outputChanges
) << "\n";
821 AuthorList::Authors::const_iterator a_it
= pimpl_
->authorlist
.begin();
822 AuthorList::Authors::const_iterator a_end
= pimpl_
->authorlist
.end();
823 for (; a_it
!= a_end
; ++a_it
) {
824 if (a_it
->second
.used())
825 os
<< "\\author " << a_it
->second
<< "\n";
827 os
<< "\\author " << Author() << "\n";
832 void BufferParams::validate(LaTeXFeatures
& features
) const
834 features
.require(documentClass().requires());
837 bool dvipost
= LaTeXFeatures::isAvailable("dvipost");
838 bool xcolorsoul
= LaTeXFeatures::isAvailable("soul") &&
839 LaTeXFeatures::isAvailable("xcolor");
841 switch (features
.runparams().flavor
) {
842 case OutputParams::LATEX
:
844 features
.require("ct-dvipost");
845 features
.require("dvipost");
846 } else if (xcolorsoul
) {
847 features
.require("ct-xcolor-soul");
848 features
.require("soul");
849 features
.require("xcolor");
851 features
.require("ct-none");
854 case OutputParams::PDFLATEX
:
856 features
.require("ct-xcolor-soul");
857 features
.require("soul");
858 features
.require("xcolor");
859 // improves color handling in PDF output
860 features
.require("pdfcolmk");
862 features
.require("ct-none");
870 // Floats with 'Here definitely' as default setting.
871 if (float_placement
.find('H') != string::npos
)
872 features
.require("float");
874 // AMS Style is at document level
875 if (use_amsmath
== package_on
876 || documentClass().provides("amsmath"))
877 features
.require("amsmath");
878 if (use_esint
== package_on
)
879 features
.require("esint");
881 // Document-level line spacing
882 if (spacing().getSpace() != Spacing::Single
&& !spacing().isDefault())
883 features
.require("setspace");
885 // the bullet shapes are buffer level not paragraph level
886 // so they are tested here
887 for (int i
= 0; i
< 4; ++i
) {
888 if (user_defined_bullet(i
) == ITEMIZE_DEFAULTS
[i
])
890 int const font
= user_defined_bullet(i
).getFont();
892 int const c
= user_defined_bullet(i
).getCharacter();
898 features
.require("latexsym");
900 } else if (font
== 1) {
901 features
.require("amssymb");
902 } else if (font
>= 2 && font
<= 5) {
903 features
.require("pifont");
907 if (pdfoptions().use_hyperref
)
908 features
.require("hyperref");
910 if (language
->lang() == "vietnamese")
911 features
.require("vietnamese");
912 else if (language
->lang() == "japanese")
913 features
.require("japanese");
917 bool BufferParams::writeLaTeX(odocstream
& os
, LaTeXFeatures
& features
,
918 TexRow
& texrow
) const
920 os
<< "\\documentclass";
922 DocumentClass
const & tclass
= documentClass();
924 ostringstream clsoptions
; // the document class options.
926 if (tokenPos(tclass
.opt_fontsize(),
927 '|', fontsize
) >= 0) {
928 // only write if existing in list (and not default)
929 clsoptions
<< fontsize
<< "pt,";
932 // custom, A3, B3 and B4 paper sizes need geometry
933 bool nonstandard_papersize
= papersize
== PAPER_B3
934 || papersize
== PAPER_B4
935 || papersize
== PAPER_A3
936 || papersize
== PAPER_CUSTOM
;
941 clsoptions
<< "a4paper,";
944 clsoptions
<< "letterpaper,";
947 clsoptions
<< "a5paper,";
950 clsoptions
<< "b5paper,";
952 case PAPER_USEXECUTIVE
:
953 clsoptions
<< "executivepaper,";
956 clsoptions
<< "legalpaper,";
968 if (sides
!= tclass
.sides()) {
971 clsoptions
<< "oneside,";
974 clsoptions
<< "twoside,";
980 if (columns
!= tclass
.columns()) {
982 clsoptions
<< "twocolumn,";
984 clsoptions
<< "onecolumn,";
988 && orientation
== ORIENTATION_LANDSCAPE
)
989 clsoptions
<< "landscape,";
991 // language should be a parameter to \documentclass
992 if (language
->babel() == "hebrew"
993 && default_language
->babel() != "hebrew")
994 // This seems necessary
995 features
.useLanguage(default_language
);
997 ostringstream language_options
;
998 bool const use_babel
= features
.useBabel();
1000 language_options
<< features
.getLanguages();
1001 if (!language
->babel().empty()) {
1002 if (!language_options
.str().empty())
1003 language_options
<< ',';
1004 language_options
<< language
->babel();
1006 // if Vietnamese is used, babel must directly be loaded with the
1007 // language options, not in the class options, see
1008 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1009 size_t viet
= language_options
.str().find("vietnam");
1010 // viet = string::npos when not found
1011 // if Japanese is used, babel must directly be loaded with the
1012 // language options, not in the class options, see
1013 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1014 size_t japan
= language_options
.str().find("japanese");
1015 // japan = string::npos when not found
1016 if (lyxrc
.language_global_options
&& !language_options
.str().empty()
1017 && viet
== string::npos
&& japan
== string::npos
)
1018 clsoptions
<< language_options
.str() << ',';
1021 // the user-defined options
1022 if (!options
.empty()) {
1023 clsoptions
<< options
<< ',';
1026 string
strOptions(clsoptions
.str());
1027 if (!strOptions
.empty()) {
1028 strOptions
= rtrim(strOptions
, ",");
1030 os
<< '[' << from_utf8(strOptions
) << ']';
1033 os
<< '{' << from_ascii(tclass
.latexname()) << "}\n";
1035 // end of \documentclass defs
1037 // font selection must be done before loading fontenc.sty
1038 string
const fonts
=
1039 loadFonts(fontsRoman
, fontsSans
,
1040 fontsTypewriter
, fontsSC
, fontsOSF
,
1041 fontsSansScale
, fontsTypewriterScale
);
1042 if (!fonts
.empty()) {
1043 os
<< from_ascii(fonts
);
1046 if (fontsDefaultFamily
!= "default")
1047 os
<< "\\renewcommand{\\familydefault}{\\"
1048 << from_ascii(fontsDefaultFamily
) << "}\n";
1050 // set font encoding
1051 // this one is not per buffer
1052 // for arabic_arabi and farsi we also need to load the LAE and LFE encoding
1053 if (lyxrc
.fontenc
!= "default") {
1054 if (language
->lang() == "arabic_arabi" || language
->lang() == "farsi") {
1055 os
<< "\\usepackage[" << from_ascii(lyxrc
.fontenc
)
1056 << ",LFE,LAE]{fontenc}\n";
1059 os
<< "\\usepackage[" << from_ascii(lyxrc
.fontenc
)
1065 // handle inputenc etc.
1066 writeEncodingPreamble(os
, features
, texrow
);
1068 if (!listings_params
.empty()) {
1069 os
<< "\\usepackage{listings}\n";
1072 // do not test validity because listings_params is supposed to be valid
1073 string par
= InsetListingsParams(listings_params
).separatedParams(true);
1074 os
<< from_ascii(par
);
1075 // count the number of newlines
1076 for (size_t i
= 0; i
< par
.size(); ++i
)
1082 if (use_geometry
|| nonstandard_papersize
) {
1083 os
<< "\\usepackage{geometry}\n";
1085 os
<< "\\geometry{verbose";
1086 if (orientation
== ORIENTATION_LANDSCAPE
)
1088 switch (papersize
) {
1090 if (!paperwidth
.empty())
1091 os
<< ",paperwidth="
1092 << from_ascii(paperwidth
);
1093 if (!paperheight
.empty())
1094 os
<< ",paperheight="
1095 << from_ascii(paperheight
);
1097 case PAPER_USLETTER
:
1098 os
<< ",letterpaper";
1101 os
<< ",legalpaper";
1103 case PAPER_USEXECUTIVE
:
1104 os
<< ",executivepaper";
1125 // default papersize ie PAPER_DEFAULT
1126 switch (lyxrc
.default_papersize
) {
1127 case PAPER_DEFAULT
: // keep compiler happy
1128 case PAPER_USLETTER
:
1129 os
<< ",letterpaper";
1132 os
<< ",legalpaper";
1134 case PAPER_USEXECUTIVE
:
1135 os
<< ",executivepaper";
1155 if (!topmargin
.empty())
1156 os
<< ",tmargin=" << from_ascii(Length(topmargin
).asLatexString());
1157 if (!bottommargin
.empty())
1158 os
<< ",bmargin=" << from_ascii(Length(bottommargin
).asLatexString());
1159 if (!leftmargin
.empty())
1160 os
<< ",lmargin=" << from_ascii(Length(leftmargin
).asLatexString());
1161 if (!rightmargin
.empty())
1162 os
<< ",rmargin=" << from_ascii(Length(rightmargin
).asLatexString());
1163 if (!headheight
.empty())
1164 os
<< ",headheight=" << from_ascii(Length(headheight
).asLatexString());
1165 if (!headsep
.empty())
1166 os
<< ",headsep=" << from_ascii(Length(headsep
).asLatexString());
1167 if (!footskip
.empty())
1168 os
<< ",footskip=" << from_ascii(Length(footskip
).asLatexString());
1169 if (!columnsep
.empty())
1170 os
<< ",columnsep=" << from_ascii(Length(columnsep
).asLatexString());
1173 } else if (orientation
== ORIENTATION_LANDSCAPE
) {
1174 features
.require("papersize");
1177 if (tokenPos(tclass
.opt_pagestyle(),
1178 '|', pagestyle
) >= 0) {
1179 if (pagestyle
== "fancy") {
1180 os
<< "\\usepackage{fancyhdr}\n";
1183 os
<< "\\pagestyle{" << from_ascii(pagestyle
) << "}\n";
1187 // Only if class has a ToC hierarchy
1188 if (tclass
.hasTocLevels()) {
1189 if (secnumdepth
!= tclass
.secnumdepth()) {
1190 os
<< "\\setcounter{secnumdepth}{"
1195 if (tocdepth
!= tclass
.tocdepth()) {
1196 os
<< "\\setcounter{tocdepth}{"
1203 if (paragraph_separation
) {
1204 switch (getDefSkip().kind()) {
1205 case VSpace::SMALLSKIP
:
1206 os
<< "\\setlength{\\parskip}{\\smallskipamount}\n";
1208 case VSpace::MEDSKIP
:
1209 os
<< "\\setlength{\\parskip}{\\medskipamount}\n";
1211 case VSpace::BIGSKIP
:
1212 os
<< "\\setlength{\\parskip}{\\bigskipamount}\n";
1214 case VSpace::LENGTH
:
1215 os
<< "\\setlength{\\parskip}{"
1216 << from_utf8(getDefSkip().length().asLatexString())
1219 default: // should never happen // Then delete it.
1220 os
<< "\\setlength{\\parskip}{\\medskipamount}\n";
1225 os
<< "\\setlength{\\parindent}{0pt}\n";
1229 // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel here.
1231 && (features
.isRequired("jurabib")
1232 || features
.isRequired("hyperref")
1233 || features
.isRequired("vietnamese")
1234 || features
.isRequired("japanese") ) ) {
1236 os
<< from_utf8(babelCall(language_options
.str()))
1238 << from_utf8(features
.getBabelOptions());
1242 // Now insert the LyX specific LaTeX commands...
1244 // The optional packages;
1245 docstring
lyxpreamble(from_ascii(features
.getPackages()));
1248 lyxpreamble
+= from_utf8(spacing().writePreamble(tclass
.provides("SetSpace")));
1251 // * Hyperref manual: "Make sure it comes last of your loaded
1252 // packages, to give it a fighting chance of not being over-written,
1253 // since its job is to redefine many LATEX commands."
1254 // * Email from Heiko Oberdiek: "It is usually better to load babel
1255 // before hyperref. Then hyperref has a chance to detect babel.
1256 // * Has to be loaded before the "LyX specific LaTeX commands" to
1257 // avoid errors with algorithm floats.
1258 // use hyperref explicitely when it is required
1259 if (features
.isRequired("hyperref")) {
1260 odocstringstream oss
;
1261 pdfoptions().writeLaTeX(oss
, documentClass().provides("hyperref"));
1262 lyxpreamble
+= oss
.str();
1265 // Will be surrounded by \makeatletter and \makeatother when needed
1266 docstring atlyxpreamble
;
1268 // Some macros LyX will need
1269 docstring
tmppreamble(from_ascii(features
.getMacros()));
1271 if (!tmppreamble
.empty())
1272 atlyxpreamble
+= "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1273 "LyX specific LaTeX commands.\n"
1274 + tmppreamble
+ '\n';
1276 // the text class specific preamble
1277 tmppreamble
= features
.getTClassPreamble();
1278 if (!tmppreamble
.empty())
1279 atlyxpreamble
+= "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1280 "Textclass specific LaTeX commands.\n"
1281 + tmppreamble
+ '\n';
1283 /* the user-defined preamble */
1284 if (!preamble
.empty())
1286 atlyxpreamble
+= "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1287 "User specified LaTeX commands.\n"
1288 + from_utf8(preamble
) + '\n';
1290 // subfig loads internally the LaTeX package "caption". As
1291 // caption is a very popular package, users will load it in
1292 // the preamble. Therefore we must load subfig behind the
1293 // user-defined preamble and check if the caption package was
1294 // loaded or not. For the case that caption is loaded before
1295 // subfig, there is the subfig option "caption=false". This
1296 // option also works when a koma-script class is used and
1297 // koma's own caption commands are used instead of caption. We
1298 // use \PassOptionsToPackage here because the user could have
1299 // already loaded subfig in the preamble.
1300 if (features
.isRequired("subfig")) {
1301 atlyxpreamble
+= "\\@ifundefined{showcaptionsetup}{}{%\n"
1302 " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1303 "\\usepackage{subfig}\n";
1306 // Itemize bullet settings need to be last in case the user
1307 // defines their own bullets that use a package included
1308 // in the user-defined preamble -- ARRae
1309 // Actually it has to be done much later than that
1310 // since some packages like frenchb make modifications
1311 // at \begin{document} time -- JMarc
1312 docstring bullets_def
;
1313 for (int i
= 0; i
< 4; ++i
) {
1314 if (user_defined_bullet(i
) != ITEMIZE_DEFAULTS
[i
]) {
1315 if (bullets_def
.empty())
1316 bullets_def
+= "\\AtBeginDocument{\n";
1317 bullets_def
+= " \\def\\labelitemi";
1319 // `i' is one less than the item to modify
1326 bullets_def
+= "ii";
1332 bullets_def
+= '{' +
1333 user_defined_bullet(i
).getText()
1338 if (!bullets_def
.empty())
1339 atlyxpreamble
+= bullets_def
+ "}\n\n";
1341 if (atlyxpreamble
.find(from_ascii("@")) != docstring::npos
)
1342 lyxpreamble
+= "\n\\makeatletter\n"
1343 + atlyxpreamble
+ "\\makeatother\n\n";
1345 lyxpreamble
+= '\n' + atlyxpreamble
;
1347 // We try to load babel late, in case it interferes
1348 // with other packages.
1349 // Jurabib and Hyperref have to be called after babel, though.
1350 if (use_babel
&& !features
.isRequired("jurabib")
1351 && !features
.isRequired("hyperref")
1352 && !features
.isRequired("vietnamese")
1353 && !features
.isRequired("japanese")) {
1355 lyxpreamble
+= from_utf8(babelCall(language_options
.str())) + '\n';
1356 lyxpreamble
+= from_utf8(features
.getBabelOptions()) + '\n';
1360 int(count(lyxpreamble
.begin(), lyxpreamble
.end(), '\n'));
1361 for (int j
= 0; j
!= nlines
; ++j
) {
1370 void BufferParams::useClassDefaults()
1372 DocumentClass
const & tclass
= documentClass();
1374 sides
= tclass
.sides();
1375 columns
= tclass
.columns();
1376 pagestyle
= tclass
.pagestyle();
1377 options
= tclass
.options();
1378 // Only if class has a ToC hierarchy
1379 if (tclass
.hasTocLevels()) {
1380 secnumdepth
= tclass
.secnumdepth();
1381 tocdepth
= tclass
.tocdepth();
1386 bool BufferParams::hasClassDefaults() const
1388 DocumentClass
const & tclass
= documentClass();
1390 return sides
== tclass
.sides()
1391 && columns
== tclass
.columns()
1392 && pagestyle
== tclass
.pagestyle()
1393 && options
== tclass
.options()
1394 && secnumdepth
== tclass
.secnumdepth()
1395 && tocdepth
== tclass
.tocdepth();
1399 DocumentClass
const & BufferParams::documentClass() const
1405 DocumentClass
const * BufferParams::documentClassPtr() const {
1410 void BufferParams::setDocumentClass(DocumentClass
const * const tc
) {
1411 // evil, but this function is evil
1412 doc_class_
= const_cast<DocumentClass
*>(tc
);
1416 bool BufferParams::setBaseClass(string
const & classname
)
1418 LYXERR(Debug::TCLASS
, "setBaseClass: " << classname
);
1419 LayoutFileList
& bcl
= LayoutFileList::get();
1420 if (!bcl
.haveClass(classname
)) {
1422 bformat(_("The document class %1$s could not be found. "
1423 "A default textclass with default layouts will be used. "
1424 "LyX might not be able to produce output unless a correct "
1425 "textclass is selected from the document settings dialog."),
1426 from_utf8(classname
));
1427 frontend::Alert::error(_("Document class not found"), s
);
1428 bcl
.addEmptyClass(classname
);
1431 if (bcl
[classname
].load()) {
1432 pimpl_
->baseClass_
= classname
;
1437 bformat(_("The document class %1$s could not be loaded."),
1438 from_utf8(classname
));
1439 frontend::Alert::error(_("Could not load class"), s
);
1444 LayoutFile
const * BufferParams::baseClass() const
1446 if (LayoutFileList::get().haveClass(pimpl_
->baseClass_
))
1447 return &(LayoutFileList::get()[pimpl_
->baseClass_
]);
1453 LayoutFileIndex
const & BufferParams::baseClassID() const
1455 return pimpl_
->baseClass_
;
1459 void BufferParams::makeDocumentClass()
1464 doc_class_
= &(DocumentClassBundle::get().newClass(*baseClass()));
1466 //FIXME It might be worth loading the children's modules here,
1467 //just as we load their bibliographies and such, instead of just
1468 //doing a check in InsetInclude.
1469 LayoutModuleList::const_iterator it
= layoutModules_
.begin();
1470 for (; it
!= layoutModules_
.end(); it
++) {
1471 string
const modName
= *it
;
1472 LyXModule
* lm
= moduleList
[modName
];
1474 docstring
const msg
=
1475 bformat(_("The module %1$s has been requested by\n"
1476 "this document but has not been found in the list of\n"
1477 "available modules. If you recently installed it, you\n"
1478 "probably need to reconfigure LyX.\n"), from_utf8(modName
));
1479 frontend::Alert::warning(_("Module not available"),
1480 msg
+ _("Some layouts may not be available."));
1481 LYXERR0("BufferParams::makeDocumentClass(): Module " <<
1482 modName
<< " requested but not found in module list.");
1485 if (!lm
->isAvailable()) {
1486 docstring
const msg
=
1487 bformat(_("The module %1$s requires a package that is\n"
1488 "not available in your LaTeX installation. LaTeX output\n"
1489 "may not be possible.\n"), from_utf8(modName
));
1490 frontend::Alert::warning(_("Package not available"), msg
);
1492 FileName layout_file
= libFileSearch("layouts", lm
->getFilename());
1493 if (!doc_class_
->read(layout_file
, TextClass::MODULE
)) {
1494 docstring
const msg
=
1495 bformat(_("Error reading module %1$s\n"), from_utf8(modName
));
1496 frontend::Alert::warning(_("Read Error"), msg
);
1499 if (!local_layout
.empty()) {
1500 if (!doc_class_
->read(local_layout
, TextClass::MODULE
)) {
1501 docstring
const msg
= _("Error reading internal layout information");
1502 frontend::Alert::warning(_("Read Error"), msg
);
1508 vector
<string
> const & BufferParams::getModules() const
1510 return layoutModules_
;
1515 bool BufferParams::addLayoutModule(string
const & modName
)
1517 LayoutModuleList::const_iterator it
= layoutModules_
.begin();
1518 LayoutModuleList::const_iterator end
= layoutModules_
.end();
1519 for (; it
!= end
; it
++)
1522 layoutModules_
.push_back(modName
);
1527 void BufferParams::clearLayoutModules()
1529 layoutModules_
.clear();
1533 Font
const BufferParams::getFont() const
1535 FontInfo f
= documentClass().defaultfont();
1536 if (fontsDefaultFamily
== "rmdefault")
1537 f
.setFamily(ROMAN_FAMILY
);
1538 else if (fontsDefaultFamily
== "sfdefault")
1539 f
.setFamily(SANS_FAMILY
);
1540 else if (fontsDefaultFamily
== "ttdefault")
1541 f
.setFamily(TYPEWRITER_FAMILY
);
1542 return Font(f
, language
);
1546 void BufferParams::readPreamble(Lexer
& lex
)
1548 if (lex
.getString() != "\\begin_preamble")
1549 lyxerr
<< "Error (BufferParams::readPreamble):"
1550 "consistency check failed." << endl
;
1552 preamble
= lex
.getLongString("\\end_preamble");
1556 void BufferParams::readLocalLayout(Lexer
& lex
)
1558 if (lex
.getString() != "\\begin_local_layout")
1559 lyxerr
<< "Error (BufferParams::readLocalLayout):"
1560 "consistency check failed." << endl
;
1562 local_layout
= lex
.getLongString("\\end_local_layout");
1566 void BufferParams::readLanguage(Lexer
& lex
)
1568 if (!lex
.next()) return;
1570 string
const tmptok
= lex
.getString();
1572 // check if tmptok is part of tex_babel in tex-defs.h
1573 language
= languages
.getLanguage(tmptok
);
1575 // Language tmptok was not found
1576 language
= default_language
;
1577 lyxerr
<< "Warning: Setting language `"
1578 << tmptok
<< "' to `" << language
->lang()
1584 void BufferParams::readGraphicsDriver(Lexer
& lex
)
1589 string
const tmptok
= lex
.getString();
1590 // check if tmptok is part of tex_graphics in tex_defs.h
1593 string
const test
= tex_graphics
[n
++];
1595 if (test
== tmptok
) {
1596 graphicsDriver
= tmptok
;
1601 "Warning: graphics driver `$$Token' not recognized!\n"
1602 " Setting graphics driver to `default'.\n");
1603 graphicsDriver
= "default";
1610 void BufferParams::readBullets(Lexer
& lex
)
1615 int const index
= lex
.getInteger();
1617 int temp_int
= lex
.getInteger();
1618 user_defined_bullet(index
).setFont(temp_int
);
1619 temp_bullet(index
).setFont(temp_int
);
1621 user_defined_bullet(index
).setCharacter(temp_int
);
1622 temp_bullet(index
).setCharacter(temp_int
);
1624 user_defined_bullet(index
).setSize(temp_int
);
1625 temp_bullet(index
).setSize(temp_int
);
1629 void BufferParams::readBulletsLaTeX(Lexer
& lex
)
1631 // The bullet class should be able to read this.
1634 int const index
= lex
.getInteger();
1636 docstring
const temp_str
= lex
.getDocString();
1638 user_defined_bullet(index
).setText(temp_str
);
1639 temp_bullet(index
).setText(temp_str
);
1643 void BufferParams::readModules(Lexer
& lex
)
1645 if (!lex
.eatLine()) {
1646 lyxerr
<< "Error (BufferParams::readModules):"
1647 "Unexpected end of input." << endl
;
1651 string mod
= lex
.getString();
1652 if (mod
== "\\end_modules")
1654 addLayoutModule(mod
);
1660 string
BufferParams::paperSizeName(PapersizePurpose purpose
) const
1662 char real_papersize
= papersize
;
1663 if (real_papersize
== PAPER_DEFAULT
)
1664 real_papersize
= lyxrc
.default_papersize
;
1666 switch (real_papersize
) {
1668 // could be anything, so don't guess
1670 case PAPER_CUSTOM
: {
1671 if (purpose
== XDVI
&& !paperwidth
.empty() &&
1672 !paperheight
.empty()) {
1673 // heightxwidth<unit>
1674 string first
= paperwidth
;
1675 string second
= paperheight
;
1676 if (orientation
== ORIENTATION_LANDSCAPE
)
1679 return first
.erase(first
.length() - 2)
1691 // dvips and dvipdfm do not know this
1692 if (purpose
== DVIPS
|| purpose
== DVIPDFM
)
1696 // dvipdfm does not know this
1697 if (purpose
== DVIPDFM
)
1701 // dvipdfm does not know this
1702 if (purpose
== DVIPDFM
)
1705 case PAPER_USEXECUTIVE
:
1706 // dvipdfm does not know this
1707 if (purpose
== DVIPDFM
)
1712 case PAPER_USLETTER
:
1714 if (purpose
== XDVI
)
1721 string
const BufferParams::dvips_options() const
1726 && papersize
== PAPER_CUSTOM
1727 && !lyxrc
.print_paper_dimension_flag
.empty()
1728 && !paperwidth
.empty()
1729 && !paperheight
.empty()) {
1730 // using a custom papersize
1731 result
= lyxrc
.print_paper_dimension_flag
;
1732 result
+= ' ' + paperwidth
;
1733 result
+= ',' + paperheight
;
1735 string
const paper_option
= paperSizeName(DVIPS
);
1736 if (!paper_option
.empty() && (paper_option
!= "letter" ||
1737 orientation
!= ORIENTATION_LANDSCAPE
)) {
1738 // dvips won't accept -t letter -t landscape.
1739 // In all other cases, include the paper size
1741 result
= lyxrc
.print_paper_flag
;
1742 result
+= ' ' + paper_option
;
1745 if (orientation
== ORIENTATION_LANDSCAPE
&&
1746 papersize
!= PAPER_CUSTOM
)
1747 result
+= ' ' + lyxrc
.print_landscape_flag
;
1752 string
BufferParams::babelCall(string
const & lang_opts
) const
1754 string lang_pack
= lyxrc
.language_package
;
1755 if (lang_pack
!= "\\usepackage{babel}")
1757 // suppress the babel call when there is no babel language defined
1758 // for the document language in the lib/languages file and if no
1759 // other languages are used (lang_opts is then empty)
1760 if (lang_opts
.empty())
1762 // If Vietnamese is used, babel must directly be loaded with the
1763 // language options, see
1764 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1765 size_t viet
= lang_opts
.find("vietnam");
1766 // viet = string::npos when not found
1767 // If Japanese is used, babel must directly be loaded with the
1768 // language options, see
1769 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1770 size_t japan
= lang_opts
.find("japanese");
1771 // japan = string::npos when not found
1772 if (!lyxrc
.language_global_options
|| viet
!= string::npos
|| japan
!= string::npos
)
1773 return "\\usepackage[" + lang_opts
+ "]{babel}";
1778 void BufferParams::writeEncodingPreamble(odocstream
& os
,
1779 LaTeXFeatures
& features
, TexRow
& texrow
) const
1781 if (inputenc
== "auto") {
1782 string
const doc_encoding
=
1783 language
->encoding()->latexName();
1784 Encoding::Package
const package
=
1785 language
->encoding()->package();
1787 // Create a list with all the input encodings used
1789 set
<string
> encodings
=
1790 features
.getEncodingSet(doc_encoding
);
1792 // If the encodings EUC-JP-plain, JIS-plain, or SJIS-plain are used, the
1793 // package inputenc must be omitted. Therefore set the encoding to empty.
1794 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
1795 if (doc_encoding
== "EUC-JP-plain" || doc_encoding
== "JIS-plain" ||
1796 doc_encoding
== "SJIS-plain")
1799 if (!encodings
.empty() || package
== Encoding::inputenc
) {
1800 os
<< "\\usepackage[";
1801 set
<string
>::const_iterator it
= encodings
.begin();
1802 set
<string
>::const_iterator
const end
= encodings
.end();
1804 os
<< from_ascii(*it
);
1807 for (; it
!= end
; ++it
)
1808 os
<< ',' << from_ascii(*it
);
1809 if (package
== Encoding::inputenc
) {
1810 if (!encodings
.empty())
1812 os
<< from_ascii(doc_encoding
);
1814 os
<< "]{inputenc}\n";
1817 if (package
== Encoding::CJK
|| features
.mustProvide("CJK")) {
1818 os
<< "\\usepackage{CJK}\n";
1821 } else if (inputenc
!= "default") {
1822 switch (encoding().package()) {
1823 case Encoding::none
:
1825 case Encoding::inputenc
:
1826 os
<< "\\usepackage[" << from_ascii(inputenc
)
1831 os
<< "\\usepackage{CJK}\n";
1837 // The encoding "armscii8" is only available when the package "armtex" is loaded.
1838 // armscii8 is used for Armenian.
1839 if (language
->encoding()->latexName() == "armscii8" || inputenc
== "armscii8") {
1840 os
<< "\\usepackage{armtex}\n";
1846 string
const BufferParams::loadFonts(string
const & rm
,
1847 string
const & sf
, string
const & tt
,
1848 bool const & sc
, bool const & osf
,
1849 int const & sfscale
, int const & ttscale
) const
1851 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1852 several packages have been replaced by others, that might not
1853 be installed on every system. We have to take care for that
1854 (see psnfss.pdf). We try to support all psnfss fonts as well
1855 as the fonts that have become de facto standard in the LaTeX
1856 world (e.g. Latin Modern). We do not support obsolete fonts
1857 (like PSLatex). In general, it should be possible to mix any
1858 rm font with any sf or tt font, respectively. (JSpitzm)
1860 -- separate math fonts.
1863 if (rm
== "default" && sf
== "default" && tt
== "default")
1870 // Computer Modern (must be explicitely selectable -- there might be classes
1871 // that define a different default font!
1873 os
<< "\\renewcommand{\\rmdefault}{cmr}\n";
1874 // osf for Computer Modern needs eco.sty
1876 os
<< "\\usepackage{eco}\n";
1878 // Latin Modern Roman
1879 else if (rm
== "lmodern")
1880 os
<< "\\usepackage{lmodern}\n";
1882 else if (rm
== "ae") {
1883 // not needed when using OT1 font encoding.
1884 if (lyxrc
.fontenc
!= "default")
1885 os
<< "\\usepackage{ae,aecompl}\n";
1888 else if (rm
== "times") {
1889 // try to load the best available package
1890 if (LaTeXFeatures::isAvailable("mathptmx"))
1891 os
<< "\\usepackage{mathptmx}\n";
1892 else if (LaTeXFeatures::isAvailable("mathptm"))
1893 os
<< "\\usepackage{mathptm}\n";
1895 os
<< "\\usepackage{times}\n";
1898 else if (rm
== "palatino") {
1899 // try to load the best available package
1900 if (LaTeXFeatures::isAvailable("mathpazo")) {
1901 os
<< "\\usepackage";
1907 // "osf" includes "sc"!
1911 os
<< "{mathpazo}\n";
1913 else if (LaTeXFeatures::isAvailable("mathpple"))
1914 os
<< "\\usepackage{mathpple}\n";
1916 os
<< "\\usepackage{palatino}\n";
1919 else if (rm
== "utopia") {
1920 // fourier supersedes utopia.sty, but does
1921 // not work with OT1 encoding.
1922 if (LaTeXFeatures::isAvailable("fourier")
1923 && lyxrc
.fontenc
!= "default") {
1924 os
<< "\\usepackage";
1935 os
<< "{fourier}\n";
1938 os
<< "\\usepackage{utopia}\n";
1940 // Bera (complete fontset)
1941 else if (rm
== "bera" && sf
== "default" && tt
== "default")
1942 os
<< "\\usepackage{bera}\n";
1944 else if (rm
!= "default")
1945 os
<< "\\usepackage" << "{" << rm
<< "}\n";
1948 // Helvetica, Bera Sans
1949 if (sf
== "helvet" || sf
== "berasans") {
1951 os
<< "\\usepackage[scaled=" << float(sfscale
) / 100
1952 << "]{" << sf
<< "}\n";
1954 os
<< "\\usepackage{" << sf
<< "}\n";
1957 else if (sf
== "avant")
1958 os
<< "\\usepackage{" << sf
<< "}\n";
1959 // Computer Modern, Latin Modern, CM Bright
1960 else if (sf
!= "default")
1961 os
<< "\\renewcommand{\\sfdefault}{" << sf
<< "}\n";
1963 // monospaced/typewriter
1964 // Courier, LuxiMono
1965 if (tt
== "luximono" || tt
== "beramono") {
1967 os
<< "\\usepackage[scaled=" << float(ttscale
) / 100
1968 << "]{" << tt
<< "}\n";
1970 os
<< "\\usepackage{" << tt
<< "}\n";
1973 else if (tt
== "courier" )
1974 os
<< "\\usepackage{" << tt
<< "}\n";
1975 // Computer Modern, Latin Modern, CM Bright
1976 else if (tt
!= "default")
1977 os
<< "\\renewcommand{\\ttdefault}{" << tt
<< "}\n";
1983 Encoding
const & BufferParams::encoding() const
1985 if (inputenc
== "auto" || inputenc
== "default")
1986 return *language
->encoding();
1987 Encoding
const * const enc
= encodings
.fromLaTeXName(inputenc
);
1990 LYXERR0("Unknown inputenc value `" << inputenc
1991 << "'. Using `auto' instead.");
1992 return *language
->encoding();
1996 CiteEngine
BufferParams::citeEngine() const
1998 // FIXME the class should provide the numerical/
1999 // authoryear choice
2000 if (documentClass().provides("natbib")
2001 && cite_engine_
!= ENGINE_NATBIB_NUMERICAL
)
2002 return ENGINE_NATBIB_AUTHORYEAR
;
2003 return cite_engine_
;
2007 void BufferParams::setCiteEngine(CiteEngine cite_engine
)
2009 cite_engine_
= cite_engine
;