]> git.lyx.org Git - lyx.git/blob - src/LaTeXFeatures.cpp
Fix bug 4741: Pasting with middle mouse button into read only document works
[lyx.git] / src / LaTeXFeatures.cpp
1 /**
2  * \file LaTeXFeatures.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author José Matos
7  * \author Lars Gullik Bjønnes
8  * \author Jean-Marc Lasgouttes
9  * \author Jürgen Vigna
10  * \author André Pönitz
11  *
12  * Full author contact details are available in file CREDITS.
13  */
14
15 #include <config.h>
16
17 #include "LaTeXFeatures.h"
18
19 #include "Color.h"
20 #include "BufferParams.h"
21 #include "Encoding.h"
22 #include "Floating.h"
23 #include "FloatList.h"
24 #include "Language.h"
25 #include "Layout.h"
26 #include "Lexer.h"
27 #include "LyXRC.h"
28 #include "TextClass.h"
29
30 #include "support/debug.h"
31 #include "support/docstream.h"
32 #include "support/FileName.h"
33 #include "support/filetools.h"
34 #include "support/lstrings.h"
35
36 using namespace std;
37 using namespace lyx::support;
38
39
40 namespace lyx {
41
42 /////////////////////////////////////////////////////////////////////
43 //
44 // Strings
45 //
46 /////////////////////////////////////////////////////////////////////
47
48 //\NeedsTeXFormat{LaTeX2e}
49 //\ProvidesPackage{lyx}[1996/01/11 LLE v0.2 (LyX LaTeX Extensions)]
50 //\message{LyX LaTeX Extensions (LLE v0.2) of 11-Jan-1996.}
51
52 static string const lyx_def =
53         "\\providecommand{\\LyX}{L\\kern-.1667em\\lower.25em\\hbox{Y}\\kern-.125emX\\@}";
54
55 static string const lyxline_def =
56         "\\newcommand{\\lyxline}[1][1pt]{%\n"
57         "  \\par\\noindent%\n"
58         "  \\rule[.5ex]{\\linewidth}{#1}\\par}";
59
60 static string const noun_def = "\\newcommand{\\noun}[1]{\\textsc{#1}}";
61
62 static string const lyxarrow_def =
63         "\\newcommand{\\lyxarrow}{%\n"
64         "\\@ifstar\n"
65         "{\\leavevmode\\,$\\triangleleft$\\,\\allowbreak}\n"
66         "{\\leavevmode\\,$\\triangleright$\\,\\allowbreak}}";
67
68 // for quotes without babel. This does not give perfect results, but
69 // anybody serious about non-english quotes should use babel (JMarc).
70
71 static string const quotedblbase_def =
72         "\\ProvideTextCommandDefault{\\quotedblbase}{%\n"
73         "  \\raisebox{-1.4ex}[1ex][.5ex]{\\textquotedblright}%\n"
74         "  \\penalty10000\\hskip0em\\relax%\n"
75         "}";
76
77 static string const quotesinglbase_def =
78         "\\ProvideTextCommandDefault{\\quotesinglbase}{%\n"
79         "  \\raisebox{-1.4ex}[1ex][.5ex]{\\textquoteright}%\n"
80         "  \\penalty10000\\hskip0em\\relax%\n"
81         "}";
82
83 static string const guillemotleft_def =
84         "\\ProvideTextCommandDefault{\\guillemotleft}{%\n"
85         "  {\\usefont{U}{lasy}{m}{n}\\char'50\\kern-.15em\\char'50}%\n"
86         "\\penalty10000\\hskip0pt\\relax%\n"
87         "}";
88
89 static string const guillemotright_def =
90         "\\ProvideTextCommandDefault{\\guillemotright}{%\n"
91         "  \\penalty10000\\hskip0pt%\n"
92         "  {\\usefont{U}{lasy}{m}{n}\\char'51\\kern-.15em\\char'51}%\n"
93         "}";
94
95 static string const guilsinglleft_def =
96         "\\ProvideTextCommandDefault{\\guilsinglleft}{%\n"
97         "  {\\usefont{U}{lasy}{m}{n}\\char'50}%\n"
98         "  \\penalty10000\\hskip0pt\\relax%\n"
99         "}";
100
101 static string const guilsinglright_def =
102         "\\ProvideTextCommandDefault{\\guilsinglright}{%\n"
103         "  \\penalty10000\\hskip0pt%\n"
104         "  {\\usefont{U}{lasy}{m}{n}\\char'51}%\n"
105         "}";
106
107 static string const paragraphleftindent_def =
108         "\\newenvironment{LyXParagraphLeftIndent}[1]%\n"
109         "{\n"
110         "  \\begin{list}{}{%\n"
111         "    \\setlength{\\topsep}{0pt}%\n"
112         "    \\addtolength{\\leftmargin}{#1}\n"
113 // ho hum, yet more things commented out with no hint as to why they
114 // weren't just removed
115 //      "%%    \\addtolength{\\leftmargin}{#1\\textwidth}\n"
116 //      "%%    \\setlength{\\textwidth}{#2\\textwidth}\n"
117 //      "%%    \\setlength\\listparindent\\parindent%\n"
118 //      "%%    \\setlength\\itemindent\\parindent%\n"
119         "    \\setlength{\\parsep}{0pt plus 1pt}%\n"
120         "  }\n"
121         "  \\item[]\n"
122         "}\n"
123         "{\\end{list}}\n";
124
125 static string const floatingfootnote_def =
126         "%% Special footnote code from the package 'stblftnt.sty'\n"
127         "%% Author: Robin Fairbairns -- Last revised Dec 13 1996\n"
128         "\\let\\SF@@footnote\\footnote\n"
129         "\\def\\footnote{\\ifx\\protect\\@typeset@protect\n"
130         "    \\expandafter\\SF@@footnote\n"
131         "  \\else\n"
132         "    \\expandafter\\SF@gobble@opt\n"
133         "  \\fi\n"
134         "}\n"
135         "\\expandafter\\def\\csname SF@gobble@opt \\endcsname{\\@ifnextchar[%]\n"
136         "  \\SF@gobble@twobracket\n"
137         "  \\@gobble\n"
138         "}\n"
139         "\\edef\\SF@gobble@opt{\\noexpand\\protect\n"
140         "  \\expandafter\\noexpand\\csname SF@gobble@opt \\endcsname}\n"
141         "\\def\\SF@gobble@twobracket[#1]#2{}\n";
142
143 static string const binom_def =
144         "%% Binom macro for standard LaTeX users\n"
145         "\\newcommand{\\binom}[2]{{#1 \\choose #2}}\n";
146
147 static string const mathcircumflex_def =
148         "%% For printing a cirumflex inside a formula\n"
149         "\\newcommand{\\mathcircumflex}[0]{\\mbox{\\^{}}}\n";
150
151 static string const tabularnewline_def =
152         "%% Because html converters don't know tabularnewline\n"
153         "\\providecommand{\\tabularnewline}{\\\\}\n";
154         
155 static string const lyxgreyedout_def =
156         "%% The greyedout annotation environment\n"
157         "\\newenvironment{lyxgreyedout}{\\textcolor[gray]{0.8}\\bgroup}{\\egroup}\n";
158
159 // We want to omit the file extension for includegraphics, but this does not
160 // work when the filename contains other dots.
161 // Idea from http://www.tex.ac.uk/cgi-bin/texfaq2html?label=unkgrfextn
162 static string const lyxdot_def =
163         "%% A simple dot to overcome graphicx limitations\n"
164         "\\newcommand{\\lyxdot}{.}\n";
165
166 static string const changetracking_dvipost_def =
167         "%% Change tracking with dvipost\n"
168         "\\dvipostlayout\n"
169         "\\dvipost{osstart color push Red}\n"
170         "\\dvipost{osend color pop}\n"
171         "\\dvipost{cbstart color push Blue}\n"
172         "\\dvipost{cbend color pop}\n"
173         "\\newcommand{\\lyxadded}[3]{\\changestart#3\\changeend}\n"
174         "\\newcommand{\\lyxdeleted}[3]{%\n"
175         "\\changestart\\overstrikeon#3\\overstrikeoff\\changeend}\n";
176
177 static string const changetracking_xcolor_ulem_def =
178         "%% Change tracking with ulem\n"
179         "\\newcommand{\\lyxadded}[3]{{\\color{lyxadded}#3}}\n"
180         "\\newcommand{\\lyxdeleted}[3]{{\\color{lyxdeleted}\\sout{#3}}}\n";
181
182 static string const changetracking_xcolor_ulem_hyperref_def =
183         "%% Change tracking with ulem\n"
184         "\\newcommand{\\lyxadded}[3]{{\\texorpdfstring{\\color{lyxadded}}{}#3}}\n"
185         "\\newcommand{\\lyxdeleted}[3]{{\\texorpdfstring{\\color{lyxdeleted}\\sout{#3}}{}}}\n";
186
187 static string const changetracking_none_def =
188         "\\newcommand{\\lyxadded}[3]{#3}\n"
189         "\\newcommand{\\lyxdeleted}[3]{}\n";
190
191 static string const textgreek_def =
192         "\\DeclareRobustCommand{\\greektext}{%\n"
193         "  \\fontencoding{LGR}\\selectfont\\def\\encodingdefault{LGR}}\n"
194         "\\DeclareRobustCommand{\\textgreek}[1]{\\leavevmode{\\greektext #1}}\n"
195         "\\DeclareFontEncoding{LGR}{}{}\n";
196
197 static string const textcyr_def =
198         "\\DeclareRobustCommand{\\cyrtext}{%\n"
199         "  \\fontencoding{T2A}\\selectfont\\def\\encodingdefault{T2A}}\n"
200         "\\DeclareRobustCommand{\\textcyr}[1]{\\leavevmode{\\cyrtext #1}}\n"
201         "\\AtBeginDocument{\\DeclareFontEncoding{T2A}{}{}}\n";
202
203 static string const lyxmathsym_def =
204         "\\DeclareRobustCommand{\\lyxmathsym}[1]{\\ifmmode\\begingroup\\def\\b@ld{bold}\n"
205         "  \\def\\rmorbf##1{\\ifx\\math@version\\b@ld\\textbf{##1}\\else\\textrm{##1}\\fi}\n"
206         "  \\mathchoice{\\hbox{\\rmorbf{#1}}}{\\hbox{\\rmorbf{#1}}}\n"
207         "  {\\hbox{\\smaller[2]\\rmorbf{#1}}}{\\hbox{\\smaller[3]\\rmorbf{#1}}}\n"
208         "  \\endgroup\\else#1\\fi}\n";
209
210 static string const papersizedvi_def =
211         "\\special{papersize=\\the\\paperwidth,\\the\\paperheight}\n";
212
213 static string const papersizepdf_def =
214         "\\pdfpageheight\\paperheight\n"
215         "\\pdfpagewidth\\paperwidth\n";
216
217 static string const cedilla_def =
218         "\\newcommand{\\docedilla}[2]{\\underaccent{#1\\mathchar'30}{#2}}\n"
219         "\\newcommand{\\cedilla}[1]{\\mathpalette\\docedilla{#1}}\n";
220
221 static string const subring_def =
222         "\\newcommand{\\dosubring}[2]{\\underaccent{#1\\mathchar'27}{#2}}\n"
223         "\\newcommand{\\subring}[1]{\\mathpalette\\dosubring{#1}}\n";
224
225 static string const subdot_def =
226         "\\newcommand{\\dosubdot}[2]{\\underaccent{#1.}{#2}}\n"
227         "\\newcommand{\\subdot}[1]{\\mathpalette\\dosubdot{#1}}\n";
228
229 static string const subhat_def =
230         "\\newcommand{\\dosubhat}[2]{\\underaccent{#1\\mathchar'136}{#2}}\n"
231         "\\newcommand{\\subhat}[1]{\\mathpalette\\dosubhat{#1}}\n";
232
233 static string const subtilde_def =
234         "\\newcommand{\\dosubtilde}[2]{\\underaccent{#1\\mathchar'176}{#2}}\n"
235         "\\newcommand{\\subtilde}[1]{\\mathpalette\\dosubtilde{#1}}\n";
236
237 static string const dacute_def =
238         "\\DeclareMathAccent{\\dacute}{\\mathalpha}{operators}{'175}\n";
239
240 static string const tipasymb_def =
241         "\\DeclareFontEncoding{T3}{}{}\n"
242         "\\DeclareSymbolFont{tipasymb}{T3}{cmr}{m}{n}\n";
243
244 static string const dgrave_def =
245         "\\DeclareMathAccent{\\dgrave}{\\mathord}{tipasymb}{'15}\n";
246
247 static string const rcap_def =
248         "\\DeclareMathAccent{\\rcap}{\\mathord}{tipasymb}{'20}\n";
249
250 static string const ogonek_def =
251         "\\newcommand{\\doogonek}[2]{\\setbox0=\\hbox{$#1#2$}\\underaccent{#1\\mkern-6mu\n"
252         "  \\ifx#2O\\hskip0.5\\wd0\\else\\ifx#2U\\hskip0.5\\wd0\\else\\hskip\\wd0\\fi\\fi\n"
253         "  \\ifx#2o\\mkern-2mu\\else\\ifx#2e\\mkern-1mu\\fi\\fi\n"
254         "  \\mathchar\"0\\hexnumber@\\symtipasymb0C}{#2}}\n"
255         "\\newcommand{\\ogonek}[1]{\\mathpalette\\doogonek{#1}}\n";
256
257 /////////////////////////////////////////////////////////////////////
258 //
259 // LaTeXFeatures
260 //
261 /////////////////////////////////////////////////////////////////////
262
263 LaTeXFeatures::Packages LaTeXFeatures::packages_;
264
265
266 LaTeXFeatures::LaTeXFeatures(Buffer const & b, BufferParams const & p,
267                              OutputParams const & r)
268         : buffer_(&b), params_(p), runparams_(r)
269 {}
270
271
272 bool LaTeXFeatures::useBabel() const
273 {
274         return lyxrc.language_use_babel ||
275                 (bufferParams().language->lang() != lyxrc.default_language &&
276                  !bufferParams().language->babel().empty()) ||
277                 this->hasLanguages();
278 }
279
280
281 void LaTeXFeatures::require(string const & name)
282 {
283         features_.insert(name);
284 }
285
286
287 void LaTeXFeatures::require(set<string> const & names)
288 {
289         features_.insert(names.begin(), names.end());
290 }
291
292
293 void LaTeXFeatures::getAvailable()
294 {
295         Lexer lex;
296         support::FileName const real_file = libFileSearch("", "packages.lst");
297
298         if (real_file.empty())
299                 return;
300
301         lex.setFile(real_file);
302
303         if (!lex.isOK())
304                 return;
305
306         // Make sure that we are clean
307         packages_.clear();
308
309         bool finished = false;
310         // Parse config-file
311         while (lex.isOK() && !finished) {
312                 switch (lex.lex()) {
313                 case Lexer::LEX_FEOF:
314                         finished = true;
315                         break;
316                 default:
317                         packages_.insert(lex.getString());
318                 }
319         }
320 }
321
322
323 void LaTeXFeatures::useLayout(docstring const & layoutname)
324 {
325         // Some code to avoid loops in dependency definition
326         static int level = 0;
327         const int maxlevel = 30;
328         if (level > maxlevel) {
329                 lyxerr << "LaTeXFeatures::useLayout: maximum level of "
330                        << "recursion attained by layout "
331                        << to_utf8(layoutname) << endl;
332                 return;
333         }
334
335         DocumentClass const & tclass = params_.documentClass();
336         if (tclass.hasLayout(layoutname)) {
337                 // Is this layout already in usedLayouts?
338                 if (find(usedLayouts_.begin(), usedLayouts_.end(), layoutname) 
339                     != usedLayouts_.end())
340                         return;
341
342                 Layout const & layout = tclass[layoutname];
343                 require(layout.requires());
344
345                 if (!layout.depends_on().empty()) {
346                         ++level;
347                         useLayout(layout.depends_on());
348                         --level;
349                 }
350                 usedLayouts_.push_back(layoutname);
351         } else {
352                 lyxerr << "LaTeXFeatures::useLayout: layout `"
353                        << to_utf8(layoutname) << "' does not exist in this class"
354                        << endl;
355         }
356
357         --level;
358 }
359
360
361 bool LaTeXFeatures::isRequired(string const & name) const
362 {
363         return features_.find(name) != features_.end();
364 }
365
366
367 bool LaTeXFeatures::mustProvide(string const & name) const
368 {
369         return isRequired(name) && !params_.documentClass().provides(name);
370 }
371
372
373 bool LaTeXFeatures::isAvailable(string const & name)
374 {
375         if (packages_.empty())
376                 getAvailable();
377         string n = name;
378         if (suffixIs(n, ".sty"))
379                 n.erase(name.length() - 4);
380         return packages_.find(n) != packages_.end();
381 }
382
383
384 void LaTeXFeatures::addPreambleSnippet(string const & preamble)
385 {
386         SnippetList::const_iterator begin = preamble_snippets_.begin();
387         SnippetList::const_iterator end   = preamble_snippets_.end();
388         if (find(begin, end, preamble) == end)
389                 preamble_snippets_.push_back(preamble);
390 }
391
392
393 void LaTeXFeatures::useFloat(string const & name, bool subfloat)
394 {
395         if (!usedFloats_[name])
396                 usedFloats_[name] = subfloat;
397         if (subfloat)
398                 require("subfig");
399         // We only need float.sty if we use non builtin floats, or if we
400         // use the "H" modifier. This includes modified table and
401         // figure floats. (Lgb)
402         Floating const & fl = params_.documentClass().floats().getType(name);
403         if (!fl.type().empty() && !fl.builtin()) {
404                 require("float");
405         }
406 }
407
408
409 void LaTeXFeatures::useLanguage(Language const * lang)
410 {
411         if (!lang->babel().empty())
412                 UsedLanguages_.insert(lang);
413         if (lang->lang() == "vietnamese")
414                 require("vietnamese");
415         // CJK languages do not have a babel name.
416         // They use the CJK package
417         if (lang->encoding()->package() == Encoding::CJK)
418                 require("CJK");
419         // japanese package is special
420         if (lang->encoding()->package() == Encoding::japanese)
421                 require("japanese");
422 }
423
424
425 void LaTeXFeatures::includeFile(docstring const & key, string const & name)
426 {
427         IncludedFiles_[key] = name;
428 }
429
430
431 bool LaTeXFeatures::hasLanguages() const
432 {
433         return !UsedLanguages_.empty();
434 }
435
436
437 string LaTeXFeatures::getLanguages() const
438 {
439         ostringstream languages;
440
441         LanguageList::const_iterator const begin = UsedLanguages_.begin();
442         for (LanguageList::const_iterator cit = begin;
443              cit != UsedLanguages_.end();
444              ++cit) {
445                 if (cit != begin)
446                         languages << ',';
447                 languages << (*cit)->babel();
448         }
449         return languages.str();
450 }
451
452
453 set<string> LaTeXFeatures::getEncodingSet(string const & doc_encoding) const
454 {
455         // This does only find encodings of languages supported by babel, but
456         // that does not matter since we don't have a language with an
457         // encoding supported by inputenc but without babel support.
458         set<string> encodings;
459         LanguageList::const_iterator it  = UsedLanguages_.begin();
460         LanguageList::const_iterator end = UsedLanguages_.end();
461         for (; it != end; ++it)
462                 if ((*it)->encoding()->latexName() != doc_encoding &&
463                     ((*it)->encoding()->package() == Encoding::inputenc
464                      || (*it)->encoding()->package() == Encoding::japanese))
465                         encodings.insert((*it)->encoding()->latexName());
466         return encodings;
467 }
468
469 namespace {
470
471 char const * simplefeatures[] = {
472 // note that the package order here will be the same in the LaTeX-output
473         "array",
474         "verbatim",
475         "longtable",
476         "rotating",
477         "latexsym",
478         "pifont",
479         // subfig is handled in BufferParams.cpp
480         "varioref",
481         "prettyref",
482         /*For a successful cooperation of the `wrapfig' package with the
483           `float' package you should load the `wrapfig' package *after*
484           the `float' package. See the caption package documentation
485           for explanation.*/
486         "float",
487         "rotfloat",
488         "wrapfig",
489         "booktabs",
490         "dvipost",
491         "fancybox",
492         "calc",
493         "units",
494         "tipa",
495         "tipx",
496         "framed",
497         "soul",
498         "textcomp",
499         "pmboxdraw",
500         "bbding",
501         "ifsym",
502         "marvosym",
503         "txfonts",
504         "mathrsfs",
505         "ascii",
506         "url",
507         "covington",
508         "csquotes",
509         "enumitem",
510         "endnotes",
511         "ifthen",
512         "amsthm",
513         // listings is handled in BufferParams.cpp
514         "bm",
515         "pdfpages",
516         "relsize",
517         "amscd",
518         "slashed"
519 };
520
521 int const nb_simplefeatures = sizeof(simplefeatures) / sizeof(char const *);
522
523 }
524
525
526 string const LaTeXFeatures::getColorOptions() const
527 {
528         ostringstream colors;
529
530         // Handling the color packages separately is needed to be able to load them
531         // before babel when hyperref is loaded with the colorlinks option
532         // for more info see Bufferparams.cpp
533
534         // [x]color.sty
535         if (mustProvide("color") || mustProvide("xcolor")) {
536                 string const package =
537                         (mustProvide("xcolor") ? "xcolor" : "color");
538                 if (params_.graphicsDriver == "default"
539                         || params_.graphicsDriver == "none")
540                         colors << "\\usepackage{" << package << "}\n";
541                 else
542                         colors << "\\usepackage["
543                                  << params_.graphicsDriver
544                                  << "]{" << package << "}\n";
545         }
546
547         // pdfcolmk must be loaded after color
548         if (mustProvide("pdfcolmk"))
549                 colors << "\\usepackage{pdfcolmk}\n";
550
551         return colors.str();
552 }
553
554
555 string const LaTeXFeatures::getPackages() const
556 {
557         ostringstream packages;
558         DocumentClass const & tclass = params_.documentClass();
559
560         // FIXME: currently, we can only load packages and macros known
561         // to LyX.
562         // However, with the Require tag of layouts/custom insets,
563         // also inknown packages can be requested. They are silently
564         // swallowed now. We should change this eventually.
565
566         //
567         //  These are all the 'simple' includes.  i.e
568         //  packages which we just \usepackage{package}
569         //
570         for (int i = 0; i < nb_simplefeatures; ++i) {
571                 if (mustProvide(simplefeatures[i]))
572                         packages << "\\usepackage{"
573                                  << simplefeatures[i] << "}\n";
574         }
575
576         //
577         // The rest of these packages are somewhat more complicated
578         // than those above.
579         //
580
581         // esint is preferred for esintoramsmath
582         if ((mustProvide("amsmath")
583              && params_.use_amsmath != BufferParams::package_off)
584             || (mustProvide("esintoramsmath")
585                 && params_.use_esint == BufferParams::package_off
586                 && params_.use_amsmath != BufferParams::package_off)) {
587                 packages << "\\usepackage{amsmath}\n";
588         } else if (mustProvide("amsbsy")) {
589                 // amsbsy is already provided by amsmath
590                 packages << "\\usepackage{amsbsy}\n";
591         }
592         
593         // wasysym is a simple feature, but it must be after amsmath if both
594         // are used
595         // wasysym redefines some integrals (e.g. iint) from amsmath. That
596         // leads to inconsistent integrals. We only load this package if
597         // the document does not contain integrals (then isRequired("esint")
598         // is false) or if esint is used, since esint redefines all relevant
599         // integral symbols from wasysym and amsmath.
600         // See http://bugzilla.lyx.org/show_bug.cgi?id=1942
601         if (mustProvide("wasysym") &&
602             (params_.use_esint != BufferParams::package_off || !isRequired("esint")))
603                 packages << "\\usepackage{wasysym}\n";
604
605         // accents must be loaded after amsmath
606         if (mustProvide("accents"))
607                 packages << "\\usepackage{accents}\n";
608
609         // [x]color and pdfcolmk are handled in getColorOptions() above
610         
611         // makeidx.sty
612         if (isRequired("makeidx")) {
613                 if (!tclass.provides("makeidx"))
614                         packages << "\\usepackage{makeidx}\n";
615                 packages << "\\makeindex\n";
616         }
617
618         // graphicx.sty
619         if (mustProvide("graphicx") && params_.graphicsDriver != "none") {
620                 if (params_.graphicsDriver == "default")
621                         packages << "\\usepackage{graphicx}\n";
622                 else
623                         packages << "\\usepackage["
624                                  << params_.graphicsDriver
625                                  << "]{graphicx}\n";
626         }
627         // shadecolor for shaded
628         if (isRequired("framed") && mustProvide("color")) {
629                 RGBColor c = rgbFromHexName(lcolor.getX11Name(Color_shadedbg));
630                 //255.0 to force conversion to double
631                 //NOTE As Jürgen Spitzmüller pointed out, an alternative would be
632                 //to use the xcolor package instead, and then we can do
633                 // \define{shadcolor}{RGB}...
634                 //and not do any conversion. We'd then need to require xcolor
635                 //in InsetNote::validate().
636                 int const stmSize = packages.precision(2);
637                 packages << "\\definecolor{shadecolor}{rgb}{"
638                         << c.r / 255.0 << ',' << c.g / 255.0 << ',' << c.b / 255.0 << "}\n";
639                 packages.precision(stmSize);
640         }
641
642         // lyxskak.sty --- newer chess support based on skak.sty
643         if (mustProvide("chess"))
644                 packages << "\\usepackage[ps,mover]{lyxskak}\n";
645
646         // setspace.sty
647         if (mustProvide("setspace") && !tclass.provides("SetSpace"))
648                 packages << "\\usepackage{setspace}\n";
649
650         // amssymb.sty
651         if (mustProvide("amssymb")
652             || params_.use_amsmath == BufferParams::package_on)
653                 packages << "\\usepackage{amssymb}\n";
654
655         // esint must be after amsmath and wasysym, since it will redeclare
656         // inconsistent integral symbols
657         if ((mustProvide("esint") || mustProvide("esintoramsmath")) &&
658             params_.use_esint != BufferParams::package_off)
659                 packages << "\\usepackage{esint}\n";
660
661         // natbib.sty
662         // Some classes load natbib themselves, but still allow (or even require)
663         // plain numeric citations (ReVTeX is such a case, see bug 5182).
664         // This special case is indicated by the "natbib-internal" key.
665         if (mustProvide("natbib") && !tclass.provides("natbib-internal")) {
666                 packages << "\\usepackage[";
667                 if (params_.citeEngine() == ENGINE_NATBIB_NUMERICAL)
668                         packages << "numbers";
669                 else
670                         packages << "authoryear";
671                 packages << "]{natbib}\n";
672         }
673
674         // jurabib -- we need version 0.6 at least.
675         if (mustProvide("jurabib"))
676                 packages << "\\usepackage{jurabib}[2004/01/25]\n";
677         
678         // xargs -- we need version 1.09 at least
679         if (mustProvide("xargs"))
680                 packages << "\\usepackage{xargs}[2008/03/08]\n";
681
682         // bibtopic -- the dot provides the aux file naming which
683         // LyX can detect.
684         if (mustProvide("bibtopic"))
685                 packages << "\\usepackage[dot]{bibtopic}\n";
686
687         if (mustProvide("xy"))
688                 packages << "\\usepackage[all]{xy}\n";
689
690         if (mustProvide("ulem"))
691                 packages << "\\PassOptionsToPackage{normalem}{ulem}\n"
692                             "\\usepackage{ulem}\n";
693
694         if (mustProvide("nomencl")) {
695                 // Make it work with the new and old version of the package,
696                 // but don't use the compatibility option since it is
697                 // incompatible to other packages.
698                 packages << "\\usepackage{nomencl}\n"
699                             "% the following is useful when we have the old nomencl.sty package\n"
700                             "\\providecommand{\\printnomenclature}{\\printglossary}\n"
701                             "\\providecommand{\\makenomenclature}{\\makeglossary}\n"
702                             "\\makenomenclature\n";
703         }
704
705         return packages.str();
706 }
707
708
709 string const LaTeXFeatures::getMacros() const
710 {
711         ostringstream macros;
712
713         if (!preamble_snippets_.empty())
714                 macros << '\n';
715         SnippetList::const_iterator pit  = preamble_snippets_.begin();
716         SnippetList::const_iterator pend = preamble_snippets_.end();
717         for (; pit != pend; ++pit)
718                 macros << *pit << '\n';
719
720         if (mustProvide("papersize")) {
721                 if (runparams_.flavor == OutputParams::LATEX)
722                         macros << papersizedvi_def << '\n';
723                 else
724                         macros << papersizepdf_def << '\n';
725         }
726
727         if (mustProvide("LyX"))
728                 macros << lyx_def << '\n';
729
730         if (mustProvide("lyxline"))
731                 macros << lyxline_def << '\n';
732
733         if (mustProvide("noun"))
734                 macros << noun_def << '\n';
735
736         if (mustProvide("lyxarrow"))
737                 macros << lyxarrow_def << '\n';
738
739         if (mustProvide("textgreek"))
740                 macros << textgreek_def << '\n';
741
742         if (mustProvide("textcyr"))
743                 macros << textcyr_def << '\n';
744
745         if (mustProvide("lyxmathsym"))
746                 macros << lyxmathsym_def << '\n';
747
748         if (mustProvide("cedilla"))
749                 macros << cedilla_def << '\n';
750
751         if (mustProvide("subring"))
752                 macros << subring_def << '\n';
753
754         if (mustProvide("subdot"))
755                 macros << subdot_def << '\n';
756
757         if (mustProvide("subhat"))
758                 macros << subhat_def << '\n';
759
760         if (mustProvide("subtilde"))
761                 macros << subtilde_def << '\n';
762
763         if (mustProvide("dacute"))
764                 macros << dacute_def << '\n';
765
766         if (mustProvide("tipasymb"))
767                 macros << tipasymb_def << '\n';
768
769         if (mustProvide("dgrave"))
770                 macros << dgrave_def << '\n';
771
772         if (mustProvide("rcap"))
773                 macros << rcap_def << '\n';
774
775         if (mustProvide("ogonek"))
776                 macros << ogonek_def << '\n';
777
778         // quotes.
779         if (mustProvide("quotesinglbase"))
780                 macros << quotesinglbase_def << '\n';
781         if (mustProvide("quotedblbase"))
782                 macros << quotedblbase_def << '\n';
783         if (mustProvide("guilsinglleft"))
784                 macros << guilsinglleft_def << '\n';
785         if (mustProvide("guilsinglright"))
786                 macros << guilsinglright_def << '\n';
787         if (mustProvide("guillemotleft"))
788                 macros << guillemotleft_def << '\n';
789         if (mustProvide("guillemotright"))
790                 macros << guillemotright_def << '\n';
791
792         // Math mode
793         if (mustProvide("binom") && !isRequired("amsmath"))
794                 macros << binom_def << '\n';
795         if (mustProvide("mathcircumflex"))
796                 macros << mathcircumflex_def << '\n';
797
798         // other
799         if (mustProvide("ParagraphLeftIndent"))
800                 macros << paragraphleftindent_def;
801         if (mustProvide("NeedLyXFootnoteCode"))
802                 macros << floatingfootnote_def;
803
804         // some problems with tex->html converters
805         if (mustProvide("NeedTabularnewline"))
806                 macros << tabularnewline_def;
807
808         // greyedout environment (note inset)
809         if (mustProvide("lyxgreyedout"))
810                 macros << lyxgreyedout_def;
811
812         if (mustProvide("lyxdot"))
813                 macros << lyxdot_def << '\n';
814
815         // floats
816         getFloatDefinitions(macros);
817
818         // change tracking
819         if (mustProvide("ct-dvipost"))
820                 macros << changetracking_dvipost_def;
821
822         if (mustProvide("ct-xcolor-ulem")) {
823                 int const prec = macros.precision(2);
824         
825                 RGBColor cadd = rgbFromHexName(lcolor.getX11Name(Color_addedtext));
826                 macros << "\\providecolor{lyxadded}{rgb}{"
827                        << cadd.r / 255.0 << ',' << cadd.g / 255.0 << ',' << cadd.b / 255.0 << "}\n";
828
829                 RGBColor cdel = rgbFromHexName(lcolor.getX11Name(Color_deletedtext));
830                 macros << "\\providecolor{lyxdeleted}{rgb}{"
831                        << cdel.r / 255.0 << ',' << cdel.g / 255.0 << ',' << cdel.b / 255.0 << "}\n";
832
833                 macros.precision(prec);
834                 
835                 if (isRequired("hyperref"))
836                         macros << changetracking_xcolor_ulem_hyperref_def;
837                 else
838                         macros << changetracking_xcolor_ulem_def;
839         }
840
841         if (mustProvide("ct-none"))
842                 macros << changetracking_none_def;
843
844         return macros.str();
845 }
846
847
848 string const LaTeXFeatures::getBabelOptions() const
849 {
850         ostringstream tmp;
851
852         LanguageList::const_iterator it  = UsedLanguages_.begin();
853         LanguageList::const_iterator end =  UsedLanguages_.end();
854         for (; it != end; ++it)
855                 if (!(*it)->latex_options().empty())
856                         tmp << (*it)->latex_options() << '\n';
857         if (!params_.language->latex_options().empty())
858                 tmp << params_.language->latex_options() << '\n';
859
860         return tmp.str();
861 }
862
863
864 docstring const LaTeXFeatures::getTClassPreamble() const
865 {
866         // the text class specific preamble
867         DocumentClass const & tclass = params_.documentClass();
868         odocstringstream tcpreamble;
869
870         tcpreamble << tclass.preamble();
871
872         list<docstring>::const_iterator cit = usedLayouts_.begin();
873         list<docstring>::const_iterator end = usedLayouts_.end();
874         for (; cit != end; ++cit) {
875                 tcpreamble << tclass[*cit].preamble();
876         }
877
878         return tcpreamble.str();
879 }
880
881
882 docstring const LaTeXFeatures::getLyXSGMLEntities() const
883 {
884         // Definition of entities used in the document that are LyX related.
885         odocstringstream entities;
886
887         if (mustProvide("lyxarrow")) {
888                 entities << "<!ENTITY lyxarrow \"-&gt;\">" << '\n';
889         }
890
891         return entities.str();
892 }
893
894
895 docstring const LaTeXFeatures::getIncludedFiles(string const & fname) const
896 {
897         odocstringstream sgmlpreamble;
898         // FIXME UNICODE
899         docstring const basename(from_utf8(onlyPath(fname)));
900
901         FileMap::const_iterator end = IncludedFiles_.end();
902         for (FileMap::const_iterator fi = IncludedFiles_.begin();
903              fi != end; ++fi)
904                 // FIXME UNICODE
905                 sgmlpreamble << "\n<!ENTITY " << fi->first
906                              << (isSGMLFilename(fi->second) ? " SYSTEM \"" : " \"")
907                              << makeRelPath(from_utf8(fi->second), basename) << "\">";
908
909         return sgmlpreamble.str();
910 }
911
912
913 void LaTeXFeatures::showStruct() const
914 {
915         lyxerr << "LyX needs the following commands when LaTeXing:"
916                << "\n***** Packages:" << getPackages()
917                << "\n***** Macros:" << getMacros()
918                << "\n***** Textclass stuff:" << to_utf8(getTClassPreamble())
919                << "\n***** done." << endl;
920 }
921
922
923 Buffer const & LaTeXFeatures::buffer() const
924 {
925         return *buffer_;
926 }
927
928
929 void LaTeXFeatures::setBuffer(Buffer const & buffer)
930 {
931         buffer_ = &buffer;
932 }
933
934
935 BufferParams const & LaTeXFeatures::bufferParams() const
936 {
937         return params_;
938 }
939
940
941 void LaTeXFeatures::getFloatDefinitions(ostream & os) const
942 {
943         FloatList const & floats = params_.documentClass().floats();
944
945         // Here we will output the code to create the needed float styles.
946         // We will try to do this as minimal as possible.
947         // \floatstyle{ruled}
948         // \newfloat{algorithm}{htbp}{loa}
949         // \floatname{algorithm}{Algorithm}
950         UsedFloats::const_iterator cit = usedFloats_.begin();
951         UsedFloats::const_iterator end = usedFloats_.end();
952         // ostringstream floats;
953         for (; cit != end; ++cit) {
954                 Floating const & fl = floats.getType((cit->first));
955
956                 // For builtin floats we do nothing.
957                 if (fl.builtin()) continue;
958
959                 // We have to special case "table" and "figure"
960                 if (fl.type() == "tabular" || fl.type() == "figure") {
961                         // Output code to modify "table" or "figure"
962                         // but only if builtin == false
963                         // and that have to be true at this point in the
964                         // function.
965                         string const type = fl.type();
966                         string const placement = fl.placement();
967                         string const style = fl.style();
968                         if (!style.empty()) {
969                                 os << "\\floatstyle{" << style << "}\n"
970                                    << "\\restylefloat{" << type << "}\n";
971                         }
972                         if (!placement.empty()) {
973                                 os << "\\floatplacement{" << type << "}{"
974                                    << placement << "}\n";
975                         }
976                 } else {
977                         // The other non builtin floats.
978
979                         string const type = fl.type();
980                         string const placement = fl.placement();
981                         string const ext = fl.ext();
982                         string const within = fl.within();
983                         string const style = fl.style();
984                         string const name = fl.name();
985                         os << "\\floatstyle{" << style << "}\n"
986                            << "\\newfloat{" << type << "}{" << placement
987                            << "}{" << ext << '}';
988                         if (!within.empty())
989                                 os << '[' << within << ']';
990                         os << '\n'
991                            << "\\floatname{" << type << "}{"
992                            << name << "}\n";
993
994                         // What missing here is to code to minimalize the code
995                         // output so that the same floatstyle will not be
996                         // used several times, when the same style is still in
997                         // effect. (Lgb)
998                 }
999                 if (cit->second)
1000                         os << "\n\\newsubfloat{" << fl.type() << "}\n";
1001         }
1002 }
1003
1004
1005 } // namespace lyx