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