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::odocstream;
53 using lyx::support::bformat;
54 using lyx::support::rtrim;
55 using lyx::support::tokenPos;
59 using std::istringstream;
61 using std::ostringstream;
64 namespace Alert = lyx::frontend::Alert;
65 namespace biblio = lyx::biblio;
71 // Paragraph separation
72 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
75 ParSepTranslator const init_parseptranslator()
77 ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
78 translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
83 ParSepTranslator const & parseptranslator()
85 static ParSepTranslator translator = init_parseptranslator();
91 typedef Translator<string, InsetQuotes::quote_language> QuotesLangTranslator;
94 QuotesLangTranslator const init_quoteslangtranslator()
96 QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
97 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
98 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
99 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
100 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
101 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
106 QuotesLangTranslator const & quoteslangtranslator()
108 static QuotesLangTranslator translator = init_quoteslangtranslator();
114 typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
117 PaperSizeTranslator const init_papersizetranslator()
119 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
120 translator.addPair(string_papersize[1], PAPER_CUSTOM);
121 translator.addPair(string_papersize[2], PAPER_USLETTER);
122 translator.addPair(string_papersize[3], PAPER_USLEGAL);
123 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
124 translator.addPair(string_papersize[5], PAPER_A3);
125 translator.addPair(string_papersize[6], PAPER_A4);
126 translator.addPair(string_papersize[7], PAPER_A5);
127 translator.addPair(string_papersize[8], PAPER_B3);
128 translator.addPair(string_papersize[9], PAPER_B4);
129 translator.addPair(string_papersize[10], PAPER_B5);
134 PaperSizeTranslator const & papersizetranslator()
136 static PaperSizeTranslator translator = init_papersizetranslator();
142 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
145 PaperOrientationTranslator const init_paperorientationtranslator()
147 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
148 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
153 PaperOrientationTranslator const & paperorientationtranslator()
155 static PaperOrientationTranslator translator = init_paperorientationtranslator();
161 typedef Translator<int, LyXTextClass::PageSides> SidesTranslator;
164 SidesTranslator const init_sidestranslator()
166 SidesTranslator translator(1, LyXTextClass::OneSide);
167 translator.addPair(2, LyXTextClass::TwoSides);
172 SidesTranslator const & sidestranslator()
174 static SidesTranslator translator = init_sidestranslator();
181 typedef Translator<int, BufferParams::AMS> AMSTranslator;
184 AMSTranslator const init_amstranslator()
186 AMSTranslator translator(0, BufferParams::AMS_OFF);
187 translator.addPair(1, BufferParams::AMS_AUTO);
188 translator.addPair(2, BufferParams::AMS_ON);
193 AMSTranslator const & amstranslator()
195 static AMSTranslator translator = init_amstranslator();
201 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
204 CiteEngineTranslator const init_citeenginetranslator()
206 CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
207 translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
208 translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
209 translator.addPair("jurabib", biblio::ENGINE_JURABIB);
214 CiteEngineTranslator const & citeenginetranslator()
216 static CiteEngineTranslator translator = init_citeenginetranslator();
222 typedef Translator<string, Spacing::Space> SpaceTranslator;
225 SpaceTranslator const init_spacetranslator()
227 SpaceTranslator translator("default", Spacing::Default);
228 translator.addPair("single", Spacing::Single);
229 translator.addPair("onehalf", Spacing::Onehalf);
230 translator.addPair("double", Spacing::Double);
231 translator.addPair("other", Spacing::Other);
236 SpaceTranslator const & spacetranslator()
238 static SpaceTranslator translator = init_spacetranslator();
242 // ends annonym namespace
246 class BufferParams::Impl
251 AuthorList authorlist;
252 BranchList branchlist;
253 boost::array<Bullet, 4> temp_bullets;
254 boost::array<Bullet, 4> user_defined_bullets;
256 /** This is the amount of space used for paragraph_separation "skip",
257 * and for detached paragraphs in "indented" documents.
263 BufferParams::Impl::Impl()
264 : defskip(VSpace::MEDSKIP)
266 // set initial author
267 authorlist.record(Author(lyxrc.user_name, lyxrc.user_email));
272 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
276 return new BufferParams::Impl(*ptr);
280 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
286 BufferParams::BufferParams()
287 : // Initialize textclass to point to article. if `first' is
288 // true in the returned pair, then `second' is the textclass
289 // number; if it is false, second is 0. In both cases, second
291 textclass(textclasslist.numberOfClass("article").second),
294 paragraph_separation = PARSEP_INDENT;
295 quotes_language = InsetQuotes::EnglishQ;
296 fontsize = "default";
299 papersize = PAPER_DEFAULT;
300 orientation = ORIENTATION_PORTRAIT;
301 use_geometry = false;
302 use_amsmath = AMS_AUTO;
303 cite_engine = biblio::ENGINE_BASIC;
304 use_bibtopic = false;
305 trackChanges = false;
306 outputChanges = false;
309 language = default_language;
310 fontsRoman = "default";
311 fontsSans = "default";
312 fontsTypewriter = "default";
313 fontsDefaultFamily = "default";
316 fontsSansScale = 100;
317 fontsTypewriterScale = 100;
319 graphicsDriver = "default";
320 sides = LyXTextClass::OneSide;
322 pagestyle = "default";
324 for (int iter = 0; iter < 4; ++iter) {
325 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
326 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
331 BufferParams::~BufferParams()
335 AuthorList & BufferParams::authors()
337 return pimpl_->authorlist;
341 AuthorList const & BufferParams::authors() const
343 return pimpl_->authorlist;
347 BranchList & BufferParams::branchlist()
349 return pimpl_->branchlist;
353 BranchList const & BufferParams::branchlist() const
355 return pimpl_->branchlist;
359 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
361 BOOST_ASSERT(index < 4);
362 return pimpl_->temp_bullets[index];
366 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
368 BOOST_ASSERT(index < 4);
369 return pimpl_->temp_bullets[index];
373 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
375 BOOST_ASSERT(index < 4);
376 return pimpl_->user_defined_bullets[index];
380 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
382 BOOST_ASSERT(index < 4);
383 return pimpl_->user_defined_bullets[index];
387 Spacing & BufferParams::spacing()
389 return pimpl_->spacing;
393 Spacing const & BufferParams::spacing() const
395 return pimpl_->spacing;
399 VSpace const & BufferParams::getDefSkip() const
401 return pimpl_->defskip;
405 void BufferParams::setDefSkip(VSpace const & vs)
407 pimpl_->defskip = vs;
411 string const BufferParams::readToken(LyXLex & lex, string const & token)
413 if (token == "\\textclass") {
415 string const classname = lex.getString();
416 pair<bool, lyx::textclass_type> pp =
417 textclasslist.numberOfClass(classname);
419 textclass = pp.second;
421 // if text class does not exist, try to load it from filepath
422 pp = textclasslist.addTextClass(classname, filepath);
424 textclass = pp.second;
430 // FIXME: isTeXClassAvailable will try to load the layout file, but will
431 // fail because of the lack of path info. Warnings will be given although
432 // the layout file will be correctly loaded later.
433 if (!getLyXTextClass().isTeXClassAvailable()) {
434 docstring const msg =
435 bformat(_("The document uses a missing "
436 "TeX class \"%1$s\".\n"), lyx::from_utf8(classname));
437 Alert::warning(_("Document class not available"),
438 msg + _("LyX will not be able to produce output."));
440 } else if (token == "\\begin_preamble") {
442 } else if (token == "\\options") {
444 options = lex.getString();
445 } else if (token == "\\language") {
447 } else if (token == "\\inputencoding") {
449 } else if (token == "\\graphics") {
450 readGraphicsDriver(lex);
451 } else if (token == "\\font_roman") {
453 } else if (token == "\\font_sans") {
455 } else if (token == "\\font_typewriter") {
456 lex >> fontsTypewriter;
457 } else if (token == "\\font_default_family") {
458 lex >> fontsDefaultFamily;
459 } else if (token == "\\font_sc") {
461 } else if (token == "\\font_osf") {
463 } else if (token == "\\font_sf_scale") {
464 lex >> fontsSansScale;
465 } else if (token == "\\font_tt_scale") {
466 lex >> fontsTypewriterScale;
467 } else if (token == "\\paragraph_separation") {
470 paragraph_separation = parseptranslator().find(parsep);
471 } else if (token == "\\defskip") {
473 pimpl_->defskip = VSpace(lex.getString());
474 } else if (token == "\\quotes_language") {
477 quotes_language = quoteslangtranslator().find(quotes_lang);
478 } else if (token == "\\papersize") {
481 papersize = papersizetranslator().find(ppsize);
482 } else if (token == "\\use_geometry") {
484 } else if (token == "\\use_amsmath") {
487 use_amsmath = amstranslator().find(use_ams);
488 } else if (token == "\\cite_engine") {
491 cite_engine = citeenginetranslator().find(engine);
492 } else if (token == "\\use_bibtopic") {
494 } else if (token == "\\tracking_changes") {
496 } else if (token == "\\output_changes") {
497 lex >> outputChanges;
498 } else if (token == "\\branch") {
500 string branch = lex.getString();
501 branchlist().add(branch);
504 string const tok = lex.getString();
505 if (tok == "\\end_branch")
507 Branch * branch_ptr = branchlist().find(branch);
508 if (tok == "\\selected") {
511 branch_ptr->setSelected(lex.getInteger());
513 // not yet operational
514 if (tok == "\\color") {
516 string color = lex.getString();
518 branch_ptr->setColor(color);
519 // Update also the LColor table:
521 color = lcolor.getX11Name(LColor::background);
522 lcolor.setColor(branch, color);
526 } else if (token == "\\author") {
528 istringstream ss(lex.getString());
531 author_map.push_back(pimpl_->authorlist.record(a));
532 } else if (token == "\\paperorientation") {
535 orientation = paperorientationtranslator().find(orient);
536 } else if (token == "\\paperwidth") {
538 } else if (token == "\\paperheight") {
540 } else if (token == "\\leftmargin") {
542 } else if (token == "\\topmargin") {
544 } else if (token == "\\rightmargin") {
546 } else if (token == "\\bottommargin") {
548 } else if (token == "\\headheight") {
550 } else if (token == "\\headsep") {
552 } else if (token == "\\footskip") {
554 } else if (token == "\\paperfontsize") {
556 } else if (token == "\\papercolumns") {
558 } else if (token == "\\papersides") {
561 sides = sidestranslator().find(psides);
562 } else if (token == "\\paperpagestyle") {
564 } else if (token == "\\bullet") {
566 } else if (token == "\\bulletLaTeX") {
567 readBulletsLaTeX(lex);
568 } else if (token == "\\secnumdepth") {
570 } else if (token == "\\tocdepth") {
572 } else if (token == "\\spacing") {
576 if (nspacing == "other") {
579 spacing().set(spacetranslator().find(nspacing), tmp_val);
580 } else if (token == "\\float_placement") {
581 lex >> float_placement;
590 void BufferParams::writeFile(ostream & os) const
592 // The top of the file is written by the buffer.
593 // Prints out the buffer info into the .lyx file given by file
596 os << "\\textclass " << textclasslist[textclass].name() << '\n';
598 // then the the preamble
599 if (!preamble.empty()) {
600 // remove '\n' from the end of preamble
601 string const tmppreamble = rtrim(preamble, "\n");
602 os << "\\begin_preamble\n"
604 << "\n\\end_preamble\n";
608 if (!options.empty()) {
609 os << "\\options " << options << '\n';
612 // then the text parameters
613 if (language != ignore_language)
614 os << "\\language " << language->lang() << '\n';
615 os << "\\inputencoding " << inputenc
616 << "\n\\font_roman " << fontsRoman
617 << "\n\\font_sans " << fontsSans
618 << "\n\\font_typewriter " << fontsTypewriter
619 << "\n\\font_default_family " << fontsDefaultFamily
620 << "\n\\font_sc " << convert<string>(fontsSC)
621 << "\n\\font_osf " << convert<string>(fontsOSF)
622 << "\n\\font_sf_scale " << fontsSansScale
623 << "\n\\font_tt_scale " << fontsTypewriterScale
624 << "\n\\graphics " << graphicsDriver << '\n';
626 if (!float_placement.empty()) {
627 os << "\\float_placement " << float_placement << '\n';
629 os << "\\paperfontsize " << fontsize << '\n';
631 spacing().writeFile(os);
633 os << "\\papersize " << string_papersize[papersize]
634 << "\n\\use_geometry " << convert<string>(use_geometry)
635 << "\n\\use_amsmath " << use_amsmath
636 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine)
637 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
638 << "\n\\paperorientation " << string_orientation[orientation]
641 BranchList::const_iterator it = branchlist().begin();
642 BranchList::const_iterator end = branchlist().end();
643 for (; it != end; ++it) {
644 os << "\\branch " << it->getBranch()
645 << "\n\\selected " << it->getSelected()
646 << "\n\\color " << lyx::X11hexname(it->getColor())
651 if (!paperwidth.empty())
652 os << "\\paperwidth "
653 << VSpace(paperwidth).asLyXCommand() << '\n';
654 if (!paperheight.empty())
655 os << "\\paperheight "
656 << VSpace(paperheight).asLyXCommand() << '\n';
657 if (!leftmargin.empty())
658 os << "\\leftmargin "
659 << VSpace(leftmargin).asLyXCommand() << '\n';
660 if (!topmargin.empty())
662 << VSpace(topmargin).asLyXCommand() << '\n';
663 if (!rightmargin.empty())
664 os << "\\rightmargin "
665 << VSpace(rightmargin).asLyXCommand() << '\n';
666 if (!bottommargin.empty())
667 os << "\\bottommargin "
668 << VSpace(bottommargin).asLyXCommand() << '\n';
669 if (!headheight.empty())
670 os << "\\headheight "
671 << VSpace(headheight).asLyXCommand() << '\n';
672 if (!headsep.empty())
674 << VSpace(headsep).asLyXCommand() << '\n';
675 if (!footskip.empty())
677 << VSpace(footskip).asLyXCommand() << '\n';
678 os << "\\secnumdepth " << secnumdepth
679 << "\n\\tocdepth " << tocdepth
680 << "\n\\paragraph_separation "
681 << string_paragraph_separation[paragraph_separation]
682 << "\n\\defskip " << getDefSkip().asLyXCommand()
683 << "\n\\quotes_language "
684 << string_quotes_language[quotes_language]
685 << "\n\\papercolumns " << columns
686 << "\n\\papersides " << sides
687 << "\n\\paperpagestyle " << pagestyle << '\n';
688 for (int i = 0; i < 4; ++i) {
689 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
690 if (user_defined_bullet(i).getFont() != -1) {
691 os << "\\bullet " << i << " "
692 << user_defined_bullet(i).getFont() << " "
693 << user_defined_bullet(i).getCharacter() << " "
694 << user_defined_bullet(i).getSize() << "\n";
697 os << "\\bulletLaTeX " << i << " \""
698 << user_defined_bullet(i).getText()
704 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
705 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
708 // FIXME: Change tracking (MG)
709 AuthorList::Authors::const_iterator it = pimpl_->authorlist.begin();
710 AuthorList::Authors::const_iterator end = pimpl_->authorlist.end();
711 for (; it != end; ++it) {
712 os << "\\author " << it->second << "\n";
718 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
719 TexRow & texrow) const
721 os << "\\documentclass";
723 LyXTextClass const & tclass = getLyXTextClass();
725 ostringstream clsoptions; // the document class options.
727 if (tokenPos(tclass.opt_fontsize(),
728 '|', fontsize) >= 0) {
729 // only write if existing in list (and not default)
730 clsoptions << fontsize << "pt,";
733 // custom, A3, B3 and B4 paper sizes need geometry
734 bool nonstandard_papersize = (papersize == PAPER_B3) ||
735 (papersize == PAPER_B4) ||
736 (papersize == PAPER_A3) ||
737 (papersize == PAPER_CUSTOM);
742 clsoptions << "a4paper,";
745 clsoptions << "letterpaper,";
748 clsoptions << "a5paper,";
751 clsoptions << "b5paper,";
753 case PAPER_USEXECUTIVE:
754 clsoptions << "executivepaper,";
757 clsoptions << "legalpaper,";
769 if (sides != tclass.sides()) {
771 case LyXTextClass::OneSide:
772 clsoptions << "oneside,";
774 case LyXTextClass::TwoSides:
775 clsoptions << "twoside,";
781 if (columns != tclass.columns()) {
783 clsoptions << "twocolumn,";
785 clsoptions << "onecolumn,";
789 && orientation == ORIENTATION_LANDSCAPE)
790 clsoptions << "landscape,";
792 // language should be a parameter to \documentclass
793 if (language->babel() == "hebrew"
794 && default_language->babel() != "hebrew")
795 // This seems necessary
796 features.useLanguage(default_language);
798 ostringstream language_options;
799 bool const use_babel = features.useBabel();
801 language_options << features.getLanguages();
802 language_options << language->babel();
803 if (lyxrc.language_global_options)
804 clsoptions << language_options.str() << ',';
807 // the user-defined options
808 if (!options.empty()) {
809 clsoptions << options << ',';
812 string strOptions(clsoptions.str());
813 if (!strOptions.empty()) {
814 strOptions = rtrim(strOptions, ",");
816 os << '[' << lyx::from_utf8(strOptions) << ']';
819 os << '{' << lyx::from_ascii(tclass.latexname()) << "}\n";
821 // end of \documentclass defs
823 // font selection must be done before loading fontenc.sty
825 loadFonts(features, fontsRoman, fontsSans,
826 fontsTypewriter, fontsSC, fontsOSF,
827 fontsSansScale, fontsTypewriterScale);
828 if (!fonts.empty()) {
829 os << lyx::from_ascii(fonts);
832 if (fontsDefaultFamily != "default")
833 os << "\\renewcommand{\\familydefault}{\\"
834 << lyx::from_ascii(fontsDefaultFamily) << "}\n";
835 // this one is not per buffer
836 if (lyxrc.fontenc != "default") {
837 os << "\\usepackage[" << lyx::from_ascii(lyxrc.fontenc)
842 if (inputenc == "auto") {
843 string const doc_encoding =
844 language->encoding()->latexName();
846 // Create a list with all the input encodings used
848 std::set<string> encodings =
849 features.getEncodingSet(doc_encoding);
851 os << "\\usepackage[";
852 std::set<string>::const_iterator it = encodings.begin();
853 std::set<string>::const_iterator const end = encodings.end();
854 for (; it != end; ++it)
855 os << lyx::from_ascii(*it) << ',';
856 os << lyx::from_ascii(doc_encoding) << "]{inputenc}\n";
858 } else if (inputenc != "default") {
859 os << "\\usepackage[" << lyx::from_ascii(inputenc)
864 if (use_geometry || nonstandard_papersize) {
865 os << "\\usepackage{geometry}\n";
867 os << "\\geometry{verbose";
868 if (orientation == ORIENTATION_LANDSCAPE)
872 if (!paperwidth.empty())
874 << lyx::from_ascii(paperwidth);
875 if (!paperheight.empty())
876 os << ",paperheight="
877 << lyx::from_ascii(paperheight);
880 os << ",letterpaper";
885 case PAPER_USEXECUTIVE:
886 os << ",executivepaper";
907 // default papersize ie PAPER_DEFAULT
908 switch (lyxrc.default_papersize) {
909 case PAPER_DEFAULT: // keep compiler happy
911 os << ",letterpaper";
916 case PAPER_USEXECUTIVE:
917 os << ",executivepaper";
937 if (!topmargin.empty())
938 os << ",tmargin=" << lyx::from_ascii(topmargin);
939 if (!bottommargin.empty())
940 os << ",bmargin=" << lyx::from_ascii(bottommargin);
941 if (!leftmargin.empty())
942 os << ",lmargin=" << lyx::from_ascii(leftmargin);
943 if (!rightmargin.empty())
944 os << ",rmargin=" << lyx::from_ascii(rightmargin);
945 if (!headheight.empty())
946 os << ",headheight=" << lyx::from_ascii(headheight);
947 if (!headsep.empty())
948 os << ",headsep=" << lyx::from_ascii(headsep);
949 if (!footskip.empty())
950 os << ",footskip=" << lyx::from_ascii(footskip);
955 if (tokenPos(tclass.opt_pagestyle(),
956 '|', pagestyle) >= 0) {
957 if (pagestyle == "fancy") {
958 os << "\\usepackage{fancyhdr}\n";
961 os << "\\pagestyle{" << lyx::from_ascii(pagestyle) << "}\n";
965 // Only if class has a ToC hierarchy
966 if (tclass.hasTocLevels()) {
967 if (secnumdepth != tclass.secnumdepth()) {
968 os << "\\setcounter{secnumdepth}{"
973 if (tocdepth != tclass.tocdepth()) {
974 os << "\\setcounter{tocdepth}{"
981 if (paragraph_separation) {
982 switch (getDefSkip().kind()) {
983 case VSpace::SMALLSKIP:
984 os << "\\setlength\\parskip{\\smallskipamount}\n";
986 case VSpace::MEDSKIP:
987 os << "\\setlength\\parskip{\\medskipamount}\n";
989 case VSpace::BIGSKIP:
990 os << "\\setlength\\parskip{\\bigskipamount}\n";
993 os << "\\setlength\\parskip{"
994 << lyx::from_ascii(getDefSkip().length().asLatexString())
997 default: // should never happen // Then delete it.
998 os << "\\setlength\\parskip{\\medskipamount}\n";
1003 os << "\\setlength\\parindent{0pt}\n";
1007 // If we use jurabib, we have to call babel here.
1008 if (use_babel && features.isRequired("jurabib")) {
1009 os << lyx::from_ascii(babelCall(language_options.str()))
1011 << lyx::from_ascii(features.getBabelOptions());
1015 // Now insert the LyX specific LaTeX commands...
1017 // The optional packages;
1018 string lyxpreamble(features.getPackages());
1020 // this might be useful...
1021 lyxpreamble += "\n\\makeatletter\n";
1023 // Some macros LyX will need
1024 string tmppreamble(features.getMacros());
1026 if (!tmppreamble.empty()) {
1027 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1028 "LyX specific LaTeX commands.\n"
1029 + tmppreamble + '\n';
1032 // the text class specific preamble
1033 tmppreamble = features.getTClassPreamble();
1034 if (!tmppreamble.empty()) {
1035 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1036 "Textclass specific LaTeX commands.\n"
1037 + tmppreamble + '\n';
1040 /* the user-defined preamble */
1041 if (!preamble.empty()) {
1042 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1043 "User specified LaTeX commands.\n"
1047 // Itemize bullet settings need to be last in case the user
1048 // defines their own bullets that use a package included
1049 // in the user-defined preamble -- ARRae
1050 // Actually it has to be done much later than that
1051 // since some packages like frenchb make modifications
1052 // at \begin{document} time -- JMarc
1054 for (int i = 0; i < 4; ++i) {
1055 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1056 if (bullets_def.empty())
1057 bullets_def="\\AtBeginDocument{\n";
1058 bullets_def += " \\def\\labelitemi";
1060 // `i' is one less than the item to modify
1067 bullets_def += "ii";
1073 bullets_def += '{' +
1074 user_defined_bullet(i).getText()
1079 if (!bullets_def.empty())
1080 lyxpreamble += bullets_def + "}\n\n";
1082 // We try to load babel late, in case it interferes
1083 // with other packages.
1084 // Jurabib has to be called after babel, though.
1085 if (use_babel && !features.isRequired("jurabib")) {
1086 lyxpreamble += babelCall(language_options.str()) + '\n';
1087 lyxpreamble += features.getBabelOptions();
1090 lyxpreamble += "\\makeatother\n";
1092 // dvipost settings come after everything else
1093 if (features.isAvailable("dvipost") && outputChanges) {
1096 "\\dvipost{osstart color push Red}\n"
1097 "\\dvipost{osend color pop}\n"
1098 "\\dvipost{cbstart color push Blue}\n"
1099 "\\dvipost{cbend color pop}\n";
1103 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1104 for (int j = 0; j != nlines; ++j) {
1109 os << lyx::from_utf8(lyxpreamble);
1114 void BufferParams::useClassDefaults()
1116 LyXTextClass const & tclass = textclasslist[textclass];
1118 sides = tclass.sides();
1119 columns = tclass.columns();
1120 pagestyle = tclass.pagestyle();
1121 options = tclass.options();
1122 // Only if class has a ToC hierarchy
1123 if (tclass.hasTocLevels()) {
1124 secnumdepth = tclass.secnumdepth();
1125 tocdepth = tclass.tocdepth();
1130 bool BufferParams::hasClassDefaults() const
1132 LyXTextClass const & tclass = textclasslist[textclass];
1134 return (sides == tclass.sides()
1135 && columns == tclass.columns()
1136 && pagestyle == tclass.pagestyle()
1137 && options == tclass.options()
1138 && secnumdepth == tclass.secnumdepth()
1139 && tocdepth == tclass.tocdepth());
1143 LyXTextClass const & BufferParams::getLyXTextClass() const
1145 return textclasslist[textclass];
1149 LyXFont const BufferParams::getFont() const
1151 LyXFont f = getLyXTextClass().defaultfont();
1152 f.setLanguage(language);
1153 if (fontsDefaultFamily == "rmdefault")
1154 f.setFamily(LyXFont::ROMAN_FAMILY);
1155 else if (fontsDefaultFamily == "sfdefault")
1156 f.setFamily(LyXFont::SANS_FAMILY);
1157 else if (fontsDefaultFamily == "ttdefault")
1158 f.setFamily(LyXFont::TYPEWRITER_FAMILY);
1163 void BufferParams::readPreamble(LyXLex & lex)
1165 if (lex.getString() != "\\begin_preamble")
1166 lyxerr << "Error (BufferParams::readPreamble):"
1167 "consistency check failed." << endl;
1169 preamble = lex.getLongString("\\end_preamble");
1173 void BufferParams::readLanguage(LyXLex & lex)
1175 if (!lex.next()) return;
1177 string const tmptok = lex.getString();
1179 // check if tmptok is part of tex_babel in tex-defs.h
1180 language = languages.getLanguage(tmptok);
1182 // Language tmptok was not found
1183 language = default_language;
1184 lyxerr << "Warning: Setting language `"
1185 << tmptok << "' to `" << language->lang()
1191 void BufferParams::readGraphicsDriver(LyXLex & lex)
1193 if (!lex.next()) return;
1195 string const tmptok = lex.getString();
1196 // check if tmptok is part of tex_graphics in tex_defs.h
1199 string const test = tex_graphics[n++];
1201 if (test == tmptok) {
1202 graphicsDriver = tmptok;
1204 } else if (test == "") {
1206 "Warning: graphics driver `$$Token' not recognized!\n"
1207 " Setting graphics driver to `default'.\n");
1208 graphicsDriver = "default";
1215 void BufferParams::readBullets(LyXLex & lex)
1217 if (!lex.next()) return;
1219 int const index = lex.getInteger();
1221 int temp_int = lex.getInteger();
1222 user_defined_bullet(index).setFont(temp_int);
1223 temp_bullet(index).setFont(temp_int);
1225 user_defined_bullet(index).setCharacter(temp_int);
1226 temp_bullet(index).setCharacter(temp_int);
1228 user_defined_bullet(index).setSize(temp_int);
1229 temp_bullet(index).setSize(temp_int);
1233 void BufferParams::readBulletsLaTeX(LyXLex & lex)
1235 // The bullet class should be able to read this.
1236 if (!lex.next()) return;
1237 int const index = lex.getInteger();
1239 string const temp_str = lex.getString();
1241 user_defined_bullet(index).setText(temp_str);
1242 temp_bullet(index).setText(temp_str);
1246 string const BufferParams::paperSizeName() const
1248 char real_papersize = papersize;
1249 if (real_papersize == PAPER_DEFAULT)
1250 real_papersize = lyxrc.default_papersize;
1252 switch (real_papersize) {
1261 case PAPER_USEXECUTIVE:
1265 case PAPER_USLETTER:
1272 string const BufferParams::dvips_options() const
1277 && papersize == PAPER_CUSTOM
1278 && !lyxrc.print_paper_dimension_flag.empty()
1279 && !paperwidth.empty()
1280 && !paperheight.empty()) {
1281 // using a custom papersize
1282 result = lyxrc.print_paper_dimension_flag;
1283 result += ' ' + paperwidth;
1284 result += ',' + paperheight;
1286 string const paper_option = paperSizeName();
1287 if (paper_option != "letter" ||
1288 orientation != ORIENTATION_LANDSCAPE) {
1289 // dvips won't accept -t letter -t landscape.
1290 // In all other cases, include the paper size
1292 result = lyxrc.print_paper_flag;
1293 result += ' ' + paper_option;
1296 if (orientation == ORIENTATION_LANDSCAPE &&
1297 papersize != PAPER_CUSTOM)
1298 result += ' ' + lyxrc.print_landscape_flag;
1303 string const BufferParams::babelCall(string const & lang_opts) const
1305 string tmp = lyxrc.language_package;
1306 if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1307 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1312 string const BufferParams::loadFonts(LaTeXFeatures & features, string const & rm,
1313 string const & sf, string const & tt,
1314 bool const & sc, bool const & osf,
1315 int const & sfscale, int const & ttscale) const
1317 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1318 several packages have been replaced by others, that might not
1319 be installed on every system. We have to take care for that
1320 (see psnfss.pdf). We try to support all psnfss fonts as well
1321 as the fonts that have become de facto standard in the LaTeX
1322 world (e.g. Latin Modern). We do not support obsolete fonts
1323 (like PSLatex). In general, it should be possible to mix any
1324 rm font with any sf or tt font, respectively. (JSpitzm)
1326 -- separate math fonts.
1329 if (rm == "default" && sf == "default" && tt == "default")
1336 // Computer Modern (must be explicitely selectable -- there might be classes
1337 // that define a different default font!
1339 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1340 // osf for Computer Modern needs eco.sty
1342 os << "\\usepackage{eco}\n";
1344 // Latin Modern Roman
1345 else if (rm == "lmodern")
1346 os << "\\usepackage{lmodern}\n";
1348 else if (rm == "ae") {
1349 // not needed when using OT1 font encoding.
1350 if (lyxrc.fontenc != "default")
1351 os << "\\usepackage{ae,aecompl}\n";
1354 else if (rm == "times") {
1355 // try to load the best available package
1356 if (features.isAvailable("mathptmx"))
1357 os << "\\usepackage{mathptmx}\n";
1358 else if (features.isAvailable("mathptm"))
1359 os << "\\usepackage{mathptm}\n";
1361 os << "\\usepackage{times}\n";
1364 else if (rm == "palatino") {
1365 // try to load the best available package
1366 if (features.isAvailable("mathpazo")) {
1367 os << "\\usepackage";
1373 // "osf" includes "sc"!
1377 os << "{mathpazo}\n";
1379 else if (features.isAvailable("mathpple"))
1380 os << "\\usepackage{mathpple}\n";
1382 os << "\\usepackage{palatino}\n";
1385 else if (rm == "utopia") {
1386 // fourier supersedes utopia.sty, but does
1387 // not work with OT1 encoding.
1388 if (features.isAvailable("fourier")
1389 && lyxrc.fontenc != "default") {
1390 os << "\\usepackage";
1401 os << "{fourier}\n";
1404 os << "\\usepackage{utopia}\n";
1406 // Bera (complete fontset)
1407 else if (rm == "bera" && sf == "default" && tt == "default")
1408 os << "\\usepackage{bera}\n";
1410 else if (rm != "default")
1411 os << "\\usepackage" << "{" << rm << "}\n";
1414 // Helvetica, Bera Sans
1415 if (sf == "helvet" || sf == "berasans") {
1417 os << "\\usepackage[scaled=" << float(sfscale) / 100
1418 << "]{" << sf << "}\n";
1420 os << "\\usepackage{" << sf << "}\n";
1423 else if (sf == "avant")
1424 os << "\\usepackage{" << sf << "}\n";
1425 // Computer Modern, Latin Modern, CM Bright
1426 else if (sf != "default")
1427 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1429 // monospaced/typewriter
1430 // Courier, LuxiMono
1431 if (tt == "luximono" || tt == "beramono") {
1433 os << "\\usepackage[scaled=" << float(ttscale) / 100
1434 << "]{" << tt << "}\n";
1436 os << "\\usepackage{" << tt << "}\n";
1439 else if (tt == "courier" )
1440 os << "\\usepackage{" << tt << "}\n";
1441 // Computer Modern, Latin Modern, CM Bright
1442 else if (tt != "default")
1443 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";