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