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 "lyxtextclasslist.h"
23 #include "FloatList.h"
28 #include "support/filetools.h"
29 #include "support/lstrings.h"
31 using lyx::layout_type;
32 using lyx::textclass_type;
37 LaTeXFeatures::LaTeXFeatures(BufferParams const & p, layout_type n)
38 : layout(n, false), params(p)
42 void LaTeXFeatures::require(string const & name)
44 // INSET_GRAPHICS: remove this when InsetFig is thrown.
45 if (name == "graphics") {
46 features.push_back("graphicx");
47 features.push_back("graphics");
49 features.push_back(name);
53 void LaTeXFeatures::useLayout(std::vector<bool>::size_type const & idx)
59 bool LaTeXFeatures::isRequired(string const & name) const
61 FeaturesList::const_iterator i = std::find(features.begin(),
64 return i != features.end();
68 void LaTeXFeatures::addExternalPreamble(string const & pream)
70 externalPreambles += pream;
74 void LaTeXFeatures::useFloat(string const & name)
76 usedFloats.insert(name);
80 void LaTeXFeatures::useLanguage(Language const * lang)
82 UsedLanguages.insert(lang);
86 void LaTeXFeatures::includeFile(string const & key, string const & name)
88 IncludedFiles[key] = name;
92 bool LaTeXFeatures::hasLanguages()
94 return !UsedLanguages.empty();
98 string LaTeXFeatures::getLanguages() const
100 ostringstream languages;
102 for (LanguageList::const_iterator cit =
103 UsedLanguages.begin();
104 cit != UsedLanguages.end();
106 languages << (*cit)->babel() << ',';
108 return languages.str().c_str();
112 set<string> LaTeXFeatures::getEncodingSet(string const & doc_encoding)
114 set<string> encodings;
115 for (LanguageList::const_iterator it =
116 UsedLanguages.begin();
117 it != UsedLanguages.end(); ++it)
118 if ((*it)->encoding()->LatexName() != doc_encoding)
119 encodings.insert((*it)->encoding()->LatexName());
124 string const LaTeXFeatures::getPackages() const
126 ostringstream packages;
127 LyXTextClass const & tclass =
128 textclasslist.TextClass(params.textclass);
132 * These are all the 'simple' includes. i.e
133 * packages which we just \usepackage{package}
137 if (isRequired("array"))
138 packages << "\\usepackage{array}\n";
141 if (isRequired("verbatim"))
142 packages << "\\usepackage{verbatim}\n";
145 if (isRequired("longtable"))
146 packages << "\\usepackage{longtable}\n";
149 if (isRequired("rotating"))
150 packages << "\\usepackage{rotating}\n";
154 if (isRequired("latexsym"))
155 packages << "\\usepackage{latexsym}\n";
158 if (isRequired("pifont"))
159 packages << "\\usepackage{pifont}\n";
162 if (isRequired("subfigure"))
163 packages << "\\usepackage{subfigure}\n";
166 if (isRequired("floatflt"))
167 packages << "\\usepackage{floatflt}\n";
171 if (isRequired("varioref"))
172 packages << "\\usepackage{varioref}\n";
175 if (isRequired("prettyref"))
176 packages << "\\usepackage{prettyref}\n";
179 * The rest of these packages are somewhat more complicated
184 if (isRequired("color")) {
185 if (params.graphicsDriver == "default")
186 packages << "\\usepackage{color}\n";
188 packages << "\\usepackage["
189 << params.graphicsDriver
194 if (isRequired("makeidx")) {
195 if (! tclass.provides(LyXTextClass::makeidx))
196 packages << "\\usepackage{makeidx}\n";
197 packages << "\\makeindex\n";
201 if (isRequired("graphicx") && params.graphicsDriver != "none") {
202 if (params.graphicsDriver == "default")
203 packages << "\\usepackage{graphicx}\n";
205 packages << "\\usepackage["
206 << params.graphicsDriver
210 // INSET_GRAPHICS: remove this when InsetFig is thrown.
212 if (isRequired("graphics") && params.graphicsDriver != "none") {
213 if (params.graphicsDriver == "default")
214 packages << "\\usepackage{graphics}\n";
216 packages << "\\usepackage["
217 << params.graphicsDriver
222 // packages << "\\usepackage{algorithm}\n";
225 // lyxskak.sty --- newer chess support based on skak.sty
226 if (isRequired("chess")) {
227 packages << "\\usepackage[ps,mover]{lyxskak}\n";
231 if ((params.spacing.getSpace() != Spacing::Single
232 && !params.spacing.isDefault())
233 || isRequired("setspace")) {
234 packages << "\\usepackage{setspace}\n";
236 switch (params.spacing.getSpace()) {
237 case Spacing::Default:
238 case Spacing::Single:
239 // we dont use setspace.sty so dont print anything
240 //packages += "\\singlespacing\n";
242 case Spacing::Onehalf:
243 packages << "\\onehalfspacing\n";
245 case Spacing::Double:
246 packages << "\\doublespacing\n";
249 packages << "\\setstretch{"
250 << params.spacing.getValue() << "}\n";
255 if (isRequired("amssymb") || params.use_amsmath)
256 packages << "\\usepackage{amssymb}\n";
258 if (isRequired("url") && ! tclass.provides(LyXTextClass::url))
259 packages << "\\IfFileExists{url.sty}{\\usepackage{url}}\n"
260 " {\\newcommand{\\url}{\\texttt}}\n";
263 // We only need float.sty if we use non builtin floats, or if we
264 // use the "H" modifier. This includes modified table and
265 // figure floats. (Lgb)
266 if (!usedFloats.empty()) {
267 UsedFloats::const_iterator beg = usedFloats.begin();
268 UsedFloats::const_iterator end = usedFloats.end();
269 for (; beg != end; ++beg) {
270 Floating const & fl = floatList.getType((*beg));
271 if (!fl.type().empty() && !fl.builtin()) {
272 const_cast<LaTeXFeatures *>(this)->require("floats");
277 if (isRequired("floats")) {
278 packages << "\\usepackage{float}\n";
282 if (isRequired("natbib")) {
283 packages << "\\usepackage[";
284 if (params.use_numerical_citations) {
285 packages << "numbers";
287 packages << "authoryear";
289 packages << "]{natbib}\n";
292 packages << externalPreambles;
294 return packages.str().c_str();
298 string const LaTeXFeatures::getMacros() const
300 ostringstream macros;
302 // always include this
303 if (true || isRequired("lyx"))
304 macros << lyx_def << '\n';
306 if (isRequired("lyxline"))
307 macros << lyxline_def << '\n';
309 if (isRequired("noun"))
310 macros << noun_def << '\n';
312 if (isRequired("lyxarrow"))
313 macros << lyxarrow_def << '\n';
316 if (isRequired("quotesinglbase"))
317 macros << quotesinglbase_def << '\n';
318 if (isRequired("quotedblbase"))
319 macros << quotedblbase_def << '\n';
320 if (isRequired("guilsinglleft"))
321 macros << guilsinglleft_def << '\n';
322 if (isRequired("guilsinglright"))
323 macros << guilsinglright_def << '\n';
324 if (isRequired("guillemotleft"))
325 macros << guillemotleft_def << '\n';
326 if (isRequired("guillemotright"))
327 macros << guillemotright_def << '\n';
330 if (isRequired("boldsymbol") && !isRequired("amsstyle"))
331 macros << boldsymbol_def << '\n';
332 if (isRequired("binom") && !isRequired("amsstyle"))
333 macros << binom_def << '\n';
336 if (isRequired("NeedLyXMinipageIndent"))
337 macros << minipageindent_def;
338 if (isRequired("ParagraphIndent"))
339 macros << paragraphindent_def;
340 if (isRequired("NeedLyXFootnoteCode"))
341 macros << floatingfootnote_def;
344 getFloatDefinitions(macros);
346 for (LanguageList::const_iterator cit = UsedLanguages.begin();
347 cit != UsedLanguages.end(); ++cit)
348 if (!(*cit)->latex_options().empty())
349 macros << (*cit)->latex_options() << '\n';
350 if (!params.language->latex_options().empty())
351 macros << params.language->latex_options() << '\n';
353 return macros.str().c_str();
357 string const LaTeXFeatures::getTClassPreamble() const
359 // the text class specific preamble
360 LyXTextClass const & tclass = textclasslist.TextClass(params.textclass);
361 ostringstream tcpreamble;
363 tcpreamble << tclass.preamble();
365 for (layout_type i = 0; i < tclass.numLayouts(); ++i) {
367 tcpreamble << tclass[i].preamble();
371 return tcpreamble.str().c_str();
375 string const LaTeXFeatures::getLyXSGMLEntities() const
377 // Definition of entities used in the document that are LyX related.
378 ostringstream entities;
380 if (isRequired("lyxarrow")) {
381 entities << "<!ENTITY lyxarrow \"->\">" << '\n';
384 return entities.str().c_str();
388 string const LaTeXFeatures::getIncludedFiles(string const & fname) const
390 ostringstream sgmlpreamble;
391 string const basename = OnlyPath(fname);
393 FileMap::const_iterator end = IncludedFiles.end();
394 for (FileMap::const_iterator fi = IncludedFiles.begin();
396 sgmlpreamble << "\n<!ENTITY " << fi->first
397 << (IsSGMLFilename(fi->second) ? " SYSTEM \"" : " \"" )
398 << MakeRelPath(fi->second, basename) << "\">";
400 return sgmlpreamble.str().c_str();
404 void LaTeXFeatures::showStruct() const {
405 lyxerr << "LyX needs the following commands when LaTeXing:"
406 << "\n***** Packages:" << getPackages()
407 << "\n***** Macros:" << getMacros()
408 << "\n***** Textclass stuff:" << getTClassPreamble()
409 << "\n***** done." << endl;
413 BufferParams const & LaTeXFeatures::bufferParams() const
418 void LaTeXFeatures::getFloatDefinitions(std::ostream & os) const
420 // Here we will output the code to create the needed float styles.
421 // We will try to do this as minimal as possible.
422 // \floatstyle{ruled}
423 // \newfloat{algorithm}{htbp}{loa}
424 // \floatname{algorithm}{Algorithm}
425 UsedFloats::const_iterator cit = usedFloats.begin();
426 UsedFloats::const_iterator end = usedFloats.end();
427 // ostringstream floats;
428 for (; cit != end; ++cit) {
429 Floating const & fl = floatList.getType((*cit));
431 // For builtin floats we do nothing.
432 if (fl.builtin()) continue;
434 // We have to special case "table" and "figure"
435 if (fl.type() == "tabular" || fl.type() == "figure") {
436 // Output code to modify "table" or "figure"
437 // but only if builtin == false
438 // and that have to be true at this point in the
440 string const type = fl.type();
441 string const placement = fl.placement();
442 string const style = fl.style();
443 if (!style.empty()) {
444 os << "\\floatstyle{" << style << "}\n"
445 << "\\restylefloat{" << type << "}\n";
447 if (!placement.empty()) {
448 os << "\\floatplacement{" << type << "}{"
449 << placement << "}\n";
452 // The other non builtin floats.
454 string const type = fl.type();
455 string const placement = fl.placement();
456 string const ext = fl.ext();
457 string const within = fl.within();
458 string const style = fl.style();
459 string const name = fl.name();
460 os << "\\floatstyle{" << style << "}\n"
461 << "\\newfloat{" << type << "}{" << placement
462 << "}{" << ext << "}";
464 os << "[" << within << "]";
466 << "\\floatname{" << type << "}{"
469 // What missing here is to code to minimalize the code
470 // outputted so that the same floatstyle will not be
471 // used several times, when the same style is still in