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