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();
179 typedef Translator<int, BufferParams::AMS> AMSTranslator;
182 AMSTranslator const init_amstranslator()
184 AMSTranslator translator(0, BufferParams::AMS_OFF);
185 translator.addPair(1, BufferParams::AMS_AUTO);
186 translator.addPair(2, BufferParams::AMS_ON);
191 AMSTranslator const & amstranslator()
193 static AMSTranslator translator = init_amstranslator();
199 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
202 CiteEngineTranslator const init_citeenginetranslator()
204 CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
205 translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
206 translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
207 translator.addPair("jurabib", biblio::ENGINE_JURABIB);
212 CiteEngineTranslator const & citeenginetranslator()
214 static CiteEngineTranslator translator = init_citeenginetranslator();
220 typedef Translator<string, Spacing::Space> SpaceTranslator;
223 SpaceTranslator const init_spacetranslator()
225 SpaceTranslator translator("default", Spacing::Default);
226 translator.addPair("single", Spacing::Single);
227 translator.addPair("onehalf", Spacing::Onehalf);
228 translator.addPair("double", Spacing::Double);
229 translator.addPair("other", Spacing::Other);
234 SpaceTranslator const & spacetranslator()
236 static SpaceTranslator translator = init_spacetranslator();
240 // ends annonym namespace
244 class BufferParams::Impl
249 AuthorList authorlist;
250 BranchList branchlist;
251 boost::array<Bullet, 4> temp_bullets;
252 boost::array<Bullet, 4> user_defined_bullets;
254 /** This is the amount of space used for paragraph_separation "skip",
255 * and for detached paragraphs in "indented" documents.
261 BufferParams::Impl::Impl()
262 : defskip(VSpace::MEDSKIP)
264 // set initial author
265 authorlist.record(Author(lyxrc.user_name, lyxrc.user_email));
270 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
274 return new BufferParams::Impl(*ptr);
278 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
284 BufferParams::BufferParams()
285 : // Initialize textclass to point to article. if `first' is
286 // true in the returned pair, then `second' is the textclass
287 // number; if it is false, second is 0. In both cases, second
289 textclass(textclasslist.numberOfClass("article").second),
292 paragraph_separation = PARSEP_INDENT;
293 quotes_language = InsetQuotes::EnglishQ;
294 fontsize = "default";
297 papersize = PAPER_DEFAULT;
298 orientation = ORIENTATION_PORTRAIT;
299 use_geometry = false;
300 use_amsmath = AMS_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 = amstranslator().find(use_ams);
486 } else if (token == "\\cite_engine") {
489 cite_engine = citeenginetranslator().find(engine);
490 } else if (token == "\\use_bibtopic") {
492 } else if (token == "\\tracking_changes") {
494 } else if (token == "\\output_changes") {
495 lex >> outputChanges;
496 } else if (token == "\\branch") {
498 string branch = lex.getString();
499 branchlist().add(branch);
502 string const tok = lex.getString();
503 if (tok == "\\end_branch")
505 Branch * branch_ptr = branchlist().find(branch);
506 if (tok == "\\selected") {
509 branch_ptr->setSelected(lex.getInteger());
511 // not yet operational
512 if (tok == "\\color") {
514 string color = lex.getString();
516 branch_ptr->setColor(color);
517 // Update also the LColor table:
519 color = lcolor.getX11Name(LColor::background);
520 lcolor.setColor(branch, color);
524 } else if (token == "\\author") {
526 istringstream ss(lex.getString());
529 author_map.push_back(pimpl_->authorlist.record(a));
530 } else if (token == "\\paperorientation") {
533 orientation = paperorientationtranslator().find(orient);
534 } else if (token == "\\paperwidth") {
536 } else if (token == "\\paperheight") {
538 } else if (token == "\\leftmargin") {
540 } else if (token == "\\topmargin") {
542 } else if (token == "\\rightmargin") {
544 } else if (token == "\\bottommargin") {
546 } else if (token == "\\headheight") {
548 } else if (token == "\\headsep") {
550 } else if (token == "\\footskip") {
552 } else if (token == "\\paperfontsize") {
554 } else if (token == "\\papercolumns") {
556 } else if (token == "\\papersides") {
559 sides = sidestranslator().find(psides);
560 } else if (token == "\\paperpagestyle") {
562 } else if (token == "\\bullet") {
564 } else if (token == "\\bulletLaTeX") {
565 readBulletsLaTeX(lex);
566 } else if (token == "\\secnumdepth") {
568 } else if (token == "\\tocdepth") {
570 } else if (token == "\\spacing") {
574 if (nspacing == "other") {
577 spacing().set(spacetranslator().find(nspacing), tmp_val);
578 } else if (token == "\\float_placement") {
579 lex >> float_placement;
588 void BufferParams::writeFile(ostream & os) const
590 // The top of the file is written by the buffer.
591 // Prints out the buffer info into the .lyx file given by file
594 os << "\\textclass " << textclasslist[textclass].name() << '\n';
596 // then the the preamble
597 if (!preamble.empty()) {
598 // remove '\n' from the end of preamble
599 string const tmppreamble = rtrim(preamble, "\n");
600 os << "\\begin_preamble\n"
602 << "\n\\end_preamble\n";
606 if (!options.empty()) {
607 os << "\\options " << options << '\n';
610 // then the text parameters
611 if (language != ignore_language)
612 os << "\\language " << language->lang() << '\n';
613 os << "\\inputencoding " << inputenc
614 << "\n\\font_roman " << fontsRoman
615 << "\n\\font_sans " << fontsSans
616 << "\n\\font_typewriter " << fontsTypewriter
617 << "\n\\font_default_family " << fontsDefaultFamily
618 << "\n\\font_sc " << convert<string>(fontsSC)
619 << "\n\\font_osf " << convert<string>(fontsOSF)
620 << "\n\\font_sf_scale " << fontsSansScale
621 << "\n\\font_tt_scale " << fontsTypewriterScale
622 << "\n\\graphics " << graphicsDriver << '\n';
624 if (!float_placement.empty()) {
625 os << "\\float_placement " << float_placement << '\n';
627 os << "\\paperfontsize " << fontsize << '\n';
629 spacing().writeFile(os);
631 os << "\\papersize " << string_papersize[papersize]
632 << "\n\\use_geometry " << convert<string>(use_geometry)
633 << "\n\\use_amsmath " << use_amsmath
634 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine)
635 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
636 << "\n\\paperorientation " << string_orientation[orientation]
639 BranchList::const_iterator it = branchlist().begin();
640 BranchList::const_iterator end = branchlist().end();
641 for (; it != end; ++it) {
642 os << "\\branch " << it->getBranch()
643 << "\n\\selected " << it->getSelected()
644 << "\n\\color " << lyx::X11hexname(it->getColor())
649 if (!paperwidth.empty())
650 os << "\\paperwidth "
651 << VSpace(paperwidth).asLyXCommand() << '\n';
652 if (!paperheight.empty())
653 os << "\\paperheight "
654 << VSpace(paperheight).asLyXCommand() << '\n';
655 if (!leftmargin.empty())
656 os << "\\leftmargin "
657 << VSpace(leftmargin).asLyXCommand() << '\n';
658 if (!topmargin.empty())
660 << VSpace(topmargin).asLyXCommand() << '\n';
661 if (!rightmargin.empty())
662 os << "\\rightmargin "
663 << VSpace(rightmargin).asLyXCommand() << '\n';
664 if (!bottommargin.empty())
665 os << "\\bottommargin "
666 << VSpace(bottommargin).asLyXCommand() << '\n';
667 if (!headheight.empty())
668 os << "\\headheight "
669 << VSpace(headheight).asLyXCommand() << '\n';
670 if (!headsep.empty())
672 << VSpace(headsep).asLyXCommand() << '\n';
673 if (!footskip.empty())
675 << VSpace(footskip).asLyXCommand() << '\n';
676 os << "\\secnumdepth " << secnumdepth
677 << "\n\\tocdepth " << tocdepth
678 << "\n\\paragraph_separation "
679 << string_paragraph_separation[paragraph_separation]
680 << "\n\\defskip " << getDefSkip().asLyXCommand()
681 << "\n\\quotes_language "
682 << string_quotes_language[quotes_language]
683 << "\n\\papercolumns " << columns
684 << "\n\\papersides " << sides
685 << "\n\\paperpagestyle " << pagestyle << '\n';
686 for (int i = 0; i < 4; ++i) {
687 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
688 if (user_defined_bullet(i).getFont() != -1) {
689 os << "\\bullet " << i << " "
690 << user_defined_bullet(i).getFont() << " "
691 << user_defined_bullet(i).getCharacter() << " "
692 << user_defined_bullet(i).getSize() << "\n";
696 os << "\\bulletLaTeX " << i << " \""
697 << lyx::to_ascii(user_defined_bullet(i).getText())
703 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
704 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
706 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
707 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
708 for (; a_it != a_end; ++a_it) {
709 os << "\\author " << a_it->second << "\n";
714 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
715 TexRow & texrow) const
717 os << "\\documentclass";
719 LyXTextClass const & tclass = getLyXTextClass();
721 ostringstream clsoptions; // the document class options.
723 if (tokenPos(tclass.opt_fontsize(),
724 '|', fontsize) >= 0) {
725 // only write if existing in list (and not default)
726 clsoptions << fontsize << "pt,";
729 // custom, A3, B3 and B4 paper sizes need geometry
730 bool nonstandard_papersize = (papersize == PAPER_B3) ||
731 (papersize == PAPER_B4) ||
732 (papersize == PAPER_A3) ||
733 (papersize == PAPER_CUSTOM);
738 clsoptions << "a4paper,";
741 clsoptions << "letterpaper,";
744 clsoptions << "a5paper,";
747 clsoptions << "b5paper,";
749 case PAPER_USEXECUTIVE:
750 clsoptions << "executivepaper,";
753 clsoptions << "legalpaper,";
765 if (sides != tclass.sides()) {
767 case LyXTextClass::OneSide:
768 clsoptions << "oneside,";
770 case LyXTextClass::TwoSides:
771 clsoptions << "twoside,";
777 if (columns != tclass.columns()) {
779 clsoptions << "twocolumn,";
781 clsoptions << "onecolumn,";
785 && orientation == ORIENTATION_LANDSCAPE)
786 clsoptions << "landscape,";
788 // language should be a parameter to \documentclass
789 if (language->babel() == "hebrew"
790 && default_language->babel() != "hebrew")
791 // This seems necessary
792 features.useLanguage(default_language);
794 ostringstream language_options;
795 bool const use_babel = features.useBabel();
797 language_options << features.getLanguages();
798 language_options << language->babel();
799 if (lyxrc.language_global_options)
800 clsoptions << language_options.str() << ',';
803 // the user-defined options
804 if (!options.empty()) {
805 clsoptions << options << ',';
808 string strOptions(clsoptions.str());
809 if (!strOptions.empty()) {
810 strOptions = rtrim(strOptions, ",");
812 os << '[' << from_utf8(strOptions) << ']';
815 os << '{' << from_ascii(tclass.latexname()) << "}\n";
817 // end of \documentclass defs
819 // font selection must be done before loading fontenc.sty
821 loadFonts(features, fontsRoman, fontsSans,
822 fontsTypewriter, fontsSC, fontsOSF,
823 fontsSansScale, fontsTypewriterScale);
824 if (!fonts.empty()) {
825 os << from_ascii(fonts);
828 if (fontsDefaultFamily != "default")
829 os << "\\renewcommand{\\familydefault}{\\"
830 << from_ascii(fontsDefaultFamily) << "}\n";
831 // this one is not per buffer
832 if (lyxrc.fontenc != "default") {
833 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
838 // TODO: Some people want to support more encodings than UTF-8. They can have a field day around here
840 os << "\\usepackage[utf8]{inputenc}\n";
843 if (inputenc == "auto") {
844 string const doc_encoding =
845 language->encoding()->latexName();
847 // Create a list with all the input encodings used
849 std::set<string> encodings =
850 features.getEncodingSet(doc_encoding);
852 os << "\\usepackage[";
853 std::set<string>::const_iterator it = encodings.begin();
854 std::set<string>::const_iterator const end = encodings.end();
855 for (; it != end; ++it)
856 os << from_ascii(*it) << ',';
857 os << from_ascii(doc_encoding) << "]{inputenc}\n";
859 } else if (inputenc != "default") {
860 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_ascii(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 string lyxpreamble(features.getPackages());
1022 // this might be useful...
1023 lyxpreamble += "\n\\makeatletter\n";
1025 // Some macros LyX will need
1026 string tmppreamble(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()) {
1044 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1045 "User specified LaTeX commands.\n"
1049 // Itemize bullet settings need to be last in case the user
1050 // defines their own bullets that use a package included
1051 // in the user-defined preamble -- ARRae
1052 // Actually it has to be done much later than that
1053 // since some packages like frenchb make modifications
1054 // at \begin{document} time -- JMarc
1056 for (int i = 0; i < 4; ++i) {
1057 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1058 if (bullets_def.empty())
1059 bullets_def="\\AtBeginDocument{\n";
1060 bullets_def += " \\def\\labelitemi";
1062 // `i' is one less than the item to modify
1069 bullets_def += "ii";
1076 bullets_def += '{' +
1077 lyx::to_ascii(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")) {
1089 lyxpreamble += babelCall(language_options.str()) + '\n';
1090 lyxpreamble += features.getBabelOptions();
1093 lyxpreamble += "\\makeatother\n";
1095 // dvipost settings come after everything else
1096 if (features.isAvailable("dvipost") && outputChanges) {
1099 "\\dvipost{osstart color push Red}\n"
1100 "\\dvipost{osend color pop}\n"
1101 "\\dvipost{cbstart color push Blue}\n"
1102 "\\dvipost{cbend color pop}\n";
1106 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1107 for (int j = 0; j != nlines; ++j) {
1112 os << from_utf8(lyxpreamble);
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";