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;
50 using lyx::support::bformat;
51 using lyx::support::rtrim;
52 using lyx::support::tokenPos;
56 using std::istringstream;
58 using std::ostringstream;
61 namespace biblio = lyx::biblio;
67 // Paragraph separation
68 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
71 ParSepTranslator const init_parseptranslator()
73 ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
74 translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
79 ParSepTranslator const & parseptranslator()
81 static ParSepTranslator translator = init_parseptranslator();
87 typedef Translator<string, InsetQuotes::quote_language> QuotesLangTranslator;
90 QuotesLangTranslator const init_quoteslangtranslator()
92 QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
93 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
94 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
95 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
96 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
97 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
102 QuotesLangTranslator const & quoteslangtranslator()
104 static QuotesLangTranslator translator = init_quoteslangtranslator();
110 typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
113 PaperSizeTranslator const init_papersizetranslator()
115 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
116 translator.addPair(string_papersize[1], PAPER_CUSTOM);
117 translator.addPair(string_papersize[2], PAPER_USLETTER);
118 translator.addPair(string_papersize[3], PAPER_USLEGAL);
119 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
120 translator.addPair(string_papersize[5], PAPER_A3);
121 translator.addPair(string_papersize[6], PAPER_A4);
122 translator.addPair(string_papersize[7], PAPER_A5);
123 translator.addPair(string_papersize[8], PAPER_B3);
124 translator.addPair(string_papersize[9], PAPER_B4);
125 translator.addPair(string_papersize[10], PAPER_B5);
130 PaperSizeTranslator const & papersizetranslator()
132 static PaperSizeTranslator translator = init_papersizetranslator();
138 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
141 PaperOrientationTranslator const init_paperorientationtranslator()
143 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
144 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
149 PaperOrientationTranslator const & paperorientationtranslator()
151 static PaperOrientationTranslator translator = init_paperorientationtranslator();
157 typedef Translator<int, LyXTextClass::PageSides> SidesTranslator;
160 SidesTranslator const init_sidestranslator()
162 SidesTranslator translator(1, LyXTextClass::OneSide);
163 translator.addPair(2, LyXTextClass::TwoSides);
168 SidesTranslator const & sidestranslator()
170 static SidesTranslator translator = init_sidestranslator();
177 typedef Translator<int, BufferParams::AMS> AMSTranslator;
180 AMSTranslator const init_amstranslator()
182 AMSTranslator translator(0, BufferParams::AMS_OFF);
183 translator.addPair(1, BufferParams::AMS_AUTO);
184 translator.addPair(2, BufferParams::AMS_ON);
189 AMSTranslator const & amstranslator()
191 static AMSTranslator translator = init_amstranslator();
197 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
200 CiteEngineTranslator const init_citeenginetranslator()
202 CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
203 translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
204 translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
205 translator.addPair("jurabib", biblio::ENGINE_JURABIB);
210 CiteEngineTranslator const & citeenginetranslator()
212 static CiteEngineTranslator translator = init_citeenginetranslator();
218 typedef Translator<string, Spacing::Space> SpaceTranslator;
221 SpaceTranslator const init_spacetranslator()
223 SpaceTranslator translator("default", Spacing::Default);
224 translator.addPair("single", Spacing::Single);
225 translator.addPair("onehalf", Spacing::Onehalf);
226 translator.addPair("double", Spacing::Double);
227 translator.addPair("other", Spacing::Other);
232 SpaceTranslator const & spacetranslator()
234 static SpaceTranslator translator = init_spacetranslator();
238 // ends annonym namespace
242 class BufferParams::Impl
247 AuthorList authorlist;
248 BranchList branchlist;
249 boost::array<Bullet, 4> temp_bullets;
250 boost::array<Bullet, 4> user_defined_bullets;
252 /** This is the amount of space used for paragraph_separation "skip",
253 * and for detached paragraphs in "indented" documents.
259 BufferParams::Impl::Impl()
260 : defskip(VSpace::MEDSKIP)
262 // set initial author
263 authorlist.record(Author(lyxrc.user_name, lyxrc.user_email));
268 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
272 return new BufferParams::Impl(*ptr);
276 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
282 BufferParams::BufferParams()
283 : // Initialize textclass to point to article. if `first' is
284 // true in the returned pair, then `second' is the textclass
285 // number; if it is false, second is 0. In both cases, second
287 textclass(textclasslist.numberOfClass("article").second),
290 paragraph_separation = PARSEP_INDENT;
291 quotes_language = InsetQuotes::EnglishQ;
292 fontsize = "default";
295 papersize = PAPER_DEFAULT;
296 orientation = ORIENTATION_PORTRAIT;
297 use_geometry = false;
298 use_amsmath = AMS_AUTO;
299 cite_engine = biblio::ENGINE_BASIC;
300 use_bibtopic = false;
301 tracking_changes = false;
302 output_changes = false;
305 language = default_language;
306 fontsRoman = "default";
307 fontsSans = "default";
308 fontsTypewriter = "default";
309 fontsDefaultFamily = "default";
312 fontsSansScale = 100;
313 fontsTypewriterScale = 100;
315 graphicsDriver = "default";
316 sides = LyXTextClass::OneSide;
318 pagestyle = "default";
320 for (int iter = 0; iter < 4; ++iter) {
321 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
322 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
327 BufferParams::~BufferParams()
331 AuthorList & BufferParams::authors()
333 return pimpl_->authorlist;
337 AuthorList const & BufferParams::authors() const
339 return pimpl_->authorlist;
343 BranchList & BufferParams::branchlist()
345 return pimpl_->branchlist;
349 BranchList const & BufferParams::branchlist() const
351 return pimpl_->branchlist;
355 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
357 BOOST_ASSERT(index < 4);
358 return pimpl_->temp_bullets[index];
362 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
364 BOOST_ASSERT(index < 4);
365 return pimpl_->temp_bullets[index];
369 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
371 BOOST_ASSERT(index < 4);
372 return pimpl_->user_defined_bullets[index];
376 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
378 BOOST_ASSERT(index < 4);
379 return pimpl_->user_defined_bullets[index];
383 Spacing & BufferParams::spacing()
385 return pimpl_->spacing;
389 Spacing const & BufferParams::spacing() const
391 return pimpl_->spacing;
395 VSpace const & BufferParams::getDefSkip() const
397 return pimpl_->defskip;
401 void BufferParams::setDefSkip(VSpace const & vs)
403 pimpl_->defskip = vs;
407 string const BufferParams::readToken(LyXLex & lex, string const & token)
409 if (token == "\\textclass") {
411 string const classname = lex.getString();
412 pair<bool, lyx::textclass_type> pp =
413 textclasslist.numberOfClass(classname);
415 textclass = pp.second;
417 // if text class does not exist, try to load it from filepath
418 pp = textclasslist.addTextClass(classname, filepath);
420 textclass = pp.second;
426 // FIXME: isTeXClassAvailable will try to load the layout file, but will
427 // fail because of the lack of path info. Warnings will be given although
428 // the layout file will be correctly loaded later.
429 if (!getLyXTextClass().isTeXClassAvailable()) {
431 bformat(_("The document uses a missing "
432 "TeX class \"%1$s\".\n"), classname);
433 Alert::warning(_("Document class not available"),
434 msg + _("LyX will not be able to produce output."));
436 } else if (token == "\\begin_preamble") {
438 } else if (token == "\\options") {
440 options = lex.getString();
441 } else if (token == "\\language") {
443 } else if (token == "\\inputencoding") {
445 } else if (token == "\\graphics") {
446 readGraphicsDriver(lex);
447 } else if (token == "\\font_roman") {
449 } else if (token == "\\font_sans") {
451 } else if (token == "\\font_typewriter") {
452 lex >> fontsTypewriter;
453 } else if (token == "\\font_default_family") {
454 lex >> fontsDefaultFamily;
455 } else if (token == "\\font_sc") {
457 } else if (token == "\\font_osf") {
459 } else if (token == "\\font_sf_scale") {
460 lex >> fontsSansScale;
461 } else if (token == "\\font_tt_scale") {
462 lex >> fontsTypewriterScale;
463 } else if (token == "\\paragraph_separation") {
466 paragraph_separation = parseptranslator().find(parsep);
467 } else if (token == "\\defskip") {
469 pimpl_->defskip = VSpace(lex.getString());
470 } else if (token == "\\quotes_language") {
473 quotes_language = quoteslangtranslator().find(quotes_lang);
474 } else if (token == "\\papersize") {
477 papersize = papersizetranslator().find(ppsize);
478 } else if (token == "\\use_geometry") {
480 } else if (token == "\\use_amsmath") {
483 use_amsmath = amstranslator().find(use_ams);
484 } else if (token == "\\cite_engine") {
487 cite_engine = citeenginetranslator().find(engine);
488 } else if (token == "\\use_bibtopic") {
490 } else if (token == "\\tracking_changes") {
491 lex >> tracking_changes;
492 } else if (token == "\\output_changes") {
493 lex >> output_changes;
494 } else if (token == "\\branch") {
496 string branch = lex.getString();
497 branchlist().add(branch);
500 string const tok = lex.getString();
501 if (tok == "\\end_branch")
503 Branch * branch_ptr = branchlist().find(branch);
504 if (tok == "\\selected") {
507 branch_ptr->setSelected(lex.getInteger());
509 // not yet operational
510 if (tok == "\\color") {
512 string color = lex.getString();
514 branch_ptr->setColor(color);
515 // Update also the LColor table:
517 color = lcolor.getX11Name(LColor::background);
518 lcolor.setColor(branch, color);
522 } else if (token == "\\author") {
524 istringstream ss(lex.getString());
527 author_map.push_back(pimpl_->authorlist.record(a));
528 } else if (token == "\\paperorientation") {
531 orientation = paperorientationtranslator().find(orient);
532 } else if (token == "\\paperwidth") {
534 } else if (token == "\\paperheight") {
536 } else if (token == "\\leftmargin") {
538 } else if (token == "\\topmargin") {
540 } else if (token == "\\rightmargin") {
542 } else if (token == "\\bottommargin") {
544 } else if (token == "\\headheight") {
546 } else if (token == "\\headsep") {
548 } else if (token == "\\footskip") {
550 } else if (token == "\\paperfontsize") {
552 } else if (token == "\\papercolumns") {
554 } else if (token == "\\papersides") {
557 sides = sidestranslator().find(psides);
558 } else if (token == "\\paperpagestyle") {
560 } else if (token == "\\bullet") {
562 } else if (token == "\\bulletLaTeX") {
563 readBulletsLaTeX(lex);
564 } else if (token == "\\secnumdepth") {
566 } else if (token == "\\tocdepth") {
568 } else if (token == "\\spacing") {
572 if (nspacing == "other") {
575 spacing().set(spacetranslator().find(nspacing), tmp_val);
576 } else if (token == "\\float_placement") {
577 lex >> float_placement;
586 void BufferParams::writeFile(ostream & os) const
588 // The top of the file is written by the buffer.
589 // Prints out the buffer info into the .lyx file given by file
592 os << "\\textclass " << textclasslist[textclass].name() << '\n';
594 // then the the preamble
595 if (!preamble.empty()) {
596 // remove '\n' from the end of preamble
597 string const tmppreamble = rtrim(preamble, "\n");
598 os << "\\begin_preamble\n"
600 << "\n\\end_preamble\n";
604 if (!options.empty()) {
605 os << "\\options " << options << '\n';
608 // then the text parameters
609 if (language != ignore_language)
610 os << "\\language " << language->lang() << '\n';
611 os << "\\inputencoding " << inputenc
612 << "\n\\font_roman " << fontsRoman
613 << "\n\\font_sans " << fontsSans
614 << "\n\\font_typewriter " << fontsTypewriter
615 << "\n\\font_default_family " << fontsDefaultFamily
616 << "\n\\font_sc " << convert<string>(fontsSC)
617 << "\n\\font_osf " << convert<string>(fontsOSF)
618 << "\n\\font_sf_scale " << fontsSansScale
619 << "\n\\font_tt_scale " << fontsTypewriterScale
620 << "\n\\graphics " << graphicsDriver << '\n';
622 if (!float_placement.empty()) {
623 os << "\\float_placement " << float_placement << '\n';
625 os << "\\paperfontsize " << fontsize << '\n';
627 spacing().writeFile(os);
629 os << "\\papersize " << string_papersize[papersize]
630 << "\n\\use_geometry " << convert<string>(use_geometry)
631 << "\n\\use_amsmath " << use_amsmath
632 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine)
633 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
634 << "\n\\paperorientation " << string_orientation[orientation]
637 BranchList::const_iterator it = branchlist().begin();
638 BranchList::const_iterator end = branchlist().end();
639 for (; it != end; ++it) {
640 os << "\\branch " << it->getBranch()
641 << "\n\\selected " << it->getSelected()
642 << "\n\\color " << lyx::X11hexname(it->getColor())
647 if (!paperwidth.empty())
648 os << "\\paperwidth "
649 << VSpace(paperwidth).asLyXCommand() << '\n';
650 if (!paperheight.empty())
651 os << "\\paperheight "
652 << VSpace(paperheight).asLyXCommand() << '\n';
653 if (!leftmargin.empty())
654 os << "\\leftmargin "
655 << VSpace(leftmargin).asLyXCommand() << '\n';
656 if (!topmargin.empty())
658 << VSpace(topmargin).asLyXCommand() << '\n';
659 if (!rightmargin.empty())
660 os << "\\rightmargin "
661 << VSpace(rightmargin).asLyXCommand() << '\n';
662 if (!bottommargin.empty())
663 os << "\\bottommargin "
664 << VSpace(bottommargin).asLyXCommand() << '\n';
665 if (!headheight.empty())
666 os << "\\headheight "
667 << VSpace(headheight).asLyXCommand() << '\n';
668 if (!headsep.empty())
670 << VSpace(headsep).asLyXCommand() << '\n';
671 if (!footskip.empty())
673 << VSpace(footskip).asLyXCommand() << '\n';
674 os << "\\secnumdepth " << secnumdepth
675 << "\n\\tocdepth " << tocdepth
676 << "\n\\paragraph_separation "
677 << string_paragraph_separation[paragraph_separation]
678 << "\n\\defskip " << getDefSkip().asLyXCommand()
679 << "\n\\quotes_language "
680 << string_quotes_language[quotes_language]
681 << "\n\\papercolumns " << columns
682 << "\n\\papersides " << sides
683 << "\n\\paperpagestyle " << pagestyle << '\n';
684 for (int i = 0; i < 4; ++i) {
685 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
686 if (user_defined_bullet(i).getFont() != -1) {
687 os << "\\bullet " << i << " "
688 << user_defined_bullet(i).getFont() << " "
689 << user_defined_bullet(i).getCharacter() << " "
690 << user_defined_bullet(i).getSize() << "\n";
693 os << "\\bulletLaTeX " << i << " \""
694 << user_defined_bullet(i).getText()
700 os << "\\tracking_changes " << convert<string>(tracking_changes) << "\n";
701 os << "\\output_changes " << convert<string>(output_changes) << "\n";
703 if (tracking_changes) {
704 AuthorList::Authors::const_iterator it = pimpl_->authorlist.begin();
705 AuthorList::Authors::const_iterator end = pimpl_->authorlist.end();
706 for (; it != end; ++it) {
707 os << "\\author " << it->second << "\n";
713 bool BufferParams::writeLaTeX(ostream & os, LaTeXFeatures & features,
714 TexRow & texrow) const
716 os << "\\documentclass";
718 LyXTextClass const & tclass = getLyXTextClass();
720 ostringstream clsoptions; // the document class options.
722 if (tokenPos(tclass.opt_fontsize(),
723 '|', fontsize) >= 0) {
724 // only write if existing in list (and not default)
725 clsoptions << fontsize << "pt,";
728 // custom, A3, B3 and B4 paper sizes need geometry
729 bool nonstandard_papersize = (papersize == PAPER_B3) ||
730 (papersize == PAPER_B4) ||
731 (papersize == PAPER_A3) ||
732 (papersize == PAPER_CUSTOM);
737 clsoptions << "a4paper,";
740 clsoptions << "letterpaper,";
743 clsoptions << "a5paper,";
746 clsoptions << "b5paper,";
748 case PAPER_USEXECUTIVE:
749 clsoptions << "executivepaper,";
752 clsoptions << "legalpaper,";
764 if (sides != tclass.sides()) {
766 case LyXTextClass::OneSide:
767 clsoptions << "oneside,";
769 case LyXTextClass::TwoSides:
770 clsoptions << "twoside,";
776 if (columns != tclass.columns()) {
778 clsoptions << "twocolumn,";
780 clsoptions << "onecolumn,";
784 && orientation == ORIENTATION_LANDSCAPE)
785 clsoptions << "landscape,";
787 // language should be a parameter to \documentclass
788 if (language->babel() == "hebrew"
789 && default_language->babel() != "hebrew")
790 // This seems necessary
791 features.useLanguage(default_language);
793 ostringstream language_options;
794 bool const use_babel = features.useBabel();
796 language_options << features.getLanguages();
797 language_options << language->babel();
798 if (lyxrc.language_global_options)
799 clsoptions << language_options.str() << ',';
802 // the user-defined options
803 if (!options.empty()) {
804 clsoptions << options << ',';
807 string strOptions(clsoptions.str());
808 if (!strOptions.empty()) {
809 strOptions = rtrim(strOptions, ",");
810 os << '[' << strOptions << ']';
813 os << '{' << tclass.latexname() << "}\n";
815 // end of \documentclass defs
817 // font selection must be done before loading fontenc.sty
819 loadFonts(features, fontsRoman, fontsSans,
820 fontsTypewriter, fontsSC, fontsOSF,
821 fontsSansScale, fontsTypewriterScale);
822 if (!fonts.empty()) {
826 if (fontsDefaultFamily != "default")
827 os << "\\renewcommand{\\familydefault}{\\"
828 << fontsDefaultFamily << "}\n";
829 // this one is not per buffer
830 if (lyxrc.fontenc != "default") {
831 os << "\\usepackage[" << lyxrc.fontenc
836 if (inputenc == "auto") {
837 string const doc_encoding =
838 language->encoding()->latexName();
840 // Create a list with all the input encodings used
842 std::set<string> encodings =
843 features.getEncodingSet(doc_encoding);
845 os << "\\usepackage[";
846 std::copy(encodings.begin(), encodings.end(),
847 std::ostream_iterator<string>(os, ","));
848 os << doc_encoding << "]{inputenc}\n";
850 } else if (inputenc != "default") {
851 os << "\\usepackage[" << inputenc
856 if (use_geometry || nonstandard_papersize) {
857 os << "\\usepackage{geometry}\n";
859 os << "\\geometry{verbose";
860 if (orientation == ORIENTATION_LANDSCAPE)
864 if (!paperwidth.empty())
867 if (!paperheight.empty())
868 os << ",paperheight="
872 os << ",letterpaper";
877 case PAPER_USEXECUTIVE:
878 os << ",executivepaper";
899 // default papersize ie PAPER_DEFAULT
900 switch (lyxrc.default_papersize) {
901 case PAPER_DEFAULT: // keep compiler happy
903 os << ",letterpaper";
908 case PAPER_USEXECUTIVE:
909 os << ",executivepaper";
929 if (!topmargin.empty())
930 os << ",tmargin=" << topmargin;
931 if (!bottommargin.empty())
932 os << ",bmargin=" << bottommargin;
933 if (!leftmargin.empty())
934 os << ",lmargin=" << leftmargin;
935 if (!rightmargin.empty())
936 os << ",rmargin=" << rightmargin;
937 if (!headheight.empty())
938 os << ",headheight=" << headheight;
939 if (!headsep.empty())
940 os << ",headsep=" << headsep;
941 if (!footskip.empty())
942 os << ",footskip=" << footskip;
947 if (tokenPos(tclass.opt_pagestyle(),
948 '|', pagestyle) >= 0) {
949 if (pagestyle == "fancy") {
950 os << "\\usepackage{fancyhdr}\n";
953 os << "\\pagestyle{" << pagestyle << "}\n";
957 // Only if class has a ToC hierarchy
958 if (tclass.hasTocLevels()) {
959 if (secnumdepth != tclass.secnumdepth()) {
960 os << "\\setcounter{secnumdepth}{"
965 if (tocdepth != tclass.tocdepth()) {
966 os << "\\setcounter{tocdepth}{"
973 if (paragraph_separation) {
974 switch (getDefSkip().kind()) {
975 case VSpace::SMALLSKIP:
976 os << "\\setlength\\parskip{\\smallskipamount}\n";
978 case VSpace::MEDSKIP:
979 os << "\\setlength\\parskip{\\medskipamount}\n";
981 case VSpace::BIGSKIP:
982 os << "\\setlength\\parskip{\\bigskipamount}\n";
985 os << "\\setlength\\parskip{"
986 << getDefSkip().length().asLatexString()
989 default: // should never happen // Then delete it.
990 os << "\\setlength\\parskip{\\medskipamount}\n";
995 os << "\\setlength\\parindent{0pt}\n";
999 // If we use jurabib, we have to call babel here.
1000 if (use_babel && features.isRequired("jurabib")) {
1001 os << babelCall(language_options.str())
1003 << features.getBabelOptions();
1007 // Now insert the LyX specific LaTeX commands...
1009 // The optional packages;
1010 string lyxpreamble(features.getPackages());
1012 // this might be useful...
1013 lyxpreamble += "\n\\makeatletter\n";
1015 // Some macros LyX will need
1016 string tmppreamble(features.getMacros());
1018 if (!tmppreamble.empty()) {
1019 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1020 "LyX specific LaTeX commands.\n"
1021 + tmppreamble + '\n';
1024 // the text class specific preamble
1025 tmppreamble = features.getTClassPreamble();
1026 if (!tmppreamble.empty()) {
1027 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1028 "Textclass specific LaTeX commands.\n"
1029 + tmppreamble + '\n';
1032 /* the user-defined preamble */
1033 if (!preamble.empty()) {
1034 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1035 "User specified LaTeX commands.\n"
1039 // Itemize bullet settings need to be last in case the user
1040 // defines their own bullets that use a package included
1041 // in the user-defined preamble -- ARRae
1042 // Actually it has to be done much later than that
1043 // since some packages like frenchb make modifications
1044 // at \begin{document} time -- JMarc
1046 for (int i = 0; i < 4; ++i) {
1047 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1048 if (bullets_def.empty())
1049 bullets_def="\\AtBeginDocument{\n";
1050 bullets_def += " \\def\\labelitemi";
1052 // `i' is one less than the item to modify
1059 bullets_def += "ii";
1065 bullets_def += '{' +
1066 user_defined_bullet(i).getText()
1071 if (!bullets_def.empty())
1072 lyxpreamble += bullets_def + "}\n\n";
1074 // We try to load babel late, in case it interferes
1075 // with other packages.
1076 // Jurabib has to be called after babel, though.
1077 if (use_babel && !features.isRequired("jurabib")) {
1078 lyxpreamble += babelCall(language_options.str()) + '\n';
1079 lyxpreamble += features.getBabelOptions();
1082 lyxpreamble += "\\makeatother\n";
1084 // dvipost settings come after everything else
1085 if (features.isAvailable("dvipost") && tracking_changes && output_changes) {
1088 "\\dvipost{osstart color push Red}\n"
1089 "\\dvipost{osend color pop}\n"
1090 "\\dvipost{cbstart color push Blue}\n"
1091 "\\dvipost{cbend color pop}\n";
1095 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1096 for (int j = 0; j != nlines; ++j) {
1105 void BufferParams::useClassDefaults()
1107 LyXTextClass const & tclass = textclasslist[textclass];
1109 sides = tclass.sides();
1110 columns = tclass.columns();
1111 pagestyle = tclass.pagestyle();
1112 options = tclass.options();
1113 // Only if class has a ToC hierarchy
1114 if (tclass.hasTocLevels()) {
1115 secnumdepth = tclass.secnumdepth();
1116 tocdepth = tclass.tocdepth();
1121 bool BufferParams::hasClassDefaults() const
1123 LyXTextClass const & tclass = textclasslist[textclass];
1125 return (sides == tclass.sides()
1126 && columns == tclass.columns()
1127 && pagestyle == tclass.pagestyle()
1128 && options == tclass.options()
1129 && secnumdepth == tclass.secnumdepth()
1130 && tocdepth == tclass.tocdepth());
1134 LyXTextClass const & BufferParams::getLyXTextClass() const
1136 return textclasslist[textclass];
1140 LyXFont const BufferParams::getFont() const
1142 LyXFont f = getLyXTextClass().defaultfont();
1143 f.setLanguage(language);
1144 if (fontsDefaultFamily == "rmdefault")
1145 f.setFamily(LyXFont::ROMAN_FAMILY);
1146 else if (fontsDefaultFamily == "sfdefault")
1147 f.setFamily(LyXFont::SANS_FAMILY);
1148 else if (fontsDefaultFamily == "ttdefault")
1149 f.setFamily(LyXFont::TYPEWRITER_FAMILY);
1154 void BufferParams::readPreamble(LyXLex & lex)
1156 if (lex.getString() != "\\begin_preamble")
1157 lyxerr << "Error (BufferParams::readPreamble):"
1158 "consistency check failed." << endl;
1160 preamble = lex.getLongString("\\end_preamble");
1164 void BufferParams::readLanguage(LyXLex & lex)
1166 if (!lex.next()) return;
1168 string const tmptok = lex.getString();
1170 // check if tmptok is part of tex_babel in tex-defs.h
1171 language = languages.getLanguage(tmptok);
1173 // Language tmptok was not found
1174 language = default_language;
1175 lyxerr << "Warning: Setting language `"
1176 << tmptok << "' to `" << language->lang()
1182 void BufferParams::readGraphicsDriver(LyXLex & lex)
1184 if (!lex.next()) return;
1186 string const tmptok = lex.getString();
1187 // check if tmptok is part of tex_graphics in tex_defs.h
1190 string const test = tex_graphics[n++];
1192 if (test == tmptok) {
1193 graphicsDriver = tmptok;
1195 } else if (test == "") {
1197 "Warning: graphics driver `$$Token' not recognized!\n"
1198 " Setting graphics driver to `default'.\n");
1199 graphicsDriver = "default";
1206 void BufferParams::readBullets(LyXLex & lex)
1208 if (!lex.next()) return;
1210 int const index = lex.getInteger();
1212 int temp_int = lex.getInteger();
1213 user_defined_bullet(index).setFont(temp_int);
1214 temp_bullet(index).setFont(temp_int);
1216 user_defined_bullet(index).setCharacter(temp_int);
1217 temp_bullet(index).setCharacter(temp_int);
1219 user_defined_bullet(index).setSize(temp_int);
1220 temp_bullet(index).setSize(temp_int);
1224 void BufferParams::readBulletsLaTeX(LyXLex & lex)
1226 // The bullet class should be able to read this.
1227 if (!lex.next()) return;
1228 int const index = lex.getInteger();
1230 string const temp_str = lex.getString();
1232 user_defined_bullet(index).setText(temp_str);
1233 temp_bullet(index).setText(temp_str);
1237 string const BufferParams::paperSizeName() const
1239 char real_papersize = papersize;
1240 if (real_papersize == PAPER_DEFAULT)
1241 real_papersize = lyxrc.default_papersize;
1243 switch (real_papersize) {
1252 case PAPER_USEXECUTIVE:
1256 case PAPER_USLETTER:
1263 string const BufferParams::dvips_options() const
1268 && papersize == PAPER_CUSTOM
1269 && !lyxrc.print_paper_dimension_flag.empty()
1270 && !paperwidth.empty()
1271 && !paperheight.empty()) {
1272 // using a custom papersize
1273 result = lyxrc.print_paper_dimension_flag;
1274 result += ' ' + paperwidth;
1275 result += ',' + paperheight;
1277 string const paper_option = paperSizeName();
1278 if (paper_option != "letter" ||
1279 orientation != ORIENTATION_LANDSCAPE) {
1280 // dvips won't accept -t letter -t landscape.
1281 // In all other cases, include the paper size
1283 result = lyxrc.print_paper_flag;
1284 result += ' ' + paper_option;
1287 if (orientation == ORIENTATION_LANDSCAPE &&
1288 papersize != PAPER_CUSTOM)
1289 result += ' ' + lyxrc.print_landscape_flag;
1294 string const BufferParams::babelCall(string const & lang_opts) const
1296 string tmp = lyxrc.language_package;
1297 if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1298 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1303 string const BufferParams::loadFonts(LaTeXFeatures & features, string const & rm,
1304 string const & sf, string const & tt,
1305 bool const & sc, bool const & osf,
1306 int const & sfscale, int const & ttscale) const
1308 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1309 several packages have been replaced by others, that might not
1310 be installed on every system. We have to take care for that
1311 (see psnfss.pdf). We try to support all psnfss fonts as well
1312 as the fonts that have become de facto standard in the LaTeX
1313 world (e.g. Latin Modern). We do not support obsolete fonts
1314 (like PSLatex). In general, it should be possible to mix any
1315 rm font with any sf or tt font, respectively. (JSpitzm)
1317 -- separate math fonts.
1320 if (rm == "default" && sf == "default" && tt == "default")
1327 // Computer Modern (must be explicitely selectable -- there might be classes
1328 // that define a different default font!
1330 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1331 // osf for Computer Modern needs eco.sty
1333 os << "\\usepackage{eco}\n";
1335 // Latin Modern Roman
1336 else if (rm == "lmodern")
1337 os << "\\usepackage{lmodern}\n";
1339 else if (rm == "ae") {
1340 // not needed when using OT1 font encoding.
1341 if (lyxrc.fontenc != "default")
1342 os << "\\usepackage{ae,aecompl}\n";
1345 else if (rm == "times") {
1346 // try to load the best available package
1347 if (features.isAvailable("mathptmx"))
1348 os << "\\usepackage{mathptmx}\n";
1349 else if (features.isAvailable("mathptm"))
1350 os << "\\usepackage{mathptm}\n";
1352 os << "\\usepackage{times}\n";
1355 else if (rm == "palatino") {
1356 // try to load the best available package
1357 if (features.isAvailable("mathpazo")) {
1358 os << "\\usepackage";
1364 // "osf" includes "sc"!
1368 os << "{mathpazo}\n";
1370 else if (features.isAvailable("mathpple"))
1371 os << "\\usepackage{mathpple}\n";
1373 os << "\\usepackage{palatino}\n";
1376 else if (rm == "utopia") {
1377 // fourier supersedes utopia.sty, but does
1378 // not work with OT1 encoding.
1379 if (features.isAvailable("fourier")
1380 && lyxrc.fontenc != "default") {
1381 os << "\\usepackage";
1392 os << "{fourier}\n";
1395 os << "\\usepackage{utopia}\n";
1397 // Bera (complete fontset)
1398 else if (rm == "bera" && sf == "default" && tt == "default")
1399 os << "\\usepackage{bera}\n";
1401 else if (rm != "default")
1402 os << "\\usepackage" << "{" << rm << "}\n";
1405 // Helvetica, Bera Sans
1406 if (sf == "helvet" || sf == "berasans") {
1408 os << "\\usepackage[scaled=" << float(sfscale) / 100
1409 << "]{" << sf << "}\n";
1411 os << "\\usepackage{" << sf << "}\n";
1414 else if (sf == "avant")
1415 os << "\\usepackage{" << sf << "}\n";
1416 // Computer Modern, Latin Modern, CM Bright
1417 else if (sf != "default")
1418 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1420 // monospaced/typewriter
1421 // Courier, LuxiMono
1422 if (tt == "luximono" || tt == "beramono") {
1424 os << "\\usepackage[scaled=" << float(ttscale) / 100
1425 << "]{" << tt << "}\n";
1427 os << "\\usepackage{" << tt << "}\n";
1430 else if (tt == "courier" )
1431 os << "\\usepackage{" << tt << "}\n";
1432 // Computer Modern, Latin Modern, CM Bright
1433 else if (tt != "default")
1434 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";