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 if (inputenc == "auto") {
839 string const doc_encoding =
840 language->encoding()->latexName();
842 // Create a list with all the input encodings used
844 std::set<string> encodings =
845 features.getEncodingSet(doc_encoding);
847 os << "\\usepackage[";
848 std::set<string>::const_iterator it = encodings.begin();
849 std::set<string>::const_iterator const end = encodings.end();
850 for (; it != end; ++it)
851 os << from_ascii(*it) << ',';
852 os << from_ascii(doc_encoding) << "]{inputenc}\n";
854 } else if (inputenc != "default") {
855 os << "\\usepackage[" << from_ascii(inputenc)
860 if (use_geometry || nonstandard_papersize) {
861 os << "\\usepackage{geometry}\n";
863 os << "\\geometry{verbose";
864 if (orientation == ORIENTATION_LANDSCAPE)
868 if (!paperwidth.empty())
870 << from_ascii(paperwidth);
871 if (!paperheight.empty())
872 os << ",paperheight="
873 << from_ascii(paperheight);
876 os << ",letterpaper";
881 case PAPER_USEXECUTIVE:
882 os << ",executivepaper";
903 // default papersize ie PAPER_DEFAULT
904 switch (lyxrc.default_papersize) {
905 case PAPER_DEFAULT: // keep compiler happy
907 os << ",letterpaper";
912 case PAPER_USEXECUTIVE:
913 os << ",executivepaper";
933 if (!topmargin.empty())
934 os << ",tmargin=" << from_ascii(topmargin);
935 if (!bottommargin.empty())
936 os << ",bmargin=" << from_ascii(bottommargin);
937 if (!leftmargin.empty())
938 os << ",lmargin=" << from_ascii(leftmargin);
939 if (!rightmargin.empty())
940 os << ",rmargin=" << from_ascii(rightmargin);
941 if (!headheight.empty())
942 os << ",headheight=" << from_ascii(headheight);
943 if (!headsep.empty())
944 os << ",headsep=" << from_ascii(headsep);
945 if (!footskip.empty())
946 os << ",footskip=" << from_ascii(footskip);
951 if (tokenPos(tclass.opt_pagestyle(),
952 '|', pagestyle) >= 0) {
953 if (pagestyle == "fancy") {
954 os << "\\usepackage{fancyhdr}\n";
957 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
961 // Only if class has a ToC hierarchy
962 if (tclass.hasTocLevels()) {
963 if (secnumdepth != tclass.secnumdepth()) {
964 os << "\\setcounter{secnumdepth}{"
969 if (tocdepth != tclass.tocdepth()) {
970 os << "\\setcounter{tocdepth}{"
977 if (paragraph_separation) {
978 switch (getDefSkip().kind()) {
979 case VSpace::SMALLSKIP:
980 os << "\\setlength\\parskip{\\smallskipamount}\n";
982 case VSpace::MEDSKIP:
983 os << "\\setlength\\parskip{\\medskipamount}\n";
985 case VSpace::BIGSKIP:
986 os << "\\setlength\\parskip{\\bigskipamount}\n";
989 os << "\\setlength\\parskip{"
990 << from_utf8(getDefSkip().length().asLatexString())
993 default: // should never happen // Then delete it.
994 os << "\\setlength\\parskip{\\medskipamount}\n";
999 os << "\\setlength\\parindent{0pt}\n";
1003 // If we use jurabib, we have to call babel here.
1004 if (use_babel && features.isRequired("jurabib")) {
1005 os << from_ascii(babelCall(language_options.str()))
1007 << from_ascii(features.getBabelOptions());
1011 // Now insert the LyX specific LaTeX commands...
1013 // The optional packages;
1014 string lyxpreamble(features.getPackages());
1016 // this might be useful...
1017 lyxpreamble += "\n\\makeatletter\n";
1019 // Some macros LyX will need
1020 string tmppreamble(features.getMacros());
1022 if (!tmppreamble.empty()) {
1023 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1024 "LyX specific LaTeX commands.\n"
1025 + tmppreamble + '\n';
1028 // the text class specific preamble
1029 tmppreamble = features.getTClassPreamble();
1030 if (!tmppreamble.empty()) {
1031 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1032 "Textclass specific LaTeX commands.\n"
1033 + tmppreamble + '\n';
1036 /* the user-defined preamble */
1037 if (!preamble.empty()) {
1038 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1039 "User specified LaTeX commands.\n"
1043 // Itemize bullet settings need to be last in case the user
1044 // defines their own bullets that use a package included
1045 // in the user-defined preamble -- ARRae
1046 // Actually it has to be done much later than that
1047 // since some packages like frenchb make modifications
1048 // at \begin{document} time -- JMarc
1050 for (int i = 0; i < 4; ++i) {
1051 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1052 if (bullets_def.empty())
1053 bullets_def="\\AtBeginDocument{\n";
1054 bullets_def += " \\def\\labelitemi";
1056 // `i' is one less than the item to modify
1063 bullets_def += "ii";
1070 bullets_def += '{' +
1071 lyx::to_ascii(user_defined_bullet(i).getText())
1076 if (!bullets_def.empty())
1077 lyxpreamble += bullets_def + "}\n\n";
1079 // We try to load babel late, in case it interferes
1080 // with other packages.
1081 // Jurabib has to be called after babel, though.
1082 if (use_babel && !features.isRequired("jurabib")) {
1083 lyxpreamble += babelCall(language_options.str()) + '\n';
1084 lyxpreamble += features.getBabelOptions();
1087 lyxpreamble += "\\makeatother\n";
1089 // dvipost settings come after everything else
1090 if (features.isAvailable("dvipost") && outputChanges) {
1093 "\\dvipost{osstart color push Red}\n"
1094 "\\dvipost{osend color pop}\n"
1095 "\\dvipost{cbstart color push Blue}\n"
1096 "\\dvipost{cbend color pop}\n";
1100 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1101 for (int j = 0; j != nlines; ++j) {
1106 os << from_utf8(lyxpreamble);
1111 void BufferParams::useClassDefaults()
1113 LyXTextClass const & tclass = textclasslist[textclass];
1115 sides = tclass.sides();
1116 columns = tclass.columns();
1117 pagestyle = tclass.pagestyle();
1118 options = tclass.options();
1119 // Only if class has a ToC hierarchy
1120 if (tclass.hasTocLevels()) {
1121 secnumdepth = tclass.secnumdepth();
1122 tocdepth = tclass.tocdepth();
1127 bool BufferParams::hasClassDefaults() const
1129 LyXTextClass const & tclass = textclasslist[textclass];
1131 return (sides == tclass.sides()
1132 && columns == tclass.columns()
1133 && pagestyle == tclass.pagestyle()
1134 && options == tclass.options()
1135 && secnumdepth == tclass.secnumdepth()
1136 && tocdepth == tclass.tocdepth());
1140 LyXTextClass const & BufferParams::getLyXTextClass() const
1142 return textclasslist[textclass];
1146 LyXFont const BufferParams::getFont() const
1148 LyXFont f = getLyXTextClass().defaultfont();
1149 f.setLanguage(language);
1150 if (fontsDefaultFamily == "rmdefault")
1151 f.setFamily(LyXFont::ROMAN_FAMILY);
1152 else if (fontsDefaultFamily == "sfdefault")
1153 f.setFamily(LyXFont::SANS_FAMILY);
1154 else if (fontsDefaultFamily == "ttdefault")
1155 f.setFamily(LyXFont::TYPEWRITER_FAMILY);
1160 void BufferParams::readPreamble(LyXLex & lex)
1162 if (lex.getString() != "\\begin_preamble")
1163 lyxerr << "Error (BufferParams::readPreamble):"
1164 "consistency check failed." << endl;
1166 preamble = lex.getLongString("\\end_preamble");
1170 void BufferParams::readLanguage(LyXLex & lex)
1172 if (!lex.next()) return;
1174 string const tmptok = lex.getString();
1176 // check if tmptok is part of tex_babel in tex-defs.h
1177 language = languages.getLanguage(tmptok);
1179 // Language tmptok was not found
1180 language = default_language;
1181 lyxerr << "Warning: Setting language `"
1182 << tmptok << "' to `" << language->lang()
1188 void BufferParams::readGraphicsDriver(LyXLex & lex)
1190 if (!lex.next()) return;
1192 string const tmptok = lex.getString();
1193 // check if tmptok is part of tex_graphics in tex_defs.h
1196 string const test = tex_graphics[n++];
1198 if (test == tmptok) {
1199 graphicsDriver = tmptok;
1201 } else if (test == "") {
1203 "Warning: graphics driver `$$Token' not recognized!\n"
1204 " Setting graphics driver to `default'.\n");
1205 graphicsDriver = "default";
1212 void BufferParams::readBullets(LyXLex & lex)
1214 if (!lex.next()) return;
1216 int const index = lex.getInteger();
1218 int temp_int = lex.getInteger();
1219 user_defined_bullet(index).setFont(temp_int);
1220 temp_bullet(index).setFont(temp_int);
1222 user_defined_bullet(index).setCharacter(temp_int);
1223 temp_bullet(index).setCharacter(temp_int);
1225 user_defined_bullet(index).setSize(temp_int);
1226 temp_bullet(index).setSize(temp_int);
1230 void BufferParams::readBulletsLaTeX(LyXLex & lex)
1232 // The bullet class should be able to read this.
1233 if (!lex.next()) return;
1234 int const index = lex.getInteger();
1236 docstring const temp_str = lex.getDocString();
1238 user_defined_bullet(index).setText(temp_str);
1239 temp_bullet(index).setText(temp_str);
1243 string const BufferParams::paperSizeName() const
1245 char real_papersize = papersize;
1246 if (real_papersize == PAPER_DEFAULT)
1247 real_papersize = lyxrc.default_papersize;
1249 switch (real_papersize) {
1258 case PAPER_USEXECUTIVE:
1262 case PAPER_USLETTER:
1269 string const BufferParams::dvips_options() const
1274 && papersize == PAPER_CUSTOM
1275 && !lyxrc.print_paper_dimension_flag.empty()
1276 && !paperwidth.empty()
1277 && !paperheight.empty()) {
1278 // using a custom papersize
1279 result = lyxrc.print_paper_dimension_flag;
1280 result += ' ' + paperwidth;
1281 result += ',' + paperheight;
1283 string const paper_option = paperSizeName();
1284 if (paper_option != "letter" ||
1285 orientation != ORIENTATION_LANDSCAPE) {
1286 // dvips won't accept -t letter -t landscape.
1287 // In all other cases, include the paper size
1289 result = lyxrc.print_paper_flag;
1290 result += ' ' + paper_option;
1293 if (orientation == ORIENTATION_LANDSCAPE &&
1294 papersize != PAPER_CUSTOM)
1295 result += ' ' + lyxrc.print_landscape_flag;
1300 string const BufferParams::babelCall(string const & lang_opts) const
1302 string tmp = lyxrc.language_package;
1303 if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1304 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1309 string const BufferParams::loadFonts(LaTeXFeatures & features, string const & rm,
1310 string const & sf, string const & tt,
1311 bool const & sc, bool const & osf,
1312 int const & sfscale, int const & ttscale) const
1314 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1315 several packages have been replaced by others, that might not
1316 be installed on every system. We have to take care for that
1317 (see psnfss.pdf). We try to support all psnfss fonts as well
1318 as the fonts that have become de facto standard in the LaTeX
1319 world (e.g. Latin Modern). We do not support obsolete fonts
1320 (like PSLatex). In general, it should be possible to mix any
1321 rm font with any sf or tt font, respectively. (JSpitzm)
1323 -- separate math fonts.
1326 if (rm == "default" && sf == "default" && tt == "default")
1333 // Computer Modern (must be explicitely selectable -- there might be classes
1334 // that define a different default font!
1336 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1337 // osf for Computer Modern needs eco.sty
1339 os << "\\usepackage{eco}\n";
1341 // Latin Modern Roman
1342 else if (rm == "lmodern")
1343 os << "\\usepackage{lmodern}\n";
1345 else if (rm == "ae") {
1346 // not needed when using OT1 font encoding.
1347 if (lyxrc.fontenc != "default")
1348 os << "\\usepackage{ae,aecompl}\n";
1351 else if (rm == "times") {
1352 // try to load the best available package
1353 if (features.isAvailable("mathptmx"))
1354 os << "\\usepackage{mathptmx}\n";
1355 else if (features.isAvailable("mathptm"))
1356 os << "\\usepackage{mathptm}\n";
1358 os << "\\usepackage{times}\n";
1361 else if (rm == "palatino") {
1362 // try to load the best available package
1363 if (features.isAvailable("mathpazo")) {
1364 os << "\\usepackage";
1370 // "osf" includes "sc"!
1374 os << "{mathpazo}\n";
1376 else if (features.isAvailable("mathpple"))
1377 os << "\\usepackage{mathpple}\n";
1379 os << "\\usepackage{palatino}\n";
1382 else if (rm == "utopia") {
1383 // fourier supersedes utopia.sty, but does
1384 // not work with OT1 encoding.
1385 if (features.isAvailable("fourier")
1386 && lyxrc.fontenc != "default") {
1387 os << "\\usepackage";
1398 os << "{fourier}\n";
1401 os << "\\usepackage{utopia}\n";
1403 // Bera (complete fontset)
1404 else if (rm == "bera" && sf == "default" && tt == "default")
1405 os << "\\usepackage{bera}\n";
1407 else if (rm != "default")
1408 os << "\\usepackage" << "{" << rm << "}\n";
1411 // Helvetica, Bera Sans
1412 if (sf == "helvet" || sf == "berasans") {
1414 os << "\\usepackage[scaled=" << float(sfscale) / 100
1415 << "]{" << sf << "}\n";
1417 os << "\\usepackage{" << sf << "}\n";
1420 else if (sf == "avant")
1421 os << "\\usepackage{" << sf << "}\n";
1422 // Computer Modern, Latin Modern, CM Bright
1423 else if (sf != "default")
1424 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1426 // monospaced/typewriter
1427 // Courier, LuxiMono
1428 if (tt == "luximono" || tt == "beramono") {
1430 os << "\\usepackage[scaled=" << float(ttscale) / 100
1431 << "]{" << tt << "}\n";
1433 os << "\\usepackage{" << tt << "}\n";
1436 else if (tt == "courier" )
1437 os << "\\usepackage{" << tt << "}\n";
1438 // Computer Modern, Latin Modern, CM Bright
1439 else if (tt != "default")
1440 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";