X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FLaTeXFeatures.C;h=9cbbc3288c564c9e76c60aa34443f15740d92782;hb=ff6706002f89b9c10b98ebd08c00962aacf0a4c7;hp=2da36b28b8c67fe849a2c4a6cf560f1accfac72a;hpb=6ee60cb738833064f09f2fa003afaca9f680a584;p=lyx.git diff --git a/src/LaTeXFeatures.C b/src/LaTeXFeatures.C index 2da36b28b8..9cbbc3288c 100644 --- a/src/LaTeXFeatures.C +++ b/src/LaTeXFeatures.C @@ -1,419 +1,463 @@ -// -*- C++ -*- -/* This file is part of - * ====================================================== - * - * LyX, The Document Processor - * - * Copyright 1995 Matthias Ettrich - * Copyright 1995-2000 the LyX Team. +/** + * \file LaTeXFeatures.C + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. * - * ====================================================== */ + * \author José Matos + * \author Lars Gullik Bjønnes + * \author Jean-Marc Lasgouttes + * \author Jürgen Vigna + * \author André Pönitz + * + * Full author contact details are available in file CREDITS. + */ #include -#ifdef __GNUG__ -#pragma implementation "LaTeXFeatures.h" -#endif +#include "LaTeXFeatures.h" -#include "LString.h" +#include "bufferparams.h" #include "debug.h" +#include "encoding.h" +#include "Floating.h" +#include "FloatList.h" +#include "language.h" #include "lyx_sty.h" #include "lyxrc.h" -#include "LaTeXFeatures.h" -#include "bufferparams.h" -#include "layout.h" + #include "support/filetools.h" -#include "FloatList.h" + +#include "support/std_sstream.h" + +using lyx::support::IsSGMLFilename; +using lyx::support::MakeRelPath; +using lyx::support::OnlyPath; using std::endl; +using std::find; +using std::string; +using std::list; +using std::ostream; +using std::ostringstream; +using std::set; -LaTeXFeatures::LaTeXFeatures(BufferParams const & p, LyXTextClass::size_type n) - : layout(n, false), params(p) -{ - // packages - array = false; - color = false; - graphics = false; // INSET_GRAPHICS: remove this when InsetFig is thrown. - graphicx = false; - setspace = false; - makeidx = false; - verbatim = false; - longtable = false; - algorithm = false; - rotating = false; - amssymb = false; - latexsym = false; - pifont = false; - subfigure = false; - floatflt = false; - url = false; - varioref = false; - prettyref = false; - chess = false; - - // commands - lyx = false; - lyxline = false; - noun = false; - lyxarrow = false; - - // quotes - quotesinglbase = false; - quotedblbase = false; - guilsinglleft = false; - guilsinglright = false; - guillemotleft = false; - guillemotright = false; - // Math mode - amsstyle = false; - binom = false; - boldsymbol = false; - - // special features - LyXParagraphIndent = false; - NeedLyXFootnoteCode = false; - NeedLyXMinipageIndent = false; +LaTeXFeatures::LaTeXFeatures(Buffer const & b, BufferParams const & p, bool n) + : buffer_(&b), params_(p), nice_(n) +{} + + +bool LaTeXFeatures::useBabel() const +{ + return lyxrc.language_use_babel || + bufferParams().language->lang() != lyxrc.default_language || + this->hasLanguages(); } void LaTeXFeatures::require(string const & name) { - if (name == "array") { - array = true; - } else if (name == "color") { - color = true; - } else if (name == "graphics") { - graphicx = true; - graphics = true;// INSET_GRAPHICS: remove this when InsetFig is thrown. - } else if (name == "setspace") { - setspace = true; - } else if (name == "makeidx") { - makeidx = true; - } else if (name == "verbatim") { - verbatim = true; - } else if (name == "longtable") { - longtable = true; - } else if (name == "algorithm") { - algorithm = true; - } else if (name == "rotating") { - rotating = true; - } else if (name == "amssymb") { - amssymb = true; - } else if (name == "latexsym") { - latexsym = true; - } else if (name == "pifont") { - pifont = true; - } else if (name == "subfigure") { - subfigure = true; - } else if (name == "floatflt") { - floatflt = true; - } else if (name == "url") { - url = true; - } else if (name == "varioref") { - varioref = true; - } else if (name == "prettyref") { - prettyref = true; - } else if (name == "chess") { - chess = true; - } else if (name == "amsstyle") { - amsstyle = true; - } else if (name == "boldsymbol") { - boldsymbol = true; - } else if (name == "binom") { - binom = true; + if (isRequired(name)) + return; + + features_.push_back(name); +} + + +void LaTeXFeatures::useLayout(string const & layoutname) +{ + // Some code to avoid loops in dependency definition + static int level = 0; + const int maxlevel = 30; + if (level > maxlevel) { + lyxerr << "LaTeXFeatures::useLayout: maximum level of " + << "recursion attained by layout " + << layoutname << endl; + return; + } + + LyXTextClass const & tclass = params_.getLyXTextClass(); + if (tclass.hasLayout(layoutname)) { + // Is this layout already in usedLayouts? + list::const_iterator cit = usedLayouts_.begin(); + list::const_iterator end = usedLayouts_.end(); + for (; cit != end; ++cit) { + if (layoutname == *cit) + return; + } + + LyXLayout_ptr const & lyt = tclass[layoutname]; + if (!lyt->depends_on().empty()) { + ++level; + useLayout(lyt->depends_on()); + --level; + } + usedLayouts_.push_back(layoutname); + } else { + lyxerr << "LaTeXFeatures::useLayout: layout `" + << layoutname << "' does not exist in this class" + << endl; } + + --level; } -string const LaTeXFeatures::getPackages() +bool LaTeXFeatures::isRequired(string const & name) const { - string packages; - LyXTextClass const & tclass = - textclasslist.TextClass(params.textclass); + return find(features_.begin(), features_.end(), name) != features_.end(); +} - // array-package - if (array) - packages += "\\usepackage{array}\n"; - // color.sty - if (color) { - if (params.graphicsDriver == "default") - packages += "\\usepackage{color}\n"; - else - packages += "\\usepackage[" - + params.graphicsDriver + "]{color}\n"; +void LaTeXFeatures::addExternalPreamble(string const & preamble) +{ + FeaturesList::const_iterator begin = preamble_snippets_.begin(); + FeaturesList::const_iterator end = preamble_snippets_.end(); + if (find(begin, end, preamble) == end) + preamble_snippets_.push_back(preamble); +} + + +void LaTeXFeatures::useFloat(string const & name) +{ + usedFloats_.insert(name); + // We only need float.sty if we use non builtin floats, or if we + // use the "H" modifier. This includes modified table and + // figure floats. (Lgb) + Floating const & fl = params_.getLyXTextClass().floats().getType(name); + if (!fl.type().empty() && !fl.builtin()) { + require("float"); } - - // makeidx.sty - if (makeidx) { - if (! tclass.provides(LyXTextClass::makeidx) - && params.language->babel() != "french") // french provides - // \index ! - packages += "\\usepackage{makeidx}\n"; - packages += "\\makeindex\n"; +} + + +void LaTeXFeatures::useLanguage(Language const * lang) +{ + UsedLanguages_.insert(lang); +} + + +void LaTeXFeatures::includeFile(string const & key, string const & name) +{ + IncludedFiles_[key] = name; +} + + +bool LaTeXFeatures::hasLanguages() const +{ + return !UsedLanguages_.empty(); +} + + +string LaTeXFeatures::getLanguages() const +{ + ostringstream languages; + + for (LanguageList::const_iterator cit = + UsedLanguages_.begin(); + cit != UsedLanguages_.end(); + ++cit) + languages << (*cit)->babel() << ','; + + return languages.str(); +} + + +set LaTeXFeatures::getEncodingSet(string const & doc_encoding) const +{ + set encodings; + LanguageList::const_iterator it = UsedLanguages_.begin(); + LanguageList::const_iterator end = UsedLanguages_.end(); + for (; it != end; ++it) + if ((*it)->encoding()->LatexName() != doc_encoding) + encodings.insert((*it)->encoding()->LatexName()); + return encodings; +} + +namespace { + +char const * simplefeatures[] = { + "array", + "verbatim", + "longtable", + "rotating", + "latexsym", + "pifont", + "subfigure", + "floatflt", + "varioref", + "prettyref", + "float", + "wasy", + "dvipost", + "fancybox", + "calc", + "jurabib" +}; + +int const nb_simplefeatures = sizeof(simplefeatures) / sizeof(char const *); + +} + + +string const LaTeXFeatures::getPackages() const +{ + ostringstream packages; + LyXTextClass const & tclass = params_.getLyXTextClass(); + + // + // These are all the 'simple' includes. i.e + // packages which we just \usepackage{package} + // + for (int i = 0; i < nb_simplefeatures; ++i) { + if (isRequired(simplefeatures[i])) + packages << "\\usepackage{" + << simplefeatures[i] << "}\n"; } - // graphicx.sty - if (graphicx && params.graphicsDriver != "none") { - if (params.graphicsDriver == "default") - packages += "\\usepackage{graphicx}\n"; - else - packages += "\\usepackage[" - + params.graphicsDriver + "]{graphicx}\n"; + // + // The rest of these packages are somewhat more complicated + // than those above. + // + + if (isRequired("amsmath") + && !tclass.provides(LyXTextClass::amsmath) + && params_.use_amsmath != BufferParams::AMS_OFF) { + packages << "\\usepackage{amsmath}\n"; } - // INSET_GRAPHICS: remove this when InsetFig is thrown. - // graphics.sty - if (graphics && params.graphicsDriver != "none") { - if (params.graphicsDriver == "default") - packages += "\\usepackage{graphics}\n"; + // color.sty + if (isRequired("color")) { + if (params_.graphicsDriver == "default") + packages << "\\usepackage[usenames]{color}\n"; else - packages += "\\usepackage[" - + params.graphicsDriver + "]{graphics}\n"; + packages << "\\usepackage[" + << params_.graphicsDriver + << ",usenames" + << "]{color}\n"; } - // verbatim.sty - if (verbatim) - packages += "\\usepackage{verbatim}\n"; + // makeidx.sty + if (isRequired("makeidx")) { + if (! tclass.provides(LyXTextClass::makeidx)) + packages << "\\usepackage{makeidx}\n"; + packages << "\\makeindex\n"; + } - if (algorithm) { - packages += "\\usepackage{algorithm}\n"; + // graphicx.sty + if (isRequired("graphicx") && params_.graphicsDriver != "none") { + if (params_.graphicsDriver == "default") + packages << "\\usepackage{graphicx}\n"; + else + packages << "\\usepackage[" + << params_.graphicsDriver + << "]{graphicx}\n"; } - // lyxchess.sty - if (chess) { - packages += "\\usepackage{lyxchess}\n"; + //if (algorithm) { + // packages << "\\usepackage{algorithm}\n"; + //} + + // lyxskak.sty --- newer chess support based on skak.sty + if (isRequired("chess")) { + packages << "\\usepackage[ps,mover]{lyxskak}\n"; } // setspace.sty - if ((params.spacing.getSpace() != Spacing::Single - && !params.spacing.isDefault()) - || setspace) { - packages += "\\usepackage{setspace}\n"; + if ((params_.spacing().getSpace() != Spacing::Single + && !params_.spacing().isDefault()) + || isRequired("setspace")) { + packages << "\\usepackage{setspace}\n"; } - switch (params.spacing.getSpace()) { + switch (params_.spacing().getSpace()) { case Spacing::Default: case Spacing::Single: // we dont use setspace.sty so dont print anything //packages += "\\singlespacing\n"; break; case Spacing::Onehalf: - packages += "\\onehalfspacing\n"; + packages << "\\onehalfspacing\n"; break; case Spacing::Double: - packages += "\\doublespacing\n"; + packages << "\\doublespacing\n"; break; case Spacing::Other: - std::ostringstream value; - value << params.spacing.getValue(); // setw? - packages += string("\\setstretch{") - + value.str().c_str() + "}\n"; + packages << "\\setstretch{" + << params_.spacing().getValue() << "}\n"; break; } - //longtable.sty - if (longtable) - packages += "\\usepackage{longtable}\n"; - - //rotating.sty - if (rotating) - packages += "\\usepackage{rotating}\n"; - // amssymb.sty - if (amssymb || params.use_amsmath) - packages += "\\usepackage{amssymb}\n"; - - // latexsym.sty - if (latexsym) - packages += "\\usepackage{latexsym}\n"; - - // pifont.sty - if (pifont) - packages += "\\usepackage{pifont}\n"; - - // subfigure.sty - if (subfigure) - packages += "\\usepackage{subfigure}\n"; - - // floatflt.sty - if (floatflt) - packages += "\\usepackage{floatflt}\n"; - + if (isRequired("amssymb") || params_.use_amsmath == BufferParams::AMS_ON) + packages << "\\usepackage{amssymb}\n"; // url.sty - if (url && ! tclass.provides(LyXTextClass::url)) - packages += "\\IfFileExists{url.sty}{\\usepackage{url}}\n" + if (isRequired("url") && ! tclass.provides(LyXTextClass::url)) + packages << "\\IfFileExists{url.sty}{\\usepackage{url}}\n" " {\\newcommand{\\url}{\\texttt}}\n"; - // varioref.sty - if (varioref) - packages += "\\usepackage{varioref}\n"; - - // prettyref.sty - if (prettyref) - packages += "\\usepackage{prettyref}\n"; - // float.sty - // We only need float.sty if we use non builtin floats. This includes - // modified table and figure floats. (Lgb) - if (!usedFloats.empty()) { - bool use_float = false; - UsedFloats::const_iterator beg = usedFloats.begin(); - UsedFloats::const_iterator end = usedFloats.end(); - for (; beg != end; ++beg) { - Floating const & fl = floatList.getType((*beg)); - if (!fl.type().empty() && !fl.builtin()) { - use_float = true; - break; - } + // natbib.sty + if (isRequired("natbib") && ! tclass.provides(LyXTextClass::natbib)) { + packages << "\\usepackage["; + if (params_.cite_engine == biblio::ENGINE_NATBIB_NUMERICAL) { + packages << "numbers"; + } else { + packages << "authoryear"; } - if (use_float) - packages += "\\usepackage{float}\n"; + packages << "]{natbib}\n"; + } + + // bibtopic -- the dot provides the aux file naming which + // LyX can detect. + if (isRequired("bibtopic")) { + packages << "\\usepackage[dot]{bibtopic}\n"; } - - packages += externalPreambles; - return packages; + return packages.str(); } -string const LaTeXFeatures::getMacros() +string const LaTeXFeatures::getMacros() const { - string macros; + ostringstream macros; + + if (!preamble_snippets_.empty()) + macros << '\n'; + FeaturesList::const_iterator pit = preamble_snippets_.begin(); + FeaturesList::const_iterator pend = preamble_snippets_.end(); + for (; pit != pend; ++pit) { + macros << *pit << '\n'; + } - // always include this - if (true || lyx) - macros += lyx_def + '\n'; + if (isRequired("LyX")) + macros << lyx_def << '\n'; - if (lyxline) - macros += lyxline_def + '\n'; + if (isRequired("lyxline")) + macros << lyxline_def << '\n'; - if (noun) { - macros += noun_def + '\n'; - } + if (isRequired("noun")) + macros << noun_def << '\n'; - if (lyxarrow) { - macros += lyxarrow_def + '\n'; - } + if (isRequired("lyxarrow")) + macros << lyxarrow_def << '\n'; - // quotes. - if (quotesinglbase) - macros += quotesinglbase_def + '\n'; - if (quotedblbase) - macros += quotedblbase_def + '\n'; - if (guilsinglleft) - macros += guilsinglleft_def + '\n'; - if (guilsinglright) - macros += guilsinglright_def + '\n'; - if (guillemotleft) - macros += guillemotleft_def + '\n'; - if (guillemotright) - macros += guillemotright_def + '\n'; - - // Math mode - if (boldsymbol && !amsstyle) - macros += boldsymbol_def + '\n'; - if (binom && !amsstyle) - macros += binom_def + '\n'; + // quotes. + if (isRequired("quotesinglbase")) + macros << quotesinglbase_def << '\n'; + if (isRequired("quotedblbase")) + macros << quotedblbase_def << '\n'; + if (isRequired("guilsinglleft")) + macros << guilsinglleft_def << '\n'; + if (isRequired("guilsinglright")) + macros << guilsinglright_def << '\n'; + if (isRequired("guillemotleft")) + macros << guillemotleft_def << '\n'; + if (isRequired("guillemotright")) + macros << guillemotright_def << '\n'; + + // Math mode + if (isRequired("boldsymbol") && !isRequired("amsmath")) + macros << boldsymbol_def << '\n'; + if (isRequired("binom") && !isRequired("amsmath")) + macros << binom_def << '\n'; + if (isRequired("mathcircumflex")) + macros << mathcircumflex_def << '\n'; // other - if (NeedLyXMinipageIndent) - macros += minipageindent_def; - if (LyXParagraphIndent) - macros += paragraphindent_def; - if (NeedLyXFootnoteCode) - macros += floatingfootnote_def; + if (isRequired("ParagraphLeftIndent")) + macros << paragraphleftindent_def; + if (isRequired("NeedLyXFootnoteCode")) + macros << floatingfootnote_def; + + // some problems with tex->html converters + if (isRequired("NeedTabularnewline")) + macros << tabularnewline_def; + + // greyedout environment (note inset) + if (isRequired("lyxgreyedout")) + macros << lyxgreyedout_def; + + if (isRequired("lyxdot")) + macros << lyxdot_def << '\n'; // floats - // Here we will output the code to create the needed float styles. - // We will try to do this as minimal as possible. - // \floatstyle{ruled} - // \newfloat{algorithm}{htbp}{loa} - // \floatname{algorithm}{Algorithm} - UsedFloats::const_iterator cit = usedFloats.begin(); - UsedFloats::const_iterator end = usedFloats.end(); - ostringstream floats; - for (; cit != end; ++cit) { - Floating const & fl = floatList.getType((*cit)); + getFloatDefinitions(macros); - // For builtin floats we do nothing. - if (fl.builtin()) continue; - - // We have to special case "table" and "figure" - if (fl.type() == "tabular" || fl.type() == "figure") { - // Output code to modify "table" or "figure" - // but only if builtin == false - } else { - // The other non builtin floats. + return macros.str(); +} - string type = fl.type(); - string placement = fl.placement(); - string ext = fl.ext(); - string within = fl.within(); - string style = fl.style(); - string name = fl.name(); - floats << "\\floatstyle{" << style << "}\n" - << "\\newfloat{" << type << "}{" << placement - << "}{" << ext << "}"; - if (!within.empty()) - floats << "[" << within << "]"; - floats << "\n" - << "\\floatname{" << type << "}{" - << name << "}\n"; - // What missing here is to code to minimalize the code - // outputted so that the same flotastyle will not be - // used several times. when the same style is still in - // effect. (Lgb) - } +string const LaTeXFeatures::getBabelOptions() const +{ + ostringstream tmp; + + LanguageList::const_iterator it = UsedLanguages_.begin(); + LanguageList::const_iterator end = UsedLanguages_.end(); + for (; it != end; ++it) + if (!(*it)->latex_options().empty()) + tmp << (*it)->latex_options() << '\n'; + if (!params_.language->latex_options().empty()) + tmp << params_.language->latex_options() << '\n'; + + return tmp.str(); +} + + +string const LaTeXFeatures::getTClassPreamble() const +{ + // the text class specific preamble + LyXTextClass const & tclass = params_.getLyXTextClass(); + ostringstream tcpreamble; + + tcpreamble << tclass.preamble(); + + list::const_iterator cit = usedLayouts_.begin(); + list::const_iterator end = usedLayouts_.end(); + for (; cit != end; ++cit) { + tcpreamble << tclass[*cit]->preamble(); } - macros += floats.str().c_str(); - for (LanguageList::const_iterator cit = UsedLanguages.begin(); - cit != UsedLanguages.end(); ++cit) - if (!(*cit)->latex_options().empty()) - macros += (*cit)->latex_options() + '\n'; - if (!params.language->latex_options().empty()) - macros += params.language->latex_options() + '\n'; + CharStyles::iterator cs = tclass.charstyles().begin(); + CharStyles::iterator csend = tclass.charstyles().end(); + for (; cs != csend; ++cs) { + if (isRequired(cs->name)) + tcpreamble << cs->preamble; + } - return macros; + return tcpreamble.str(); } -string const LaTeXFeatures::getTClassPreamble() +string const LaTeXFeatures::getLyXSGMLEntities() const { - // the text class specific preamble - LyXTextClass const & tclass = - textclasslist.TextClass(params.textclass); - string tcpreamble = tclass.preamble(); - - for (unsigned int i = 0; i < tclass.numLayouts(); ++i) { - if (layout[i]) { - tcpreamble += tclass[i].preamble(); - } + // Definition of entities used in the document that are LyX related. + ostringstream entities; + + if (isRequired("lyxarrow")) { + entities << "" << '\n'; } - return tcpreamble; -} + return entities.str(); +} -string const LaTeXFeatures::getIncludedFiles(string const fname) const +string const LaTeXFeatures::getIncludedFiles(string const & fname) const { - string sgmlpreamble; - string basename = OnlyPath(fname); + ostringstream sgmlpreamble; + string const basename = OnlyPath(fname); - FileMap::const_iterator end = IncludedFiles.end(); - for (FileMap::const_iterator fi = IncludedFiles.begin(); + FileMap::const_iterator end = IncludedFiles_.end(); + for (FileMap::const_iterator fi = IncludedFiles_.begin(); fi != end; ++fi) - sgmlpreamble += "\nfirst - + (IsSGMLFilename(fi->second) ? " SYSTEM \"" : " \"" ) - + MakeRelPath(fi->second,basename) + "\">"; + sgmlpreamble << "\nfirst + << (IsSGMLFilename(fi->second) ? " SYSTEM \"" : " \"") + << MakeRelPath(fi->second, basename) << "\">"; - return sgmlpreamble; + return sgmlpreamble.str(); } -void LaTeXFeatures::showStruct() { +void LaTeXFeatures::showStruct() const { lyxerr << "LyX needs the following commands when LaTeXing:" << "\n***** Packages:" << getPackages() << "\n***** Macros:" << getMacros() @@ -422,7 +466,81 @@ void LaTeXFeatures::showStruct() { } +Buffer const & LaTeXFeatures::buffer() const +{ + return *buffer_; +} + + +void LaTeXFeatures::setBuffer(Buffer const & buffer) +{ + buffer_ = &buffer; +} + + BufferParams const & LaTeXFeatures::bufferParams() const { - return params; + return params_; +} + + +void LaTeXFeatures::getFloatDefinitions(ostream & os) const +{ + FloatList const & floats = params_.getLyXTextClass().floats(); + + // Here we will output the code to create the needed float styles. + // We will try to do this as minimal as possible. + // \floatstyle{ruled} + // \newfloat{algorithm}{htbp}{loa} + // \floatname{algorithm}{Algorithm} + UsedFloats::const_iterator cit = usedFloats_.begin(); + UsedFloats::const_iterator end = usedFloats_.end(); + // ostringstream floats; + for (; cit != end; ++cit) { + Floating const & fl = floats.getType((*cit)); + + // For builtin floats we do nothing. + if (fl.builtin()) continue; + + // We have to special case "table" and "figure" + if (fl.type() == "tabular" || fl.type() == "figure") { + // Output code to modify "table" or "figure" + // but only if builtin == false + // and that have to be true at this point in the + // function. + string const type = fl.type(); + string const placement = fl.placement(); + string const style = fl.style(); + if (!style.empty()) { + os << "\\floatstyle{" << style << "}\n" + << "\\restylefloat{" << type << "}\n"; + } + if (!placement.empty()) { + os << "\\floatplacement{" << type << "}{" + << placement << "}\n"; + } + } else { + // The other non builtin floats. + + string const type = fl.type(); + string const placement = fl.placement(); + string const ext = fl.ext(); + string const within = fl.within(); + string const style = fl.style(); + string const name = fl.name(); + os << "\\floatstyle{" << style << "}\n" + << "\\newfloat{" << type << "}{" << placement + << "}{" << ext << '}'; + if (!within.empty()) + os << '[' << within << ']'; + os << '\n' + << "\\floatname{" << type << "}{" + << name << "}\n"; + + // What missing here is to code to minimalize the code + // output so that the same floatstyle will not be + // used several times, when the same style is still in + // effect. (Lgb) + } + } }