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