1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich
7 * Copyright 1995-2001 the LyX Team.
9 * ====================================================== */
14 #pragma implementation
17 #include "LaTeXFeatures.h"
21 #include "bufferparams.h"
22 #include "FloatList.h"
27 #include "support/filetools.h"
28 #include "support/lstrings.h"
30 using lyx::textclass_type;
38 LaTeXFeatures::LaTeXFeatures(BufferParams const & p)
43 void LaTeXFeatures::require(string const & name)
48 features.push_back(name);
52 void LaTeXFeatures::useLayout(string const & layoutname)
54 // Some code to avoid loops in dependency definition
56 const int maxlevel = 30;
57 if (level > maxlevel) {
58 lyxerr << "LaTeXFeatures::useLayout: maximum level of "
59 << "recursion attained by layout "
60 << layoutname << endl;
64 LyXTextClass tclass = params.getLyXTextClass();
65 if (tclass.hasLayout(layoutname)) {
66 // Is this layout already in usedLayouts?
67 list<string>::const_iterator cit = usedLayouts.begin();
68 list<string>::const_iterator end = usedLayouts.end();
69 for (; cit != end; ++cit) {
70 if (layoutname == *cit)
74 LyXLayout_ptr lyt = tclass[layoutname];
75 if (!lyt->depends_on().empty()) {
77 useLayout(lyt->depends_on());
80 usedLayouts.push_back(layoutname);
82 lyxerr << "LaTeXFeatures::useLayout: layout `"
83 << layoutname << "' does not exist in this class"
91 bool LaTeXFeatures::isRequired(string const & name) const
93 FeaturesList::const_iterator i = find(features.begin(),
96 return i != features.end();
100 void LaTeXFeatures::addExternalPreamble(string const & pream)
102 externalPreambles += pream;
106 void LaTeXFeatures::useFloat(string const & name)
108 usedFloats.insert(name);
109 // We only need float.sty if we use non builtin floats, or if we
110 // use the "H" modifier. This includes modified table and
111 // figure floats. (Lgb)
112 Floating const & fl = floatList.getType(name);
113 if (!fl.type().empty() && !fl.builtin()) {
119 void LaTeXFeatures::useLanguage(Language const * lang)
121 UsedLanguages.insert(lang);
125 void LaTeXFeatures::includeFile(string const & key, string const & name)
127 IncludedFiles[key] = name;
131 bool LaTeXFeatures::hasLanguages()
133 return !UsedLanguages.empty();
137 string LaTeXFeatures::getLanguages() const
139 ostringstream languages;
141 for (LanguageList::const_iterator cit =
142 UsedLanguages.begin();
143 cit != UsedLanguages.end();
145 languages << (*cit)->babel() << ',';
147 return languages.str().c_str();
151 set<string> LaTeXFeatures::getEncodingSet(string const & doc_encoding)
153 set<string> encodings;
154 for (LanguageList::const_iterator it =
155 UsedLanguages.begin();
156 it != UsedLanguages.end(); ++it)
157 if ((*it)->encoding()->LatexName() != doc_encoding)
158 encodings.insert((*it)->encoding()->LatexName());
164 char const * simplefeatures[] = {
179 const int nb_simplefeatures = sizeof(simplefeatures) / sizeof(char const *);
183 string const LaTeXFeatures::getPackages() const
185 ostringstream packages;
186 LyXTextClass const & tclass = params.getLyXTextClass();
190 // These are all the 'simple' includes. i.e
191 // packages which we just \usepackage{package}
193 for (int i = 0; i < nb_simplefeatures; ++i) {
194 if (isRequired(simplefeatures[i]))
195 packages << "\\usepackage{"
196 << simplefeatures[i] << "}\n";
200 // The rest of these packages are somewhat more complicated
204 if (isRequired("amsmath")
205 && ! tclass.provides(LyXTextClass::amsmath)) {
206 packages << "\\usepackage{amsmath}\n";
210 if (isRequired("color")) {
211 if (params.graphicsDriver == "default")
212 packages << "\\usepackage{color}\n";
214 packages << "\\usepackage["
215 << params.graphicsDriver
220 if (isRequired("makeidx")) {
221 if (! tclass.provides(LyXTextClass::makeidx))
222 packages << "\\usepackage{makeidx}\n";
223 packages << "\\makeindex\n";
227 if (isRequired("graphicx") && params.graphicsDriver != "none") {
228 if (params.graphicsDriver == "default")
229 packages << "\\usepackage{graphicx}\n";
231 packages << "\\usepackage["
232 << params.graphicsDriver
237 // packages << "\\usepackage{algorithm}\n";
240 // lyxskak.sty --- newer chess support based on skak.sty
241 if (isRequired("chess")) {
242 packages << "\\usepackage[ps,mover]{lyxskak}\n";
246 if ((params.spacing.getSpace() != Spacing::Single
247 && !params.spacing.isDefault())
248 || isRequired("setspace")) {
249 packages << "\\usepackage{setspace}\n";
251 switch (params.spacing.getSpace()) {
252 case Spacing::Default:
253 case Spacing::Single:
254 // we dont use setspace.sty so dont print anything
255 //packages += "\\singlespacing\n";
257 case Spacing::Onehalf:
258 packages << "\\onehalfspacing\n";
260 case Spacing::Double:
261 packages << "\\doublespacing\n";
264 packages << "\\setstretch{"
265 << params.spacing.getValue() << "}\n";
270 if (isRequired("amssymb") || params.use_amsmath)
271 packages << "\\usepackage{amssymb}\n";
273 if (isRequired("url") && ! tclass.provides(LyXTextClass::url))
274 packages << "\\IfFileExists{url.sty}{\\usepackage{url}}\n"
275 " {\\newcommand{\\url}{\\texttt}}\n";
279 if (isRequired("natbib") && ! tclass.provides(LyXTextClass::natbib)) {
280 packages << "\\usepackage[";
281 if (params.use_numerical_citations) {
282 packages << "numbers";
284 packages << "authoryear";
286 packages << "]{natbib}\n";
289 packages << externalPreambles;
291 return packages.str().c_str();
295 string const LaTeXFeatures::getMacros() const
297 ostringstream macros;
299 if (isRequired("LyX"))
300 macros << lyx_def << '\n';
302 if (isRequired("lyxline"))
303 macros << lyxline_def << '\n';
305 if (isRequired("noun"))
306 macros << noun_def << '\n';
308 if (isRequired("lyxarrow"))
309 macros << lyxarrow_def << '\n';
312 if (isRequired("quotesinglbase"))
313 macros << quotesinglbase_def << '\n';
314 if (isRequired("quotedblbase"))
315 macros << quotedblbase_def << '\n';
316 if (isRequired("guilsinglleft"))
317 macros << guilsinglleft_def << '\n';
318 if (isRequired("guilsinglright"))
319 macros << guilsinglright_def << '\n';
320 if (isRequired("guillemotleft"))
321 macros << guillemotleft_def << '\n';
322 if (isRequired("guillemotright"))
323 macros << guillemotright_def << '\n';
326 if (isRequired("boldsymbol") && !isRequired("amsmath"))
327 macros << boldsymbol_def << '\n';
328 if (isRequired("binom") && !isRequired("amsmath"))
329 macros << binom_def << '\n';
330 if (isRequired("mathcircumflex"))
331 macros << mathcircumflex_def << '\n';
334 if (isRequired("NeedLyXMinipageIndent"))
335 macros << minipageindent_def;
336 if (isRequired("ParagraphLeftIndent"))
337 macros << paragraphleftindent_def;
338 if (isRequired("NeedLyXFootnoteCode"))
339 macros << floatingfootnote_def;
342 getFloatDefinitions(macros);
344 return macros.str().c_str();
348 string const LaTeXFeatures::getBabelOptions() const
352 for (LanguageList::const_iterator cit = UsedLanguages.begin();
353 cit != UsedLanguages.end(); ++cit)
354 if (!(*cit)->latex_options().empty())
355 tmp << (*cit)->latex_options() << '\n';
356 if (!params.language->latex_options().empty())
357 tmp << params.language->latex_options() << '\n';
359 return tmp.str().c_str();
363 string const LaTeXFeatures::getTClassPreamble() const
365 // the text class specific preamble
366 LyXTextClass const & tclass = params.getLyXTextClass();
367 ostringstream tcpreamble;
369 tcpreamble << tclass.preamble();
371 list<string>::const_iterator cit = usedLayouts.begin();
372 list<string>::const_iterator end = usedLayouts.end();
373 for (; cit != end; ++cit) {
374 tcpreamble << tclass[*cit]->preamble();
377 return tcpreamble.str().c_str();
381 string const LaTeXFeatures::getLyXSGMLEntities() const
383 // Definition of entities used in the document that are LyX related.
384 ostringstream entities;
386 if (isRequired("lyxarrow")) {
387 entities << "<!ENTITY lyxarrow \"->\">" << '\n';
390 return entities.str().c_str();
394 string const LaTeXFeatures::getIncludedFiles(string const & fname) const
396 ostringstream sgmlpreamble;
397 string const basename = OnlyPath(fname);
399 FileMap::const_iterator end = IncludedFiles.end();
400 for (FileMap::const_iterator fi = IncludedFiles.begin();
402 sgmlpreamble << "\n<!ENTITY " << fi->first
403 << (IsSGMLFilename(fi->second) ? " SYSTEM \"" : " \"")
404 << MakeRelPath(fi->second, basename) << "\">";
406 return sgmlpreamble.str().c_str();
410 void LaTeXFeatures::showStruct() const {
411 lyxerr << "LyX needs the following commands when LaTeXing:"
412 << "\n***** Packages:" << getPackages()
413 << "\n***** Macros:" << getMacros()
414 << "\n***** Textclass stuff:" << getTClassPreamble()
415 << "\n***** done." << endl;
419 BufferParams const & LaTeXFeatures::bufferParams() const
425 void LaTeXFeatures::getFloatDefinitions(ostream & os) const
427 // Here we will output the code to create the needed float styles.
428 // We will try to do this as minimal as possible.
429 // \floatstyle{ruled}
430 // \newfloat{algorithm}{htbp}{loa}
431 // \floatname{algorithm}{Algorithm}
432 UsedFloats::const_iterator cit = usedFloats.begin();
433 UsedFloats::const_iterator end = usedFloats.end();
434 // ostringstream floats;
435 for (; cit != end; ++cit) {
436 Floating const & fl = floatList.getType((*cit));
438 // For builtin floats we do nothing.
439 if (fl.builtin()) continue;
441 // We have to special case "table" and "figure"
442 if (fl.type() == "tabular" || fl.type() == "figure") {
443 // Output code to modify "table" or "figure"
444 // but only if builtin == false
445 // and that have to be true at this point in the
447 string const type = fl.type();
448 string const placement = fl.placement();
449 string const style = fl.style();
450 if (!style.empty()) {
451 os << "\\floatstyle{" << style << "}\n"
452 << "\\restylefloat{" << type << "}\n";
454 if (!placement.empty()) {
455 os << "\\floatplacement{" << type << "}{"
456 << placement << "}\n";
459 // The other non builtin floats.
461 string const type = fl.type();
462 string const placement = fl.placement();
463 string const ext = fl.ext();
464 string const within = fl.within();
465 string const style = fl.style();
466 string const name = fl.name();
467 os << "\\floatstyle{" << style << "}\n"
468 << "\\newfloat{" << type << "}{" << placement
469 << "}{" << ext << "}";
471 os << "[" << within << "]";
473 << "\\floatname{" << type << "}{"
476 // What missing here is to code to minimalize the code
477 // output so that the same floatstyle will not be
478 // used several times, when the same style is still in