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