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"
32 #include "lyxtextclasslist.h"
33 #include "outputparams.h"
34 #include "tex-strings.h"
39 #include "frontends/Alert.h"
41 #include "support/lyxalgo.h" // for lyx::count
42 #include "support/convert.h"
43 #include "support/translator.h"
45 #include <boost/array.hpp>
52 using support::bformat;
54 using support::tokenPos;
58 using std::istringstream;
60 using std::ostringstream;
63 namespace Alert = lyx::frontend::Alert;
69 // Paragraph separation
70 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
73 ParSepTranslator const init_parseptranslator()
75 ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
76 translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
81 ParSepTranslator const & parseptranslator()
83 static ParSepTranslator translator = init_parseptranslator();
89 typedef Translator<string, InsetQuotes::quote_language> QuotesLangTranslator;
92 QuotesLangTranslator const init_quoteslangtranslator()
94 QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
95 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
96 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
97 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
98 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
99 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
104 QuotesLangTranslator const & quoteslangtranslator()
106 static QuotesLangTranslator translator = init_quoteslangtranslator();
112 typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
115 PaperSizeTranslator const init_papersizetranslator()
117 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
118 translator.addPair(string_papersize[1], PAPER_CUSTOM);
119 translator.addPair(string_papersize[2], PAPER_USLETTER);
120 translator.addPair(string_papersize[3], PAPER_USLEGAL);
121 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
122 translator.addPair(string_papersize[5], PAPER_A3);
123 translator.addPair(string_papersize[6], PAPER_A4);
124 translator.addPair(string_papersize[7], PAPER_A5);
125 translator.addPair(string_papersize[8], PAPER_B3);
126 translator.addPair(string_papersize[9], PAPER_B4);
127 translator.addPair(string_papersize[10], PAPER_B5);
132 PaperSizeTranslator const & papersizetranslator()
134 static PaperSizeTranslator translator = init_papersizetranslator();
140 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
143 PaperOrientationTranslator const init_paperorientationtranslator()
145 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
146 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
151 PaperOrientationTranslator const & paperorientationtranslator()
153 static PaperOrientationTranslator translator = init_paperorientationtranslator();
159 typedef Translator<int, LyXTextClass::PageSides> SidesTranslator;
162 SidesTranslator const init_sidestranslator()
164 SidesTranslator translator(1, LyXTextClass::OneSide);
165 translator.addPair(2, LyXTextClass::TwoSides);
170 SidesTranslator const & sidestranslator()
172 static SidesTranslator translator = init_sidestranslator();
178 typedef Translator<int, BufferParams::Package> PackageTranslator;
181 PackageTranslator const init_packagetranslator()
183 PackageTranslator translator(0, BufferParams::package_off);
184 translator.addPair(1, BufferParams::package_auto);
185 translator.addPair(2, BufferParams::package_on);
190 PackageTranslator const & packagetranslator()
192 static PackageTranslator translator = init_packagetranslator();
198 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
201 CiteEngineTranslator const init_citeenginetranslator()
203 CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
204 translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
205 translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
206 translator.addPair("jurabib", biblio::ENGINE_JURABIB);
211 CiteEngineTranslator const & citeenginetranslator()
213 static CiteEngineTranslator translator = init_citeenginetranslator();
219 typedef Translator<string, Spacing::Space> SpaceTranslator;
222 SpaceTranslator const init_spacetranslator()
224 SpaceTranslator translator("default", Spacing::Default);
225 translator.addPair("single", Spacing::Single);
226 translator.addPair("onehalf", Spacing::Onehalf);
227 translator.addPair("double", Spacing::Double);
228 translator.addPair("other", Spacing::Other);
233 SpaceTranslator const & spacetranslator()
235 static SpaceTranslator translator = init_spacetranslator();
239 // ends annonym namespace
243 class BufferParams::Impl
248 AuthorList authorlist;
249 BranchList branchlist;
250 boost::array<Bullet, 4> temp_bullets;
251 boost::array<Bullet, 4> user_defined_bullets;
253 /** This is the amount of space used for paragraph_separation "skip",
254 * and for detached paragraphs in "indented" documents.
260 BufferParams::Impl::Impl()
261 : defskip(VSpace::MEDSKIP)
263 // set initial author
264 authorlist.record(Author(lyxrc.user_name, lyxrc.user_email));
269 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
273 return new BufferParams::Impl(*ptr);
277 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
283 BufferParams::BufferParams()
284 : // Initialize textclass to point to article. if `first' is
285 // true in the returned pair, then `second' is the textclass
286 // number; if it is false, second is 0. In both cases, second
288 textclass(textclasslist.numberOfClass("article").second),
291 paragraph_separation = PARSEP_INDENT;
292 quotes_language = InsetQuotes::EnglishQ;
293 fontsize = "default";
296 papersize = PAPER_DEFAULT;
297 orientation = ORIENTATION_PORTRAIT;
298 use_geometry = false;
299 use_amsmath = package_auto;
300 use_esint = package_auto;
301 cite_engine = biblio::ENGINE_BASIC;
302 use_bibtopic = false;
303 trackChanges = false;
304 outputChanges = false;
307 language = default_language;
308 fontsRoman = "default";
309 fontsSans = "default";
310 fontsTypewriter = "default";
311 fontsDefaultFamily = "default";
314 fontsSansScale = 100;
315 fontsTypewriterScale = 100;
317 graphicsDriver = "default";
318 sides = LyXTextClass::OneSide;
320 pagestyle = "default";
322 for (int iter = 0; iter < 4; ++iter) {
323 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
324 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
329 BufferParams::~BufferParams()
333 AuthorList & BufferParams::authors()
335 return pimpl_->authorlist;
339 AuthorList const & BufferParams::authors() const
341 return pimpl_->authorlist;
345 BranchList & BufferParams::branchlist()
347 return pimpl_->branchlist;
351 BranchList const & BufferParams::branchlist() const
353 return pimpl_->branchlist;
357 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
359 BOOST_ASSERT(index < 4);
360 return pimpl_->temp_bullets[index];
364 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
366 BOOST_ASSERT(index < 4);
367 return pimpl_->temp_bullets[index];
371 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
373 BOOST_ASSERT(index < 4);
374 return pimpl_->user_defined_bullets[index];
378 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
380 BOOST_ASSERT(index < 4);
381 return pimpl_->user_defined_bullets[index];
385 Spacing & BufferParams::spacing()
387 return pimpl_->spacing;
391 Spacing const & BufferParams::spacing() const
393 return pimpl_->spacing;
397 VSpace const & BufferParams::getDefSkip() const
399 return pimpl_->defskip;
403 void BufferParams::setDefSkip(VSpace const & vs)
405 pimpl_->defskip = vs;
409 string const BufferParams::readToken(LyXLex & lex, string const & token)
411 if (token == "\\textclass") {
413 string const classname = lex.getString();
414 pair<bool, lyx::textclass_type> pp =
415 textclasslist.numberOfClass(classname);
417 textclass = pp.second;
419 // if text class does not exist, try to load it from filepath
420 pp = textclasslist.addTextClass(classname, filepath);
422 textclass = pp.second;
428 // FIXME: isTeXClassAvailable will try to load the layout file, but will
429 // fail because of the lack of path info. Warnings will be given although
430 // the layout file will be correctly loaded later.
431 if (!getLyXTextClass().isTeXClassAvailable()) {
432 docstring const msg =
433 bformat(_("The document uses a missing "
434 "TeX class \"%1$s\".\n"), from_utf8(classname));
435 Alert::warning(_("Document class not available"),
436 msg + _("LyX will not be able to produce output."));
438 } else if (token == "\\begin_preamble") {
440 } else if (token == "\\options") {
442 options = lex.getString();
443 } else if (token == "\\language") {
445 } else if (token == "\\inputencoding") {
447 } else if (token == "\\graphics") {
448 readGraphicsDriver(lex);
449 } else if (token == "\\font_roman") {
451 } else if (token == "\\font_sans") {
453 } else if (token == "\\font_typewriter") {
454 lex >> fontsTypewriter;
455 } else if (token == "\\font_default_family") {
456 lex >> fontsDefaultFamily;
457 } else if (token == "\\font_sc") {
459 } else if (token == "\\font_osf") {
461 } else if (token == "\\font_sf_scale") {
462 lex >> fontsSansScale;
463 } else if (token == "\\font_tt_scale") {
464 lex >> fontsTypewriterScale;
465 } else if (token == "\\paragraph_separation") {
468 paragraph_separation = parseptranslator().find(parsep);
469 } else if (token == "\\defskip") {
471 pimpl_->defskip = VSpace(lex.getString());
472 } else if (token == "\\quotes_language") {
475 quotes_language = quoteslangtranslator().find(quotes_lang);
476 } else if (token == "\\papersize") {
479 papersize = papersizetranslator().find(ppsize);
480 } else if (token == "\\use_geometry") {
482 } else if (token == "\\use_amsmath") {
485 use_amsmath = packagetranslator().find(use_ams);
486 } else if (token == "\\use_esint") {
489 use_esint = packagetranslator().find(useesint);
490 } else if (token == "\\cite_engine") {
493 cite_engine = citeenginetranslator().find(engine);
494 } else if (token == "\\use_bibtopic") {
496 } else if (token == "\\tracking_changes") {
498 } else if (token == "\\output_changes") {
499 lex >> outputChanges;
500 } else if (token == "\\branch") {
502 docstring branch = lex.getDocString();
503 branchlist().add(branch);
506 string const tok = lex.getString();
507 if (tok == "\\end_branch")
509 Branch * branch_ptr = branchlist().find(branch);
510 if (tok == "\\selected") {
513 branch_ptr->setSelected(lex.getInteger());
515 // not yet operational
516 if (tok == "\\color") {
518 string color = lex.getString();
520 branch_ptr->setColor(color);
521 // Update also the LColor table:
523 color = lcolor.getX11Name(LColor::background);
525 lcolor.setColor(to_utf8(branch), color);
529 } else if (token == "\\author") {
531 istringstream ss(lex.getString());
534 author_map.push_back(pimpl_->authorlist.record(a));
535 } else if (token == "\\paperorientation") {
538 orientation = paperorientationtranslator().find(orient);
539 } else if (token == "\\paperwidth") {
541 } else if (token == "\\paperheight") {
543 } else if (token == "\\leftmargin") {
545 } else if (token == "\\topmargin") {
547 } else if (token == "\\rightmargin") {
549 } else if (token == "\\bottommargin") {
551 } else if (token == "\\headheight") {
553 } else if (token == "\\headsep") {
555 } else if (token == "\\footskip") {
557 } else if (token == "\\paperfontsize") {
559 } else if (token == "\\papercolumns") {
561 } else if (token == "\\papersides") {
564 sides = sidestranslator().find(psides);
565 } else if (token == "\\paperpagestyle") {
567 } else if (token == "\\bullet") {
569 } else if (token == "\\bulletLaTeX") {
570 readBulletsLaTeX(lex);
571 } else if (token == "\\secnumdepth") {
573 } else if (token == "\\tocdepth") {
575 } else if (token == "\\spacing") {
579 if (nspacing == "other") {
582 spacing().set(spacetranslator().find(nspacing), tmp_val);
583 } else if (token == "\\float_placement") {
584 lex >> float_placement;
593 void BufferParams::writeFile(ostream & os) const
595 // The top of the file is written by the buffer.
596 // Prints out the buffer info into the .lyx file given by file
599 os << "\\textclass " << textclasslist[textclass].name() << '\n';
601 // then the the preamble
602 if (!preamble.empty()) {
603 // remove '\n' from the end of preamble
604 string const tmppreamble = rtrim(preamble, "\n");
605 os << "\\begin_preamble\n"
607 << "\n\\end_preamble\n";
611 if (!options.empty()) {
612 os << "\\options " << options << '\n';
615 // then the text parameters
616 if (language != ignore_language)
617 os << "\\language " << language->lang() << '\n';
618 os << "\\inputencoding " << inputenc
619 << "\n\\font_roman " << fontsRoman
620 << "\n\\font_sans " << fontsSans
621 << "\n\\font_typewriter " << fontsTypewriter
622 << "\n\\font_default_family " << fontsDefaultFamily
623 << "\n\\font_sc " << convert<string>(fontsSC)
624 << "\n\\font_osf " << convert<string>(fontsOSF)
625 << "\n\\font_sf_scale " << fontsSansScale
626 << "\n\\font_tt_scale " << fontsTypewriterScale
627 << "\n\\graphics " << graphicsDriver << '\n';
629 if (!float_placement.empty()) {
630 os << "\\float_placement " << float_placement << '\n';
632 os << "\\paperfontsize " << fontsize << '\n';
634 spacing().writeFile(os);
636 os << "\\papersize " << string_papersize[papersize]
637 << "\n\\use_geometry " << convert<string>(use_geometry)
638 << "\n\\use_amsmath " << use_amsmath
639 << "\n\\use_esint " << use_esint
640 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine)
641 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
642 << "\n\\paperorientation " << string_orientation[orientation]
645 BranchList::const_iterator it = branchlist().begin();
646 BranchList::const_iterator end = branchlist().end();
647 for (; it != end; ++it) {
648 os << "\\branch " << to_utf8(it->getBranch())
649 << "\n\\selected " << it->getSelected()
650 << "\n\\color " << lyx::X11hexname(it->getColor())
655 if (!paperwidth.empty())
656 os << "\\paperwidth "
657 << VSpace(paperwidth).asLyXCommand() << '\n';
658 if (!paperheight.empty())
659 os << "\\paperheight "
660 << VSpace(paperheight).asLyXCommand() << '\n';
661 if (!leftmargin.empty())
662 os << "\\leftmargin "
663 << VSpace(leftmargin).asLyXCommand() << '\n';
664 if (!topmargin.empty())
666 << VSpace(topmargin).asLyXCommand() << '\n';
667 if (!rightmargin.empty())
668 os << "\\rightmargin "
669 << VSpace(rightmargin).asLyXCommand() << '\n';
670 if (!bottommargin.empty())
671 os << "\\bottommargin "
672 << VSpace(bottommargin).asLyXCommand() << '\n';
673 if (!headheight.empty())
674 os << "\\headheight "
675 << VSpace(headheight).asLyXCommand() << '\n';
676 if (!headsep.empty())
678 << VSpace(headsep).asLyXCommand() << '\n';
679 if (!footskip.empty())
681 << VSpace(footskip).asLyXCommand() << '\n';
682 os << "\\secnumdepth " << secnumdepth
683 << "\n\\tocdepth " << tocdepth
684 << "\n\\paragraph_separation "
685 << string_paragraph_separation[paragraph_separation]
686 << "\n\\defskip " << getDefSkip().asLyXCommand()
687 << "\n\\quotes_language "
688 << string_quotes_language[quotes_language]
689 << "\n\\papercolumns " << columns
690 << "\n\\papersides " << sides
691 << "\n\\paperpagestyle " << pagestyle << '\n';
692 for (int i = 0; i < 4; ++i) {
693 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
694 if (user_defined_bullet(i).getFont() != -1) {
695 os << "\\bullet " << i << " "
696 << user_defined_bullet(i).getFont() << " "
697 << user_defined_bullet(i).getCharacter() << " "
698 << user_defined_bullet(i).getSize() << "\n";
702 os << "\\bulletLaTeX " << i << " \""
703 << lyx::to_ascii(user_defined_bullet(i).getText())
709 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
710 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
712 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
713 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
714 for (; a_it != a_end; ++a_it) {
715 os << "\\author " << a_it->second << "\n";
720 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
721 TexRow & texrow) const
723 os << "\\documentclass";
725 LyXTextClass const & tclass = getLyXTextClass();
727 ostringstream clsoptions; // the document class options.
729 if (tokenPos(tclass.opt_fontsize(),
730 '|', fontsize) >= 0) {
731 // only write if existing in list (and not default)
732 clsoptions << fontsize << "pt,";
735 // custom, A3, B3 and B4 paper sizes need geometry
736 bool nonstandard_papersize = papersize == PAPER_B3
737 || papersize == PAPER_B4
738 || papersize == PAPER_A3
739 || papersize == PAPER_CUSTOM;
744 clsoptions << "a4paper,";
747 clsoptions << "letterpaper,";
750 clsoptions << "a5paper,";
753 clsoptions << "b5paper,";
755 case PAPER_USEXECUTIVE:
756 clsoptions << "executivepaper,";
759 clsoptions << "legalpaper,";
771 if (sides != tclass.sides()) {
773 case LyXTextClass::OneSide:
774 clsoptions << "oneside,";
776 case LyXTextClass::TwoSides:
777 clsoptions << "twoside,";
783 if (columns != tclass.columns()) {
785 clsoptions << "twocolumn,";
787 clsoptions << "onecolumn,";
791 && orientation == ORIENTATION_LANDSCAPE)
792 clsoptions << "landscape,";
794 // language should be a parameter to \documentclass
795 if (language->babel() == "hebrew"
796 && default_language->babel() != "hebrew")
797 // This seems necessary
798 features.useLanguage(default_language);
800 ostringstream language_options;
801 bool const use_babel = features.useBabel();
803 language_options << features.getLanguages();
804 language_options << language->babel();
805 if (lyxrc.language_global_options)
806 clsoptions << language_options.str() << ',';
809 // the user-defined options
810 if (!options.empty()) {
811 clsoptions << options << ',';
814 string strOptions(clsoptions.str());
815 if (!strOptions.empty()) {
816 strOptions = rtrim(strOptions, ",");
818 os << '[' << from_utf8(strOptions) << ']';
821 os << '{' << from_ascii(tclass.latexname()) << "}\n";
823 // end of \documentclass defs
825 // font selection must be done before loading fontenc.sty
827 loadFonts(features, fontsRoman, fontsSans,
828 fontsTypewriter, fontsSC, fontsOSF,
829 fontsSansScale, fontsTypewriterScale);
830 if (!fonts.empty()) {
831 os << from_ascii(fonts);
834 if (fontsDefaultFamily != "default")
835 os << "\\renewcommand{\\familydefault}{\\"
836 << from_ascii(fontsDefaultFamily) << "}\n";
837 // this one is not per buffer
838 if (lyxrc.fontenc != "default") {
839 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
844 if (inputenc == "auto") {
845 string const doc_encoding =
846 language->encoding()->latexName();
848 // Create a list with all the input encodings used
850 std::set<string> encodings =
851 features.getEncodingSet(doc_encoding);
853 os << "\\usepackage[";
854 std::set<string>::const_iterator it = encodings.begin();
855 std::set<string>::const_iterator const end = encodings.end();
856 for (; it != end; ++it)
857 os << from_ascii(*it) << ',';
858 os << from_ascii(doc_encoding) << "]{inputenc}\n";
860 } else if (inputenc != "default") {
861 os << "\\usepackage[" << from_ascii(inputenc)
866 if (use_geometry || nonstandard_papersize) {
867 os << "\\usepackage{geometry}\n";
869 os << "\\geometry{verbose";
870 if (orientation == ORIENTATION_LANDSCAPE)
874 if (!paperwidth.empty())
876 << from_ascii(paperwidth);
877 if (!paperheight.empty())
878 os << ",paperheight="
879 << from_ascii(paperheight);
882 os << ",letterpaper";
887 case PAPER_USEXECUTIVE:
888 os << ",executivepaper";
909 // default papersize ie PAPER_DEFAULT
910 switch (lyxrc.default_papersize) {
911 case PAPER_DEFAULT: // keep compiler happy
913 os << ",letterpaper";
918 case PAPER_USEXECUTIVE:
919 os << ",executivepaper";
939 if (!topmargin.empty())
940 os << ",tmargin=" << from_ascii(topmargin);
941 if (!bottommargin.empty())
942 os << ",bmargin=" << from_ascii(bottommargin);
943 if (!leftmargin.empty())
944 os << ",lmargin=" << from_ascii(leftmargin);
945 if (!rightmargin.empty())
946 os << ",rmargin=" << from_ascii(rightmargin);
947 if (!headheight.empty())
948 os << ",headheight=" << from_ascii(headheight);
949 if (!headsep.empty())
950 os << ",headsep=" << from_ascii(headsep);
951 if (!footskip.empty())
952 os << ",footskip=" << from_ascii(footskip);
957 if (tokenPos(tclass.opt_pagestyle(),
958 '|', pagestyle) >= 0) {
959 if (pagestyle == "fancy") {
960 os << "\\usepackage{fancyhdr}\n";
963 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
967 // Only if class has a ToC hierarchy
968 if (tclass.hasTocLevels()) {
969 if (secnumdepth != tclass.secnumdepth()) {
970 os << "\\setcounter{secnumdepth}{"
975 if (tocdepth != tclass.tocdepth()) {
976 os << "\\setcounter{tocdepth}{"
983 if (paragraph_separation) {
984 switch (getDefSkip().kind()) {
985 case VSpace::SMALLSKIP:
986 os << "\\setlength\\parskip{\\smallskipamount}\n";
988 case VSpace::MEDSKIP:
989 os << "\\setlength\\parskip{\\medskipamount}\n";
991 case VSpace::BIGSKIP:
992 os << "\\setlength\\parskip{\\bigskipamount}\n";
995 os << "\\setlength\\parskip{"
996 << from_utf8(getDefSkip().length().asLatexString())
999 default: // should never happen // Then delete it.
1000 os << "\\setlength\\parskip{\\medskipamount}\n";
1005 os << "\\setlength\\parindent{0pt}\n";
1009 // If we use jurabib, we have to call babel here.
1010 if (use_babel && features.isRequired("jurabib")) {
1011 os << from_ascii(babelCall(language_options.str()))
1013 << from_ascii(features.getBabelOptions());
1017 // Now insert the LyX specific LaTeX commands...
1019 // The optional packages;
1020 docstring lyxpreamble(from_ascii(features.getPackages()));
1022 // this might be useful...
1023 lyxpreamble += "\n\\makeatletter\n";
1025 // Some macros LyX will need
1026 docstring tmppreamble(from_ascii(features.getMacros()));
1028 if (!tmppreamble.empty()) {
1029 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1030 "LyX specific LaTeX commands.\n"
1031 + tmppreamble + '\n';
1034 // the text class specific preamble
1035 tmppreamble = features.getTClassPreamble();
1036 if (!tmppreamble.empty()) {
1037 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1038 "Textclass specific LaTeX commands.\n"
1039 + tmppreamble + '\n';
1042 /* the user-defined preamble */
1043 if (!preamble.empty()) {
1045 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1046 "User specified LaTeX commands.\n"
1047 + from_utf8(preamble) + '\n';
1050 // Itemize bullet settings need to be last in case the user
1051 // defines their own bullets that use a package included
1052 // in the user-defined preamble -- ARRae
1053 // Actually it has to be done much later than that
1054 // since some packages like frenchb make modifications
1055 // at \begin{document} time -- JMarc
1056 docstring bullets_def;
1057 for (int i = 0; i < 4; ++i) {
1058 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1059 if (bullets_def.empty())
1060 bullets_def += "\\AtBeginDocument{\n";
1061 bullets_def += " \\def\\labelitemi";
1063 // `i' is one less than the item to modify
1070 bullets_def += "ii";
1076 bullets_def += '{' +
1077 user_defined_bullet(i).getText()
1082 if (!bullets_def.empty())
1083 lyxpreamble += bullets_def + "}\n\n";
1085 // We try to load babel late, in case it interferes
1086 // with other packages.
1087 // Jurabib has to be called after babel, though.
1088 if (use_babel && !features.isRequired("jurabib")) {
1090 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1091 lyxpreamble += from_utf8(features.getBabelOptions());
1094 lyxpreamble += "\\makeatother\n";
1096 // dvipost settings come after everything else
1097 if (features.isAvailable("dvipost") && outputChanges) {
1100 "\\dvipost{osstart color push Red}\n"
1101 "\\dvipost{osend color pop}\n"
1102 "\\dvipost{cbstart color push Blue}\n"
1103 "\\dvipost{cbend color pop}\n";
1107 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1108 for (int j = 0; j != nlines; ++j) {
1117 void BufferParams::useClassDefaults()
1119 LyXTextClass const & tclass = textclasslist[textclass];
1121 sides = tclass.sides();
1122 columns = tclass.columns();
1123 pagestyle = tclass.pagestyle();
1124 options = tclass.options();
1125 // Only if class has a ToC hierarchy
1126 if (tclass.hasTocLevels()) {
1127 secnumdepth = tclass.secnumdepth();
1128 tocdepth = tclass.tocdepth();
1133 bool BufferParams::hasClassDefaults() const
1135 LyXTextClass const & tclass = textclasslist[textclass];
1137 return (sides == tclass.sides()
1138 && columns == tclass.columns()
1139 && pagestyle == tclass.pagestyle()
1140 && options == tclass.options()
1141 && secnumdepth == tclass.secnumdepth()
1142 && tocdepth == tclass.tocdepth());
1146 LyXTextClass const & BufferParams::getLyXTextClass() const
1148 return textclasslist[textclass];
1152 LyXFont const BufferParams::getFont() const
1154 LyXFont f = getLyXTextClass().defaultfont();
1155 f.setLanguage(language);
1156 if (fontsDefaultFamily == "rmdefault")
1157 f.setFamily(LyXFont::ROMAN_FAMILY);
1158 else if (fontsDefaultFamily == "sfdefault")
1159 f.setFamily(LyXFont::SANS_FAMILY);
1160 else if (fontsDefaultFamily == "ttdefault")
1161 f.setFamily(LyXFont::TYPEWRITER_FAMILY);
1166 void BufferParams::readPreamble(LyXLex & lex)
1168 if (lex.getString() != "\\begin_preamble")
1169 lyxerr << "Error (BufferParams::readPreamble):"
1170 "consistency check failed." << endl;
1172 preamble = lex.getLongString("\\end_preamble");
1176 void BufferParams::readLanguage(LyXLex & lex)
1178 if (!lex.next()) return;
1180 string const tmptok = lex.getString();
1182 // check if tmptok is part of tex_babel in tex-defs.h
1183 language = languages.getLanguage(tmptok);
1185 // Language tmptok was not found
1186 language = default_language;
1187 lyxerr << "Warning: Setting language `"
1188 << tmptok << "' to `" << language->lang()
1194 void BufferParams::readGraphicsDriver(LyXLex & lex)
1196 if (!lex.next()) return;
1198 string const tmptok = lex.getString();
1199 // check if tmptok is part of tex_graphics in tex_defs.h
1202 string const test = tex_graphics[n++];
1204 if (test == tmptok) {
1205 graphicsDriver = tmptok;
1207 } else if (test == "") {
1209 "Warning: graphics driver `$$Token' not recognized!\n"
1210 " Setting graphics driver to `default'.\n");
1211 graphicsDriver = "default";
1218 void BufferParams::readBullets(LyXLex & lex)
1220 if (!lex.next()) return;
1222 int const index = lex.getInteger();
1224 int temp_int = lex.getInteger();
1225 user_defined_bullet(index).setFont(temp_int);
1226 temp_bullet(index).setFont(temp_int);
1228 user_defined_bullet(index).setCharacter(temp_int);
1229 temp_bullet(index).setCharacter(temp_int);
1231 user_defined_bullet(index).setSize(temp_int);
1232 temp_bullet(index).setSize(temp_int);
1236 void BufferParams::readBulletsLaTeX(LyXLex & lex)
1238 // The bullet class should be able to read this.
1239 if (!lex.next()) return;
1240 int const index = lex.getInteger();
1242 docstring const temp_str = lex.getDocString();
1244 user_defined_bullet(index).setText(temp_str);
1245 temp_bullet(index).setText(temp_str);
1249 string const BufferParams::paperSizeName() const
1251 char real_papersize = papersize;
1252 if (real_papersize == PAPER_DEFAULT)
1253 real_papersize = lyxrc.default_papersize;
1255 switch (real_papersize) {
1264 case PAPER_USEXECUTIVE:
1268 case PAPER_USLETTER:
1275 string const BufferParams::dvips_options() const
1280 && papersize == PAPER_CUSTOM
1281 && !lyxrc.print_paper_dimension_flag.empty()
1282 && !paperwidth.empty()
1283 && !paperheight.empty()) {
1284 // using a custom papersize
1285 result = lyxrc.print_paper_dimension_flag;
1286 result += ' ' + paperwidth;
1287 result += ',' + paperheight;
1289 string const paper_option = paperSizeName();
1290 if (paper_option != "letter" ||
1291 orientation != ORIENTATION_LANDSCAPE) {
1292 // dvips won't accept -t letter -t landscape.
1293 // In all other cases, include the paper size
1295 result = lyxrc.print_paper_flag;
1296 result += ' ' + paper_option;
1299 if (orientation == ORIENTATION_LANDSCAPE &&
1300 papersize != PAPER_CUSTOM)
1301 result += ' ' + lyxrc.print_landscape_flag;
1306 string const BufferParams::babelCall(string const & lang_opts) const
1308 string tmp = lyxrc.language_package;
1309 if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1310 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1315 string const BufferParams::loadFonts(LaTeXFeatures & features, string const & rm,
1316 string const & sf, string const & tt,
1317 bool const & sc, bool const & osf,
1318 int const & sfscale, int const & ttscale) const
1320 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1321 several packages have been replaced by others, that might not
1322 be installed on every system. We have to take care for that
1323 (see psnfss.pdf). We try to support all psnfss fonts as well
1324 as the fonts that have become de facto standard in the LaTeX
1325 world (e.g. Latin Modern). We do not support obsolete fonts
1326 (like PSLatex). In general, it should be possible to mix any
1327 rm font with any sf or tt font, respectively. (JSpitzm)
1329 -- separate math fonts.
1332 if (rm == "default" && sf == "default" && tt == "default")
1339 // Computer Modern (must be explicitely selectable -- there might be classes
1340 // that define a different default font!
1342 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1343 // osf for Computer Modern needs eco.sty
1345 os << "\\usepackage{eco}\n";
1347 // Latin Modern Roman
1348 else if (rm == "lmodern")
1349 os << "\\usepackage{lmodern}\n";
1351 else if (rm == "ae") {
1352 // not needed when using OT1 font encoding.
1353 if (lyxrc.fontenc != "default")
1354 os << "\\usepackage{ae,aecompl}\n";
1357 else if (rm == "times") {
1358 // try to load the best available package
1359 if (features.isAvailable("mathptmx"))
1360 os << "\\usepackage{mathptmx}\n";
1361 else if (features.isAvailable("mathptm"))
1362 os << "\\usepackage{mathptm}\n";
1364 os << "\\usepackage{times}\n";
1367 else if (rm == "palatino") {
1368 // try to load the best available package
1369 if (features.isAvailable("mathpazo")) {
1370 os << "\\usepackage";
1376 // "osf" includes "sc"!
1380 os << "{mathpazo}\n";
1382 else if (features.isAvailable("mathpple"))
1383 os << "\\usepackage{mathpple}\n";
1385 os << "\\usepackage{palatino}\n";
1388 else if (rm == "utopia") {
1389 // fourier supersedes utopia.sty, but does
1390 // not work with OT1 encoding.
1391 if (features.isAvailable("fourier")
1392 && lyxrc.fontenc != "default") {
1393 os << "\\usepackage";
1404 os << "{fourier}\n";
1407 os << "\\usepackage{utopia}\n";
1409 // Bera (complete fontset)
1410 else if (rm == "bera" && sf == "default" && tt == "default")
1411 os << "\\usepackage{bera}\n";
1413 else if (rm != "default")
1414 os << "\\usepackage" << "{" << rm << "}\n";
1417 // Helvetica, Bera Sans
1418 if (sf == "helvet" || sf == "berasans") {
1420 os << "\\usepackage[scaled=" << float(sfscale) / 100
1421 << "]{" << sf << "}\n";
1423 os << "\\usepackage{" << sf << "}\n";
1426 else if (sf == "avant")
1427 os << "\\usepackage{" << sf << "}\n";
1428 // Computer Modern, Latin Modern, CM Bright
1429 else if (sf != "default")
1430 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1432 // monospaced/typewriter
1433 // Courier, LuxiMono
1434 if (tt == "luximono" || tt == "beramono") {
1436 os << "\\usepackage[scaled=" << float(ttscale) / 100
1437 << "]{" << tt << "}\n";
1439 os << "\\usepackage{" << tt << "}\n";
1442 else if (tt == "courier" )
1443 os << "\\usepackage{" << tt << "}\n";
1444 // Computer Modern, Latin Modern, CM Bright
1445 else if (tt != "default")
1446 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";