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 tracking_changes = false;
304 output_changes = 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") {
493 lex >> tracking_changes;
494 } else if (token == "\\output_changes") {
495 lex >> output_changes;
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>(tracking_changes) << "\n";
703 os << "\\output_changes " << convert<string>(output_changes) << "\n";
705 if (tracking_changes) {
706 AuthorList::Authors::const_iterator it = pimpl_->authorlist.begin();
707 AuthorList::Authors::const_iterator end = pimpl_->authorlist.end();
708 for (; it != end; ++it) {
709 os << "\\author " << it->second << "\n";
715 bool BufferParams::writeLaTeX(ostream & os, LaTeXFeatures & features,
716 TexRow & texrow) const
718 os << "\\documentclass";
720 LyXTextClass const & tclass = getLyXTextClass();
722 ostringstream clsoptions; // the document class options.
724 if (tokenPos(tclass.opt_fontsize(),
725 '|', fontsize) >= 0) {
726 // only write if existing in list (and not default)
727 clsoptions << fontsize << "pt,";
730 // custom, A3, B3 and B4 paper sizes need geometry
731 bool nonstandard_papersize = (papersize == PAPER_B3) ||
732 (papersize == PAPER_B4) ||
733 (papersize == PAPER_A3) ||
734 (papersize == PAPER_CUSTOM);
739 clsoptions << "a4paper,";
742 clsoptions << "letterpaper,";
745 clsoptions << "a5paper,";
748 clsoptions << "b5paper,";
750 case PAPER_USEXECUTIVE:
751 clsoptions << "executivepaper,";
754 clsoptions << "legalpaper,";
766 if (sides != tclass.sides()) {
768 case LyXTextClass::OneSide:
769 clsoptions << "oneside,";
771 case LyXTextClass::TwoSides:
772 clsoptions << "twoside,";
778 if (columns != tclass.columns()) {
780 clsoptions << "twocolumn,";
782 clsoptions << "onecolumn,";
786 && orientation == ORIENTATION_LANDSCAPE)
787 clsoptions << "landscape,";
789 // language should be a parameter to \documentclass
790 if (language->babel() == "hebrew"
791 && default_language->babel() != "hebrew")
792 // This seems necessary
793 features.useLanguage(default_language);
795 ostringstream language_options;
796 bool const use_babel = features.useBabel();
798 language_options << features.getLanguages();
799 language_options << language->babel();
800 if (lyxrc.language_global_options)
801 clsoptions << language_options.str() << ',';
804 // the user-defined options
805 if (!options.empty()) {
806 clsoptions << options << ',';
809 string strOptions(clsoptions.str());
810 if (!strOptions.empty()) {
811 strOptions = rtrim(strOptions, ",");
812 os << '[' << strOptions << ']';
815 os << '{' << tclass.latexname() << "}\n";
817 // end of \documentclass defs
819 // font selection must be done before loading fontenc.sty
821 loadFonts(features, fontsRoman, fontsSans,
822 fontsTypewriter, fontsSC, fontsOSF,
823 fontsSansScale, fontsTypewriterScale);
824 if (!fonts.empty()) {
828 if (fontsDefaultFamily != "default")
829 os << "\\renewcommand{\\familydefault}{\\"
830 << fontsDefaultFamily << "}\n";
831 // this one is not per buffer
832 if (lyxrc.fontenc != "default") {
833 os << "\\usepackage[" << lyxrc.fontenc
838 if (inputenc == "auto") {
839 string const doc_encoding =
840 language->encoding()->latexName();
842 // Create a list with all the input encodings used
844 std::set<string> encodings =
845 features.getEncodingSet(doc_encoding);
847 os << "\\usepackage[";
848 std::copy(encodings.begin(), encodings.end(),
849 std::ostream_iterator<string>(os, ","));
850 os << doc_encoding << "]{inputenc}\n";
852 } else if (inputenc != "default") {
853 os << "\\usepackage[" << inputenc
858 if (use_geometry || nonstandard_papersize) {
859 os << "\\usepackage{geometry}\n";
861 os << "\\geometry{verbose";
862 if (orientation == ORIENTATION_LANDSCAPE)
866 if (!paperwidth.empty())
869 if (!paperheight.empty())
870 os << ",paperheight="
874 os << ",letterpaper";
879 case PAPER_USEXECUTIVE:
880 os << ",executivepaper";
901 // default papersize ie PAPER_DEFAULT
902 switch (lyxrc.default_papersize) {
903 case PAPER_DEFAULT: // keep compiler happy
905 os << ",letterpaper";
910 case PAPER_USEXECUTIVE:
911 os << ",executivepaper";
931 if (!topmargin.empty())
932 os << ",tmargin=" << topmargin;
933 if (!bottommargin.empty())
934 os << ",bmargin=" << bottommargin;
935 if (!leftmargin.empty())
936 os << ",lmargin=" << leftmargin;
937 if (!rightmargin.empty())
938 os << ",rmargin=" << rightmargin;
939 if (!headheight.empty())
940 os << ",headheight=" << headheight;
941 if (!headsep.empty())
942 os << ",headsep=" << headsep;
943 if (!footskip.empty())
944 os << ",footskip=" << footskip;
949 if (tokenPos(tclass.opt_pagestyle(),
950 '|', pagestyle) >= 0) {
951 if (pagestyle == "fancy") {
952 os << "\\usepackage{fancyhdr}\n";
955 os << "\\pagestyle{" << pagestyle << "}\n";
959 // Only if class has a ToC hierarchy
960 if (tclass.hasTocLevels()) {
961 if (secnumdepth != tclass.secnumdepth()) {
962 os << "\\setcounter{secnumdepth}{"
967 if (tocdepth != tclass.tocdepth()) {
968 os << "\\setcounter{tocdepth}{"
975 if (paragraph_separation) {
976 switch (getDefSkip().kind()) {
977 case VSpace::SMALLSKIP:
978 os << "\\setlength\\parskip{\\smallskipamount}\n";
980 case VSpace::MEDSKIP:
981 os << "\\setlength\\parskip{\\medskipamount}\n";
983 case VSpace::BIGSKIP:
984 os << "\\setlength\\parskip{\\bigskipamount}\n";
987 os << "\\setlength\\parskip{"
988 << getDefSkip().length().asLatexString()
991 default: // should never happen // Then delete it.
992 os << "\\setlength\\parskip{\\medskipamount}\n";
997 os << "\\setlength\\parindent{0pt}\n";
1001 // If we use jurabib, we have to call babel here.
1002 if (use_babel && features.isRequired("jurabib")) {
1003 os << babelCall(language_options.str())
1005 << features.getBabelOptions();
1009 // Now insert the LyX specific LaTeX commands...
1011 // The optional packages;
1012 string lyxpreamble(features.getPackages());
1014 // this might be useful...
1015 lyxpreamble += "\n\\makeatletter\n";
1017 // Some macros LyX will need
1018 string tmppreamble(features.getMacros());
1020 if (!tmppreamble.empty()) {
1021 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1022 "LyX specific LaTeX commands.\n"
1023 + tmppreamble + '\n';
1026 // the text class specific preamble
1027 tmppreamble = features.getTClassPreamble();
1028 if (!tmppreamble.empty()) {
1029 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1030 "Textclass specific LaTeX commands.\n"
1031 + tmppreamble + '\n';
1034 /* the user-defined preamble */
1035 if (!preamble.empty()) {
1036 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1037 "User specified LaTeX commands.\n"
1041 // Itemize bullet settings need to be last in case the user
1042 // defines their own bullets that use a package included
1043 // in the user-defined preamble -- ARRae
1044 // Actually it has to be done much later than that
1045 // since some packages like frenchb make modifications
1046 // at \begin{document} time -- JMarc
1048 for (int i = 0; i < 4; ++i) {
1049 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1050 if (bullets_def.empty())
1051 bullets_def="\\AtBeginDocument{\n";
1052 bullets_def += " \\def\\labelitemi";
1054 // `i' is one less than the item to modify
1061 bullets_def += "ii";
1067 bullets_def += '{' +
1068 user_defined_bullet(i).getText()
1073 if (!bullets_def.empty())
1074 lyxpreamble += bullets_def + "}\n\n";
1076 // We try to load babel late, in case it interferes
1077 // with other packages.
1078 // Jurabib has to be called after babel, though.
1079 if (use_babel && !features.isRequired("jurabib")) {
1080 lyxpreamble += babelCall(language_options.str()) + '\n';
1081 lyxpreamble += features.getBabelOptions();
1084 lyxpreamble += "\\makeatother\n";
1086 // dvipost settings come after everything else
1087 if (features.isAvailable("dvipost") && tracking_changes && output_changes) {
1090 "\\dvipost{osstart color push Red}\n"
1091 "\\dvipost{osend color pop}\n"
1092 "\\dvipost{cbstart color push Blue}\n"
1093 "\\dvipost{cbend color pop}\n";
1097 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1098 for (int j = 0; j != nlines; ++j) {
1107 void BufferParams::useClassDefaults()
1109 LyXTextClass const & tclass = textclasslist[textclass];
1111 sides = tclass.sides();
1112 columns = tclass.columns();
1113 pagestyle = tclass.pagestyle();
1114 options = tclass.options();
1115 // Only if class has a ToC hierarchy
1116 if (tclass.hasTocLevels()) {
1117 secnumdepth = tclass.secnumdepth();
1118 tocdepth = tclass.tocdepth();
1123 bool BufferParams::hasClassDefaults() const
1125 LyXTextClass const & tclass = textclasslist[textclass];
1127 return (sides == tclass.sides()
1128 && columns == tclass.columns()
1129 && pagestyle == tclass.pagestyle()
1130 && options == tclass.options()
1131 && secnumdepth == tclass.secnumdepth()
1132 && tocdepth == tclass.tocdepth());
1136 LyXTextClass const & BufferParams::getLyXTextClass() const
1138 return textclasslist[textclass];
1142 LyXFont const BufferParams::getFont() const
1144 LyXFont f = getLyXTextClass().defaultfont();
1145 f.setLanguage(language);
1146 if (fontsDefaultFamily == "rmdefault")
1147 f.setFamily(LyXFont::ROMAN_FAMILY);
1148 else if (fontsDefaultFamily == "sfdefault")
1149 f.setFamily(LyXFont::SANS_FAMILY);
1150 else if (fontsDefaultFamily == "ttdefault")
1151 f.setFamily(LyXFont::TYPEWRITER_FAMILY);
1156 void BufferParams::readPreamble(LyXLex & lex)
1158 if (lex.getString() != "\\begin_preamble")
1159 lyxerr << "Error (BufferParams::readPreamble):"
1160 "consistency check failed." << endl;
1162 preamble = lex.getLongString("\\end_preamble");
1166 void BufferParams::readLanguage(LyXLex & lex)
1168 if (!lex.next()) return;
1170 string const tmptok = lex.getString();
1172 // check if tmptok is part of tex_babel in tex-defs.h
1173 language = languages.getLanguage(tmptok);
1175 // Language tmptok was not found
1176 language = default_language;
1177 lyxerr << "Warning: Setting language `"
1178 << tmptok << "' to `" << language->lang()
1184 void BufferParams::readGraphicsDriver(LyXLex & lex)
1186 if (!lex.next()) return;
1188 string const tmptok = lex.getString();
1189 // check if tmptok is part of tex_graphics in tex_defs.h
1192 string const test = tex_graphics[n++];
1194 if (test == tmptok) {
1195 graphicsDriver = tmptok;
1197 } else if (test == "") {
1199 "Warning: graphics driver `$$Token' not recognized!\n"
1200 " Setting graphics driver to `default'.\n");
1201 graphicsDriver = "default";
1208 void BufferParams::readBullets(LyXLex & lex)
1210 if (!lex.next()) return;
1212 int const index = lex.getInteger();
1214 int temp_int = lex.getInteger();
1215 user_defined_bullet(index).setFont(temp_int);
1216 temp_bullet(index).setFont(temp_int);
1218 user_defined_bullet(index).setCharacter(temp_int);
1219 temp_bullet(index).setCharacter(temp_int);
1221 user_defined_bullet(index).setSize(temp_int);
1222 temp_bullet(index).setSize(temp_int);
1226 void BufferParams::readBulletsLaTeX(LyXLex & lex)
1228 // The bullet class should be able to read this.
1229 if (!lex.next()) return;
1230 int const index = lex.getInteger();
1232 string const temp_str = lex.getString();
1234 user_defined_bullet(index).setText(temp_str);
1235 temp_bullet(index).setText(temp_str);
1239 string const BufferParams::paperSizeName() const
1241 char real_papersize = papersize;
1242 if (real_papersize == PAPER_DEFAULT)
1243 real_papersize = lyxrc.default_papersize;
1245 switch (real_papersize) {
1254 case PAPER_USEXECUTIVE:
1258 case PAPER_USLETTER:
1265 string const BufferParams::dvips_options() const
1270 && papersize == PAPER_CUSTOM
1271 && !lyxrc.print_paper_dimension_flag.empty()
1272 && !paperwidth.empty()
1273 && !paperheight.empty()) {
1274 // using a custom papersize
1275 result = lyxrc.print_paper_dimension_flag;
1276 result += ' ' + paperwidth;
1277 result += ',' + paperheight;
1279 string const paper_option = paperSizeName();
1280 if (paper_option != "letter" ||
1281 orientation != ORIENTATION_LANDSCAPE) {
1282 // dvips won't accept -t letter -t landscape.
1283 // In all other cases, include the paper size
1285 result = lyxrc.print_paper_flag;
1286 result += ' ' + paper_option;
1289 if (orientation == ORIENTATION_LANDSCAPE &&
1290 papersize != PAPER_CUSTOM)
1291 result += ' ' + lyxrc.print_landscape_flag;
1296 string const BufferParams::babelCall(string const & lang_opts) const
1298 string tmp = lyxrc.language_package;
1299 if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1300 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1305 string const BufferParams::loadFonts(LaTeXFeatures & features, string const & rm,
1306 string const & sf, string const & tt,
1307 bool const & sc, bool const & osf,
1308 int const & sfscale, int const & ttscale) const
1310 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1311 several packages have been replaced by others, that might not
1312 be installed on every system. We have to take care for that
1313 (see psnfss.pdf). We try to support all psnfss fonts as well
1314 as the fonts that have become de facto standard in the LaTeX
1315 world (e.g. Latin Modern). We do not support obsolete fonts
1316 (like PSLatex). In general, it should be possible to mix any
1317 rm font with any sf or tt font, respectively. (JSpitzm)
1319 -- separate math fonts.
1322 if (rm == "default" && sf == "default" && tt == "default")
1329 // Computer Modern (must be explicitely selectable -- there might be classes
1330 // that define a different default font!
1332 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1333 // osf for Computer Modern needs eco.sty
1335 os << "\\usepackage{eco}\n";
1337 // Latin Modern Roman
1338 else if (rm == "lmodern")
1339 os << "\\usepackage{lmodern}\n";
1341 else if (rm == "ae") {
1342 // not needed when using OT1 font encoding.
1343 if (lyxrc.fontenc != "default")
1344 os << "\\usepackage{ae,aecompl}\n";
1347 else if (rm == "times") {
1348 // try to load the best available package
1349 if (features.isAvailable("mathptmx"))
1350 os << "\\usepackage{mathptmx}\n";
1351 else if (features.isAvailable("mathptm"))
1352 os << "\\usepackage{mathptm}\n";
1354 os << "\\usepackage{times}\n";
1357 else if (rm == "palatino") {
1358 // try to load the best available package
1359 if (features.isAvailable("mathpazo")) {
1360 os << "\\usepackage";
1366 // "osf" includes "sc"!
1370 os << "{mathpazo}\n";
1372 else if (features.isAvailable("mathpple"))
1373 os << "\\usepackage{mathpple}\n";
1375 os << "\\usepackage{palatino}\n";
1378 else if (rm == "utopia") {
1379 // fourier supersedes utopia.sty, but does
1380 // not work with OT1 encoding.
1381 if (features.isAvailable("fourier")
1382 && lyxrc.fontenc != "default") {
1383 os << "\\usepackage";
1394 os << "{fourier}\n";
1397 os << "\\usepackage{utopia}\n";
1399 // Bera (complete fontset)
1400 else if (rm == "bera" && sf == "default" && tt == "default")
1401 os << "\\usepackage{bera}\n";
1403 else if (rm != "default")
1404 os << "\\usepackage" << "{" << rm << "}\n";
1407 // Helvetica, Bera Sans
1408 if (sf == "helvet" || sf == "berasans") {
1410 os << "\\usepackage[scaled=" << float(sfscale) / 100
1411 << "]{" << sf << "}\n";
1413 os << "\\usepackage{" << sf << "}\n";
1416 else if (sf == "avant")
1417 os << "\\usepackage{" << sf << "}\n";
1418 // Computer Modern, Latin Modern, CM Bright
1419 else if (sf != "default")
1420 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1422 // monospaced/typewriter
1423 // Courier, LuxiMono
1424 if (tt == "luximono" || tt == "beramono") {
1426 os << "\\usepackage[scaled=" << float(ttscale) / 100
1427 << "]{" << tt << "}\n";
1429 os << "\\usepackage{" << tt << "}\n";
1432 else if (tt == "courier" )
1433 os << "\\usepackage{" << tt << "}\n";
1434 // Computer Modern, Latin Modern, CM Bright
1435 else if (tt != "default")
1436 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";