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 Alert = lyx::frontend::Alert;
64 namespace biblio = lyx::biblio;
70 // Paragraph separation
71 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
74 ParSepTranslator const init_parseptranslator()
76 ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
77 translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
82 ParSepTranslator const & parseptranslator()
84 static ParSepTranslator translator = init_parseptranslator();
90 typedef Translator<string, InsetQuotes::quote_language> QuotesLangTranslator;
93 QuotesLangTranslator const init_quoteslangtranslator()
95 QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
96 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
97 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
98 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
99 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
100 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
105 QuotesLangTranslator const & quoteslangtranslator()
107 static QuotesLangTranslator translator = init_quoteslangtranslator();
113 typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
116 PaperSizeTranslator const init_papersizetranslator()
118 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
119 translator.addPair(string_papersize[1], PAPER_CUSTOM);
120 translator.addPair(string_papersize[2], PAPER_USLETTER);
121 translator.addPair(string_papersize[3], PAPER_USLEGAL);
122 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
123 translator.addPair(string_papersize[5], PAPER_A3);
124 translator.addPair(string_papersize[6], PAPER_A4);
125 translator.addPair(string_papersize[7], PAPER_A5);
126 translator.addPair(string_papersize[8], PAPER_B3);
127 translator.addPair(string_papersize[9], PAPER_B4);
128 translator.addPair(string_papersize[10], PAPER_B5);
133 PaperSizeTranslator const & papersizetranslator()
135 static PaperSizeTranslator translator = init_papersizetranslator();
141 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
144 PaperOrientationTranslator const init_paperorientationtranslator()
146 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
147 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
152 PaperOrientationTranslator const & paperorientationtranslator()
154 static PaperOrientationTranslator translator = init_paperorientationtranslator();
160 typedef Translator<int, LyXTextClass::PageSides> SidesTranslator;
163 SidesTranslator const init_sidestranslator()
165 SidesTranslator translator(1, LyXTextClass::OneSide);
166 translator.addPair(2, LyXTextClass::TwoSides);
171 SidesTranslator const & sidestranslator()
173 static SidesTranslator translator = init_sidestranslator();
180 typedef Translator<int, BufferParams::AMS> AMSTranslator;
183 AMSTranslator const init_amstranslator()
185 AMSTranslator translator(0, BufferParams::AMS_OFF);
186 translator.addPair(1, BufferParams::AMS_AUTO);
187 translator.addPair(2, BufferParams::AMS_ON);
192 AMSTranslator const & amstranslator()
194 static AMSTranslator translator = init_amstranslator();
200 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
203 CiteEngineTranslator const init_citeenginetranslator()
205 CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
206 translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
207 translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
208 translator.addPair("jurabib", biblio::ENGINE_JURABIB);
213 CiteEngineTranslator const & citeenginetranslator()
215 static CiteEngineTranslator translator = init_citeenginetranslator();
221 typedef Translator<string, Spacing::Space> SpaceTranslator;
224 SpaceTranslator const init_spacetranslator()
226 SpaceTranslator translator("default", Spacing::Default);
227 translator.addPair("single", Spacing::Single);
228 translator.addPair("onehalf", Spacing::Onehalf);
229 translator.addPair("double", Spacing::Double);
230 translator.addPair("other", Spacing::Other);
235 SpaceTranslator const & spacetranslator()
237 static SpaceTranslator translator = init_spacetranslator();
241 // ends annonym namespace
245 class BufferParams::Impl
250 AuthorList authorlist;
251 BranchList branchlist;
252 boost::array<Bullet, 4> temp_bullets;
253 boost::array<Bullet, 4> user_defined_bullets;
255 /** This is the amount of space used for paragraph_separation "skip",
256 * and for detached paragraphs in "indented" documents.
262 BufferParams::Impl::Impl()
263 : defskip(VSpace::MEDSKIP)
265 // set initial author
266 authorlist.record(Author(lyxrc.user_name, lyxrc.user_email));
271 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
275 return new BufferParams::Impl(*ptr);
279 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
285 BufferParams::BufferParams()
286 : // Initialize textclass to point to article. if `first' is
287 // true in the returned pair, then `second' is the textclass
288 // number; if it is false, second is 0. In both cases, second
290 textclass(textclasslist.numberOfClass("article").second),
293 paragraph_separation = PARSEP_INDENT;
294 quotes_language = InsetQuotes::EnglishQ;
295 fontsize = "default";
298 papersize = PAPER_DEFAULT;
299 orientation = ORIENTATION_PORTRAIT;
300 use_geometry = false;
301 use_amsmath = AMS_AUTO;
302 cite_engine = biblio::ENGINE_BASIC;
303 use_bibtopic = false;
304 trackChanges = false;
305 outputChanges = false;
308 language = default_language;
309 fontsRoman = "default";
310 fontsSans = "default";
311 fontsTypewriter = "default";
312 fontsDefaultFamily = "default";
315 fontsSansScale = 100;
316 fontsTypewriterScale = 100;
318 graphicsDriver = "default";
319 sides = LyXTextClass::OneSide;
321 pagestyle = "default";
323 for (int iter = 0; iter < 4; ++iter) {
324 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
325 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
330 BufferParams::~BufferParams()
334 AuthorList & BufferParams::authors()
336 return pimpl_->authorlist;
340 AuthorList const & BufferParams::authors() const
342 return pimpl_->authorlist;
346 BranchList & BufferParams::branchlist()
348 return pimpl_->branchlist;
352 BranchList const & BufferParams::branchlist() const
354 return pimpl_->branchlist;
358 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
360 BOOST_ASSERT(index < 4);
361 return pimpl_->temp_bullets[index];
365 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
367 BOOST_ASSERT(index < 4);
368 return pimpl_->temp_bullets[index];
372 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
374 BOOST_ASSERT(index < 4);
375 return pimpl_->user_defined_bullets[index];
379 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
381 BOOST_ASSERT(index < 4);
382 return pimpl_->user_defined_bullets[index];
386 Spacing & BufferParams::spacing()
388 return pimpl_->spacing;
392 Spacing const & BufferParams::spacing() const
394 return pimpl_->spacing;
398 VSpace const & BufferParams::getDefSkip() const
400 return pimpl_->defskip;
404 void BufferParams::setDefSkip(VSpace const & vs)
406 pimpl_->defskip = vs;
410 string const BufferParams::readToken(LyXLex & lex, string const & token)
412 if (token == "\\textclass") {
414 string const classname = lex.getString();
415 pair<bool, lyx::textclass_type> pp =
416 textclasslist.numberOfClass(classname);
418 textclass = pp.second;
420 // if text class does not exist, try to load it from filepath
421 pp = textclasslist.addTextClass(classname, filepath);
423 textclass = pp.second;
429 // FIXME: isTeXClassAvailable will try to load the layout file, but will
430 // fail because of the lack of path info. Warnings will be given although
431 // the layout file will be correctly loaded later.
432 if (!getLyXTextClass().isTeXClassAvailable()) {
433 docstring const msg =
434 bformat(_("The document uses a missing "
435 "TeX class \"%1$s\".\n"), lyx::from_utf8(classname));
436 Alert::warning(_("Document class not available"),
437 msg + _("LyX will not be able to produce output."));
439 } else if (token == "\\begin_preamble") {
441 } else if (token == "\\options") {
443 options = lex.getString();
444 } else if (token == "\\language") {
446 } else if (token == "\\inputencoding") {
448 } else if (token == "\\graphics") {
449 readGraphicsDriver(lex);
450 } else if (token == "\\font_roman") {
452 } else if (token == "\\font_sans") {
454 } else if (token == "\\font_typewriter") {
455 lex >> fontsTypewriter;
456 } else if (token == "\\font_default_family") {
457 lex >> fontsDefaultFamily;
458 } else if (token == "\\font_sc") {
460 } else if (token == "\\font_osf") {
462 } else if (token == "\\font_sf_scale") {
463 lex >> fontsSansScale;
464 } else if (token == "\\font_tt_scale") {
465 lex >> fontsTypewriterScale;
466 } else if (token == "\\paragraph_separation") {
469 paragraph_separation = parseptranslator().find(parsep);
470 } else if (token == "\\defskip") {
472 pimpl_->defskip = VSpace(lex.getString());
473 } else if (token == "\\quotes_language") {
476 quotes_language = quoteslangtranslator().find(quotes_lang);
477 } else if (token == "\\papersize") {
480 papersize = papersizetranslator().find(ppsize);
481 } else if (token == "\\use_geometry") {
483 } else if (token == "\\use_amsmath") {
486 use_amsmath = amstranslator().find(use_ams);
487 } else if (token == "\\cite_engine") {
490 cite_engine = citeenginetranslator().find(engine);
491 } else if (token == "\\use_bibtopic") {
493 } else if (token == "\\tracking_changes") {
495 } else if (token == "\\output_changes") {
496 lex >> outputChanges;
497 } else if (token == "\\branch") {
499 string branch = lex.getString();
500 branchlist().add(branch);
503 string const tok = lex.getString();
504 if (tok == "\\end_branch")
506 Branch * branch_ptr = branchlist().find(branch);
507 if (tok == "\\selected") {
510 branch_ptr->setSelected(lex.getInteger());
512 // not yet operational
513 if (tok == "\\color") {
515 string color = lex.getString();
517 branch_ptr->setColor(color);
518 // Update also the LColor table:
520 color = lcolor.getX11Name(LColor::background);
521 lcolor.setColor(branch, color);
525 } else if (token == "\\author") {
527 istringstream ss(lex.getString());
530 author_map.push_back(pimpl_->authorlist.record(a));
531 } else if (token == "\\paperorientation") {
534 orientation = paperorientationtranslator().find(orient);
535 } else if (token == "\\paperwidth") {
537 } else if (token == "\\paperheight") {
539 } else if (token == "\\leftmargin") {
541 } else if (token == "\\topmargin") {
543 } else if (token == "\\rightmargin") {
545 } else if (token == "\\bottommargin") {
547 } else if (token == "\\headheight") {
549 } else if (token == "\\headsep") {
551 } else if (token == "\\footskip") {
553 } else if (token == "\\paperfontsize") {
555 } else if (token == "\\papercolumns") {
557 } else if (token == "\\papersides") {
560 sides = sidestranslator().find(psides);
561 } else if (token == "\\paperpagestyle") {
563 } else if (token == "\\bullet") {
565 } else if (token == "\\bulletLaTeX") {
566 readBulletsLaTeX(lex);
567 } else if (token == "\\secnumdepth") {
569 } else if (token == "\\tocdepth") {
571 } else if (token == "\\spacing") {
575 if (nspacing == "other") {
578 spacing().set(spacetranslator().find(nspacing), tmp_val);
579 } else if (token == "\\float_placement") {
580 lex >> float_placement;
589 void BufferParams::writeFile(ostream & os) const
591 // The top of the file is written by the buffer.
592 // Prints out the buffer info into the .lyx file given by file
595 os << "\\textclass " << textclasslist[textclass].name() << '\n';
597 // then the the preamble
598 if (!preamble.empty()) {
599 // remove '\n' from the end of preamble
600 string const tmppreamble = rtrim(preamble, "\n");
601 os << "\\begin_preamble\n"
603 << "\n\\end_preamble\n";
607 if (!options.empty()) {
608 os << "\\options " << options << '\n';
611 // then the text parameters
612 if (language != ignore_language)
613 os << "\\language " << language->lang() << '\n';
614 os << "\\inputencoding " << inputenc
615 << "\n\\font_roman " << fontsRoman
616 << "\n\\font_sans " << fontsSans
617 << "\n\\font_typewriter " << fontsTypewriter
618 << "\n\\font_default_family " << fontsDefaultFamily
619 << "\n\\font_sc " << convert<string>(fontsSC)
620 << "\n\\font_osf " << convert<string>(fontsOSF)
621 << "\n\\font_sf_scale " << fontsSansScale
622 << "\n\\font_tt_scale " << fontsTypewriterScale
623 << "\n\\graphics " << graphicsDriver << '\n';
625 if (!float_placement.empty()) {
626 os << "\\float_placement " << float_placement << '\n';
628 os << "\\paperfontsize " << fontsize << '\n';
630 spacing().writeFile(os);
632 os << "\\papersize " << string_papersize[papersize]
633 << "\n\\use_geometry " << convert<string>(use_geometry)
634 << "\n\\use_amsmath " << use_amsmath
635 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine)
636 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
637 << "\n\\paperorientation " << string_orientation[orientation]
640 BranchList::const_iterator it = branchlist().begin();
641 BranchList::const_iterator end = branchlist().end();
642 for (; it != end; ++it) {
643 os << "\\branch " << it->getBranch()
644 << "\n\\selected " << it->getSelected()
645 << "\n\\color " << lyx::X11hexname(it->getColor())
650 if (!paperwidth.empty())
651 os << "\\paperwidth "
652 << VSpace(paperwidth).asLyXCommand() << '\n';
653 if (!paperheight.empty())
654 os << "\\paperheight "
655 << VSpace(paperheight).asLyXCommand() << '\n';
656 if (!leftmargin.empty())
657 os << "\\leftmargin "
658 << VSpace(leftmargin).asLyXCommand() << '\n';
659 if (!topmargin.empty())
661 << VSpace(topmargin).asLyXCommand() << '\n';
662 if (!rightmargin.empty())
663 os << "\\rightmargin "
664 << VSpace(rightmargin).asLyXCommand() << '\n';
665 if (!bottommargin.empty())
666 os << "\\bottommargin "
667 << VSpace(bottommargin).asLyXCommand() << '\n';
668 if (!headheight.empty())
669 os << "\\headheight "
670 << VSpace(headheight).asLyXCommand() << '\n';
671 if (!headsep.empty())
673 << VSpace(headsep).asLyXCommand() << '\n';
674 if (!footskip.empty())
676 << VSpace(footskip).asLyXCommand() << '\n';
677 os << "\\secnumdepth " << secnumdepth
678 << "\n\\tocdepth " << tocdepth
679 << "\n\\paragraph_separation "
680 << string_paragraph_separation[paragraph_separation]
681 << "\n\\defskip " << getDefSkip().asLyXCommand()
682 << "\n\\quotes_language "
683 << string_quotes_language[quotes_language]
684 << "\n\\papercolumns " << columns
685 << "\n\\papersides " << sides
686 << "\n\\paperpagestyle " << pagestyle << '\n';
687 for (int i = 0; i < 4; ++i) {
688 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
689 if (user_defined_bullet(i).getFont() != -1) {
690 os << "\\bullet " << i << " "
691 << user_defined_bullet(i).getFont() << " "
692 << user_defined_bullet(i).getCharacter() << " "
693 << user_defined_bullet(i).getSize() << "\n";
696 os << "\\bulletLaTeX " << i << " \""
697 << user_defined_bullet(i).getText()
703 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
704 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
707 // FIXME: Change tracking (MG)
708 AuthorList::Authors::const_iterator it = pimpl_->authorlist.begin();
709 AuthorList::Authors::const_iterator end = pimpl_->authorlist.end();
710 for (; it != end; ++it) {
711 os << "\\author " << it->second << "\n";
717 bool BufferParams::writeLaTeX(ostream & os, LaTeXFeatures & features,
718 TexRow & texrow) const
720 os << "\\documentclass";
722 LyXTextClass const & tclass = getLyXTextClass();
724 ostringstream clsoptions; // the document class options.
726 if (tokenPos(tclass.opt_fontsize(),
727 '|', fontsize) >= 0) {
728 // only write if existing in list (and not default)
729 clsoptions << fontsize << "pt,";
732 // custom, A3, B3 and B4 paper sizes need geometry
733 bool nonstandard_papersize = (papersize == PAPER_B3) ||
734 (papersize == PAPER_B4) ||
735 (papersize == PAPER_A3) ||
736 (papersize == PAPER_CUSTOM);
741 clsoptions << "a4paper,";
744 clsoptions << "letterpaper,";
747 clsoptions << "a5paper,";
750 clsoptions << "b5paper,";
752 case PAPER_USEXECUTIVE:
753 clsoptions << "executivepaper,";
756 clsoptions << "legalpaper,";
768 if (sides != tclass.sides()) {
770 case LyXTextClass::OneSide:
771 clsoptions << "oneside,";
773 case LyXTextClass::TwoSides:
774 clsoptions << "twoside,";
780 if (columns != tclass.columns()) {
782 clsoptions << "twocolumn,";
784 clsoptions << "onecolumn,";
788 && orientation == ORIENTATION_LANDSCAPE)
789 clsoptions << "landscape,";
791 // language should be a parameter to \documentclass
792 if (language->babel() == "hebrew"
793 && default_language->babel() != "hebrew")
794 // This seems necessary
795 features.useLanguage(default_language);
797 ostringstream language_options;
798 bool const use_babel = features.useBabel();
800 language_options << features.getLanguages();
801 language_options << language->babel();
802 if (lyxrc.language_global_options)
803 clsoptions << language_options.str() << ',';
806 // the user-defined options
807 if (!options.empty()) {
808 clsoptions << options << ',';
811 string strOptions(clsoptions.str());
812 if (!strOptions.empty()) {
813 strOptions = rtrim(strOptions, ",");
814 os << '[' << strOptions << ']';
817 os << '{' << tclass.latexname() << "}\n";
819 // end of \documentclass defs
821 // font selection must be done before loading fontenc.sty
823 loadFonts(features, fontsRoman, fontsSans,
824 fontsTypewriter, fontsSC, fontsOSF,
825 fontsSansScale, fontsTypewriterScale);
826 if (!fonts.empty()) {
830 if (fontsDefaultFamily != "default")
831 os << "\\renewcommand{\\familydefault}{\\"
832 << fontsDefaultFamily << "}\n";
833 // this one is not per buffer
834 if (lyxrc.fontenc != "default") {
835 os << "\\usepackage[" << lyxrc.fontenc
840 if (inputenc == "auto") {
841 string const doc_encoding =
842 language->encoding()->latexName();
844 // Create a list with all the input encodings used
846 std::set<string> encodings =
847 features.getEncodingSet(doc_encoding);
849 os << "\\usepackage[";
850 std::copy(encodings.begin(), encodings.end(),
851 std::ostream_iterator<string>(os, ","));
852 os << doc_encoding << "]{inputenc}\n";
854 } else if (inputenc != "default") {
855 os << "\\usepackage[" << 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())
871 if (!paperheight.empty())
872 os << ",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=" << topmargin;
935 if (!bottommargin.empty())
936 os << ",bmargin=" << bottommargin;
937 if (!leftmargin.empty())
938 os << ",lmargin=" << leftmargin;
939 if (!rightmargin.empty())
940 os << ",rmargin=" << rightmargin;
941 if (!headheight.empty())
942 os << ",headheight=" << headheight;
943 if (!headsep.empty())
944 os << ",headsep=" << headsep;
945 if (!footskip.empty())
946 os << ",footskip=" << footskip;
951 if (tokenPos(tclass.opt_pagestyle(),
952 '|', pagestyle) >= 0) {
953 if (pagestyle == "fancy") {
954 os << "\\usepackage{fancyhdr}\n";
957 os << "\\pagestyle{" << 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 << 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 << babelCall(language_options.str())
1007 << 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";
1069 bullets_def += '{' +
1070 user_defined_bullet(i).getText()
1075 if (!bullets_def.empty())
1076 lyxpreamble += bullets_def + "}\n\n";
1078 // We try to load babel late, in case it interferes
1079 // with other packages.
1080 // Jurabib has to be called after babel, though.
1081 if (use_babel && !features.isRequired("jurabib")) {
1082 lyxpreamble += babelCall(language_options.str()) + '\n';
1083 lyxpreamble += features.getBabelOptions();
1086 lyxpreamble += "\\makeatother\n";
1088 // dvipost settings come after everything else
1089 if (features.isAvailable("dvipost") && outputChanges) {
1092 "\\dvipost{osstart color push Red}\n"
1093 "\\dvipost{osend color pop}\n"
1094 "\\dvipost{cbstart color push Blue}\n"
1095 "\\dvipost{cbend color pop}\n";
1099 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1100 for (int j = 0; j != nlines; ++j) {
1109 void BufferParams::useClassDefaults()
1111 LyXTextClass const & tclass = textclasslist[textclass];
1113 sides = tclass.sides();
1114 columns = tclass.columns();
1115 pagestyle = tclass.pagestyle();
1116 options = tclass.options();
1117 // Only if class has a ToC hierarchy
1118 if (tclass.hasTocLevels()) {
1119 secnumdepth = tclass.secnumdepth();
1120 tocdepth = tclass.tocdepth();
1125 bool BufferParams::hasClassDefaults() const
1127 LyXTextClass const & tclass = textclasslist[textclass];
1129 return (sides == tclass.sides()
1130 && columns == tclass.columns()
1131 && pagestyle == tclass.pagestyle()
1132 && options == tclass.options()
1133 && secnumdepth == tclass.secnumdepth()
1134 && tocdepth == tclass.tocdepth());
1138 LyXTextClass const & BufferParams::getLyXTextClass() const
1140 return textclasslist[textclass];
1144 LyXFont const BufferParams::getFont() const
1146 LyXFont f = getLyXTextClass().defaultfont();
1147 f.setLanguage(language);
1148 if (fontsDefaultFamily == "rmdefault")
1149 f.setFamily(LyXFont::ROMAN_FAMILY);
1150 else if (fontsDefaultFamily == "sfdefault")
1151 f.setFamily(LyXFont::SANS_FAMILY);
1152 else if (fontsDefaultFamily == "ttdefault")
1153 f.setFamily(LyXFont::TYPEWRITER_FAMILY);
1158 void BufferParams::readPreamble(LyXLex & lex)
1160 if (lex.getString() != "\\begin_preamble")
1161 lyxerr << "Error (BufferParams::readPreamble):"
1162 "consistency check failed." << endl;
1164 preamble = lex.getLongString("\\end_preamble");
1168 void BufferParams::readLanguage(LyXLex & lex)
1170 if (!lex.next()) return;
1172 string const tmptok = lex.getString();
1174 // check if tmptok is part of tex_babel in tex-defs.h
1175 language = languages.getLanguage(tmptok);
1177 // Language tmptok was not found
1178 language = default_language;
1179 lyxerr << "Warning: Setting language `"
1180 << tmptok << "' to `" << language->lang()
1186 void BufferParams::readGraphicsDriver(LyXLex & lex)
1188 if (!lex.next()) return;
1190 string const tmptok = lex.getString();
1191 // check if tmptok is part of tex_graphics in tex_defs.h
1194 string const test = tex_graphics[n++];
1196 if (test == tmptok) {
1197 graphicsDriver = tmptok;
1199 } else if (test == "") {
1201 "Warning: graphics driver `$$Token' not recognized!\n"
1202 " Setting graphics driver to `default'.\n");
1203 graphicsDriver = "default";
1210 void BufferParams::readBullets(LyXLex & lex)
1212 if (!lex.next()) return;
1214 int const index = lex.getInteger();
1216 int temp_int = lex.getInteger();
1217 user_defined_bullet(index).setFont(temp_int);
1218 temp_bullet(index).setFont(temp_int);
1220 user_defined_bullet(index).setCharacter(temp_int);
1221 temp_bullet(index).setCharacter(temp_int);
1223 user_defined_bullet(index).setSize(temp_int);
1224 temp_bullet(index).setSize(temp_int);
1228 void BufferParams::readBulletsLaTeX(LyXLex & lex)
1230 // The bullet class should be able to read this.
1231 if (!lex.next()) return;
1232 int const index = lex.getInteger();
1234 string const temp_str = lex.getString();
1236 user_defined_bullet(index).setText(temp_str);
1237 temp_bullet(index).setText(temp_str);
1241 string const BufferParams::paperSizeName() const
1243 char real_papersize = papersize;
1244 if (real_papersize == PAPER_DEFAULT)
1245 real_papersize = lyxrc.default_papersize;
1247 switch (real_papersize) {
1256 case PAPER_USEXECUTIVE:
1260 case PAPER_USLETTER:
1267 string const BufferParams::dvips_options() const
1272 && papersize == PAPER_CUSTOM
1273 && !lyxrc.print_paper_dimension_flag.empty()
1274 && !paperwidth.empty()
1275 && !paperheight.empty()) {
1276 // using a custom papersize
1277 result = lyxrc.print_paper_dimension_flag;
1278 result += ' ' + paperwidth;
1279 result += ',' + paperheight;
1281 string const paper_option = paperSizeName();
1282 if (paper_option != "letter" ||
1283 orientation != ORIENTATION_LANDSCAPE) {
1284 // dvips won't accept -t letter -t landscape.
1285 // In all other cases, include the paper size
1287 result = lyxrc.print_paper_flag;
1288 result += ' ' + paper_option;
1291 if (orientation == ORIENTATION_LANDSCAPE &&
1292 papersize != PAPER_CUSTOM)
1293 result += ' ' + lyxrc.print_landscape_flag;
1298 string const BufferParams::babelCall(string const & lang_opts) const
1300 string tmp = lyxrc.language_package;
1301 if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1302 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1307 string const BufferParams::loadFonts(LaTeXFeatures & features, string const & rm,
1308 string const & sf, string const & tt,
1309 bool const & sc, bool const & osf,
1310 int const & sfscale, int const & ttscale) const
1312 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1313 several packages have been replaced by others, that might not
1314 be installed on every system. We have to take care for that
1315 (see psnfss.pdf). We try to support all psnfss fonts as well
1316 as the fonts that have become de facto standard in the LaTeX
1317 world (e.g. Latin Modern). We do not support obsolete fonts
1318 (like PSLatex). In general, it should be possible to mix any
1319 rm font with any sf or tt font, respectively. (JSpitzm)
1321 -- separate math fonts.
1324 if (rm == "default" && sf == "default" && tt == "default")
1331 // Computer Modern (must be explicitely selectable -- there might be classes
1332 // that define a different default font!
1334 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1335 // osf for Computer Modern needs eco.sty
1337 os << "\\usepackage{eco}\n";
1339 // Latin Modern Roman
1340 else if (rm == "lmodern")
1341 os << "\\usepackage{lmodern}\n";
1343 else if (rm == "ae") {
1344 // not needed when using OT1 font encoding.
1345 if (lyxrc.fontenc != "default")
1346 os << "\\usepackage{ae,aecompl}\n";
1349 else if (rm == "times") {
1350 // try to load the best available package
1351 if (features.isAvailable("mathptmx"))
1352 os << "\\usepackage{mathptmx}\n";
1353 else if (features.isAvailable("mathptm"))
1354 os << "\\usepackage{mathptm}\n";
1356 os << "\\usepackage{times}\n";
1359 else if (rm == "palatino") {
1360 // try to load the best available package
1361 if (features.isAvailable("mathpazo")) {
1362 os << "\\usepackage";
1368 // "osf" includes "sc"!
1372 os << "{mathpazo}\n";
1374 else if (features.isAvailable("mathpple"))
1375 os << "\\usepackage{mathpple}\n";
1377 os << "\\usepackage{palatino}\n";
1380 else if (rm == "utopia") {
1381 // fourier supersedes utopia.sty, but does
1382 // not work with OT1 encoding.
1383 if (features.isAvailable("fourier")
1384 && lyxrc.fontenc != "default") {
1385 os << "\\usepackage";
1396 os << "{fourier}\n";
1399 os << "\\usepackage{utopia}\n";
1401 // Bera (complete fontset)
1402 else if (rm == "bera" && sf == "default" && tt == "default")
1403 os << "\\usepackage{bera}\n";
1405 else if (rm != "default")
1406 os << "\\usepackage" << "{" << rm << "}\n";
1409 // Helvetica, Bera Sans
1410 if (sf == "helvet" || sf == "berasans") {
1412 os << "\\usepackage[scaled=" << float(sfscale) / 100
1413 << "]{" << sf << "}\n";
1415 os << "\\usepackage{" << sf << "}\n";
1418 else if (sf == "avant")
1419 os << "\\usepackage{" << sf << "}\n";
1420 // Computer Modern, Latin Modern, CM Bright
1421 else if (sf != "default")
1422 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1424 // monospaced/typewriter
1425 // Courier, LuxiMono
1426 if (tt == "luximono" || tt == "beramono") {
1428 os << "\\usepackage[scaled=" << float(ttscale) / 100
1429 << "]{" << tt << "}\n";
1431 os << "\\usepackage{" << tt << "}\n";
1434 else if (tt == "courier" )
1435 os << "\\usepackage{" << tt << "}\n";
1436 // Computer Modern, Latin Modern, CM Bright
1437 else if (tt != "default")
1438 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";