]> git.lyx.org Git - lyx.git/blob - src/LaTeXFeatures.cpp
Merge branch 'master' of git.lyx.org:lyx
[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 "Buffer.h"
20 #include "BufferParams.h"
21 #include "ColorSet.h"
22 #include "Converter.h"
23 #include "Encoding.h"
24 #include "Floating.h"
25 #include "FloatList.h"
26 #include "Language.h"
27 #include "LaTeXFonts.h"
28 #include "LaTeXPackages.h"
29 #include "Layout.h"
30 #include "Lexer.h"
31 #include "LyXRC.h"
32 #include "TextClass.h"
33
34 #include "insets/InsetLayout.h"
35
36 #include "support/debug.h"
37 #include "support/docstream.h"
38 #include "support/FileName.h"
39 #include "support/filetools.h"
40 #include "support/gettext.h"
41 #include "support/lstrings.h"
42 #include "support/regex.h"
43
44 #include <algorithm>
45
46
47 using namespace std;
48 using namespace lyx::support;
49
50
51 namespace lyx {
52
53 /////////////////////////////////////////////////////////////////////
54 //
55 // Strings
56 //
57 /////////////////////////////////////////////////////////////////////
58
59 //\NeedsTeXFormat{LaTeX2e}
60 //\ProvidesPackage{lyx}[1996/01/11 LLE v0.2 (LyX LaTeX Extensions)]
61 //\message{LyX LaTeX Extensions (LLE v0.2) of 11-Jan-1996.}
62
63 static docstring const lyx_def = from_ascii(
64         "\\providecommand{\\LyX}{L\\kern-.1667em\\lower.25em\\hbox{Y}\\kern-.125emX\\@}");
65
66 static docstring const lyx_hyperref_def = from_ascii(
67         "\\providecommand{\\LyX}{\\texorpdfstring%\n"
68         "  {L\\kern-.1667em\\lower.25em\\hbox{Y}\\kern-.125emX\\@}\n"
69         "  {LyX}}");
70
71 static docstring const noun_def = from_ascii(
72         "\\newcommand{\\noun}[1]{\\textsc{#1}}");
73
74 static docstring const lyxarrow_def = from_ascii(
75         "\\DeclareRobustCommand*{\\lyxarrow}{%\n"
76         "\\@ifstar\n"
77         "{\\leavevmode\\,$\\triangleleft$\\,\\allowbreak}\n"
78         "{\\leavevmode\\,$\\triangleright$\\,\\allowbreak}}");
79
80 // for quotes without babel. This does not give perfect results, but
81 // anybody serious about non-english quotes should use babel (JMarc).
82
83 static docstring const quotedblbase_def = from_ascii(
84         "\\ProvideTextCommandDefault{\\quotedblbase}{%\n"
85         "  \\raisebox{-1.4ex}[1ex][.5ex]{\\textquotedblright}%\n"
86         "  \\penalty10000\\hskip0em\\relax%\n"
87         "}");
88
89 static docstring const quotesinglbase_def = from_ascii(
90         "\\ProvideTextCommandDefault{\\quotesinglbase}{%\n"
91         "  \\raisebox{-1.4ex}[1ex][.5ex]{\\textquoteright}%\n"
92         "  \\penalty10000\\hskip0em\\relax%\n"
93         "}");
94
95 static docstring const guillemotleft_def = from_ascii(
96         "\\ProvideTextCommandDefault{\\guillemotleft}{%\n"
97         "  {\\usefont{U}{lasy}{m}{n}\\char'50\\kern-.15em\\char'50}%\n"
98         "\\penalty10000\\hskip0pt\\relax%\n"
99         "}");
100
101 static docstring const guillemotright_def = from_ascii(
102         "\\ProvideTextCommandDefault{\\guillemotright}{%\n"
103         "  \\penalty10000\\hskip0pt%\n"
104         "  {\\usefont{U}{lasy}{m}{n}\\char'51\\kern-.15em\\char'51}%\n"
105         "}");
106
107 static docstring const guilsinglleft_def = from_ascii(
108         "\\ProvideTextCommandDefault{\\guilsinglleft}{%\n"
109         "  {\\usefont{U}{lasy}{m}{n}\\char'50}%\n"
110         "  \\penalty10000\\hskip0pt\\relax%\n"
111         "}");
112
113 static docstring const guilsinglright_def = from_ascii(
114         "\\ProvideTextCommandDefault{\\guilsinglright}{%\n"
115         "  \\penalty10000\\hskip0pt%\n"
116         "  {\\usefont{U}{lasy}{m}{n}\\char'51}%\n"
117         "}");
118
119 static docstring const paragraphleftindent_def = from_ascii(
120         "\\newenvironment{LyXParagraphLeftIndent}[1]%\n"
121         "{\n"
122         "  \\begin{list}{}{%\n"
123         "    \\setlength{\\topsep}{0pt}%\n"
124         "    \\addtolength{\\leftmargin}{#1}\n"
125 // ho hum, yet more things commented out with no hint as to why they
126 // weren't just removed
127 //      "%%    \\addtolength{\\leftmargin}{#1\\textwidth}\n"
128 //      "%%    \\setlength{\\textwidth}{#2\\textwidth}\n"
129 //      "%%    \\setlength\\listparindent\\parindent%\n"
130 //      "%%    \\setlength\\itemindent\\parindent%\n"
131         "    \\setlength{\\parsep}{0pt plus 1pt}%\n"
132         "  }\n"
133         "  \\item[]\n"
134         "}\n"
135         "{\\end{list}}\n");
136
137 static docstring const floatingfootnote_def = from_ascii(
138         "%% Special footnote code from the package 'stblftnt.sty'\n"
139         "%% Author: Robin Fairbairns -- Last revised Dec 13 1996\n"
140         "\\let\\SF@@footnote\\footnote\n"
141         "\\def\\footnote{\\ifx\\protect\\@typeset@protect\n"
142         "    \\expandafter\\SF@@footnote\n"
143         "  \\else\n"
144         "    \\expandafter\\SF@gobble@opt\n"
145         "  \\fi\n"
146         "}\n"
147         "\\expandafter\\def\\csname SF@gobble@opt \\endcsname{\\@ifnextchar[%]\n"
148         "  \\SF@gobble@twobracket\n"
149         "  \\@gobble\n"
150         "}\n"
151         "\\edef\\SF@gobble@opt{\\noexpand\\protect\n"
152         "  \\expandafter\\noexpand\\csname SF@gobble@opt \\endcsname}\n"
153         "\\def\\SF@gobble@twobracket[#1]#2{}\n");
154
155 static docstring const binom_def = from_ascii(
156         "%% Binom macro for standard LaTeX users\n"
157         "\\newcommand{\\binom}[2]{{#1 \\choose #2}}\n");
158
159 static docstring const mathcircumflex_def = from_ascii(
160         "%% For printing a cirumflex inside a formula\n"
161         "\\newcommand{\\mathcircumflex}[0]{\\mbox{\\^{}}}\n");
162
163 static docstring const tabularnewline_def = from_ascii(
164         "%% Because html converters don't know tabularnewline\n"
165         "\\providecommand{\\tabularnewline}{\\\\}\n");
166
167 static docstring const lyxgreyedout_def = from_ascii(
168         "%% The greyedout annotation environment\n"
169         "\\newenvironment{lyxgreyedout}\n"
170         "  {\\textcolor{note_fontcolor}\\bgroup\\ignorespaces}\n"
171         "  {\\ignorespacesafterend\\egroup}\n");
172
173 // We want to omit the file extension for includegraphics, but this does not
174 // work when the filename contains other dots.
175 // Idea from http://www.tex.ac.uk/cgi-bin/texfaq2html?label=unkgrfextn
176 static docstring const lyxdot_def = from_ascii(
177         "%% A simple dot to overcome graphicx limitations\n"
178         "\\newcommand{\\lyxdot}{.}\n");
179
180 static docstring const changetracking_dvipost_def = from_ascii(
181         "%% Change tracking with dvipost\n"
182         "\\dvipostlayout\n"
183         "\\dvipost{osstart color push Red}\n"
184         "\\dvipost{osend color pop}\n"
185         "\\dvipost{cbstart color push Blue}\n"
186         "\\dvipost{cbend color pop}\n"
187         "\\DeclareRobustCommand{\\lyxadded}[3]{\\changestart#3\\changeend}\n"
188         "\\DeclareRobustCommand{\\lyxdeleted}[3]{%\n"
189         "\\changestart\\overstrikeon#3\\overstrikeoff\\changeend}\n");
190
191 static docstring const changetracking_xcolor_ulem_def = from_ascii(
192         "%% Change tracking with ulem\n"
193         "\\DeclareRobustCommand{\\lyxadded}[3]{{\\color{lyxadded}{}#3}}\n"
194         "\\DeclareRobustCommand{\\lyxdeleted}[3]{{\\color{lyxdeleted}\\sout{#3}}}\n");
195
196 static docstring const changetracking_xcolor_ulem_hyperref_def = from_ascii(
197         "%% Change tracking with ulem\n"
198         "\\DeclareRobustCommand{\\lyxadded}[3]{{\\texorpdfstring{\\color{lyxadded}{}}{}#3}}\n"
199         "\\DeclareRobustCommand{\\lyxdeleted}[3]{{\\texorpdfstring{\\color{lyxdeleted}\\sout{#3}}{}}}\n");
200
201 static docstring const changetracking_none_def = from_ascii(
202         "\\newcommand{\\lyxadded}[3]{#3}\n"
203         "\\newcommand{\\lyxdeleted}[3]{}\n");
204
205 static docstring const textgreek_LGR_def = from_ascii(
206         "\\DeclareFontEncoding{LGR}{}{}\n");
207 static docstring const textgreek_def = from_ascii(
208         "\\DeclareRobustCommand{\\greektext}{%\n"
209         "  \\fontencoding{LGR}\\selectfont\\def\\encodingdefault{LGR}}\n"
210         "\\DeclareRobustCommand{\\textgreek}[1]{\\leavevmode{\\greektext #1}}\n"
211         "\\ProvideTextCommand{\\~}{LGR}[1]{\\char126#1}\n");
212
213 static docstring const textcyr_T2A_def = from_ascii(
214         "\\InputIfFileExists{t2aenc.def}{}{%\n"
215         "  \\errmessage{File `t2aenc.def' not found: Cyrillic script not supported}}\n");
216 static docstring const textcyr_def = from_ascii(
217         "\\DeclareRobustCommand{\\cyrtext}{%\n"
218         "  \\fontencoding{T2A}\\selectfont\\def\\encodingdefault{T2A}}\n"
219         "\\DeclareRobustCommand{\\textcyr}[1]{\\leavevmode{\\cyrtext #1}}\n");
220
221 static docstring const lyxmathsym_def = from_ascii(
222         "\\newcommand{\\lyxmathsym}[1]{\\ifmmode\\begingroup\\def\\b@ld{bold}\n"
223         "  \\text{\\ifx\\math@version\\b@ld\\bfseries\\fi#1}\\endgroup\\else#1\\fi}\n");
224
225 static docstring const papersizedvi_def = from_ascii(
226         "\\special{papersize=\\the\\paperwidth,\\the\\paperheight}\n");
227
228 static docstring const papersizepdf_def = from_ascii(
229         "\\pdfpageheight\\paperheight\n"
230         "\\pdfpagewidth\\paperwidth\n");
231
232 static docstring const cedilla_def = from_ascii(
233         "\\newcommand{\\docedilla}[2]{\\underaccent{#1\\mathchar'30}{#2}}\n"
234         "\\newcommand{\\cedilla}[1]{\\mathpalette\\docedilla{#1}}\n");
235
236 static docstring const subring_def = from_ascii(
237         "\\newcommand{\\dosubring}[2]{\\underaccent{#1\\mathchar'27}{#2}}\n"
238         "\\newcommand{\\subring}[1]{\\mathpalette\\dosubring{#1}}\n");
239
240 static docstring const subdot_def = from_ascii(
241         "\\newcommand{\\dosubdot}[2]{\\underaccent{#1.}{#2}}\n"
242         "\\newcommand{\\subdot}[1]{\\mathpalette\\dosubdot{#1}}\n");
243
244 static docstring const subhat_def = from_ascii(
245         "\\newcommand{\\dosubhat}[2]{\\underaccent{#1\\mathchar'136}{#2}}\n"
246         "\\newcommand{\\subhat}[1]{\\mathpalette\\dosubhat{#1}}\n");
247
248 static docstring const subtilde_def = from_ascii(
249         "\\newcommand{\\dosubtilde}[2]{\\underaccent{#1\\mathchar'176}{#2}}\n"
250         "\\newcommand{\\subtilde}[1]{\\mathpalette\\dosubtilde{#1}}\n");
251
252 static docstring const dacute_def = from_ascii(
253         "\\DeclareMathAccent{\\dacute}{\\mathalpha}{operators}{'175}\n");
254
255 static docstring const tipasymb_def = from_ascii(
256         "\\DeclareFontEncoding{T3}{}{}\n"
257         "\\DeclareSymbolFont{tipasymb}{T3}{cmr}{m}{n}\n");
258
259 static docstring const dgrave_def = from_ascii(
260         "\\DeclareMathAccent{\\dgrave}{\\mathord}{tipasymb}{'15}\n");
261
262 static docstring const rcap_def = from_ascii(
263         "\\DeclareMathAccent{\\rcap}{\\mathord}{tipasymb}{'20}\n");
264
265 static docstring const ogonek_def = from_ascii(
266         "\\newcommand{\\doogonek}[2]{\\setbox0=\\hbox{$#1#2$}\\underaccent{#1\\mkern-6mu\n"
267         "  \\ifx#2O\\hskip0.5\\wd0\\else\\ifx#2U\\hskip0.5\\wd0\\else\\hskip\\wd0\\fi\\fi\n"
268         "  \\ifx#2o\\mkern-2mu\\else\\ifx#2e\\mkern-1mu\\fi\\fi\n"
269         "  \\mathchar\"0\\hexnumber@\\symtipasymb0C}{#2}}\n"
270         "\\newcommand{\\ogonek}[1]{\\mathpalette\\doogonek{#1}}\n");
271
272 static docstring const lyxaccent_def = from_ascii(
273         "%% custom text accent \\LyxTextAccent[<rise value (length)>]{<accent>}{<base>}\n"
274         "\\newcommand*{\\LyxTextAccent}[3][0ex]{%\n"
275         "  \\hmode@bgroup\\ooalign{\\null#3\\crcr\\hidewidth\n"
276         "  \\raise#1\\hbox{#2}\\hidewidth}\\egroup}\n"
277         "%% select a font size smaller than the current font size:\n"
278         "\\newcommand{\\LyxAccentSize}[1][\\sf@size]{%\n"
279         "  \\check@mathfonts\\fontsize#1\\z@\\math@fontsfalse\\selectfont\n"
280         "}\n");
281
282 static docstring const textcommabelow_def = from_ascii(
283         "\\ProvideTextCommandDefault{\\textcommabelow}[1]{%%\n"
284         "  \\LyxTextAccent[-.31ex]{\\LyxAccentSize,}{#1}}\n");
285
286 static docstring const textcommaabove_def = from_ascii(
287         "\\ProvideTextCommandDefault{\\textcommaabove}[1]{%%\n"
288         "  \\LyxTextAccent[.5ex]{\\LyxAccentSize`}{#1}}\n");
289
290 static docstring const textcommaaboveright_def = from_ascii(
291         "\\ProvideTextCommandDefault{\\textcommaaboveright}[1]{%%\n"
292         "  \\LyxTextAccent[.5ex]{\\LyxAccentSize\\ `}{#1}}\n");
293
294 // Baltic languages use a comma-accent instead of a cedilla
295 static docstring const textbaltic_def = from_ascii(
296         "%% use comma accent instead of cedilla for these characters:\n"
297         "\\DeclareTextCompositeCommand{\\c}{T1}{g}{\\textcommaabove{g}}\n"
298         "\\DeclareTextCompositeCommand{\\c}{T1}{G}{\\textcommabelow{G}}\n"
299         "\\DeclareTextCompositeCommand{\\c}{T1}{k}{\\textcommabelow{k}}\n"
300         "\\DeclareTextCompositeCommand{\\c}{T1}{K}{\\textcommabelow{K}}\n"
301         "\\DeclareTextCompositeCommand{\\c}{T1}{l}{\\textcommabelow{l}}\n"
302         "\\DeclareTextCompositeCommand{\\c}{T1}{L}{\\textcommabelow{L}}\n"
303         "\\DeclareTextCompositeCommand{\\c}{T1}{n}{\\textcommabelow{n}}\n"
304         "\\DeclareTextCompositeCommand{\\c}{T1}{N}{\\textcommabelow{N}}\n"
305         "\\DeclareTextCompositeCommand{\\c}{T1}{r}{\\textcommabelow{r}}\n"
306         "\\DeclareTextCompositeCommand{\\c}{T1}{R}{\\textcommabelow{R}}\n");
307
308 static docstring const lyxref_def = from_ascii(
309                 "\\RS@ifundefined{subsecref}\n"
310                 "  {\\newref{subsec}{name = \\RSsectxt}}\n"
311                 "  {}\n"
312                 "\\RS@ifundefined{thmref}\n"
313                 "  {\\def\\RSthmtxt{theorem~}\\newref{thm}{name = \\RSthmtxt}}\n"
314                 "  {}\n"
315                 "\\RS@ifundefined{lemref}\n"
316                 "  {\\def\\RSlemtxt{lemma~}\\newref{lem}{name = \\RSlemtxt}}\n"
317                 "  {}\n");
318
319 // Make sure the columns are also outputed as rtl
320 static docstring const rtloutputdblcol_def = from_ascii(
321         "\\def\\@outputdblcol{%\n"
322         "  \\if@firstcolumn\n"
323         "    \\global \\@firstcolumnfalse\n"
324         "    \\global \\setbox\\@leftcolumn \\box\\@outputbox\n"
325         "  \\else\n"
326         "    \\global \\@firstcolumntrue\n"
327         "    \\setbox\\@outputbox \\vbox {%\n"
328         "      \\hb@xt@\\textwidth {%\n"
329         "      \\kern\\textwidth \\kern-\\columnwidth %**\n"
330         "      \\hb@xt@\\columnwidth {%\n"
331         "         \\box\\@leftcolumn \\hss}%\n"
332         "      \\kern-\\textwidth %**\n"
333         "      \\hfil\n"
334         "      {\\normalcolor\\vrule \\@width\\columnseprule}%\n"
335         "      \\hfil\n"
336         "      \\kern-\\textwidth  %**\n"
337         "      \\hb@xt@\\columnwidth {%\n"
338         "         \\box\\@outputbox \\hss}%\n"
339         "      \\kern-\\columnwidth \\kern\\textwidth %**\n"
340         "    }%\n"
341         "  }%\n"
342         "  \\@combinedblfloats\n"
343         "  \\@outputpage\n"
344         "  \\begingroup\n"
345         "  \\@dblfloatplacement\n"
346         "  \\@startdblcolumn\n"
347         "  \\@whilesw\\if@fcolmade \\fi\n"
348         "  {\\@outputpage\n"
349         "    \\@startdblcolumn}%\n"
350         "  \\endgroup\n"
351         "  \\fi\n"
352         "}\n"
353         "\\@mparswitchtrue\n");
354
355
356 /////////////////////////////////////////////////////////////////////
357 //
358 // LyXHTML strings
359 //
360 /////////////////////////////////////////////////////////////////////
361
362 static docstring const lyxnoun_style = from_ascii(
363         "dfn.lyxnoun {\n"
364         "  font-variant: small-caps;\n"
365         "}\n");
366
367
368 // this is how it normally renders, but it might not always do so.
369 static docstring const lyxstrikeout_style = from_ascii(
370         "del.strikeout {\n"
371         "  text-decoration: line-through;\n"
372         "}\n");
373
374
375 /////////////////////////////////////////////////////////////////////
376 //
377 // LaTeXFeatures
378 //
379 /////////////////////////////////////////////////////////////////////
380
381
382 LaTeXFeatures::LaTeXFeatures(Buffer const & b, BufferParams const & p,
383                              OutputParams const & r)
384         : buffer_(&b), params_(p), runparams_(r), in_float_(false)
385 {}
386
387
388 LaTeXFeatures::LangPackage LaTeXFeatures::langPackage() const
389 {
390         string const local_lp = bufferParams().lang_package;
391
392         // Locally, custom is just stored as a string
393         // in bufferParams().lang_package.
394         if (local_lp != "auto"
395             && local_lp != "babel"
396             && local_lp != "default"
397             && local_lp != "none")
398                  return LANG_PACK_CUSTOM;
399
400         if (local_lp == "none")
401                 return LANG_PACK_NONE;
402
403         /* If "auto" is selected, we load polyglossia with non-TeX fonts,
404          * else we select babel.
405          * If babel is selected (either directly or via the "auto"
406          * mechanism), we really do only require it if we have
407          * a language that needs it.
408          */
409         bool const polyglossia_required =
410                 params_.useNonTeXFonts
411                 && isAvailable("polyglossia")
412                 && !isProvided("babel")
413                 && this->hasOnlyPolyglossiaLanguages();
414         bool const babel_required =
415                 !bufferParams().language->babel().empty()
416                 || !this->getBabelLanguages().empty();
417
418         if (local_lp == "auto") {
419                 // polyglossia requirement has priority over babel
420                 if (polyglossia_required)
421                         return LANG_PACK_POLYGLOSSIA;
422                 else if (babel_required)
423                         return LANG_PACK_BABEL;
424         }
425
426         if (local_lp == "babel") {
427                 if (babel_required)
428                         return LANG_PACK_BABEL;
429         }
430
431         if (local_lp == "default") {
432                 switch (lyxrc.language_package_selection) {
433                 case LyXRC::LP_AUTO:
434                         // polyglossia requirement has priority over babel
435                         if (polyglossia_required)
436                                 return LANG_PACK_POLYGLOSSIA;
437                         else if (babel_required)
438                                 return LANG_PACK_BABEL;
439                         break;
440                 case LyXRC::LP_BABEL:
441                         if (babel_required)
442                                 return LANG_PACK_BABEL;
443                         break;
444                 case LyXRC::LP_CUSTOM:
445                         return LANG_PACK_CUSTOM;
446                 case LyXRC::LP_NONE:
447                         return LANG_PACK_NONE;
448                 }
449         }
450
451         return LANG_PACK_NONE;
452 }
453
454
455 void LaTeXFeatures::require(string const & name)
456 {
457         features_.insert(name);
458 }
459
460
461 void LaTeXFeatures::require(set<string> const & names)
462 {
463         features_.insert(names.begin(), names.end());
464 }
465
466
467 void LaTeXFeatures::useLayout(docstring const & layoutname)
468 {
469         useLayout(layoutname, 0);
470 }
471
472
473 void LaTeXFeatures::useLayout(docstring const & layoutname, int level)
474 {
475         // Some code to avoid loops in dependency definition
476         const int maxlevel = 30;
477         if (level > maxlevel) {
478                 lyxerr << "LaTeXFeatures::useLayout: maximum level of "
479                        << "recursion attained by layout "
480                        << to_utf8(layoutname) << endl;
481                 return;
482         }
483
484         DocumentClass const & tclass = params_.documentClass();
485         if (tclass.hasLayout(layoutname)) {
486                 // Is this layout already in usedLayouts?
487                 if (find(usedLayouts_.begin(), usedLayouts_.end(), layoutname)
488                     != usedLayouts_.end())
489                         return;
490
491                 Layout const & layout = tclass[layoutname];
492                 require(layout.requires());
493
494                 if (!layout.depends_on().empty()) {
495                         useLayout(layout.depends_on(), level + 1);
496                 }
497                 usedLayouts_.push_back(layoutname);
498         } else {
499                 lyxerr << "LaTeXFeatures::useLayout: layout `"
500                        << to_utf8(layoutname) << "' does not exist in this class"
501                        << endl;
502         }
503 }
504
505
506 void LaTeXFeatures::useInsetLayout(InsetLayout const & lay)
507 {
508         docstring const & lname = lay.name();
509         DocumentClass const & tclass = params_.documentClass();
510
511         // this is a default inset layout, nothing useful here
512         if (!tclass.hasInsetLayout(lname))
513                 return;
514         // Is this layout already in usedInsetLayouts?
515         if (find(usedInsetLayouts_.begin(), usedInsetLayouts_.end(), lname)
516                         != usedInsetLayouts_.end())
517                 return;
518
519         require(lay.requires());
520         usedInsetLayouts_.push_back(lname);
521 }
522
523
524 bool LaTeXFeatures::isRequired(string const & name) const
525 {
526         return features_.find(name) != features_.end();
527 }
528
529
530 bool LaTeXFeatures::isProvided(string const & name) const
531 {
532         if (params_.useNonTeXFonts)
533                 return params_.documentClass().provides(name);
534
535         bool const ot1 = (params_.font_encoding() == "default"
536                 || params_.font_encoding() == "OT1");
537         bool const complete = (params_.fontsSans() == "default"
538                 && params_.fontsTypewriter() == "default");
539         bool const nomath = (params_.fontsMath() == "default");
540         return params_.documentClass().provides(name)
541                 || theLaTeXFonts().getLaTeXFont(
542                         from_ascii(params_.fontsRoman())).provides(name, ot1,
543                                                                   complete,
544                                                                   nomath)
545                 || theLaTeXFonts().getLaTeXFont(
546                         from_ascii(params_.fontsSans())).provides(name, ot1,
547                                                                  complete,
548                                                                  nomath)
549                 || theLaTeXFonts().getLaTeXFont(
550                         from_ascii(params_.fontsTypewriter())).provides(name, ot1,
551                                                                        complete,
552                                                                        nomath)
553                 || theLaTeXFonts().getLaTeXFont(
554                         from_ascii(params_.fontsMath())).provides(name, ot1,
555                                                                        complete,
556                                                                        nomath);
557         // TODO: "textbaltic" provided, if the font-encoding is "L7x"
558         //       "textgreek" provided, if a language with font-encoding LGR is used in the document
559         //       "textcyr" provided, if a language with font-encoding T2A is used in the document
560 }
561
562
563 bool LaTeXFeatures::mustProvide(string const & name) const
564 {
565         return isRequired(name) && !isProvided(name);
566 }
567
568
569 bool LaTeXFeatures::isAvailable(string const & name)
570 {
571         string::size_type const i = name.find("->");
572         if (i != string::npos) {
573                 string const from = name.substr(0,i);
574                 string const to = name.substr(i+2);
575                 //LYXERR0("from=[" << from << "] to=[" << to << "]");
576                 return theConverters().isReachable(from, to);
577         }
578         return LaTeXPackages::isAvailable(name);
579 }
580
581
582 void LaTeXFeatures::addPreambleSnippet(string const & preamble,
583                 bool allowdupes)
584 {
585         SnippetList::const_iterator begin = preamble_snippets_.begin();
586         SnippetList::const_iterator end   = preamble_snippets_.end();
587         if (allowdupes || find(begin, end, preamble) == end)
588                 preamble_snippets_.push_back(preamble);
589 }
590
591
592 void LaTeXFeatures::addCSSSnippet(std::string const & snippet)
593 {
594         SnippetList::const_iterator begin = css_snippets_.begin();
595         SnippetList::const_iterator end   = css_snippets_.end();
596         if (find(begin, end, snippet) == end)
597                 css_snippets_.push_back(snippet);
598 }
599
600
601 void LaTeXFeatures::useFloat(string const & name, bool subfloat)
602 {
603         if (!usedFloats_[name])
604                 usedFloats_[name] = subfloat;
605         if (subfloat)
606                 require("subfig");
607         // We only need float.sty if we use non builtin floats, or if we
608         // use the "H" modifier. This includes modified table and
609         // figure floats. (Lgb)
610         Floating const & fl = params_.documentClass().floats().getType(name);
611         if (!fl.floattype().empty() && fl.usesFloatPkg()) {
612                 require("float");
613         }
614 }
615
616
617 void LaTeXFeatures::useLanguage(Language const * lang)
618 {
619         if (!lang->babel().empty() || !lang->polyglossia().empty())
620                 UsedLanguages_.insert(lang);
621         if (!lang->requires().empty())
622                 require(lang->requires());
623         // CJK languages do not have a babel name.
624         // They use the CJK package
625         if (lang->encoding()->package() == Encoding::CJK)
626                 require("CJK");
627         // japanese package is special
628         if (lang->encoding()->package() == Encoding::japanese)
629                 require("japanese");
630 }
631
632
633 void LaTeXFeatures::includeFile(docstring const & key, string const & name)
634 {
635         IncludedFiles_[key] = name;
636 }
637
638
639 bool LaTeXFeatures::hasLanguages() const
640 {
641         return !UsedLanguages_.empty();
642 }
643
644
645 bool LaTeXFeatures::hasOnlyPolyglossiaLanguages() const
646 {
647         // first the main language
648         if (params_.language->polyglossia().empty())
649                 return false;
650         // now the secondary languages
651         LanguageList::const_iterator const begin = UsedLanguages_.begin();
652         for (LanguageList::const_iterator cit = begin;
653              cit != UsedLanguages_.end();
654              ++cit) {
655                 if ((*cit)->polyglossia().empty())
656                         return false;
657         }
658         return true;
659 }
660
661
662 bool LaTeXFeatures::hasPolyglossiaExclusiveLanguages() const
663 {
664         // first the main language
665         if (params_.language->isPolyglossiaExclusive())
666                 return true;
667         // now the secondary languages
668         LanguageList::const_iterator const begin = UsedLanguages_.begin();
669         for (LanguageList::const_iterator cit = begin;
670              cit != UsedLanguages_.end();
671              ++cit) {
672                 if ((*cit)->isPolyglossiaExclusive())
673                         return true;
674         }
675         return false;
676 }
677
678
679 string LaTeXFeatures::getBabelLanguages() const
680 {
681         ostringstream languages;
682
683         bool first = true;
684         LanguageList::const_iterator const begin = UsedLanguages_.begin();
685         for (LanguageList::const_iterator cit = begin;
686              cit != UsedLanguages_.end();
687              ++cit) {
688                 if ((*cit)->babel().empty())
689                         continue;
690                 if (!first)
691                         languages << ',';
692                 else
693                         first = false;
694                 languages << (*cit)->babel();
695         }
696         return languages.str();
697 }
698
699
700 std::map<std::string, std::string> LaTeXFeatures::getPolyglossiaLanguages() const
701 {
702         std::map<std::string, std::string> languages;
703
704         LanguageList::const_iterator const begin = UsedLanguages_.begin();
705         for (LanguageList::const_iterator cit = begin;
706              cit != UsedLanguages_.end();
707              ++cit) {
708                 languages[(*cit)->polyglossia()] = (*cit)->polyglossiaOpts();
709         }
710         return languages;
711 }
712
713
714 set<string> LaTeXFeatures::getEncodingSet(string const & doc_encoding) const
715 {
716         // This does only find encodings of languages supported by babel, but
717         // that does not matter since we don't have a language with an
718         // encoding supported by inputenc but without babel support.
719         set<string> encodings;
720         LanguageList::const_iterator it  = UsedLanguages_.begin();
721         LanguageList::const_iterator end = UsedLanguages_.end();
722         for (; it != end; ++it)
723                 if ((*it)->encoding()->latexName() != doc_encoding &&
724                     ((*it)->encoding()->package() == Encoding::inputenc
725                      || (*it)->encoding()->package() == Encoding::japanese))
726                         encodings.insert((*it)->encoding()->latexName());
727         return encodings;
728 }
729
730
731 void LaTeXFeatures::getFontEncodings(vector<string> & encodings) const
732 {
733         // these must be loaded if glyphs of this script are used
734         // unless a language providing them is used in the document
735         // FIXME: currently the option is written twice in this case
736         if (mustProvide("textgreek"))
737                 encodings.insert(encodings.begin(), "LGR");
738         if (mustProvide("textcyr"))
739                 encodings.insert(encodings.begin(), "T2A");
740
741         LanguageList::const_iterator it  = UsedLanguages_.begin();
742         LanguageList::const_iterator end = UsedLanguages_.end();
743         for (; it != end; ++it)
744                 if (!(*it)->fontenc().empty()
745                     && ascii_lowercase((*it)->fontenc()) != "none") {
746                         vector<string> extraencs = getVectorFromString((*it)->fontenc());
747                         vector<string>::const_iterator fit = extraencs.begin();
748                         for (; fit != extraencs.end(); ++fit) {
749                                 if (find(encodings.begin(), encodings.end(), *fit) == encodings.end())
750                                         encodings.insert(encodings.begin(), *fit);
751                         }
752                 }
753 }
754
755 namespace {
756
757 char const * simplefeatures[] = {
758 // note that the package order here will be the same in the LaTeX-output
759         "array",
760         "verbatim",
761         "longtable",
762         "rotating",
763         "latexsym",
764         "pifont",
765         // subfig is handled in BufferParams.cpp
766         "varioref",
767         "prettyref",
768         "refstyle",
769         /*For a successful cooperation of the `wrapfig' package with the
770           `float' package you should load the `wrapfig' package *after*
771           the `float' package. See the caption package documentation
772           for explanation.*/
773         "float",
774         "rotfloat",
775         "wrapfig",
776         "booktabs",
777         "dvipost",
778         "fancybox",
779         "calc",
780         "units",
781         "framed",
782         "soul",
783         "textcomp",
784         "pmboxdraw",
785         "bbding",
786         "ifsym",
787         "txfonts",
788         "pxfonts",
789         "mathdesign",
790         "mathrsfs",
791         "mathabx",
792         "mathtools",
793         // "cancel",
794         "ascii",
795         "url",
796         "covington",
797         "csquotes",
798         "enumitem",
799         "endnotes",
800         "hhline",
801         "ifthen",
802         // listings is handled in BufferParams.cpp
803         "bm",
804         "pdfpages",
805         "amscd",
806         "slashed",
807         "multicol",
808         "multirow",
809         "tfrupee",
810         "shapepar",
811         "rsphrase",
812         "hpstatement",
813         "algorithm2e",
814         "sectionbox",
815         "tcolorbox",
816         "pdfcomment",
817         "fixme",
818         "todonotes",
819         "forest",
820         "varwidth"
821 };
822
823 char const * bibliofeatures[] = {
824         // Known bibliography packages (will be loaded before natbib)
825         "achicago",
826         "apacite",
827         "apalike",
828         "astron",
829         "authordate1-4",
830         "babelbib",
831         "bibgerm",
832         "chicago",
833         "chscite",
834         "harvard",
835         "mslapa",
836         "named"
837 };
838
839 int const nb_bibliofeatures = sizeof(bibliofeatures) / sizeof(char const *);
840
841 int const nb_simplefeatures = sizeof(simplefeatures) / sizeof(char const *);
842
843 }
844
845
846 string const LaTeXFeatures::getColorOptions() const
847 {
848         ostringstream colors;
849
850         // Handling the color packages separately is needed to be able to load them
851         // before babel when hyperref is loaded with the colorlinks option
852         // for more info see Bufferparams.cpp
853
854         // [x]color.sty
855         if (mustProvide("color") || mustProvide("xcolor")) {
856                 string const package =
857                         (mustProvide("xcolor") ? "xcolor" : "color");
858                 if (params_.graphics_driver == "default"
859                         || params_.graphics_driver == "none")
860                         colors << "\\usepackage{" << package << "}\n";
861                 else
862                         colors << "\\usepackage["
863                                  << params_.graphics_driver
864                                  << "]{" << package << "}\n";
865         }
866
867         // pdfcolmk must be loaded after color
868         if (mustProvide("pdfcolmk"))
869                 colors << "\\usepackage{pdfcolmk}\n";
870
871         // the following 3 color commands must be set after color
872         // is loaded and before pdfpages, therefore add the command
873         // here define the set color
874         if (mustProvide("pagecolor")) {
875                 colors << "\\definecolor{page_backgroundcolor}{rgb}{";
876                 colors << outputLaTeXColor(params_.backgroundcolor) << "}\n";
877                 // set the page color
878                 colors << "\\pagecolor{page_backgroundcolor}\n";
879         }
880
881         if (mustProvide("fontcolor")) {
882                 colors << "\\definecolor{document_fontcolor}{rgb}{";
883                 colors << outputLaTeXColor(params_.fontcolor) << "}\n";
884                 // set the color
885                 colors << "\\color{document_fontcolor}\n";
886         }
887
888         if (mustProvide("lyxgreyedout")) {
889                 colors << "\\definecolor{note_fontcolor}{rgb}{";
890                 colors << outputLaTeXColor(params_.notefontcolor) << "}\n";
891                 // the color will be set together with the definition of
892                 // the lyxgreyedout environment (see lyxgreyedout_def)
893         }
894
895         // color for shaded boxes
896         if (isRequired("framed") && mustProvide("color")) {
897                 colors << "\\definecolor{shadecolor}{rgb}{";
898                 colors << outputLaTeXColor(params_.boxbgcolor) << "}\n";
899                 // this color is automatically used by the LaTeX-package "framed"
900         }
901
902         return colors.str();
903 }
904
905
906 string const LaTeXFeatures::getPackageOptions() const
907 {
908         ostringstream packageopts;
909         // Output all the package option stuff we have been asked to do.
910         map<string, string>::const_iterator it =
911                 params_.documentClass().packageOptions().begin();
912         map<string, string>::const_iterator en =
913                 params_.documentClass().packageOptions().end();
914         for (; it != en; ++it)
915                 if (mustProvide(it->first))
916                         packageopts << "\\PassOptionsToPackage{" << it->second << "}"
917                                  << "{" << it->first << "}\n";
918         return packageopts.str();
919 }
920
921
922 string const LaTeXFeatures::getPackages() const
923 {
924         ostringstream packages;
925
926         // FIXME: currently, we can only load packages and macros known
927         // to LyX.
928         // However, with the Require tag of layouts/custom insets,
929         // also unknown packages can be requested. They are silently
930         // swallowed now. We should change this eventually.
931
932         //  These are all the 'simple' includes.  i.e
933         //  packages which we just \usepackage{package}
934         for (int i = 0; i < nb_simplefeatures; ++i) {
935                 if (mustProvide(simplefeatures[i]))
936                         packages << "\\usepackage{" << simplefeatures[i] << "}\n";
937         }
938
939         // The rest of these packages are somewhat more complicated
940         // than those above.
941
942         // The tipa package and its extensions (tipx, tone) must not
943         // be loaded with non-TeX fonts, since fontspec includes the
944         // respective macros
945         if (mustProvide("tipa") && !params_.useNonTeXFonts)
946                 packages << "\\usepackage{tipa}\n";
947         if (mustProvide("tipx") && !params_.useNonTeXFonts)
948                 packages << "\\usepackage{tipx}\n";
949         if (mustProvide("tone") && !params_.useNonTeXFonts)
950                 packages << "\\usepackage{tone}\n";
951
952         // if fontspec or newtxmath is used, AMS packages have to be loaded
953         // before fontspec (in BufferParams)
954         string const amsPackages = loadAMSPackages();
955         bool const ot1 = (params_.font_encoding() == "default" || params_.font_encoding() == "OT1");
956         bool const use_newtxmath =
957                 theLaTeXFonts().getLaTeXFont(from_ascii(params_.fontsMath())).getUsedPackage(
958                         ot1, false, false) == "newtxmath";
959
960         if (!params_.useNonTeXFonts && !use_newtxmath && !amsPackages.empty())
961                 packages << amsPackages;
962
963         if (mustProvide("cancel") &&
964             params_.use_package("cancel") != BufferParams::package_off)
965                 packages << "\\usepackage{cancel}\n";
966
967         // marvosym and bbding both define the \Cross macro
968         if (mustProvide("marvosym")) {
969             if (mustProvide("bbding"))
970                 packages << "\\let\\Cross\\relax\n";
971             packages << "\\usepackage{marvosym}\n";
972         }
973
974         // accents must be loaded after amsmath
975         if (mustProvide("accents") &&
976             params_.use_package("accents") != BufferParams::package_off)
977                 packages << "\\usepackage{accents}\n";
978
979         // mathdots must be loaded after amsmath
980         if (mustProvide("mathdots") &&
981                 params_.use_package("mathdots") != BufferParams::package_off)
982                 packages << "\\usepackage{mathdots}\n";
983
984         // yhmath must be loaded after amsmath
985         if (mustProvide("yhmath") &&
986             params_.use_package("yhmath") != BufferParams::package_off)
987                 packages << "\\usepackage{yhmath}\n";
988
989         // stmaryrd must be loaded after amsmath
990         if (mustProvide("stmaryrd") &&
991             params_.use_package("stmaryrd") != BufferParams::package_off)
992                 packages << "\\usepackage{stmaryrd}\n";
993
994         if (mustProvide("stackrel") &&
995             params_.use_package("stackrel") != BufferParams::package_off)
996                 packages << "\\usepackage{stackrel}\n";
997
998         if (mustProvide("undertilde") &&
999                 params_.use_package("undertilde") != BufferParams::package_off)
1000                 packages << "\\usepackage{undertilde}\n";
1001
1002         // [x]color and pdfcolmk are handled in getColorOptions() above
1003
1004         // makeidx.sty
1005         if (isRequired("makeidx") || isRequired("splitidx")) {
1006                 if (!isProvided("makeidx") && !isRequired("splitidx"))
1007                         packages << "\\usepackage{makeidx}\n";
1008                 if (mustProvide("splitidx"))
1009                         packages << "\\usepackage{splitidx}\n";
1010                 packages << "\\makeindex\n";
1011         }
1012
1013         // graphicx.sty
1014         if (mustProvide("graphicx") && params_.graphics_driver != "none") {
1015                 if (params_.graphics_driver == "default")
1016                         packages << "\\usepackage{graphicx}\n";
1017                 else
1018                         packages << "\\usepackage["
1019                                  << params_.graphics_driver
1020                                  << "]{graphicx}\n";
1021         }
1022
1023         // lyxskak.sty --- newer chess support based on skak.sty
1024         if (mustProvide("chess"))
1025                 packages << "\\usepackage[ps,mover]{lyxskak}\n";
1026
1027         // setspace.sty
1028         if (mustProvide("setspace") && !isProvided("SetSpace"))
1029                 packages << "\\usepackage{setspace}\n";
1030
1031         // we need to assure that mhchem is loaded before esint and every other
1032         // package that redefines command of amsmath because mhchem loads amlatex
1033         // (this info is from the author of mhchem from June 2013)
1034         if (mustProvide("mhchem") &&
1035             params_.use_package("mhchem") != BufferParams::package_off)
1036                 packages << "\\PassOptionsToPackage{version=3}{mhchem}\n"
1037                             "\\usepackage{mhchem}\n";
1038
1039         // wasysym is a simple feature, but it must be after amsmath if both
1040         // are used
1041         // wasysym redefines some integrals (e.g. iint) from amsmath. That
1042         // leads to inconsistent integrals. We only load this package if
1043         // the document does not contain integrals (then isRequired("esint")
1044         // is false) or if esint is used, since esint redefines all relevant
1045         // integral symbols from wasysym and amsmath.
1046         // See http://www.lyx.org/trac/ticket/1942
1047         if (mustProvide("wasysym") &&
1048             params_.use_package("wasysym") != BufferParams::package_off &&
1049             (params_.use_package("esint") != BufferParams::package_off || !isRequired("esint")))
1050                 packages << "\\usepackage{wasysym}\n";
1051
1052         // esint must be after amsmath (and packages requiring amsmath, like mhchem)
1053         // and wasysym, since it will redeclare inconsistent integral symbols
1054         if (mustProvide("esint") &&
1055             params_.use_package("esint") != BufferParams::package_off)
1056                 packages << "\\usepackage{esint}\n";
1057
1058         // Known bibliography packages (simple \usepackage{package})
1059         for (int i = 0; i < nb_bibliofeatures; ++i) {
1060                 if (mustProvide(bibliofeatures[i]))
1061                         packages << "\\usepackage{"
1062                                  << bibliofeatures[i] << "}\n";
1063         }
1064
1065         // Compatibility between achicago and natbib
1066         if (mustProvide("achicago") && mustProvide("natbib"))
1067                 packages << "\\let\\achicagobib\\thebibliography\n";
1068
1069         // natbib.sty
1070         // Some classes load natbib themselves, but still allow (or even require)
1071         // plain numeric citations (ReVTeX is such a case, see bug 5182).
1072         // This special case is indicated by the "natbib-internal" key.
1073         if (mustProvide("natbib") && !isProvided("natbib-internal")) {
1074                 packages << "\\usepackage[";
1075                 if (params_.citeEngineType() == ENGINE_TYPE_NUMERICAL)
1076                         packages << "numbers";
1077                 else
1078                         packages << "authoryear";
1079                 packages << "]{natbib}\n";
1080         }
1081
1082         // Compatibility between achicago and natbib
1083         if (mustProvide("achicago") && mustProvide("natbib")) {
1084                 packages << "\\let\\thebibliography\\achicagobib\n";
1085                 packages << "\\let\\SCcite\\astroncite\n";
1086                 packages << "\\let\\UnexpandableProtect\\protect\n";
1087         }
1088
1089         // jurabib -- we need version 0.6 at least.
1090         if (mustProvide("jurabib"))
1091                 packages << "\\usepackage{jurabib}[2004/01/25]\n";
1092
1093         // opcit -- we pass custombst as we output \bibliographystyle ourselves
1094         if (mustProvide("opcit")) {
1095                 if (isRequired("hyperref"))
1096                         packages << "\\usepackage[custombst,hyperref]{opcit}\n";
1097                 else
1098                         packages << "\\usepackage[custombst]{opcit}\n";
1099         }
1100
1101         // xargs -- we need version 1.09 at least
1102         if (mustProvide("xargs"))
1103                 packages << "\\usepackage{xargs}[2008/03/08]\n";
1104
1105         if (mustProvide("xy"))
1106                 packages << "\\usepackage[all]{xy}\n";
1107
1108         if (mustProvide("feyn"))
1109                 packages << "\\usepackage{feyn}\n"; //Diagram
1110
1111         if (mustProvide("ulem"))
1112                 packages << "\\PassOptionsToPackage{normalem}{ulem}\n"
1113                             "\\usepackage{ulem}\n";
1114
1115         if (mustProvide("nomencl")) {
1116                 // Make it work with the new and old version of the package,
1117                 // but don't use the compatibility option since it is
1118                 // incompatible to other packages.
1119                 packages << "\\usepackage{nomencl}\n"
1120                             "% the following is useful when we have the old nomencl.sty package\n"
1121                             "\\providecommand{\\printnomenclature}{\\printglossary}\n"
1122                             "\\providecommand{\\makenomenclature}{\\makeglossary}\n"
1123                             "\\makenomenclature\n";
1124         }
1125
1126         // fixltx2e provides subscript
1127         if (mustProvide("subscript") && !isRequired("fixltx2e"))
1128                 packages << "\\usepackage{subscript}\n";
1129
1130         // footmisc must be loaded after setspace
1131         // Set options here, load the package after the user preamble to
1132         // avoid problems with manual loaded footmisc.
1133         if (mustProvide("footmisc"))
1134                 packages << "\\PassOptionsToPackage{stable}{footmisc}\n";
1135
1136         if (mustProvide("microtype")){
1137                 packages << "\\usepackage{microtype}\n";
1138         }
1139
1140         return packages.str();
1141 }
1142
1143
1144 string LaTeXFeatures::getPreambleSnippets() const
1145 {
1146         ostringstream snip;
1147         SnippetList::const_iterator pit  = preamble_snippets_.begin();
1148         SnippetList::const_iterator pend = preamble_snippets_.end();
1149         for (; pit != pend; ++pit)
1150                 snip << *pit << '\n';
1151         return snip.str();
1152 }
1153
1154
1155 std::string LaTeXFeatures::getCSSSnippets() const
1156 {
1157         ostringstream snip;
1158         SnippetList::const_iterator pit  = css_snippets_.begin();
1159         SnippetList::const_iterator pend = css_snippets_.end();
1160         for (; pit != pend; ++pit)
1161                 snip << *pit << '\n';
1162         return snip.str();
1163 }
1164
1165
1166 docstring const LaTeXFeatures::getMacros() const
1167 {
1168         odocstringstream macros;
1169
1170         if (!preamble_snippets_.empty()) {
1171                 macros << '\n';
1172                 macros << from_utf8(getPreambleSnippets());
1173         }
1174
1175         if (mustProvide("papersize")) {
1176                 if (runparams_.flavor == OutputParams::LATEX)
1177                         macros << papersizedvi_def << '\n';
1178                 else
1179                         macros << papersizepdf_def << '\n';
1180         }
1181
1182         if (mustProvide("LyX")) {
1183                 if (isRequired("hyperref"))
1184                         macros << lyx_hyperref_def << '\n';
1185                 else
1186                         macros << lyx_def << '\n';
1187         }
1188
1189         if (mustProvide("noun"))
1190                 macros << noun_def << '\n';
1191
1192         if (mustProvide("lyxarrow"))
1193                 macros << lyxarrow_def << '\n';
1194
1195         if (!usePolyglossia() && mustProvide("textgreek")) {
1196                 // ensure LGR font encoding is defined also if fontenc is not loaded by LyX
1197                 if (params_.font_encoding() == "default")
1198                         macros << textgreek_LGR_def;
1199                 macros << textgreek_def << '\n';
1200         }
1201
1202         if (!usePolyglossia() && mustProvide("textcyr")) {
1203                 // ensure T2A font encoding is set up also if fontenc is not loaded by LyX
1204                 if (params_.font_encoding() == "default")
1205                         macros << textcyr_T2A_def;
1206                 macros << textcyr_def << '\n';
1207         }
1208
1209         // non-standard text accents:
1210         if (mustProvide("textcommaabove") || mustProvide("textcommaaboveright") ||
1211             mustProvide("textcommabelow") || mustProvide("textbaltic"))
1212                 macros << lyxaccent_def;
1213
1214         if (mustProvide("textcommabelow") || mustProvide("textbaltic"))
1215                 macros << textcommabelow_def << '\n';
1216
1217         if (mustProvide("textcommaabove") || mustProvide("textbaltic"))
1218                 macros << textcommaabove_def << '\n';
1219
1220         if (mustProvide("textcommaaboveright"))
1221                 macros << textcommaaboveright_def << '\n';
1222
1223         if (mustProvide("textbaltic"))
1224                 macros << textbaltic_def << '\n';
1225
1226         if (mustProvide("lyxmathsym"))
1227                 macros << lyxmathsym_def << '\n';
1228
1229         if (mustProvide("cedilla"))
1230                 macros << cedilla_def << '\n';
1231
1232         if (mustProvide("subring"))
1233                 macros << subring_def << '\n';
1234
1235         if (mustProvide("subdot"))
1236                 macros << subdot_def << '\n';
1237
1238         if (mustProvide("subhat"))
1239                 macros << subhat_def << '\n';
1240
1241         if (mustProvide("subtilde"))
1242                 macros << subtilde_def << '\n';
1243
1244         if (mustProvide("dacute"))
1245                 macros << dacute_def << '\n';
1246
1247         if (mustProvide("tipasymb"))
1248                 macros << tipasymb_def << '\n';
1249
1250         if (mustProvide("dgrave"))
1251                 macros << dgrave_def << '\n';
1252
1253         if (mustProvide("rcap"))
1254                 macros << rcap_def << '\n';
1255
1256         if (mustProvide("ogonek"))
1257                 macros << ogonek_def << '\n';
1258
1259         // quotes.
1260         if (mustProvide("quotesinglbase"))
1261                 macros << quotesinglbase_def << '\n';
1262         if (mustProvide("quotedblbase"))
1263                 macros << quotedblbase_def << '\n';
1264         if (mustProvide("guilsinglleft"))
1265                 macros << guilsinglleft_def << '\n';
1266         if (mustProvide("guilsinglright"))
1267                 macros << guilsinglright_def << '\n';
1268         if (mustProvide("guillemotleft"))
1269                 macros << guillemotleft_def << '\n';
1270         if (mustProvide("guillemotright"))
1271                 macros << guillemotright_def << '\n';
1272
1273         // Math mode
1274         if (mustProvide("binom") && !isRequired("amsmath"))
1275                 macros << binom_def << '\n';
1276         if (mustProvide("mathcircumflex"))
1277                 macros << mathcircumflex_def << '\n';
1278
1279         // other
1280         if (mustProvide("ParagraphLeftIndent"))
1281                 macros << paragraphleftindent_def;
1282         if (mustProvide("NeedLyXFootnoteCode"))
1283                 macros << floatingfootnote_def;
1284
1285         // some problems with tex->html converters
1286         if (mustProvide("NeedTabularnewline"))
1287                 macros << tabularnewline_def;
1288
1289         // greyed-out environment (note inset)
1290         // the color is specified in the routine
1291         // getColorOptions() to avoid LaTeX-package clashes
1292         if (mustProvide("lyxgreyedout"))
1293                 macros << lyxgreyedout_def;
1294
1295         if (mustProvide("lyxdot"))
1296                 macros << lyxdot_def << '\n';
1297
1298         // floats
1299         getFloatDefinitions(macros);
1300
1301         if (mustProvide("refstyle"))
1302                 macros << lyxref_def << '\n';
1303
1304         // change tracking
1305         if (mustProvide("ct-dvipost"))
1306                 macros << changetracking_dvipost_def;
1307
1308         if (mustProvide("ct-xcolor-ulem")) {
1309                 streamsize const prec = macros.precision(2);
1310
1311                 RGBColor cadd = rgbFromHexName(lcolor.getX11Name(Color_addedtext));
1312                 macros << "\\providecolor{lyxadded}{rgb}{"
1313                        << cadd.r / 255.0 << ',' << cadd.g / 255.0 << ',' << cadd.b / 255.0 << "}\n";
1314
1315                 RGBColor cdel = rgbFromHexName(lcolor.getX11Name(Color_deletedtext));
1316                 macros << "\\providecolor{lyxdeleted}{rgb}{"
1317                        << cdel.r / 255.0 << ',' << cdel.g / 255.0 << ',' << cdel.b / 255.0 << "}\n";
1318
1319                 macros.precision(prec);
1320
1321                 if (isRequired("hyperref"))
1322                         macros << changetracking_xcolor_ulem_hyperref_def;
1323                 else
1324                         macros << changetracking_xcolor_ulem_def;
1325         }
1326
1327         if (mustProvide("ct-none"))
1328                 macros << changetracking_none_def;
1329
1330         if (mustProvide("rtloutputdblcol"))
1331                 macros << rtloutputdblcol_def;
1332
1333         return macros.str();
1334 }
1335
1336
1337 string const LaTeXFeatures::getBabelPresettings() const
1338 {
1339         ostringstream tmp;
1340
1341         LanguageList::const_iterator it  = UsedLanguages_.begin();
1342         LanguageList::const_iterator end = UsedLanguages_.end();
1343         for (; it != end; ++it)
1344                 if (!(*it)->babel_presettings().empty())
1345                         tmp << (*it)->babel_presettings() << '\n';
1346         if (!params_.language->babel_presettings().empty())
1347                 tmp << params_.language->babel_presettings() << '\n';
1348
1349         if (!contains(tmp.str(), '@'))
1350                 return tmp.str();
1351
1352         return "\\makeatletter\n" + tmp.str() + "\\makeatother\n";
1353 }
1354
1355
1356 string const LaTeXFeatures::getBabelPostsettings() const
1357 {
1358         ostringstream tmp;
1359
1360         LanguageList::const_iterator it  = UsedLanguages_.begin();
1361         LanguageList::const_iterator end = UsedLanguages_.end();
1362         for (; it != end; ++it)
1363                 if (!(*it)->babel_postsettings().empty())
1364                         tmp << (*it)->babel_postsettings() << '\n';
1365         if (!params_.language->babel_postsettings().empty())
1366                 tmp << params_.language->babel_postsettings() << '\n';
1367
1368         if (!contains(tmp.str(), '@'))
1369                 return tmp.str();
1370
1371         return "\\makeatletter\n" + tmp.str() + "\\makeatother\n";
1372 }
1373
1374
1375 bool LaTeXFeatures::needBabelLangOptions() const
1376 {
1377         if (!lyxrc.language_global_options || params_.language->asBabelOptions())
1378                 return true;
1379
1380         LanguageList::const_iterator it  = UsedLanguages_.begin();
1381         LanguageList::const_iterator end = UsedLanguages_.end();
1382         for (; it != end; ++it)
1383                 if ((*it)->asBabelOptions())
1384                         return true;
1385
1386         return false;
1387 }
1388
1389
1390 string const LaTeXFeatures::loadAMSPackages() const
1391 {
1392         ostringstream tmp;
1393
1394         if (mustProvide("amsmath")
1395             && params_.use_package("amsmath") != BufferParams::package_off) {
1396                 tmp << "\\usepackage{amsmath}\n";
1397         } else {
1398                 // amsbsy and amstext are already provided by amsmath
1399                 if (mustProvide("amsbsy"))
1400                         tmp << "\\usepackage{amsbsy}\n";
1401                 if (mustProvide("amstext"))
1402                         tmp << "\\usepackage{amstext}\n";
1403         }
1404
1405         if (mustProvide("amsthm"))
1406                 tmp << "\\usepackage{amsthm}\n";
1407
1408         if (mustProvide("amssymb")
1409             && params_.use_package("amssymb") != BufferParams::package_off)
1410                 tmp << "\\usepackage{amssymb}\n";
1411
1412         return tmp.str();
1413 }
1414
1415
1416 docstring const LaTeXFeatures::getTClassPreamble() const
1417 {
1418         // the text class specific preamble
1419         DocumentClass const & tclass = params_.documentClass();
1420         odocstringstream tcpreamble;
1421
1422         tcpreamble << tclass.preamble();
1423
1424         list<docstring>::const_iterator cit = usedLayouts_.begin();
1425         list<docstring>::const_iterator end = usedLayouts_.end();
1426         for (; cit != end; ++cit)
1427                 tcpreamble << tclass[*cit].preamble();
1428
1429         cit = usedInsetLayouts_.begin();
1430         end = usedInsetLayouts_.end();
1431         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1432         for (; cit != end; ++cit) {
1433                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1434                 if (it == ils.end())
1435                         continue;
1436                 tcpreamble << it->second.preamble();
1437         }
1438
1439         return tcpreamble.str();
1440 }
1441
1442
1443 docstring const LaTeXFeatures::getTClassHTMLPreamble() const
1444 {
1445         DocumentClass const & tclass = params_.documentClass();
1446         odocstringstream tcpreamble;
1447
1448         tcpreamble << tclass.htmlpreamble();
1449
1450         list<docstring>::const_iterator cit = usedLayouts_.begin();
1451         list<docstring>::const_iterator end = usedLayouts_.end();
1452         for (; cit != end; ++cit)
1453                 tcpreamble << tclass[*cit].htmlpreamble();
1454
1455         cit = usedInsetLayouts_.begin();
1456         end = usedInsetLayouts_.end();
1457         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1458         for (; cit != end; ++cit) {
1459                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1460                 if (it == ils.end())
1461                         continue;
1462                 tcpreamble << it->second.htmlpreamble();
1463         }
1464
1465         return tcpreamble.str();
1466 }
1467
1468
1469 docstring const LaTeXFeatures::getTClassHTMLStyles() const
1470 {
1471         DocumentClass const & tclass = params_.documentClass();
1472         odocstringstream tcpreamble;
1473
1474         if (mustProvide("noun"))
1475                 tcpreamble << lyxnoun_style;
1476         // this isn't exact, but it won't hurt that much if it
1477         // wasn't for this.
1478         if (mustProvide("ulem"))
1479                 tcpreamble << lyxstrikeout_style;
1480
1481         tcpreamble << tclass.htmlstyles();
1482
1483         list<docstring>::const_iterator cit = usedLayouts_.begin();
1484         list<docstring>::const_iterator end = usedLayouts_.end();
1485         for (; cit != end; ++cit)
1486                 tcpreamble << tclass[*cit].htmlstyle();
1487
1488         cit = usedInsetLayouts_.begin();
1489         end = usedInsetLayouts_.end();
1490         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1491         for (; cit != end; ++cit) {
1492                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1493                 if (it == ils.end())
1494                         continue;
1495                 tcpreamble << it->second.htmlstyle();
1496         }
1497
1498         return tcpreamble.str();
1499 }
1500
1501
1502 namespace {
1503
1504 docstring const getFloatI18nPreamble(docstring const & type,
1505                         docstring const & name, Language const * lang,
1506                         Encoding const & enc, bool const polyglossia)
1507 {
1508         // Check whether name can be encoded in the buffer encoding
1509         bool encodable = true;
1510         for (size_t i = 0; i < name.size(); ++i) {
1511                 if (!enc.encodable(name[i])) {
1512                         encodable = false;
1513                         break;
1514                 }
1515         }
1516
1517         docstring const language = polyglossia ? from_ascii(lang->polyglossia())
1518                                                : from_ascii(lang->babel());
1519         docstring const langenc = from_ascii(lang->encoding()->iconvName());
1520         docstring const texenc = from_ascii(lang->encoding()->latexName());
1521         docstring const bufenc = from_ascii(enc.iconvName());
1522         docstring const s1 = docstring(1, 0xF0000);
1523         docstring const s2 = docstring(1, 0xF0001);
1524         docstring const translated = encodable ? name
1525                 : from_ascii("\\inputencoding{") + texenc + from_ascii("}")
1526                         + s1 + langenc + s2 + name + s1 + bufenc + s2;
1527
1528         odocstringstream os;
1529         os << "\\addto\\captions" << language
1530            << "{\\renewcommand{\\" << type << "name}{" << translated << "}}\n";
1531         return os.str();
1532 }
1533
1534
1535 docstring const i18npreamble(docstring const & templ, Language const * lang,
1536                              Encoding const & enc, bool const polyglossia,
1537                              bool const need_fixedwidth)
1538 {
1539         if (templ.empty())
1540                 return templ;
1541
1542         string preamble = polyglossia ?
1543                 subst(to_utf8(templ), "$$lang", lang->polyglossia()) :
1544                 subst(to_utf8(templ), "$$lang", lang->babel());
1545
1546         string const langenc = lang->encoding()->iconvName();
1547         string const texenc = lang->encoding()->latexName();
1548         string const bufenc = enc.iconvName();
1549         Encoding const * testenc(&enc);
1550         bool lang_fallback = false;
1551         bool ascii_fallback = false;
1552         if (need_fixedwidth && !enc.hasFixedWidth()) {
1553                 if (lang->encoding()->hasFixedWidth()) {
1554                         testenc = lang->encoding();
1555                         lang_fallback = true;
1556                 } else {
1557                         // We need a fixed width encoding, but both the buffer
1558                         // encoding and the language encoding are variable
1559                         // width. As a last fallback, try to convert to pure
1560                         // ASCII using the LaTeX commands defined in unicodesymbols.
1561                         testenc = encodings.fromLyXName("ascii");
1562                         if (!testenc)
1563                                 return docstring();
1564                         ascii_fallback = true;
1565                 }
1566         }
1567         // First and second character of plane 15 (Private Use Area)
1568         string const s1 = "\xf3\xb0\x80\x80"; // U+F0000
1569         string const s2 = "\xf3\xb0\x80\x81"; // U+F0001
1570         // FIXME UNICODE
1571         // lyx::regex is not unicode-safe.
1572         // Should use QRegExp or (boost::u32regex, but that requires ICU)
1573         static regex const reg("_\\(([^\\)]+)\\)");
1574         smatch sub;
1575         while (regex_search(preamble, sub, reg)) {
1576                 string const key = sub.str(1);
1577                 docstring const name = lang->translateLayout(key);
1578                 // Check whether name can be encoded in the buffer encoding
1579                 bool encodable = true;
1580                 for (size_t i = 0; i < name.size() && encodable; ++i)
1581                         if (!testenc->encodable(name[i]))
1582                                 encodable = false;
1583                 string translated;
1584                 if (encodable && !lang_fallback)
1585                         translated = to_utf8(name);
1586                 else if (ascii_fallback)
1587                         translated = to_ascii(testenc->latexString(name).first);
1588                 else
1589                         translated = "\\inputencoding{" + texenc + "}"
1590                                 + s1 + langenc + s2 + to_utf8(name)
1591                                 + s1 + bufenc + s2;
1592                 preamble = subst(preamble, sub.str(), translated);
1593         }
1594         return from_utf8(preamble);
1595 }
1596
1597 }
1598
1599
1600 docstring const LaTeXFeatures::getTClassI18nPreamble(bool use_babel, bool use_polyglossia) const
1601 {
1602         DocumentClass const & tclass = params_.documentClass();
1603         // collect preamble snippets in a set to prevent multiple identical
1604         // commands (would happen if e.g. both theorem and theorem* are used)
1605         set<docstring> snippets;
1606         typedef LanguageList::const_iterator lang_it;
1607         lang_it const lbeg = UsedLanguages_.begin();
1608         lang_it const lend =  UsedLanguages_.end();
1609         list<docstring>::const_iterator cit = usedLayouts_.begin();
1610         list<docstring>::const_iterator end = usedLayouts_.end();
1611         for (; cit != end; ++cit) {
1612                 // language dependent commands (once per document)
1613                 snippets.insert(i18npreamble(tclass[*cit].langpreamble(),
1614                                                 buffer().language(),
1615                                                 buffer().params().encoding(),
1616                                                 use_polyglossia, false));
1617                 // commands for language changing (for multilanguage documents)
1618                 if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
1619                         snippets.insert(i18npreamble(
1620                                                 tclass[*cit].babelpreamble(),
1621                                                 buffer().language(),
1622                                                 buffer().params().encoding(),
1623                                                 use_polyglossia, false));
1624                         for (lang_it lit = lbeg; lit != lend; ++lit)
1625                                 snippets.insert(i18npreamble(
1626                                                 tclass[*cit].babelpreamble(),
1627                                                 *lit,
1628                                                 buffer().params().encoding(),
1629                                                 use_polyglossia, false));
1630                 }
1631         }
1632         if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
1633                 FloatList const & floats = params_.documentClass().floats();
1634                 UsedFloats::const_iterator fit = usedFloats_.begin();
1635                 UsedFloats::const_iterator fend = usedFloats_.end();
1636                 for (; fit != fend; ++fit) {
1637                         Floating const & fl = floats.getType(fit->first);
1638                         // we assume builtin floats are translated
1639                         if (fl.isPredefined())
1640                                 continue;
1641                         docstring const type = from_ascii(fl.floattype());
1642                         docstring const flname = from_utf8(fl.name());
1643                         docstring name = buffer().language()->translateLayout(fl.name());
1644                         // only request translation if we have a real translation
1645                         // (that differs from the source)
1646                         if (flname != name)
1647                                 snippets.insert(getFloatI18nPreamble(
1648                                                 type, name, buffer().language(),
1649                                                 buffer().params().encoding(),
1650                                                 use_polyglossia));
1651                         for (lang_it lit = lbeg; lit != lend; ++lit) {
1652                                 string const code = (*lit)->code();
1653                                 name = (*lit)->translateLayout(fl.name());
1654                                 // we assume we have a suitable translation if
1655                                 // either the language is English (we need to
1656                                 // translate into English if English is a secondary
1657                                 // language) or if translateIfPossible returns
1658                                 // something different to the English source.
1659                                 bool const have_translation =
1660                                         (flname != name || contains(code, "en"));
1661                                 if (have_translation)
1662                                         snippets.insert(getFloatI18nPreamble(
1663                                                 type, name, *lit,
1664                                                 buffer().params().encoding(),
1665                                                 use_polyglossia));
1666                         }
1667                 }
1668         }
1669
1670         cit = usedInsetLayouts_.begin();
1671         end = usedInsetLayouts_.end();
1672         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1673         for (; cit != end; ++cit) {
1674                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1675                 if (it == ils.end())
1676                         continue;
1677                 // The listings package does not work with variable width
1678                 // encodings, only with fixed width encodings. Therefore we
1679                 // need to force a fixed width encoding for
1680                 // \lstlistlistingname and \lstlistingname (bug 9382).
1681                 // This needs to be consistent with InsetListings::latex().
1682                 bool const need_fixedwidth = !runparams_.isFullUnicode() &&
1683                                 it->second.fixedwidthpreambleencoding();
1684                 // language dependent commands (once per document)
1685                 snippets.insert(i18npreamble(it->second.langpreamble(),
1686                                                 buffer().language(),
1687                                                 buffer().params().encoding(),
1688                                                 use_polyglossia, need_fixedwidth));
1689                 // commands for language changing (for multilanguage documents)
1690                 if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
1691                         snippets.insert(i18npreamble(
1692                                                 it->second.babelpreamble(),
1693                                                 buffer().language(),
1694                                                 buffer().params().encoding(),
1695                                                 use_polyglossia, need_fixedwidth));
1696                         for (lang_it lit = lbeg; lit != lend; ++lit)
1697                                 snippets.insert(i18npreamble(
1698                                                 it->second.babelpreamble(),
1699                                                 *lit,
1700                                                 buffer().params().encoding(),
1701                                                 use_polyglossia, need_fixedwidth));
1702                 }
1703         }
1704
1705         odocstringstream tcpreamble;
1706         set<docstring>::const_iterator const send = snippets.end();
1707         set<docstring>::const_iterator it = snippets.begin();
1708         for (; it != send; ++it)
1709                 tcpreamble << *it;
1710         return tcpreamble.str();
1711 }
1712
1713
1714 docstring const LaTeXFeatures::getLyXSGMLEntities() const
1715 {
1716         // Definition of entities used in the document that are LyX related.
1717         odocstringstream entities;
1718
1719         if (mustProvide("lyxarrow")) {
1720                 entities << "<!ENTITY lyxarrow \"-&gt;\">" << '\n';
1721         }
1722
1723         return entities.str();
1724 }
1725
1726
1727 docstring const LaTeXFeatures::getIncludedFiles(string const & fname) const
1728 {
1729         odocstringstream sgmlpreamble;
1730         // FIXME UNICODE
1731         docstring const basename(from_utf8(onlyPath(fname)));
1732
1733         FileMap::const_iterator end = IncludedFiles_.end();
1734         for (FileMap::const_iterator fi = IncludedFiles_.begin();
1735              fi != end; ++fi)
1736                 // FIXME UNICODE
1737                 sgmlpreamble << "\n<!ENTITY " << fi->first
1738                              << (isSGMLFileName(fi->second) ? " SYSTEM \"" : " \"")
1739                              << makeRelPath(from_utf8(fi->second), basename) << "\">";
1740
1741         return sgmlpreamble.str();
1742 }
1743
1744
1745 void LaTeXFeatures::showStruct() const
1746 {
1747         lyxerr << "LyX needs the following commands when LaTeXing:"
1748                << "\n***** Packages:" << getPackages()
1749                << "\n***** Macros:" << to_utf8(getMacros())
1750                << "\n***** Textclass stuff:" << to_utf8(getTClassPreamble())
1751                << "\n***** done." << endl;
1752 }
1753
1754
1755 Buffer const & LaTeXFeatures::buffer() const
1756 {
1757         return *buffer_;
1758 }
1759
1760
1761 void LaTeXFeatures::setBuffer(Buffer const & buffer)
1762 {
1763         buffer_ = &buffer;
1764 }
1765
1766
1767 BufferParams const & LaTeXFeatures::bufferParams() const
1768 {
1769         return params_;
1770 }
1771
1772
1773 void LaTeXFeatures::getFloatDefinitions(odocstream & os) const
1774 {
1775         FloatList const & floats = params_.documentClass().floats();
1776
1777         // Here we will output the code to create the needed float styles.
1778         // We will try to do this as minimal as possible.
1779         // \floatstyle{ruled}
1780         // \newfloat{algorithm}{htbp}{loa}
1781         // \providecommand{\algorithmname}{Algorithm}
1782         // \floatname{algorithm}{\protect\algorithmname}
1783         UsedFloats::const_iterator cit = usedFloats_.begin();
1784         UsedFloats::const_iterator end = usedFloats_.end();
1785         for (; cit != end; ++cit) {
1786                 Floating const & fl = floats.getType(cit->first);
1787
1788                 // For builtin floats we do nothing.
1789                 if (fl.isPredefined())
1790                         continue;
1791
1792                 // We have to special case "table" and "figure"
1793                 if (fl.floattype() == "tabular" || fl.floattype() == "figure") {
1794                         // Output code to modify "table" or "figure"
1795                         // but only if builtin == false
1796                         // and that have to be true at this point in the
1797                         // function.
1798                         docstring const type = from_ascii(fl.floattype());
1799                         docstring const placement = from_ascii(fl.placement());
1800                         docstring const style = from_ascii(fl.style());
1801                         if (!style.empty()) {
1802                                 os << "\\floatstyle{" << style << "}\n"
1803                                    << "\\restylefloat{" << type << "}\n";
1804                         }
1805                         if (!placement.empty()) {
1806                                 os << "\\floatplacement{" << type << "}{"
1807                                    << placement << "}\n";
1808                         }
1809                 } else {
1810                         // The other non builtin floats.
1811
1812                         docstring const type = from_ascii(fl.floattype());
1813                         docstring const placement = from_ascii(fl.placement());
1814                         docstring const ext = from_ascii(fl.ext());
1815                         docstring const within = from_ascii(fl.within());
1816                         docstring const style = from_ascii(fl.style());
1817                         docstring const name =
1818                                 buffer().language()->translateLayout(fl.name());
1819                         os << "\\floatstyle{" << style << "}\n"
1820                            << "\\newfloat{" << type << "}{" << placement
1821                            << "}{" << ext << '}';
1822                         if (!within.empty())
1823                                 os << '[' << within << ']';
1824                         os << '\n'
1825                            << "\\providecommand{\\" << type << "name}{"
1826                            << name << "}\n"
1827                            << "\\floatname{" << type << "}{\\protect\\"
1828                            << type << "name}\n";
1829
1830                         // What missing here is to code to minimalize the code
1831                         // output so that the same floatstyle will not be
1832                         // used several times, when the same style is still in
1833                         // effect. (Lgb)
1834                 }
1835                 if (cit->second)
1836                         // The subfig package is loaded later
1837                         os << "\n\\AtBeginDocument{\\newsubfloat{" << from_ascii(fl.floattype()) << "}}\n";
1838         }
1839 }
1840
1841
1842 void LaTeXFeatures::resolveAlternatives()
1843 {
1844         for (Features::iterator it = features_.begin(); it != features_.end();) {
1845                 if (contains(*it, '|')) {
1846                         vector<string> const alternatives = getVectorFromString(*it, "|");
1847                         vector<string>::const_iterator const end = alternatives.end();
1848                         vector<string>::const_iterator ita = alternatives.begin();
1849                         // Is any alternative already required? => use that
1850                         for (; ita != end; ++ita) {
1851                                 if (isRequired(*ita))
1852                                         break;
1853                         }
1854                         // Is any alternative available? => use the first one
1855                         // (bug 9498)
1856                         if (ita == end) {
1857                                 for (ita = alternatives.begin(); ita != end; ++ita) {
1858                                         if (isAvailable(*ita)) {
1859                                                 require(*ita);
1860                                                 break;
1861                                         }
1862                                 }
1863                         }
1864                         // This will not work, but not requiring something
1865                         // would be more confusing
1866                         if (ita == end)
1867                                 require(alternatives.front());
1868                         features_.erase(it);
1869                         it = features_.begin();
1870                 } else
1871                         ++it;
1872         }
1873 }
1874
1875
1876 } // namespace lyx