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