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>
49 namespace support = lyx::support;
52 using lyx::support::bformat;
53 using lyx::support::rtrim;
54 using lyx::support::tokenPos;
58 using std::istringstream;
60 using std::ostringstream;
63 namespace biblio = lyx::biblio;
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"), lyx::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";
695 os << "\\bulletLaTeX " << i << " \""
696 << user_defined_bullet(i).getText()
702 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
703 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
706 // FIXME: Change tracking (MG)
707 AuthorList::Authors::const_iterator it = pimpl_->authorlist.begin();
708 AuthorList::Authors::const_iterator end = pimpl_->authorlist.end();
709 for (; it != end; ++it) {
710 os << "\\author " << it->second << "\n";
716 bool BufferParams::writeLaTeX(ostream & os, LaTeXFeatures & features,
717 TexRow & texrow) const
719 os << "\\documentclass";
721 LyXTextClass const & tclass = getLyXTextClass();
723 ostringstream clsoptions; // the document class options.
725 if (tokenPos(tclass.opt_fontsize(),
726 '|', fontsize) >= 0) {
727 // only write if existing in list (and not default)
728 clsoptions << fontsize << "pt,";
731 // custom, A3, B3 and B4 paper sizes need geometry
732 bool nonstandard_papersize = (papersize == PAPER_B3) ||
733 (papersize == PAPER_B4) ||
734 (papersize == PAPER_A3) ||
735 (papersize == PAPER_CUSTOM);
740 clsoptions << "a4paper,";
743 clsoptions << "letterpaper,";
746 clsoptions << "a5paper,";
749 clsoptions << "b5paper,";
751 case PAPER_USEXECUTIVE:
752 clsoptions << "executivepaper,";
755 clsoptions << "legalpaper,";
767 if (sides != tclass.sides()) {
769 case LyXTextClass::OneSide:
770 clsoptions << "oneside,";
772 case LyXTextClass::TwoSides:
773 clsoptions << "twoside,";
779 if (columns != tclass.columns()) {
781 clsoptions << "twocolumn,";
783 clsoptions << "onecolumn,";
787 && orientation == ORIENTATION_LANDSCAPE)
788 clsoptions << "landscape,";
790 // language should be a parameter to \documentclass
791 if (language->babel() == "hebrew"
792 && default_language->babel() != "hebrew")
793 // This seems necessary
794 features.useLanguage(default_language);
796 ostringstream language_options;
797 bool const use_babel = features.useBabel();
799 language_options << features.getLanguages();
800 language_options << language->babel();
801 if (lyxrc.language_global_options)
802 clsoptions << language_options.str() << ',';
805 // the user-defined options
806 if (!options.empty()) {
807 clsoptions << options << ',';
810 string strOptions(clsoptions.str());
811 if (!strOptions.empty()) {
812 strOptions = rtrim(strOptions, ",");
813 os << '[' << strOptions << ']';
816 os << '{' << tclass.latexname() << "}\n";
818 // end of \documentclass defs
820 // font selection must be done before loading fontenc.sty
822 loadFonts(features, fontsRoman, fontsSans,
823 fontsTypewriter, fontsSC, fontsOSF,
824 fontsSansScale, fontsTypewriterScale);
825 if (!fonts.empty()) {
829 if (fontsDefaultFamily != "default")
830 os << "\\renewcommand{\\familydefault}{\\"
831 << fontsDefaultFamily << "}\n";
832 // this one is not per buffer
833 if (lyxrc.fontenc != "default") {
834 os << "\\usepackage[" << lyxrc.fontenc
839 if (inputenc == "auto") {
840 string const doc_encoding =
841 language->encoding()->latexName();
843 // Create a list with all the input encodings used
845 std::set<string> encodings =
846 features.getEncodingSet(doc_encoding);
848 os << "\\usepackage[";
849 std::copy(encodings.begin(), encodings.end(),
850 std::ostream_iterator<string>(os, ","));
851 os << doc_encoding << "]{inputenc}\n";
853 } else if (inputenc != "default") {
854 os << "\\usepackage[" << inputenc
859 if (use_geometry || nonstandard_papersize) {
860 os << "\\usepackage{geometry}\n";
862 os << "\\geometry{verbose";
863 if (orientation == ORIENTATION_LANDSCAPE)
867 if (!paperwidth.empty())
870 if (!paperheight.empty())
871 os << ",paperheight="
875 os << ",letterpaper";
880 case PAPER_USEXECUTIVE:
881 os << ",executivepaper";
902 // default papersize ie PAPER_DEFAULT
903 switch (lyxrc.default_papersize) {
904 case PAPER_DEFAULT: // keep compiler happy
906 os << ",letterpaper";
911 case PAPER_USEXECUTIVE:
912 os << ",executivepaper";
932 if (!topmargin.empty())
933 os << ",tmargin=" << topmargin;
934 if (!bottommargin.empty())
935 os << ",bmargin=" << bottommargin;
936 if (!leftmargin.empty())
937 os << ",lmargin=" << leftmargin;
938 if (!rightmargin.empty())
939 os << ",rmargin=" << rightmargin;
940 if (!headheight.empty())
941 os << ",headheight=" << headheight;
942 if (!headsep.empty())
943 os << ",headsep=" << headsep;
944 if (!footskip.empty())
945 os << ",footskip=" << footskip;
950 if (tokenPos(tclass.opt_pagestyle(),
951 '|', pagestyle) >= 0) {
952 if (pagestyle == "fancy") {
953 os << "\\usepackage{fancyhdr}\n";
956 os << "\\pagestyle{" << pagestyle << "}\n";
960 // Only if class has a ToC hierarchy
961 if (tclass.hasTocLevels()) {
962 if (secnumdepth != tclass.secnumdepth()) {
963 os << "\\setcounter{secnumdepth}{"
968 if (tocdepth != tclass.tocdepth()) {
969 os << "\\setcounter{tocdepth}{"
976 if (paragraph_separation) {
977 switch (getDefSkip().kind()) {
978 case VSpace::SMALLSKIP:
979 os << "\\setlength\\parskip{\\smallskipamount}\n";
981 case VSpace::MEDSKIP:
982 os << "\\setlength\\parskip{\\medskipamount}\n";
984 case VSpace::BIGSKIP:
985 os << "\\setlength\\parskip{\\bigskipamount}\n";
988 os << "\\setlength\\parskip{"
989 << getDefSkip().length().asLatexString()
992 default: // should never happen // Then delete it.
993 os << "\\setlength\\parskip{\\medskipamount}\n";
998 os << "\\setlength\\parindent{0pt}\n";
1002 // If we use jurabib, we have to call babel here.
1003 if (use_babel && features.isRequired("jurabib")) {
1004 os << babelCall(language_options.str())
1006 << features.getBabelOptions();
1010 // Now insert the LyX specific LaTeX commands...
1012 // The optional packages;
1013 string lyxpreamble(features.getPackages());
1015 // this might be useful...
1016 lyxpreamble += "\n\\makeatletter\n";
1018 // Some macros LyX will need
1019 string tmppreamble(features.getMacros());
1021 if (!tmppreamble.empty()) {
1022 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1023 "LyX specific LaTeX commands.\n"
1024 + tmppreamble + '\n';
1027 // the text class specific preamble
1028 tmppreamble = features.getTClassPreamble();
1029 if (!tmppreamble.empty()) {
1030 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1031 "Textclass specific LaTeX commands.\n"
1032 + tmppreamble + '\n';
1035 /* the user-defined preamble */
1036 if (!preamble.empty()) {
1037 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1038 "User specified LaTeX commands.\n"
1042 // Itemize bullet settings need to be last in case the user
1043 // defines their own bullets that use a package included
1044 // in the user-defined preamble -- ARRae
1045 // Actually it has to be done much later than that
1046 // since some packages like frenchb make modifications
1047 // at \begin{document} time -- JMarc
1049 for (int i = 0; i < 4; ++i) {
1050 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1051 if (bullets_def.empty())
1052 bullets_def="\\AtBeginDocument{\n";
1053 bullets_def += " \\def\\labelitemi";
1055 // `i' is one less than the item to modify
1062 bullets_def += "ii";
1068 bullets_def += '{' +
1069 user_defined_bullet(i).getText()
1074 if (!bullets_def.empty())
1075 lyxpreamble += bullets_def + "}\n\n";
1077 // We try to load babel late, in case it interferes
1078 // with other packages.
1079 // Jurabib has to be called after babel, though.
1080 if (use_babel && !features.isRequired("jurabib")) {
1081 lyxpreamble += babelCall(language_options.str()) + '\n';
1082 lyxpreamble += features.getBabelOptions();
1085 lyxpreamble += "\\makeatother\n";
1087 // dvipost settings come after everything else
1088 if (features.isAvailable("dvipost") && outputChanges) {
1091 "\\dvipost{osstart color push Red}\n"
1092 "\\dvipost{osend color pop}\n"
1093 "\\dvipost{cbstart color push Blue}\n"
1094 "\\dvipost{cbend color pop}\n";
1098 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1099 for (int j = 0; j != nlines; ++j) {
1108 void BufferParams::useClassDefaults()
1110 LyXTextClass const & tclass = textclasslist[textclass];
1112 sides = tclass.sides();
1113 columns = tclass.columns();
1114 pagestyle = tclass.pagestyle();
1115 options = tclass.options();
1116 // Only if class has a ToC hierarchy
1117 if (tclass.hasTocLevels()) {
1118 secnumdepth = tclass.secnumdepth();
1119 tocdepth = tclass.tocdepth();
1124 bool BufferParams::hasClassDefaults() const
1126 LyXTextClass const & tclass = textclasslist[textclass];
1128 return (sides == tclass.sides()
1129 && columns == tclass.columns()
1130 && pagestyle == tclass.pagestyle()
1131 && options == tclass.options()
1132 && secnumdepth == tclass.secnumdepth()
1133 && tocdepth == tclass.tocdepth());
1137 LyXTextClass const & BufferParams::getLyXTextClass() const
1139 return textclasslist[textclass];
1143 LyXFont const BufferParams::getFont() const
1145 LyXFont f = getLyXTextClass().defaultfont();
1146 f.setLanguage(language);
1147 if (fontsDefaultFamily == "rmdefault")
1148 f.setFamily(LyXFont::ROMAN_FAMILY);
1149 else if (fontsDefaultFamily == "sfdefault")
1150 f.setFamily(LyXFont::SANS_FAMILY);
1151 else if (fontsDefaultFamily == "ttdefault")
1152 f.setFamily(LyXFont::TYPEWRITER_FAMILY);
1157 void BufferParams::readPreamble(LyXLex & lex)
1159 if (lex.getString() != "\\begin_preamble")
1160 lyxerr << "Error (BufferParams::readPreamble):"
1161 "consistency check failed." << endl;
1163 preamble = lex.getLongString("\\end_preamble");
1167 void BufferParams::readLanguage(LyXLex & lex)
1169 if (!lex.next()) return;
1171 string const tmptok = lex.getString();
1173 // check if tmptok is part of tex_babel in tex-defs.h
1174 language = languages.getLanguage(tmptok);
1176 // Language tmptok was not found
1177 language = default_language;
1178 lyxerr << "Warning: Setting language `"
1179 << tmptok << "' to `" << language->lang()
1185 void BufferParams::readGraphicsDriver(LyXLex & lex)
1187 if (!lex.next()) return;
1189 string const tmptok = lex.getString();
1190 // check if tmptok is part of tex_graphics in tex_defs.h
1193 string const test = tex_graphics[n++];
1195 if (test == tmptok) {
1196 graphicsDriver = tmptok;
1198 } else if (test == "") {
1200 "Warning: graphics driver `$$Token' not recognized!\n"
1201 " Setting graphics driver to `default'.\n");
1202 graphicsDriver = "default";
1209 void BufferParams::readBullets(LyXLex & lex)
1211 if (!lex.next()) return;
1213 int const index = lex.getInteger();
1215 int temp_int = lex.getInteger();
1216 user_defined_bullet(index).setFont(temp_int);
1217 temp_bullet(index).setFont(temp_int);
1219 user_defined_bullet(index).setCharacter(temp_int);
1220 temp_bullet(index).setCharacter(temp_int);
1222 user_defined_bullet(index).setSize(temp_int);
1223 temp_bullet(index).setSize(temp_int);
1227 void BufferParams::readBulletsLaTeX(LyXLex & lex)
1229 // The bullet class should be able to read this.
1230 if (!lex.next()) return;
1231 int const index = lex.getInteger();
1233 string const temp_str = lex.getString();
1235 user_defined_bullet(index).setText(temp_str);
1236 temp_bullet(index).setText(temp_str);
1240 string const BufferParams::paperSizeName() const
1242 char real_papersize = papersize;
1243 if (real_papersize == PAPER_DEFAULT)
1244 real_papersize = lyxrc.default_papersize;
1246 switch (real_papersize) {
1255 case PAPER_USEXECUTIVE:
1259 case PAPER_USLETTER:
1266 string const BufferParams::dvips_options() const
1271 && papersize == PAPER_CUSTOM
1272 && !lyxrc.print_paper_dimension_flag.empty()
1273 && !paperwidth.empty()
1274 && !paperheight.empty()) {
1275 // using a custom papersize
1276 result = lyxrc.print_paper_dimension_flag;
1277 result += ' ' + paperwidth;
1278 result += ',' + paperheight;
1280 string const paper_option = paperSizeName();
1281 if (paper_option != "letter" ||
1282 orientation != ORIENTATION_LANDSCAPE) {
1283 // dvips won't accept -t letter -t landscape.
1284 // In all other cases, include the paper size
1286 result = lyxrc.print_paper_flag;
1287 result += ' ' + paper_option;
1290 if (orientation == ORIENTATION_LANDSCAPE &&
1291 papersize != PAPER_CUSTOM)
1292 result += ' ' + lyxrc.print_landscape_flag;
1297 string const BufferParams::babelCall(string const & lang_opts) const
1299 string tmp = lyxrc.language_package;
1300 if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1301 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1306 string const BufferParams::loadFonts(LaTeXFeatures & features, string const & rm,
1307 string const & sf, string const & tt,
1308 bool const & sc, bool const & osf,
1309 int const & sfscale, int const & ttscale) const
1311 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1312 several packages have been replaced by others, that might not
1313 be installed on every system. We have to take care for that
1314 (see psnfss.pdf). We try to support all psnfss fonts as well
1315 as the fonts that have become de facto standard in the LaTeX
1316 world (e.g. Latin Modern). We do not support obsolete fonts
1317 (like PSLatex). In general, it should be possible to mix any
1318 rm font with any sf or tt font, respectively. (JSpitzm)
1320 -- separate math fonts.
1323 if (rm == "default" && sf == "default" && tt == "default")
1330 // Computer Modern (must be explicitely selectable -- there might be classes
1331 // that define a different default font!
1333 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1334 // osf for Computer Modern needs eco.sty
1336 os << "\\usepackage{eco}\n";
1338 // Latin Modern Roman
1339 else if (rm == "lmodern")
1340 os << "\\usepackage{lmodern}\n";
1342 else if (rm == "ae") {
1343 // not needed when using OT1 font encoding.
1344 if (lyxrc.fontenc != "default")
1345 os << "\\usepackage{ae,aecompl}\n";
1348 else if (rm == "times") {
1349 // try to load the best available package
1350 if (features.isAvailable("mathptmx"))
1351 os << "\\usepackage{mathptmx}\n";
1352 else if (features.isAvailable("mathptm"))
1353 os << "\\usepackage{mathptm}\n";
1355 os << "\\usepackage{times}\n";
1358 else if (rm == "palatino") {
1359 // try to load the best available package
1360 if (features.isAvailable("mathpazo")) {
1361 os << "\\usepackage";
1367 // "osf" includes "sc"!
1371 os << "{mathpazo}\n";
1373 else if (features.isAvailable("mathpple"))
1374 os << "\\usepackage{mathpple}\n";
1376 os << "\\usepackage{palatino}\n";
1379 else if (rm == "utopia") {
1380 // fourier supersedes utopia.sty, but does
1381 // not work with OT1 encoding.
1382 if (features.isAvailable("fourier")
1383 && lyxrc.fontenc != "default") {
1384 os << "\\usepackage";
1395 os << "{fourier}\n";
1398 os << "\\usepackage{utopia}\n";
1400 // Bera (complete fontset)
1401 else if (rm == "bera" && sf == "default" && tt == "default")
1402 os << "\\usepackage{bera}\n";
1404 else if (rm != "default")
1405 os << "\\usepackage" << "{" << rm << "}\n";
1408 // Helvetica, Bera Sans
1409 if (sf == "helvet" || sf == "berasans") {
1411 os << "\\usepackage[scaled=" << float(sfscale) / 100
1412 << "]{" << sf << "}\n";
1414 os << "\\usepackage{" << sf << "}\n";
1417 else if (sf == "avant")
1418 os << "\\usepackage{" << sf << "}\n";
1419 // Computer Modern, Latin Modern, CM Bright
1420 else if (sf != "default")
1421 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1423 // monospaced/typewriter
1424 // Courier, LuxiMono
1425 if (tt == "luximono" || tt == "beramono") {
1427 os << "\\usepackage[scaled=" << float(ttscale) / 100
1428 << "]{" << tt << "}\n";
1430 os << "\\usepackage{" << tt << "}\n";
1433 else if (tt == "courier" )
1434 os << "\\usepackage{" << tt << "}\n";
1435 // Computer Modern, Latin Modern, CM Bright
1436 else if (tt != "default")
1437 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";