]> git.lyx.org Git - lyx.git/blob - src/LaTeXFeatures.C
remove unused stuff
[lyx.git] / src / LaTeXFeatures.C
1 /**
2  * \file LaTeXFeatures.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author José Matos
7  * \author Lars Gullik Bjønnes
8  * \author Jean-Marc Lasgouttes
9  * \author Jürgen Vigna
10  * \author André Pönitz
11  *
12  * Full author contact details are available in file CREDITS.
13  */
14
15 #include <config.h>
16
17 #include "LaTeXFeatures.h"
18
19 #include "bufferparams.h"
20 #include "Color.h"
21 #include "debug.h"
22 #include "encoding.h"
23 #include "Floating.h"
24 #include "FloatList.h"
25 #include "LColor.h"
26 #include "language.h"
27 #include "lyxlex.h"
28 #include "lyx_sty.h"
29 #include "lyxrc.h"
30
31 #include "support/docstream.h"
32 #include "support/filetools.h"
33
34
35 namespace lyx {
36
37 using support::isSGMLFilename;
38 using support::libFileSearch;
39 using support::makeRelPath;
40 using support::onlyPath;
41
42 using std::endl;
43 using std::find;
44 using std::string;
45 using std::list;
46 using std::ostream;
47 using std::ostringstream;
48 using std::set;
49
50 LaTeXFeatures::PackagesList LaTeXFeatures::packages_;
51
52
53 LaTeXFeatures::LaTeXFeatures(Buffer const & b, BufferParams const & p,
54                              OutputParams const & r)
55         : buffer_(&b), params_(p), runparams_(r)
56 {}
57
58
59 bool LaTeXFeatures::useBabel() const
60 {
61         return lyxrc.language_use_babel ||
62                 bufferParams().language->lang() != lyxrc.default_language ||
63                 this->hasLanguages();
64 }
65
66
67 void LaTeXFeatures::require(string const & name)
68 {
69         if (isRequired(name))
70                 return;
71
72         features_.push_back(name);
73 }
74
75
76 void LaTeXFeatures::getAvailable()
77 {
78         LyXLex lex(0, 0);
79         support::FileName const real_file = libFileSearch("", "packages.lst");
80
81         if (real_file.empty())
82                 return;
83
84         lex.setFile(real_file);
85
86         if (!lex.isOK())
87                 return;
88
89         // Make sure that we are clean
90         packages_.clear();
91
92         bool finished = false;
93         // Parse config-file
94         while (lex.isOK() && !finished) {
95                 switch (lex.lex()) {
96                 case LyXLex::LEX_FEOF:
97                         finished = true;
98                         break;
99                 default:
100                         string const name = lex.getString();
101                         PackagesList::const_iterator begin = packages_.begin();
102                         PackagesList::const_iterator end   = packages_.end();
103                         if (find(begin, end, name) == end)
104                                 packages_.push_back(name);
105                 }
106         }
107
108         return;
109 }
110
111
112 void LaTeXFeatures::useLayout(string const & layoutname)
113 {
114         // Some code to avoid loops in dependency definition
115         static int level = 0;
116         const int maxlevel = 30;
117         if (level > maxlevel) {
118                 lyxerr << "LaTeXFeatures::useLayout: maximum level of "
119                        << "recursion attained by layout "
120                        << layoutname << endl;
121                 return;
122         }
123
124         LyXTextClass const & tclass = params_.getLyXTextClass();
125         if (tclass.hasLayout(layoutname)) {
126                 // Is this layout already in usedLayouts?
127                 list<string>::const_iterator cit = usedLayouts_.begin();
128                 list<string>::const_iterator end = usedLayouts_.end();
129                 for (; cit != end; ++cit) {
130                         if (layoutname == *cit)
131                                 return;
132                 }
133
134                 LyXLayout_ptr const & lyt = tclass[layoutname];
135                 if (!lyt->depends_on().empty()) {
136                         ++level;
137                         useLayout(lyt->depends_on());
138                         --level;
139                 }
140                 usedLayouts_.push_back(layoutname);
141         } else {
142                 lyxerr << "LaTeXFeatures::useLayout: layout `"
143                        << layoutname << "' does not exist in this class"
144                        << endl;
145         }
146
147         --level;
148 }
149
150
151 bool LaTeXFeatures::isRequired(string const & name) const
152 {
153         return find(features_.begin(), features_.end(), name) != features_.end();
154 }
155
156
157 bool LaTeXFeatures::isAvailable(string const & name) const
158 {
159         if (packages_.empty())
160                 getAvailable();
161         return find(packages_.begin(), packages_.end(), name) != packages_.end();
162 }
163
164
165 void LaTeXFeatures::addExternalPreamble(string const & preamble)
166 {
167         FeaturesList::const_iterator begin = preamble_snippets_.begin();
168         FeaturesList::const_iterator end   = preamble_snippets_.end();
169         if (find(begin, end, preamble) == end)
170                 preamble_snippets_.push_back(preamble);
171 }
172
173
174 void LaTeXFeatures::useFloat(string const & name)
175 {
176         usedFloats_.insert(name);
177         // We only need float.sty if we use non builtin floats, or if we
178         // use the "H" modifier. This includes modified table and
179         // figure floats. (Lgb)
180         Floating const & fl = params_.getLyXTextClass().floats().getType(name);
181         if (!fl.type().empty() && !fl.builtin()) {
182                 require("float");
183         }
184 }
185
186
187 void LaTeXFeatures::useLanguage(Language const * lang)
188 {
189         UsedLanguages_.insert(lang);
190 }
191
192
193 void LaTeXFeatures::includeFile(docstring const & key, string const & name)
194 {
195         IncludedFiles_[key] = name;
196 }
197
198
199 bool LaTeXFeatures::hasLanguages() const
200 {
201         return !UsedLanguages_.empty();
202 }
203
204
205 string LaTeXFeatures::getLanguages() const
206 {
207         ostringstream languages;
208
209         for (LanguageList::const_iterator cit =
210                     UsedLanguages_.begin();
211              cit != UsedLanguages_.end();
212              ++cit)
213                 languages << (*cit)->babel() << ',';
214         return languages.str();
215 }
216
217
218 set<string> LaTeXFeatures::getEncodingSet(string const & doc_encoding) const
219 {
220         set<string> encodings;
221         LanguageList::const_iterator it  = UsedLanguages_.begin();
222         LanguageList::const_iterator end = UsedLanguages_.end();
223         for (; it != end; ++it)
224                 if ((*it)->encoding()->latexName() != doc_encoding)
225                         encodings.insert((*it)->encoding()->latexName());
226         return encodings;
227 }
228
229 namespace {
230
231 char const * simplefeatures[] = {
232         "array",
233         "verbatim",
234         "longtable",
235         "rotating",
236         "latexsym",
237         "pifont",
238         "subfigure",
239         "floatflt",
240         "varioref",
241         "prettyref",
242         "float",
243         "booktabs",
244         "dvipost",
245         "fancybox",
246         "calc",
247         "nicefrac",
248         "tipa",
249         "framed",
250 };
251
252 int const nb_simplefeatures = sizeof(simplefeatures) / sizeof(char const *);
253
254 }
255
256
257 string const LaTeXFeatures::getPackages() const
258 {
259         ostringstream packages;
260         LyXTextClass const & tclass = params_.getLyXTextClass();
261
262         //
263         //  These are all the 'simple' includes.  i.e
264         //  packages which we just \usepackage{package}
265         //
266         for (int i = 0; i < nb_simplefeatures; ++i) {
267                 if (isRequired(simplefeatures[i]))
268                         packages << "\\usepackage{"
269                                  << simplefeatures[i] << "}\n";
270         }
271
272         //
273         // The rest of these packages are somewhat more complicated
274         // than those above.
275         //
276
277         if (isRequired("amsmath")
278             && !tclass.provides(LyXTextClass::amsmath)
279             && params_.use_amsmath != BufferParams::package_off) {
280                 packages << "\\usepackage{amsmath}\n";
281         }
282
283         // wasysym is a simple feature, but it must be after amsmath if both
284         // are used
285         // wasysym redefines some integrals (e.g. iint) from amsmath. That
286         // leads to inconsistent integrals. We only load this package if
287         // esint is used, since esint redefines all relevant integral
288         // symbols from wasysym and amsmath.
289         // See http://bugzilla.lyx.org/show_bug.cgi?id=1942
290         if (isRequired("wasysym") && isRequired("esint") &&
291             params_.use_esint != BufferParams::package_off)
292                 packages << "\\usepackage{wasysym}\n";
293
294         // color.sty
295         if (isRequired("color")) {
296                 if (params_.graphicsDriver == "default")
297                         packages << "\\usepackage{color}\n";
298                 else
299                         packages << "\\usepackage["
300                                  << params_.graphicsDriver
301                                  << "]{color}\n";
302         }
303
304         // makeidx.sty
305         if (isRequired("makeidx")) {
306                 if (!tclass.provides(LyXTextClass::makeidx))
307                         packages << "\\usepackage{makeidx}\n";
308                 packages << "\\makeindex\n";
309         }
310
311         // graphicx.sty
312         if (isRequired("graphicx") && params_.graphicsDriver != "none") {
313                 if (params_.graphicsDriver == "default")
314                         packages << "\\usepackage{graphicx}\n";
315                 else
316                         packages << "\\usepackage["
317                                  << params_.graphicsDriver
318                                  << "]{graphicx}\n";
319         }
320         // shadecolor for shaded
321         if (isRequired("framed")) {
322                 RGBColor c = RGBColor(lcolor.getX11Name(LColor::shadedbg));
323                 packages << "\\definecolor{shadecolor}{rgb}{" 
324                         << c.r/255 << ',' << c.g/255 << ',' << c.b/255 << "}\n";
325         }
326
327         //if (algorithm) {
328         //      packages << "\\usepackage{algorithm}\n";
329         //}
330
331         // lyxskak.sty --- newer chess support based on skak.sty
332         if (isRequired("chess")) {
333                 packages << "\\usepackage[ps,mover]{lyxskak}\n";
334         }
335
336         // setspace.sty
337         if ((params_.spacing().getSpace() != Spacing::Single
338              && !params_.spacing().isDefault())
339             || isRequired("setspace")) {
340                 packages << "\\usepackage{setspace}\n";
341         }
342         switch (params_.spacing().getSpace()) {
343         case Spacing::Default:
344         case Spacing::Single:
345                 // we dont use setspace.sty so dont print anything
346                 //packages += "\\singlespacing\n";
347                 break;
348         case Spacing::Onehalf:
349                 packages << "\\onehalfspacing\n";
350                 break;
351         case Spacing::Double:
352                 packages << "\\doublespacing\n";
353                 break;
354         case Spacing::Other:
355                 packages << "\\setstretch{"
356                          << params_.spacing().getValue() << "}\n";
357                 break;
358         }
359
360         // amssymb.sty
361         if (isRequired("amssymb") || params_.use_amsmath == BufferParams::package_on)
362                 packages << "\\usepackage{amssymb}\n";
363
364         // esint must be after amsmath and wasysym, since it will redeclare
365         // inconsistent integral symbols
366         if (isRequired("esint") && params_.use_esint != BufferParams::package_off)
367                 packages << "\\usepackage{esint}\n";
368
369         // url.sty
370         if (isRequired("url") && ! tclass.provides(LyXTextClass::url))
371                 packages << "\\IfFileExists{url.sty}{\\usepackage{url}}\n"
372                             "                      {\\newcommand{\\url}{\\texttt}}\n";
373
374         // float.sty
375         // natbib.sty
376         if (isRequired("natbib") && ! tclass.provides(LyXTextClass::natbib)) {
377                 packages << "\\usepackage[";
378                 if (params_.cite_engine == biblio::ENGINE_NATBIB_NUMERICAL) {
379                         packages << "numbers";
380                 } else {
381                         packages << "authoryear";
382                 }
383                 packages << "]{natbib}\n";
384         }
385
386         // jurabib -- we need version 0.6 at least.
387         if (isRequired("jurabib")) {
388                 packages << "\\usepackage{jurabib}[2004/01/25]\n";
389         }
390
391         // bibtopic -- the dot provides the aux file naming which
392         // LyX can detect.
393         if (isRequired("bibtopic")) {
394                 packages << "\\usepackage[dot]{bibtopic}\n";
395         }
396
397         if (isRequired("xy"))
398                 packages << "\\usepackage[all]{xy}\n";
399
400         if (isRequired("nomencl")) {
401                 packages << "\\usepackage{nomencl}[2005/09/22]\n"
402                          << "\\makenomenclature\n";
403         }
404  
405         return packages.str();
406 }
407
408
409 string const LaTeXFeatures::getMacros() const
410 {
411         ostringstream macros;
412
413         if (!preamble_snippets_.empty())
414                 macros << '\n';
415         FeaturesList::const_iterator pit  = preamble_snippets_.begin();
416         FeaturesList::const_iterator pend = preamble_snippets_.end();
417         for (; pit != pend; ++pit) {
418                 macros << *pit << '\n';
419         }
420
421         if (isRequired("LyX"))
422                 macros << lyx_def << '\n';
423
424         if (isRequired("lyxline"))
425                 macros << lyxline_def << '\n';
426
427         if (isRequired("noun"))
428                 macros << noun_def << '\n';
429
430         if (isRequired("lyxarrow"))
431                 macros << lyxarrow_def << '\n';
432
433         // quotes.
434         if (isRequired("quotesinglbase"))
435                 macros << quotesinglbase_def << '\n';
436         if (isRequired("quotedblbase"))
437                 macros << quotedblbase_def << '\n';
438         if (isRequired("guilsinglleft"))
439                 macros << guilsinglleft_def << '\n';
440         if (isRequired("guilsinglright"))
441                 macros << guilsinglright_def << '\n';
442         if (isRequired("guillemotleft"))
443                 macros << guillemotleft_def << '\n';
444         if (isRequired("guillemotright"))
445                 macros << guillemotright_def << '\n';
446
447         // Math mode
448         if (isRequired("boldsymbol") && !isRequired("amsmath"))
449                 macros << boldsymbol_def << '\n';
450         if (isRequired("binom") && !isRequired("amsmath"))
451                 macros << binom_def << '\n';
452         if (isRequired("mathcircumflex"))
453                 macros << mathcircumflex_def << '\n';
454
455         // other
456         if (isRequired("ParagraphLeftIndent"))
457                 macros << paragraphleftindent_def;
458         if (isRequired("NeedLyXFootnoteCode"))
459                 macros << floatingfootnote_def;
460
461         // some problems with tex->html converters
462         if (isRequired("NeedTabularnewline"))
463                 macros << tabularnewline_def;
464
465         // greyedout environment (note inset)
466         if (isRequired("lyxgreyedout"))
467                 macros << lyxgreyedout_def;
468
469         if (isRequired("lyxdot"))
470                 macros << lyxdot_def << '\n';
471
472         // floats
473         getFloatDefinitions(macros);
474
475         return macros.str();
476 }
477
478
479 string const LaTeXFeatures::getBabelOptions() const
480 {
481         ostringstream tmp;
482
483         LanguageList::const_iterator it  = UsedLanguages_.begin();
484         LanguageList::const_iterator end =  UsedLanguages_.end();
485         for (; it != end; ++it)
486                 if (!(*it)->latex_options().empty())
487                         tmp << (*it)->latex_options() << '\n';
488         if (!params_.language->latex_options().empty())
489                 tmp << params_.language->latex_options() << '\n';
490
491         return tmp.str();
492 }
493
494
495 docstring const LaTeXFeatures::getTClassPreamble() const
496 {
497         // the text class specific preamble
498         LyXTextClass const & tclass = params_.getLyXTextClass();
499         odocstringstream tcpreamble;
500
501         tcpreamble << tclass.preamble();
502
503         list<string>::const_iterator cit = usedLayouts_.begin();
504         list<string>::const_iterator end = usedLayouts_.end();
505         for (; cit != end; ++cit) {
506                 tcpreamble << tclass[*cit]->preamble();
507         }
508
509         CharStyles::iterator cs = tclass.charstyles().begin();
510         CharStyles::iterator csend = tclass.charstyles().end();
511         for (; cs != csend; ++cs) {
512                 if (isRequired(cs->name))
513                         tcpreamble << cs->preamble;
514         }
515
516         return tcpreamble.str();
517 }
518
519
520 docstring const LaTeXFeatures::getLyXSGMLEntities() const
521 {
522         // Definition of entities used in the document that are LyX related.
523         odocstringstream entities;
524
525         if (isRequired("lyxarrow")) {
526                 entities << "<!ENTITY lyxarrow \"-&gt;\">" << '\n';
527         }
528
529         return entities.str();
530 }
531
532
533 docstring const LaTeXFeatures::getIncludedFiles(string const & fname) const
534 {
535         odocstringstream sgmlpreamble;
536         string const basename = onlyPath(fname);
537
538         FileMap::const_iterator end = IncludedFiles_.end();
539         for (FileMap::const_iterator fi = IncludedFiles_.begin();
540              fi != end; ++fi)
541                 sgmlpreamble << "\n<!ENTITY " << fi->first
542                              << (isSGMLFilename(fi->second) ? " SYSTEM \"" : " \"")
543                              << from_ascii(makeRelPath(fi->second, basename)) << "\">";
544
545         return sgmlpreamble.str();
546 }
547
548
549 void LaTeXFeatures::showStruct() const {
550         lyxerr << "LyX needs the following commands when LaTeXing:"
551                << "\n***** Packages:" << getPackages()
552                << "\n***** Macros:" << getMacros()
553                << "\n***** Textclass stuff:" << to_utf8(getTClassPreamble())
554                << "\n***** done." << endl;
555 }
556
557
558 Buffer const & LaTeXFeatures::buffer() const
559 {
560         return *buffer_;
561 }
562
563
564 void LaTeXFeatures::setBuffer(Buffer const & buffer)
565 {
566         buffer_ = &buffer;
567 }
568
569
570 BufferParams const & LaTeXFeatures::bufferParams() const
571 {
572         return params_;
573 }
574
575
576 void LaTeXFeatures::getFloatDefinitions(ostream & os) const
577 {
578         FloatList const & floats = params_.getLyXTextClass().floats();
579
580         // Here we will output the code to create the needed float styles.
581         // We will try to do this as minimal as possible.
582         // \floatstyle{ruled}
583         // \newfloat{algorithm}{htbp}{loa}
584         // \floatname{algorithm}{Algorithm}
585         UsedFloats::const_iterator cit = usedFloats_.begin();
586         UsedFloats::const_iterator end = usedFloats_.end();
587         // ostringstream floats;
588         for (; cit != end; ++cit) {
589                 Floating const & fl = floats.getType((*cit));
590
591                 // For builtin floats we do nothing.
592                 if (fl.builtin()) continue;
593
594                 // We have to special case "table" and "figure"
595                 if (fl.type() == "tabular" || fl.type() == "figure") {
596                         // Output code to modify "table" or "figure"
597                         // but only if builtin == false
598                         // and that have to be true at this point in the
599                         // function.
600                         string const type = fl.type();
601                         string const placement = fl.placement();
602                         string const style = fl.style();
603                         if (!style.empty()) {
604                                 os << "\\floatstyle{" << style << "}\n"
605                                    << "\\restylefloat{" << type << "}\n";
606                         }
607                         if (!placement.empty()) {
608                                 os << "\\floatplacement{" << type << "}{"
609                                    << placement << "}\n";
610                         }
611                 } else {
612                         // The other non builtin floats.
613
614                         string const type = fl.type();
615                         string const placement = fl.placement();
616                         string const ext = fl.ext();
617                         string const within = fl.within();
618                         string const style = fl.style();
619                         string const name = fl.name();
620                         os << "\\floatstyle{" << style << "}\n"
621                            << "\\newfloat{" << type << "}{" << placement
622                            << "}{" << ext << '}';
623                         if (!within.empty())
624                                 os << '[' << within << ']';
625                         os << '\n'
626                            << "\\floatname{" << type << "}{"
627                            << name << "}\n";
628
629                         // What missing here is to code to minimalize the code
630                         // output so that the same floatstyle will not be
631                         // used several times, when the same style is still in
632                         // effect. (Lgb)
633                 }
634         }
635 }
636
637
638 } // namespace lyx