]> git.lyx.org Git - features.git/blob - src/LaTeXFeatures.C
"ding-dong, the witch is dead!", says John
[features.git] / src / LaTeXFeatures.C
1 /* This file is part of
2  * ====================================================== 
3  * 
4  *           LyX, The Document Processor
5  *        
6  *           Copyright 1995 Matthias Ettrich
7  *           Copyright 1995-2001 the LyX Team.
8  *
9  * ====================================================== */
10
11 #include <config.h>
12
13 #ifdef __GNUG__
14 #pragma implementation
15 #endif
16
17 #include "LaTeXFeatures.h"
18 #include "debug.h"
19 #include "lyx_sty.h"
20 #include "lyxrc.h"
21 #include "bufferparams.h"
22 #include "lyxtextclasslist.h"
23 #include "FloatList.h"
24 #include "language.h"
25 #include "encoding.h"
26 #include "LString.h"
27
28 #include "support/filetools.h"
29 #include "support/lstrings.h"
30
31 using lyx::layout_type;
32 using lyx::textclass_type;
33
34 using std::endl;
35 using std::set;
36 using std::vector;
37 using std::find;
38 using std::ostream;
39
40
41 LaTeXFeatures::LaTeXFeatures(BufferParams const & p, layout_type n)
42         : layout(n, false), params(p)
43 {}
44
45
46 void LaTeXFeatures::require(string const & name)
47 {
48         if (isRequired(name))
49                 return;
50         
51         features.push_back(name);
52 }
53
54
55 void LaTeXFeatures::useLayout(vector<bool>::size_type const & idx)
56 {
57         layout[idx] = true;
58 }
59
60
61 bool LaTeXFeatures::isRequired(string const & name) const
62 {
63         FeaturesList::const_iterator i = find(features.begin(), 
64                                               features.end(),
65                                               name);
66         return i != features.end();
67 }
68
69
70 void LaTeXFeatures::addExternalPreamble(string const & pream)
71 {
72         externalPreambles += pream;
73 }
74
75
76 void LaTeXFeatures::useFloat(string const & name)
77 {
78         usedFloats.insert(name);
79         // We only need float.sty if we use non builtin floats, or if we
80         // use the "H" modifier. This includes modified table and
81         // figure floats. (Lgb)
82         Floating const & fl = floatList.getType(name);
83         if (!fl.type().empty() && !fl.builtin()) {
84                 require("float");
85         }
86 }
87
88
89 void LaTeXFeatures::useLanguage(Language const * lang)
90 {
91         UsedLanguages.insert(lang);
92 }
93
94
95 void LaTeXFeatures::includeFile(string const & key, string const & name) 
96 {
97         IncludedFiles[key] = name;
98 }
99
100
101 bool LaTeXFeatures::hasLanguages() 
102 {
103         return !UsedLanguages.empty();
104 }
105
106
107 string LaTeXFeatures::getLanguages() const 
108 {
109         ostringstream languages;
110
111         for (LanguageList::const_iterator cit =
112                     UsedLanguages.begin();
113              cit != UsedLanguages.end(); 
114              ++cit)
115                 languages << (*cit)->babel() << ',';
116
117         return languages.str().c_str();
118 }
119
120
121 set<string> LaTeXFeatures::getEncodingSet(string const & doc_encoding) 
122 {
123         set<string> encodings;
124         for (LanguageList::const_iterator it =
125                      UsedLanguages.begin();
126              it != UsedLanguages.end(); ++it)
127                 if ((*it)->encoding()->LatexName() != doc_encoding)
128                         encodings.insert((*it)->encoding()->LatexName());
129         return encodings;
130 }
131
132 namespace {
133         
134 char const * simplefeatures[] = {
135         "array",
136         "verbatim",
137         "longtable",
138         "rotating",
139         "latexsym",
140         "pifont",
141         "subfigure",
142         "floatflt",
143         "varioref",
144         "prettyref",
145         "float"
146 };
147
148 const int nb_simplefeatures = sizeof(simplefeatures) / sizeof(char const *);
149
150 }
151
152 string const LaTeXFeatures::getPackages() const
153 {
154         ostringstream packages;
155         LyXTextClass const & tclass =
156                 textclasslist.TextClass(params.textclass);
157
158
159         /**
160          *  These are all the 'simple' includes.  i.e
161          *  packages which we just \usepackage{package}
162          **/
163         for (int i = 0 ; i < nb_simplefeatures ; ++i) {
164                 if (isRequired(simplefeatures[i]))
165                         packages << "\\usepackage{"
166                                  << simplefeatures[i]
167                                  << "}\n";
168         }
169         
170         /**
171          * The rest of these packages are somewhat more complicated
172          * than those above.
173          **/
174
175         if (isRequired("amsmath")
176             && ! tclass.provides(LyXTextClass::amsmath)) {
177                 packages << "\\usepackage{amsmath}\n";
178         }
179                 
180         // color.sty
181         if (isRequired("color")) {
182                 if (params.graphicsDriver == "default")
183                         packages << "\\usepackage{color}\n";
184                 else
185                         packages << "\\usepackage[" 
186                                  << params.graphicsDriver
187                                  << "]{color}\n";
188         }
189                 
190         // makeidx.sty
191         if (isRequired("makeidx")) {
192                 if (! tclass.provides(LyXTextClass::makeidx))
193                         packages << "\\usepackage{makeidx}\n";
194                 packages << "\\makeindex\n";
195         }
196
197         // graphicx.sty
198         if (isRequired("graphicx") && params.graphicsDriver != "none") {
199                 if (params.graphicsDriver == "default")
200                         packages << "\\usepackage{graphicx}\n";
201                 else
202                         packages << "\\usepackage[" 
203                                  << params.graphicsDriver
204                                  << "]{graphicx}\n";
205         }
206
207         //if (algorithm) {
208         //      packages << "\\usepackage{algorithm}\n";
209         //}
210
211         // lyxskak.sty --- newer chess support based on skak.sty
212         if (isRequired("chess")) {
213                 packages << "\\usepackage[ps,mover]{lyxskak}\n";
214         }
215
216         // setspace.sty
217         if ((params.spacing.getSpace() != Spacing::Single
218              && !params.spacing.isDefault())
219             || isRequired("setspace")) {
220                 packages << "\\usepackage{setspace}\n";
221         }
222         switch (params.spacing.getSpace()) {
223         case Spacing::Default:
224         case Spacing::Single:
225                 // we dont use setspace.sty so dont print anything
226                 //packages += "\\singlespacing\n";
227                 break;
228         case Spacing::Onehalf:
229                 packages << "\\onehalfspacing\n";
230                 break;
231         case Spacing::Double:
232                 packages << "\\doublespacing\n";
233                 break;
234         case Spacing::Other:
235                 packages << "\\setstretch{"
236                          << params.spacing.getValue() << "}\n";
237                 break;
238         }
239
240         // amssymb.sty
241         if (isRequired("amssymb") || params.use_amsmath)
242                 packages << "\\usepackage{amssymb}\n";
243         // url.sty
244         if (isRequired("url") && ! tclass.provides(LyXTextClass::url))
245                 packages << "\\IfFileExists{url.sty}{\\usepackage{url}}\n"
246                             "                      {\\newcommand{\\url}{\\texttt}}\n";
247
248         // float.sty
249         // natbib.sty
250         if (isRequired("natbib")) {
251                 packages << "\\usepackage[";
252                 if (params.use_numerical_citations) {
253                         packages << "numbers";
254                 } else {
255                         packages << "authoryear";
256                 }
257                 packages << "]{natbib}\n";
258         }
259         
260         packages << externalPreambles;
261
262         return packages.str().c_str();
263 }
264
265
266 string const LaTeXFeatures::getMacros() const
267 {
268         ostringstream macros;
269
270         // always include this
271         if (true || isRequired("lyx")) 
272                 macros << lyx_def << '\n';
273
274         if (isRequired("lyxline")) 
275                 macros << lyxline_def << '\n';
276
277         if (isRequired("noun"))
278                 macros << noun_def << '\n';
279
280         if (isRequired("lyxarrow"))
281                 macros << lyxarrow_def << '\n';
282
283         // quotes. 
284         if (isRequired("quotesinglbase"))
285                 macros << quotesinglbase_def << '\n';
286         if (isRequired("quotedblbase"))
287                 macros << quotedblbase_def << '\n';
288         if (isRequired("guilsinglleft"))
289                 macros << guilsinglleft_def << '\n';
290         if (isRequired("guilsinglright"))
291                 macros << guilsinglright_def << '\n';
292         if (isRequired("guillemotleft"))
293                 macros << guillemotleft_def << '\n';
294         if (isRequired("guillemotright"))
295                 macros << guillemotright_def << '\n';
296     
297         // Math mode    
298         if (isRequired("boldsymbol") && !isRequired("amsmath"))
299                 macros << boldsymbol_def << '\n';
300         if (isRequired("binom") && !isRequired("amsmath"))
301                 macros << binom_def << '\n';
302
303         // other
304         if (isRequired("NeedLyXMinipageIndent"))
305                 macros << minipageindent_def;
306         if (isRequired("ParagraphIndent")) 
307                 macros << paragraphindent_def;
308         if (isRequired("NeedLyXFootnoteCode")) 
309                 macros << floatingfootnote_def;
310
311         // floats
312         getFloatDefinitions(macros);
313
314         for (LanguageList::const_iterator cit = UsedLanguages.begin();
315              cit != UsedLanguages.end(); ++cit)
316                 if (!(*cit)->latex_options().empty())
317                         macros << (*cit)->latex_options() << '\n';
318         if (!params.language->latex_options().empty())
319                 macros << params.language->latex_options() << '\n';
320
321         return macros.str().c_str();
322 }
323
324
325 string const LaTeXFeatures::getTClassPreamble() const
326 {
327         // the text class specific preamble 
328         LyXTextClass const & tclass = textclasslist.TextClass(params.textclass);
329         ostringstream tcpreamble;
330
331         tcpreamble << tclass.preamble();
332
333         for (layout_type i = 0; i < tclass.numLayouts(); ++i) {
334                 if (layout[i]) {
335                         tcpreamble << tclass[i].preamble();
336                 }
337         }
338
339         return tcpreamble.str().c_str();
340 }       
341
342
343 string const LaTeXFeatures::getLyXSGMLEntities() const
344 {
345         // Definition of entities used in the document that are LyX related.
346         ostringstream entities;
347
348         if (isRequired("lyxarrow")) {
349                 entities << "<!ENTITY lyxarrow \"-&gt;\">" << '\n';
350         }
351
352         return entities.str().c_str();
353 }
354
355
356 string const LaTeXFeatures::getIncludedFiles(string const & fname) const
357 {
358         ostringstream sgmlpreamble;
359         string const basename = OnlyPath(fname);
360
361         FileMap::const_iterator end = IncludedFiles.end();
362         for (FileMap::const_iterator fi = IncludedFiles.begin();
363              fi != end; ++fi)
364                 sgmlpreamble << "\n<!ENTITY " << fi->first
365                              << (IsSGMLFilename(fi->second) ? " SYSTEM \"" : " \"")
366                              << MakeRelPath(fi->second, basename) << "\">";
367
368         return sgmlpreamble.str().c_str();
369 }
370
371
372 void LaTeXFeatures::showStruct() const {
373         lyxerr << "LyX needs the following commands when LaTeXing:"
374                << "\n***** Packages:" << getPackages()
375                << "\n***** Macros:" << getMacros()
376                << "\n***** Textclass stuff:" << getTClassPreamble()
377                << "\n***** done." << endl;
378 }
379
380
381 BufferParams const & LaTeXFeatures::bufferParams() const
382 {
383         return params;
384 }
385
386 void LaTeXFeatures::getFloatDefinitions(ostream & os) const
387 {
388         // Here we will output the code to create the needed float styles.
389         // We will try to do this as minimal as possible.
390         // \floatstyle{ruled}
391         // \newfloat{algorithm}{htbp}{loa}
392         // \floatname{algorithm}{Algorithm}
393         UsedFloats::const_iterator cit = usedFloats.begin();
394         UsedFloats::const_iterator end = usedFloats.end();
395         // ostringstream floats;
396         for (; cit != end; ++cit) {
397                 Floating const & fl = floatList.getType((*cit));
398                 
399                 // For builtin floats we do nothing.
400                 if (fl.builtin()) continue;
401                 
402                 // We have to special case "table" and "figure"
403                 if (fl.type() == "tabular" || fl.type() == "figure") {
404                         // Output code to modify "table" or "figure"
405                         // but only if builtin == false
406                         // and that have to be true at this point in the
407                         // function.
408                         string const type = fl.type();
409                         string const placement = fl.placement();
410                         string const style = fl.style();
411                         if (!style.empty()) {
412                                 os << "\\floatstyle{" << style << "}\n"
413                                    << "\\restylefloat{" << type << "}\n";
414                         }
415                         if (!placement.empty()) {
416                                 os << "\\floatplacement{" << type << "}{"
417                                    << placement << "}\n";
418                         }
419                 } else {
420                         // The other non builtin floats.
421                         
422                         string const type = fl.type();
423                         string const placement = fl.placement();
424                         string const ext = fl.ext();
425                         string const within = fl.within();
426                         string const style = fl.style();
427                         string const name = fl.name();
428                         os << "\\floatstyle{" << style << "}\n"
429                            << "\\newfloat{" << type << "}{" << placement
430                            << "}{" << ext << "}";
431                         if (!within.empty())
432                                 os << "[" << within << "]";
433                         os << "\n"
434                            << "\\floatname{" << type << "}{"
435                            << name << "}\n";
436                         
437                         // What missing here is to code to minimalize the code
438                         // output so that the same floatstyle will not be
439                         // used several times, when the same style is still in
440                         // effect. (Lgb)
441                 }
442         }
443 }