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 "BranchList.h"
27 #include "LaTeXFeatures.h"
33 #include "TextClassList.h"
34 #include "OutputParams.h"
39 #include "frontends/alert.h"
40 #include "insets/InsetListingsParams.h"
42 #include "support/lyxalgo.h" // for lyx::count
43 #include "support/convert.h"
44 #include "support/Translator.h"
46 #include <boost/array.hpp>
52 using std::istringstream
;
54 using std::ostringstream
;
57 using lyx::support::bformat
;
58 using lyx::support::rtrim
;
59 using lyx::support::tokenPos
;
62 static char const * const string_paragraph_separation
[] = {
67 static char const * const string_quotes_language
[] = {
68 "english", "swedish", "german", "polish", "french", "danish", ""
72 static char const * const string_papersize
[] = {
73 "default", "custom", "letterpaper", "executivepaper", "legalpaper",
74 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
78 static char const * const string_orientation
[] = {
79 "portrait", "landscape", ""
83 static char const * const string_footnotekinds
[] = {
84 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
88 static char const * const tex_graphics
[] = {
89 "default", "dvips", "dvitops", "emtex",
90 "ln", "oztex", "textures", "none", ""
99 // Paragraph separation
100 typedef Translator
<string
, BufferParams::PARSEP
> ParSepTranslator
;
103 ParSepTranslator
const init_parseptranslator()
105 ParSepTranslator
translator(string_paragraph_separation
[0], BufferParams::PARSEP_INDENT
);
106 translator
.addPair(string_paragraph_separation
[1], BufferParams::PARSEP_SKIP
);
111 ParSepTranslator
const & parseptranslator()
113 static ParSepTranslator translator
= init_parseptranslator();
119 typedef Translator
<string
, InsetQuotes::quote_language
> QuotesLangTranslator
;
122 QuotesLangTranslator
const init_quoteslangtranslator()
124 QuotesLangTranslator
translator(string_quotes_language
[0], InsetQuotes::EnglishQ
);
125 translator
.addPair(string_quotes_language
[1], InsetQuotes::SwedishQ
);
126 translator
.addPair(string_quotes_language
[2], InsetQuotes::GermanQ
);
127 translator
.addPair(string_quotes_language
[3], InsetQuotes::PolishQ
);
128 translator
.addPair(string_quotes_language
[4], InsetQuotes::FrenchQ
);
129 translator
.addPair(string_quotes_language
[5], InsetQuotes::DanishQ
);
134 QuotesLangTranslator
const & quoteslangtranslator()
136 static QuotesLangTranslator translator
= init_quoteslangtranslator();
142 typedef Translator
<std::string
, PAPER_SIZE
> PaperSizeTranslator
;
145 PaperSizeTranslator
const init_papersizetranslator()
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
= init_papersizetranslator();
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, TextClass::PageSides
> SidesTranslator
;
192 SidesTranslator
const init_sidestranslator()
194 SidesTranslator
translator(1, TextClass::OneSide
);
195 translator
.addPair(2, TextClass::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
, biblio::CiteEngine
> CiteEngineTranslator
;
231 CiteEngineTranslator
const init_citeenginetranslator()
233 CiteEngineTranslator
translator("basic", biblio::ENGINE_BASIC
);
234 translator
.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL
);
235 translator
.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR
);
236 translator
.addPair("jurabib", biblio::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();
270 textclass_type
defaultTextclass()
272 // Initialize textclass to point to article. if `first' is
273 // true in the returned pair, then `second' is the textclass
274 // number; if it is false, second is 0. In both cases, second
276 return textclasslist
.numberOfClass("article").second
;
282 class BufferParams::Impl
287 AuthorList authorlist
;
288 BranchList branchlist
;
289 boost::array
<Bullet
, 4> temp_bullets
;
290 boost::array
<Bullet
, 4> user_defined_bullets
;
292 /** This is the amount of space used for paragraph_separation "skip",
293 * and for detached paragraphs in "indented" documents.
299 BufferParams::Impl::Impl()
300 : defskip(VSpace::MEDSKIP
)
302 // set initial author
304 authorlist
.record(Author(from_utf8(lyxrc
.user_name
), from_utf8(lyxrc
.user_email
)));
309 BufferParams::MemoryTraits::clone(BufferParams::Impl
const * ptr
)
313 return new BufferParams::Impl(*ptr
);
317 void BufferParams::MemoryTraits::destroy(BufferParams::Impl
* ptr
)
323 BufferParams::BufferParams()
324 : textclass(defaultTextclass()), pimpl_(new Impl
)
326 paragraph_separation
= PARSEP_INDENT
;
327 quotes_language
= InsetQuotes::EnglishQ
;
328 fontsize
= "default";
331 papersize
= PAPER_DEFAULT
;
332 orientation
= ORIENTATION_PORTRAIT
;
333 use_geometry
= false;
334 use_amsmath
= package_auto
;
335 use_esint
= package_auto
;
336 cite_engine_
= biblio::ENGINE_BASIC
;
337 use_bibtopic
= false;
338 trackChanges
= false;
339 outputChanges
= false;
342 language
= default_language
;
343 fontsRoman
= "default";
344 fontsSans
= "default";
345 fontsTypewriter
= "default";
346 fontsDefaultFamily
= "default";
349 fontsSansScale
= 100;
350 fontsTypewriterScale
= 100;
352 graphicsDriver
= "default";
353 sides
= TextClass::OneSide
;
355 listings_params
= string();
356 pagestyle
= "default";
358 for (int iter
= 0; iter
< 4; ++iter
) {
359 user_defined_bullet(iter
) = ITEMIZE_DEFAULTS
[iter
];
360 temp_bullet(iter
) = ITEMIZE_DEFAULTS
[iter
];
365 BufferParams::~BufferParams()
369 docstring
const BufferParams::B_(string
const & l10n
) const
371 BOOST_ASSERT(language
);
372 return getMessages(language
->code()).get(l10n
);
376 AuthorList
& BufferParams::authors()
378 return pimpl_
->authorlist
;
382 AuthorList
const & BufferParams::authors() const
384 return pimpl_
->authorlist
;
388 BranchList
& BufferParams::branchlist()
390 return pimpl_
->branchlist
;
394 BranchList
const & BufferParams::branchlist() const
396 return pimpl_
->branchlist
;
400 Bullet
& BufferParams::temp_bullet(lyx::size_type
const index
)
402 BOOST_ASSERT(index
< 4);
403 return pimpl_
->temp_bullets
[index
];
407 Bullet
const & BufferParams::temp_bullet(lyx::size_type
const index
) const
409 BOOST_ASSERT(index
< 4);
410 return pimpl_
->temp_bullets
[index
];
414 Bullet
& BufferParams::user_defined_bullet(lyx::size_type
const index
)
416 BOOST_ASSERT(index
< 4);
417 return pimpl_
->user_defined_bullets
[index
];
421 Bullet
const & BufferParams::user_defined_bullet(lyx::size_type
const index
) const
423 BOOST_ASSERT(index
< 4);
424 return pimpl_
->user_defined_bullets
[index
];
428 Spacing
& BufferParams::spacing()
430 return pimpl_
->spacing
;
434 Spacing
const & BufferParams::spacing() const
436 return pimpl_
->spacing
;
440 VSpace
const & BufferParams::getDefSkip() const
442 return pimpl_
->defskip
;
446 void BufferParams::setDefSkip(VSpace
const & vs
)
448 pimpl_
->defskip
= vs
;
452 string
const BufferParams::readToken(Lexer
& lex
, string
const & token
)
454 if (token
== "\\textclass") {
456 string
const classname
= lex
.getString();
457 pair
<bool, lyx::textclass_type
> pp
=
458 textclasslist
.numberOfClass(classname
);
460 textclass
= pp
.second
;
462 // if text class does not exist, try to load it from filepath
463 pp
= textclasslist
.addTextClass(classname
, filepath
);
465 textclass
= pp
.second
;
467 textclass
= defaultTextclass();
471 // FIXME: isTeXClassAvailable will try to load the layout file, but will
472 // fail because of the lack of path info. Warnings will be given although
473 // the layout file will be correctly loaded later.
474 if (!getTextClass().isTeXClassAvailable()) {
475 docstring
const msg
=
476 bformat(_("The layout file requested by this document,\n"
478 "is not usable. This is probably because a LaTeX\n"
479 "class or style file required by it is not\n"
480 "available. See the Customization documentation\n"
481 "for more information.\n"), from_utf8(classname
));
482 frontend::Alert::warning(_("Document class not available"),
483 msg
+ _("LyX will not be able to produce output."));
485 } else if (token
== "\\begin_preamble") {
487 } else if (token
== "\\options") {
489 options
= lex
.getString();
490 } else if (token
== "\\language") {
492 } else if (token
== "\\inputencoding") {
494 } else if (token
== "\\graphics") {
495 readGraphicsDriver(lex
);
496 } else if (token
== "\\font_roman") {
498 } else if (token
== "\\font_sans") {
500 } else if (token
== "\\font_typewriter") {
501 lex
>> fontsTypewriter
;
502 } else if (token
== "\\font_default_family") {
503 lex
>> fontsDefaultFamily
;
504 } else if (token
== "\\font_sc") {
506 } else if (token
== "\\font_osf") {
508 } else if (token
== "\\font_sf_scale") {
509 lex
>> fontsSansScale
;
510 } else if (token
== "\\font_tt_scale") {
511 lex
>> fontsTypewriterScale
;
512 } else if (token
== "\\paragraph_separation") {
515 paragraph_separation
= parseptranslator().find(parsep
);
516 } else if (token
== "\\defskip") {
518 pimpl_
->defskip
= VSpace(lex
.getString());
519 } else if (token
== "\\quotes_language") {
522 quotes_language
= quoteslangtranslator().find(quotes_lang
);
523 } else if (token
== "\\papersize") {
526 papersize
= papersizetranslator().find(ppsize
);
527 } else if (token
== "\\use_geometry") {
529 } else if (token
== "\\use_amsmath") {
532 use_amsmath
= packagetranslator().find(use_ams
);
533 } else if (token
== "\\use_esint") {
536 use_esint
= packagetranslator().find(useesint
);
537 } else if (token
== "\\cite_engine") {
540 cite_engine_
= citeenginetranslator().find(engine
);
541 } else if (token
== "\\use_bibtopic") {
543 } else if (token
== "\\tracking_changes") {
545 } else if (token
== "\\output_changes") {
546 lex
>> outputChanges
;
547 } else if (token
== "\\branch") {
549 docstring branch
= lex
.getDocString();
550 branchlist().add(branch
);
553 string
const tok
= lex
.getString();
554 if (tok
== "\\end_branch")
556 Branch
* branch_ptr
= branchlist().find(branch
);
557 if (tok
== "\\selected") {
560 branch_ptr
->setSelected(lex
.getInteger());
562 // not yet operational
563 if (tok
== "\\color") {
565 string color
= lex
.getString();
567 branch_ptr
->setColor(color
);
568 // Update also the Color table:
570 color
= lcolor
.getX11Name(Color::background
);
572 lcolor
.setColor(to_utf8(branch
), color
);
576 } else if (token
== "\\author") {
578 istringstream
ss(lex
.getString());
581 author_map
.push_back(pimpl_
->authorlist
.record(a
));
582 } else if (token
== "\\paperorientation") {
585 orientation
= paperorientationtranslator().find(orient
);
586 } else if (token
== "\\paperwidth") {
588 } else if (token
== "\\paperheight") {
590 } else if (token
== "\\leftmargin") {
592 } else if (token
== "\\topmargin") {
594 } else if (token
== "\\rightmargin") {
596 } else if (token
== "\\bottommargin") {
598 } else if (token
== "\\headheight") {
600 } else if (token
== "\\headsep") {
602 } else if (token
== "\\footskip") {
604 } else if (token
== "\\paperfontsize") {
606 } else if (token
== "\\papercolumns") {
608 } else if (token
== "\\listings_params") {
611 listings_params
= InsetListingsParams(par
).params();
612 } else if (token
== "\\papersides") {
615 sides
= sidestranslator().find(psides
);
616 } else if (token
== "\\paperpagestyle") {
618 } else if (token
== "\\bullet") {
620 } else if (token
== "\\bulletLaTeX") {
621 readBulletsLaTeX(lex
);
622 } else if (token
== "\\secnumdepth") {
624 } else if (token
== "\\tocdepth") {
626 } else if (token
== "\\spacing") {
630 if (nspacing
== "other") {
633 spacing().set(spacetranslator().find(nspacing
), tmp_val
);
634 } else if (token
== "\\float_placement") {
635 lex
>> float_placement
;
644 void BufferParams::writeFile(ostream
& os
) const
646 // The top of the file is written by the buffer.
647 // Prints out the buffer info into the .lyx file given by file
650 os
<< "\\textclass " << textclasslist
[textclass
].name() << '\n';
653 if (!preamble
.empty()) {
654 // remove '\n' from the end of preamble
655 string
const tmppreamble
= rtrim(preamble
, "\n");
656 os
<< "\\begin_preamble\n"
658 << "\n\\end_preamble\n";
662 if (!options
.empty()) {
663 os
<< "\\options " << options
<< '\n';
666 // then the text parameters
667 if (language
!= ignore_language
)
668 os
<< "\\language " << language
->lang() << '\n';
669 os
<< "\\inputencoding " << inputenc
670 << "\n\\font_roman " << fontsRoman
671 << "\n\\font_sans " << fontsSans
672 << "\n\\font_typewriter " << fontsTypewriter
673 << "\n\\font_default_family " << fontsDefaultFamily
674 << "\n\\font_sc " << convert
<string
>(fontsSC
)
675 << "\n\\font_osf " << convert
<string
>(fontsOSF
)
676 << "\n\\font_sf_scale " << fontsSansScale
677 << "\n\\font_tt_scale " << fontsTypewriterScale
678 << "\n\\graphics " << graphicsDriver
<< '\n';
680 if (!float_placement
.empty()) {
681 os
<< "\\float_placement " << float_placement
<< '\n';
683 os
<< "\\paperfontsize " << fontsize
<< '\n';
685 spacing().writeFile(os
);
687 os
<< "\\papersize " << string_papersize
[papersize
]
688 << "\n\\use_geometry " << convert
<string
>(use_geometry
)
689 << "\n\\use_amsmath " << use_amsmath
690 << "\n\\use_esint " << use_esint
691 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_
)
692 << "\n\\use_bibtopic " << convert
<string
>(use_bibtopic
)
693 << "\n\\paperorientation " << string_orientation
[orientation
]
696 BranchList::const_iterator it
= branchlist().begin();
697 BranchList::const_iterator end
= branchlist().end();
698 for (; it
!= end
; ++it
) {
699 os
<< "\\branch " << to_utf8(it
->getBranch())
700 << "\n\\selected " << it
->getSelected()
701 << "\n\\color " << lyx::X11hexname(it
->getColor())
706 if (!paperwidth
.empty())
707 os
<< "\\paperwidth "
708 << VSpace(paperwidth
).asLyXCommand() << '\n';
709 if (!paperheight
.empty())
710 os
<< "\\paperheight "
711 << VSpace(paperheight
).asLyXCommand() << '\n';
712 if (!leftmargin
.empty())
713 os
<< "\\leftmargin "
714 << VSpace(leftmargin
).asLyXCommand() << '\n';
715 if (!topmargin
.empty())
717 << VSpace(topmargin
).asLyXCommand() << '\n';
718 if (!rightmargin
.empty())
719 os
<< "\\rightmargin "
720 << VSpace(rightmargin
).asLyXCommand() << '\n';
721 if (!bottommargin
.empty())
722 os
<< "\\bottommargin "
723 << VSpace(bottommargin
).asLyXCommand() << '\n';
724 if (!headheight
.empty())
725 os
<< "\\headheight "
726 << VSpace(headheight
).asLyXCommand() << '\n';
727 if (!headsep
.empty())
729 << VSpace(headsep
).asLyXCommand() << '\n';
730 if (!footskip
.empty())
732 << VSpace(footskip
).asLyXCommand() << '\n';
733 os
<< "\\secnumdepth " << secnumdepth
734 << "\n\\tocdepth " << tocdepth
735 << "\n\\paragraph_separation "
736 << string_paragraph_separation
[paragraph_separation
]
737 << "\n\\defskip " << getDefSkip().asLyXCommand()
738 << "\n\\quotes_language "
739 << string_quotes_language
[quotes_language
]
740 << "\n\\papercolumns " << columns
741 << "\n\\papersides " << sides
742 << "\n\\paperpagestyle " << pagestyle
<< '\n';
743 if (!listings_params
.empty())
744 os
<< "\\listings_params \"" <<
745 InsetListingsParams(listings_params
).encodedString() << "\"\n";
746 for (int i
= 0; i
< 4; ++i
) {
747 if (user_defined_bullet(i
) != ITEMIZE_DEFAULTS
[i
]) {
748 if (user_defined_bullet(i
).getFont() != -1) {
749 os
<< "\\bullet " << i
<< " "
750 << user_defined_bullet(i
).getFont() << " "
751 << user_defined_bullet(i
).getCharacter() << " "
752 << user_defined_bullet(i
).getSize() << "\n";
756 os
<< "\\bulletLaTeX " << i
<< " \""
757 << lyx::to_ascii(user_defined_bullet(i
).getText())
763 os
<< "\\tracking_changes " << convert
<string
>(trackChanges
) << "\n";
764 os
<< "\\output_changes " << convert
<string
>(outputChanges
) << "\n";
766 AuthorList::Authors::const_iterator a_it
= pimpl_
->authorlist
.begin();
767 AuthorList::Authors::const_iterator a_end
= pimpl_
->authorlist
.end();
768 for (; a_it
!= a_end
; ++a_it
) {
769 if (a_it
->second
.used())
770 os
<< "\\author " << a_it
->second
<< "\n";
772 os
<< "\\author " << Author() << "\n";
777 bool BufferParams::writeLaTeX(odocstream
& os
, LaTeXFeatures
& features
,
778 TexRow
& texrow
) const
780 os
<< "\\documentclass";
782 TextClass
const & tclass
= getTextClass();
784 ostringstream clsoptions
; // the document class options.
786 if (tokenPos(tclass
.opt_fontsize(),
787 '|', fontsize
) >= 0) {
788 // only write if existing in list (and not default)
789 clsoptions
<< fontsize
<< "pt,";
792 // custom, A3, B3 and B4 paper sizes need geometry
793 bool nonstandard_papersize
= papersize
== PAPER_B3
794 || papersize
== PAPER_B4
795 || papersize
== PAPER_A3
796 || papersize
== PAPER_CUSTOM
;
801 clsoptions
<< "a4paper,";
804 clsoptions
<< "letterpaper,";
807 clsoptions
<< "a5paper,";
810 clsoptions
<< "b5paper,";
812 case PAPER_USEXECUTIVE
:
813 clsoptions
<< "executivepaper,";
816 clsoptions
<< "legalpaper,";
828 if (sides
!= tclass
.sides()) {
830 case TextClass::OneSide
:
831 clsoptions
<< "oneside,";
833 case TextClass::TwoSides
:
834 clsoptions
<< "twoside,";
840 if (columns
!= tclass
.columns()) {
842 clsoptions
<< "twocolumn,";
844 clsoptions
<< "onecolumn,";
848 && orientation
== ORIENTATION_LANDSCAPE
)
849 clsoptions
<< "landscape,";
851 // language should be a parameter to \documentclass
852 if (language
->babel() == "hebrew"
853 && default_language
->babel() != "hebrew")
854 // This seems necessary
855 features
.useLanguage(default_language
);
857 ostringstream language_options
;
858 bool const use_babel
= features
.useBabel();
860 language_options
<< features
.getLanguages();
861 if (!language
->babel().empty()) {
862 if (!language_options
.str().empty())
863 language_options
<< ',';
864 language_options
<< language
->babel();
866 if (lyxrc
.language_global_options
&& !language_options
.str().empty())
867 clsoptions
<< language_options
.str() << ',';
870 // the user-defined options
871 if (!options
.empty()) {
872 clsoptions
<< options
<< ',';
875 string
strOptions(clsoptions
.str());
876 if (!strOptions
.empty()) {
877 strOptions
= rtrim(strOptions
, ",");
879 os
<< '[' << from_utf8(strOptions
) << ']';
882 os
<< '{' << from_ascii(tclass
.latexname()) << "}\n";
884 // end of \documentclass defs
886 // font selection must be done before loading fontenc.sty
888 loadFonts(fontsRoman
, fontsSans
,
889 fontsTypewriter
, fontsSC
, fontsOSF
,
890 fontsSansScale
, fontsTypewriterScale
);
891 if (!fonts
.empty()) {
892 os
<< from_ascii(fonts
);
895 if (fontsDefaultFamily
!= "default")
896 os
<< "\\renewcommand{\\familydefault}{\\"
897 << from_ascii(fontsDefaultFamily
) << "}\n";
900 // this one is not per buffer
901 // for arabic_arabi and farsi we also need to load the LAE and LFE encoding
902 if (lyxrc
.fontenc
!= "default") {
903 if (language
->lang() == "arabic_arabi" || language
->lang() == "farsi") {
904 os
<< "\\usepackage[" << from_ascii(lyxrc
.fontenc
)
905 << ",LFE,LAE]{fontenc}\n";
908 os
<< "\\usepackage[" << from_ascii(lyxrc
.fontenc
)
914 // handle inputenc etc.
915 writeEncodingPreamble(os
, features
, texrow
);
917 if (!listings_params
.empty()) {
918 os
<< "\\usepackage{listings}\n";
921 // do not test validity because listings_params is supposed to be valid
922 string par
= InsetListingsParams(listings_params
).separatedParams(true);
923 os
<< from_ascii(par
);
924 // count the number of newlines
925 for (size_t i
= 0; i
< par
.size(); ++i
)
931 if (use_geometry
|| nonstandard_papersize
) {
932 os
<< "\\usepackage{geometry}\n";
934 os
<< "\\geometry{verbose";
935 if (orientation
== ORIENTATION_LANDSCAPE
)
939 if (!paperwidth
.empty())
941 << from_ascii(paperwidth
);
942 if (!paperheight
.empty())
943 os
<< ",paperheight="
944 << from_ascii(paperheight
);
947 os
<< ",letterpaper";
952 case PAPER_USEXECUTIVE
:
953 os
<< ",executivepaper";
974 // default papersize ie PAPER_DEFAULT
975 switch (lyxrc
.default_papersize
) {
976 case PAPER_DEFAULT
: // keep compiler happy
978 os
<< ",letterpaper";
983 case PAPER_USEXECUTIVE
:
984 os
<< ",executivepaper";
1004 if (!topmargin
.empty())
1005 os
<< ",tmargin=" << from_ascii(Length(topmargin
).asLatexString());
1006 if (!bottommargin
.empty())
1007 os
<< ",bmargin=" << from_ascii(Length(bottommargin
).asLatexString());
1008 if (!leftmargin
.empty())
1009 os
<< ",lmargin=" << from_ascii(Length(leftmargin
).asLatexString());
1010 if (!rightmargin
.empty())
1011 os
<< ",rmargin=" << from_ascii(Length(rightmargin
).asLatexString());
1012 if (!headheight
.empty())
1013 os
<< ",headheight=" << from_ascii(Length(headheight
).asLatexString());
1014 if (!headsep
.empty())
1015 os
<< ",headsep=" << from_ascii(Length(headsep
).asLatexString());
1016 if (!footskip
.empty())
1017 os
<< ",footskip=" << from_ascii(Length(footskip
).asLatexString());
1022 if (tokenPos(tclass
.opt_pagestyle(),
1023 '|', pagestyle
) >= 0) {
1024 if (pagestyle
== "fancy") {
1025 os
<< "\\usepackage{fancyhdr}\n";
1028 os
<< "\\pagestyle{" << from_ascii(pagestyle
) << "}\n";
1032 // Only if class has a ToC hierarchy
1033 if (tclass
.hasTocLevels()) {
1034 if (secnumdepth
!= tclass
.secnumdepth()) {
1035 os
<< "\\setcounter{secnumdepth}{"
1040 if (tocdepth
!= tclass
.tocdepth()) {
1041 os
<< "\\setcounter{tocdepth}{"
1048 if (paragraph_separation
) {
1049 switch (getDefSkip().kind()) {
1050 case VSpace::SMALLSKIP
:
1051 os
<< "\\setlength{\\parskip}{\\smallskipamount}\n";
1053 case VSpace::MEDSKIP
:
1054 os
<< "\\setlength{\\parskip}{\\medskipamount}\n";
1056 case VSpace::BIGSKIP
:
1057 os
<< "\\setlength{\\parskip}{\\bigskipamount}\n";
1059 case VSpace::LENGTH
:
1060 os
<< "\\setlength{\\parskip}{"
1061 << from_utf8(getDefSkip().length().asLatexString())
1064 default: // should never happen // Then delete it.
1065 os
<< "\\setlength{\\parskip}{\\medskipamount}\n";
1070 os
<< "\\setlength{\\parindent}{0pt}\n";
1074 // If we use jurabib, we have to call babel here.
1075 if (use_babel
&& features
.isRequired("jurabib")) {
1076 os
<< from_ascii(babelCall(language_options
.str()))
1078 << from_ascii(features
.getBabelOptions());
1082 // Now insert the LyX specific LaTeX commands...
1084 // The optional packages;
1085 docstring
lyxpreamble(from_ascii(features
.getPackages()));
1087 // this might be useful...
1088 lyxpreamble
+= "\n\\makeatletter\n";
1090 // Some macros LyX will need
1091 docstring
tmppreamble(from_ascii(features
.getMacros()));
1093 if (!tmppreamble
.empty()) {
1094 lyxpreamble
+= "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1095 "LyX specific LaTeX commands.\n"
1096 + tmppreamble
+ '\n';
1099 // the text class specific preamble
1100 tmppreamble
= features
.getTClassPreamble();
1101 if (!tmppreamble
.empty()) {
1102 lyxpreamble
+= "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1103 "Textclass specific LaTeX commands.\n"
1104 + tmppreamble
+ '\n';
1107 /* the user-defined preamble */
1108 if (!preamble
.empty()) {
1110 lyxpreamble
+= "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1111 "User specified LaTeX commands.\n"
1112 + from_utf8(preamble
) + '\n';
1115 // Itemize bullet settings need to be last in case the user
1116 // defines their own bullets that use a package included
1117 // in the user-defined preamble -- ARRae
1118 // Actually it has to be done much later than that
1119 // since some packages like frenchb make modifications
1120 // at \begin{document} time -- JMarc
1121 docstring bullets_def
;
1122 for (int i
= 0; i
< 4; ++i
) {
1123 if (user_defined_bullet(i
) != ITEMIZE_DEFAULTS
[i
]) {
1124 if (bullets_def
.empty())
1125 bullets_def
+= "\\AtBeginDocument{\n";
1126 bullets_def
+= " \\def\\labelitemi";
1128 // `i' is one less than the item to modify
1135 bullets_def
+= "ii";
1141 bullets_def
+= '{' +
1142 user_defined_bullet(i
).getText()
1147 if (!bullets_def
.empty())
1148 lyxpreamble
+= bullets_def
+ "}\n\n";
1150 // We try to load babel late, in case it interferes
1151 // with other packages.
1152 // Jurabib has to be called after babel, though.
1153 if (use_babel
&& !features
.isRequired("jurabib")) {
1155 lyxpreamble
+= from_utf8(babelCall(language_options
.str())) + '\n';
1156 lyxpreamble
+= from_utf8(features
.getBabelOptions());
1159 lyxpreamble
+= "\\makeatother\n\n";
1162 int(lyx::count(lyxpreamble
.begin(), lyxpreamble
.end(), '\n'));
1163 for (int j
= 0; j
!= nlines
; ++j
) {
1172 void BufferParams::useClassDefaults()
1174 TextClass
const & tclass
= textclasslist
[textclass
];
1176 sides
= tclass
.sides();
1177 columns
= tclass
.columns();
1178 pagestyle
= tclass
.pagestyle();
1179 options
= tclass
.options();
1180 // Only if class has a ToC hierarchy
1181 if (tclass
.hasTocLevels()) {
1182 secnumdepth
= tclass
.secnumdepth();
1183 tocdepth
= tclass
.tocdepth();
1188 bool BufferParams::hasClassDefaults() const
1190 TextClass
const & tclass
= textclasslist
[textclass
];
1192 return (sides
== tclass
.sides()
1193 && columns
== tclass
.columns()
1194 && pagestyle
== tclass
.pagestyle()
1195 && options
== tclass
.options()
1196 && secnumdepth
== tclass
.secnumdepth()
1197 && tocdepth
== tclass
.tocdepth());
1201 TextClass
const & BufferParams::getTextClass() const
1203 return textclasslist
[textclass
];
1207 Font
const BufferParams::getFont() const
1209 Font f
= getTextClass().defaultfont();
1210 f
.setLanguage(language
);
1211 if (fontsDefaultFamily
== "rmdefault")
1212 f
.setFamily(Font::ROMAN_FAMILY
);
1213 else if (fontsDefaultFamily
== "sfdefault")
1214 f
.setFamily(Font::SANS_FAMILY
);
1215 else if (fontsDefaultFamily
== "ttdefault")
1216 f
.setFamily(Font::TYPEWRITER_FAMILY
);
1221 void BufferParams::readPreamble(Lexer
& lex
)
1223 if (lex
.getString() != "\\begin_preamble")
1224 lyxerr
<< "Error (BufferParams::readPreamble):"
1225 "consistency check failed." << endl
;
1227 preamble
= lex
.getLongString("\\end_preamble");
1231 void BufferParams::readLanguage(Lexer
& lex
)
1233 if (!lex
.next()) return;
1235 string
const tmptok
= lex
.getString();
1237 // check if tmptok is part of tex_babel in tex-defs.h
1238 language
= languages
.getLanguage(tmptok
);
1240 // Language tmptok was not found
1241 language
= default_language
;
1242 lyxerr
<< "Warning: Setting language `"
1243 << tmptok
<< "' to `" << language
->lang()
1249 void BufferParams::readGraphicsDriver(Lexer
& lex
)
1251 if (!lex
.next()) return;
1253 string
const tmptok
= lex
.getString();
1254 // check if tmptok is part of tex_graphics in tex_defs.h
1257 string
const test
= tex_graphics
[n
++];
1259 if (test
== tmptok
) {
1260 graphicsDriver
= tmptok
;
1262 } else if (test
== "") {
1264 "Warning: graphics driver `$$Token' not recognized!\n"
1265 " Setting graphics driver to `default'.\n");
1266 graphicsDriver
= "default";
1273 void BufferParams::readBullets(Lexer
& lex
)
1275 if (!lex
.next()) return;
1277 int const index
= lex
.getInteger();
1279 int temp_int
= lex
.getInteger();
1280 user_defined_bullet(index
).setFont(temp_int
);
1281 temp_bullet(index
).setFont(temp_int
);
1283 user_defined_bullet(index
).setCharacter(temp_int
);
1284 temp_bullet(index
).setCharacter(temp_int
);
1286 user_defined_bullet(index
).setSize(temp_int
);
1287 temp_bullet(index
).setSize(temp_int
);
1291 void BufferParams::readBulletsLaTeX(Lexer
& lex
)
1293 // The bullet class should be able to read this.
1294 if (!lex
.next()) return;
1295 int const index
= lex
.getInteger();
1297 docstring
const temp_str
= lex
.getDocString();
1299 user_defined_bullet(index
).setText(temp_str
);
1300 temp_bullet(index
).setText(temp_str
);
1304 string
const BufferParams::paperSizeName() const
1306 char real_papersize
= papersize
;
1307 if (real_papersize
== PAPER_DEFAULT
)
1308 real_papersize
= lyxrc
.default_papersize
;
1310 switch (real_papersize
) {
1319 case PAPER_USEXECUTIVE
:
1323 case PAPER_USLETTER
:
1330 string
const BufferParams::dvips_options() const
1335 && papersize
== PAPER_CUSTOM
1336 && !lyxrc
.print_paper_dimension_flag
.empty()
1337 && !paperwidth
.empty()
1338 && !paperheight
.empty()) {
1339 // using a custom papersize
1340 result
= lyxrc
.print_paper_dimension_flag
;
1341 result
+= ' ' + paperwidth
;
1342 result
+= ',' + paperheight
;
1344 string
const paper_option
= paperSizeName();
1345 if (paper_option
!= "letter" ||
1346 orientation
!= ORIENTATION_LANDSCAPE
) {
1347 // dvips won't accept -t letter -t landscape.
1348 // In all other cases, include the paper size
1350 result
= lyxrc
.print_paper_flag
;
1351 result
+= ' ' + paper_option
;
1354 if (orientation
== ORIENTATION_LANDSCAPE
&&
1355 papersize
!= PAPER_CUSTOM
)
1356 result
+= ' ' + lyxrc
.print_landscape_flag
;
1361 string
const BufferParams::babelCall(string
const & lang_opts
) const
1363 string lang_pack
= lyxrc
.language_package
;
1364 if (lang_pack
!= "\\usepackage{babel}")
1366 // suppress the babel call when there is no babel language defined
1367 // for the document language in the lib/languages file and if no
1368 // other languages are used (lang_opts is then empty)
1369 if (lang_opts
.empty())
1371 if (!lyxrc
.language_global_options
)
1372 return "\\usepackage[" + lang_opts
+ "]{babel}";
1377 void BufferParams::writeEncodingPreamble(odocstream
& os
,
1378 LaTeXFeatures
& features
, TexRow
& texrow
) const
1380 if (inputenc
== "auto") {
1381 string
const doc_encoding
=
1382 language
->encoding()->latexName();
1383 Encoding::Package
const package
=
1384 language
->encoding()->package();
1386 // Create a list with all the input encodings used
1388 std::set
<string
> encodings
=
1389 features
.getEncodingSet(doc_encoding
);
1391 if (!encodings
.empty() || package
== Encoding::inputenc
) {
1392 os
<< "\\usepackage[";
1393 std::set
<string
>::const_iterator it
= encodings
.begin();
1394 std::set
<string
>::const_iterator
const end
= encodings
.end();
1396 os
<< from_ascii(*it
);
1399 for (; it
!= end
; ++it
)
1400 os
<< ',' << from_ascii(*it
);
1401 if (package
== Encoding::inputenc
) {
1402 if (!encodings
.empty())
1404 os
<< from_ascii(doc_encoding
);
1406 os
<< "]{inputenc}\n";
1409 if (package
== Encoding::CJK
) {
1410 os
<< "\\usepackage{CJK}\n";
1413 } else if (inputenc
!= "default") {
1414 switch (encoding().package()) {
1415 case Encoding::none
:
1417 case Encoding::inputenc
:
1418 os
<< "\\usepackage[" << from_ascii(inputenc
)
1423 os
<< "\\usepackage{CJK}\n";
1429 // The encoding "armscii8" is only available when the package "armtex" is loaded.
1430 // armscii8 is used for Armenian.
1431 if (language
->encoding()->latexName() == "armscii8" || inputenc
== "armscii8") {
1432 os
<< "\\usepackage{armtex}\n";
1438 string
const BufferParams::loadFonts(string
const & rm
,
1439 string
const & sf
, string
const & tt
,
1440 bool const & sc
, bool const & osf
,
1441 int const & sfscale
, int const & ttscale
) const
1443 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1444 several packages have been replaced by others, that might not
1445 be installed on every system. We have to take care for that
1446 (see psnfss.pdf). We try to support all psnfss fonts as well
1447 as the fonts that have become de facto standard in the LaTeX
1448 world (e.g. Latin Modern). We do not support obsolete fonts
1449 (like PSLatex). In general, it should be possible to mix any
1450 rm font with any sf or tt font, respectively. (JSpitzm)
1452 -- separate math fonts.
1455 if (rm
== "default" && sf
== "default" && tt
== "default")
1462 // Computer Modern (must be explicitely selectable -- there might be classes
1463 // that define a different default font!
1465 os
<< "\\renewcommand{\\rmdefault}{cmr}\n";
1466 // osf for Computer Modern needs eco.sty
1468 os
<< "\\usepackage{eco}\n";
1470 // Latin Modern Roman
1471 else if (rm
== "lmodern")
1472 os
<< "\\usepackage{lmodern}\n";
1474 else if (rm
== "ae") {
1475 // not needed when using OT1 font encoding.
1476 if (lyxrc
.fontenc
!= "default")
1477 os
<< "\\usepackage{ae,aecompl}\n";
1480 else if (rm
== "times") {
1481 // try to load the best available package
1482 if (LaTeXFeatures::isAvailable("mathptmx"))
1483 os
<< "\\usepackage{mathptmx}\n";
1484 else if (LaTeXFeatures::isAvailable("mathptm"))
1485 os
<< "\\usepackage{mathptm}\n";
1487 os
<< "\\usepackage{times}\n";
1490 else if (rm
== "palatino") {
1491 // try to load the best available package
1492 if (LaTeXFeatures::isAvailable("mathpazo")) {
1493 os
<< "\\usepackage";
1499 // "osf" includes "sc"!
1503 os
<< "{mathpazo}\n";
1505 else if (LaTeXFeatures::isAvailable("mathpple"))
1506 os
<< "\\usepackage{mathpple}\n";
1508 os
<< "\\usepackage{palatino}\n";
1511 else if (rm
== "utopia") {
1512 // fourier supersedes utopia.sty, but does
1513 // not work with OT1 encoding.
1514 if (LaTeXFeatures::isAvailable("fourier")
1515 && lyxrc
.fontenc
!= "default") {
1516 os
<< "\\usepackage";
1527 os
<< "{fourier}\n";
1530 os
<< "\\usepackage{utopia}\n";
1532 // Bera (complete fontset)
1533 else if (rm
== "bera" && sf
== "default" && tt
== "default")
1534 os
<< "\\usepackage{bera}\n";
1536 else if (rm
!= "default")
1537 os
<< "\\usepackage" << "{" << rm
<< "}\n";
1540 // Helvetica, Bera Sans
1541 if (sf
== "helvet" || sf
== "berasans") {
1543 os
<< "\\usepackage[scaled=" << float(sfscale
) / 100
1544 << "]{" << sf
<< "}\n";
1546 os
<< "\\usepackage{" << sf
<< "}\n";
1549 else if (sf
== "avant")
1550 os
<< "\\usepackage{" << sf
<< "}\n";
1551 // Computer Modern, Latin Modern, CM Bright
1552 else if (sf
!= "default")
1553 os
<< "\\renewcommand{\\sfdefault}{" << sf
<< "}\n";
1555 // monospaced/typewriter
1556 // Courier, LuxiMono
1557 if (tt
== "luximono" || tt
== "beramono") {
1559 os
<< "\\usepackage[scaled=" << float(ttscale
) / 100
1560 << "]{" << tt
<< "}\n";
1562 os
<< "\\usepackage{" << tt
<< "}\n";
1565 else if (tt
== "courier" )
1566 os
<< "\\usepackage{" << tt
<< "}\n";
1567 // Computer Modern, Latin Modern, CM Bright
1568 else if (tt
!= "default")
1569 os
<< "\\renewcommand{\\ttdefault}{" << tt
<< "}\n";
1575 Encoding
const & BufferParams::encoding() const
1577 if (inputenc
== "auto" || inputenc
== "default")
1578 return *(language
->encoding());
1579 Encoding
const * const enc
=
1580 encodings
.getFromLaTeXName(inputenc
);
1583 lyxerr
<< "Unknown inputenc value `" << inputenc
1584 << "'. Using `auto' instead." << endl
;
1585 return *(language
->encoding());
1589 biblio::CiteEngine
BufferParams::getEngine() const
1591 // FIXME the class should provide the numerical/
1592 // authoryear choice
1593 if (getTextClass().provides("natbib")
1594 && cite_engine_
!= biblio::ENGINE_NATBIB_NUMERICAL
)
1595 return biblio::ENGINE_NATBIB_AUTHORYEAR
;
1596 return cite_engine_
;
1600 void BufferParams::setCiteEngine(biblio::CiteEngine
const cite_engine
)
1602 cite_engine_
= cite_engine
;