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