]> git.lyx.org Git - lyx.git/blob - src/LaTeXFeatures.cpp
Fix typo.
[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         return packages.str();
1137 }
1138
1139
1140 string LaTeXFeatures::getPreambleSnippets() const
1141 {
1142         ostringstream snip;
1143         SnippetList::const_iterator pit  = preamble_snippets_.begin();
1144         SnippetList::const_iterator pend = preamble_snippets_.end();
1145         for (; pit != pend; ++pit)
1146                 snip << *pit << '\n';
1147         return snip.str();
1148 }
1149
1150
1151 std::string LaTeXFeatures::getCSSSnippets() const
1152 {
1153         ostringstream snip;
1154         SnippetList::const_iterator pit  = css_snippets_.begin();
1155         SnippetList::const_iterator pend = css_snippets_.end();
1156         for (; pit != pend; ++pit)
1157                 snip << *pit << '\n';
1158         return snip.str();
1159 }
1160
1161
1162 docstring const LaTeXFeatures::getMacros() const
1163 {
1164         odocstringstream macros;
1165
1166         if (!preamble_snippets_.empty()) {
1167                 macros << '\n';
1168                 macros << from_utf8(getPreambleSnippets());
1169         }
1170
1171         if (mustProvide("papersize")) {
1172                 if (runparams_.flavor == OutputParams::LATEX)
1173                         macros << papersizedvi_def << '\n';
1174                 else
1175                         macros << papersizepdf_def << '\n';
1176         }
1177
1178         if (mustProvide("LyX")) {
1179                 if (isRequired("hyperref"))
1180                         macros << lyx_hyperref_def << '\n';
1181                 else
1182                         macros << lyx_def << '\n';
1183         }
1184
1185         if (mustProvide("noun"))
1186                 macros << noun_def << '\n';
1187
1188         if (mustProvide("lyxarrow"))
1189                 macros << lyxarrow_def << '\n';
1190
1191         if (!usePolyglossia() && mustProvide("textgreek")) {
1192                 // ensure LGR font encoding is defined also if fontenc is not loaded by LyX
1193                 if (params_.font_encoding() == "default")
1194                         macros << textgreek_LGR_def;
1195                 macros << textgreek_def << '\n';
1196         }
1197
1198         if (!usePolyglossia() && mustProvide("textcyr")) {
1199                 // ensure T2A font encoding is set up also if fontenc is not loaded by LyX
1200                 if (params_.font_encoding() == "default")
1201                         macros << textcyr_T2A_def;
1202                 macros << textcyr_def << '\n';
1203         }
1204
1205         // non-standard text accents:
1206         if (mustProvide("textcommaabove") || mustProvide("textcommaaboveright") ||
1207             mustProvide("textcommabelow") || mustProvide("textbaltic"))
1208                 macros << lyxaccent_def;
1209
1210         if (mustProvide("textcommabelow") || mustProvide("textbaltic"))
1211                 macros << textcommabelow_def << '\n';
1212
1213         if (mustProvide("textcommaabove") || mustProvide("textbaltic"))
1214                 macros << textcommaabove_def << '\n';
1215
1216         if (mustProvide("textcommaaboveright"))
1217                 macros << textcommaaboveright_def << '\n';
1218
1219         if (mustProvide("textbaltic"))
1220                 macros << textbaltic_def << '\n';
1221
1222         if (mustProvide("lyxmathsym"))
1223                 macros << lyxmathsym_def << '\n';
1224
1225         if (mustProvide("cedilla"))
1226                 macros << cedilla_def << '\n';
1227
1228         if (mustProvide("subring"))
1229                 macros << subring_def << '\n';
1230
1231         if (mustProvide("subdot"))
1232                 macros << subdot_def << '\n';
1233
1234         if (mustProvide("subhat"))
1235                 macros << subhat_def << '\n';
1236
1237         if (mustProvide("subtilde"))
1238                 macros << subtilde_def << '\n';
1239
1240         if (mustProvide("dacute"))
1241                 macros << dacute_def << '\n';
1242
1243         if (mustProvide("tipasymb"))
1244                 macros << tipasymb_def << '\n';
1245
1246         if (mustProvide("dgrave"))
1247                 macros << dgrave_def << '\n';
1248
1249         if (mustProvide("rcap"))
1250                 macros << rcap_def << '\n';
1251
1252         if (mustProvide("ogonek"))
1253                 macros << ogonek_def << '\n';
1254
1255         // quotes.
1256         if (mustProvide("quotesinglbase"))
1257                 macros << quotesinglbase_def << '\n';
1258         if (mustProvide("quotedblbase"))
1259                 macros << quotedblbase_def << '\n';
1260         if (mustProvide("guilsinglleft"))
1261                 macros << guilsinglleft_def << '\n';
1262         if (mustProvide("guilsinglright"))
1263                 macros << guilsinglright_def << '\n';
1264         if (mustProvide("guillemotleft"))
1265                 macros << guillemotleft_def << '\n';
1266         if (mustProvide("guillemotright"))
1267                 macros << guillemotright_def << '\n';
1268
1269         // Math mode
1270         if (mustProvide("binom") && !isRequired("amsmath"))
1271                 macros << binom_def << '\n';
1272         if (mustProvide("mathcircumflex"))
1273                 macros << mathcircumflex_def << '\n';
1274
1275         // other
1276         if (mustProvide("ParagraphLeftIndent"))
1277                 macros << paragraphleftindent_def;
1278         if (mustProvide("NeedLyXFootnoteCode"))
1279                 macros << floatingfootnote_def;
1280
1281         // some problems with tex->html converters
1282         if (mustProvide("NeedTabularnewline"))
1283                 macros << tabularnewline_def;
1284
1285         // greyed-out environment (note inset)
1286         // the color is specified in the routine
1287         // getColorOptions() to avoid LaTeX-package clashes
1288         if (mustProvide("lyxgreyedout"))
1289                 macros << lyxgreyedout_def;
1290
1291         if (mustProvide("lyxdot"))
1292                 macros << lyxdot_def << '\n';
1293
1294         // floats
1295         getFloatDefinitions(macros);
1296
1297         if (mustProvide("refstyle"))
1298                 macros << lyxref_def << '\n';
1299
1300         // change tracking
1301         if (mustProvide("ct-dvipost"))
1302                 macros << changetracking_dvipost_def;
1303
1304         if (mustProvide("ct-xcolor-ulem")) {
1305                 streamsize const prec = macros.precision(2);
1306
1307                 RGBColor cadd = rgbFromHexName(lcolor.getX11Name(Color_addedtext));
1308                 macros << "\\providecolor{lyxadded}{rgb}{"
1309                        << cadd.r / 255.0 << ',' << cadd.g / 255.0 << ',' << cadd.b / 255.0 << "}\n";
1310
1311                 RGBColor cdel = rgbFromHexName(lcolor.getX11Name(Color_deletedtext));
1312                 macros << "\\providecolor{lyxdeleted}{rgb}{"
1313                        << cdel.r / 255.0 << ',' << cdel.g / 255.0 << ',' << cdel.b / 255.0 << "}\n";
1314
1315                 macros.precision(prec);
1316
1317                 if (isRequired("hyperref"))
1318                         macros << changetracking_xcolor_ulem_hyperref_def;
1319                 else
1320                         macros << changetracking_xcolor_ulem_def;
1321         }
1322
1323         if (mustProvide("ct-none"))
1324                 macros << changetracking_none_def;
1325
1326         if (mustProvide("rtloutputdblcol"))
1327                 macros << rtloutputdblcol_def;
1328
1329         return macros.str();
1330 }
1331
1332
1333 string const LaTeXFeatures::getBabelPresettings() const
1334 {
1335         ostringstream tmp;
1336
1337         LanguageList::const_iterator it  = UsedLanguages_.begin();
1338         LanguageList::const_iterator end = UsedLanguages_.end();
1339         for (; it != end; ++it)
1340                 if (!(*it)->babel_presettings().empty())
1341                         tmp << (*it)->babel_presettings() << '\n';
1342         if (!params_.language->babel_presettings().empty())
1343                 tmp << params_.language->babel_presettings() << '\n';
1344
1345         if (!contains(tmp.str(), '@'))
1346                 return tmp.str();
1347
1348         return "\\makeatletter\n" + tmp.str() + "\\makeatother\n";
1349 }
1350
1351
1352 string const LaTeXFeatures::getBabelPostsettings() const
1353 {
1354         ostringstream tmp;
1355
1356         LanguageList::const_iterator it  = UsedLanguages_.begin();
1357         LanguageList::const_iterator end = UsedLanguages_.end();
1358         for (; it != end; ++it)
1359                 if (!(*it)->babel_postsettings().empty())
1360                         tmp << (*it)->babel_postsettings() << '\n';
1361         if (!params_.language->babel_postsettings().empty())
1362                 tmp << params_.language->babel_postsettings() << '\n';
1363
1364         if (!contains(tmp.str(), '@'))
1365                 return tmp.str();
1366
1367         return "\\makeatletter\n" + tmp.str() + "\\makeatother\n";
1368 }
1369
1370
1371 bool LaTeXFeatures::needBabelLangOptions() const
1372 {
1373         if (!lyxrc.language_global_options || params_.language->asBabelOptions())
1374                 return true;
1375
1376         LanguageList::const_iterator it  = UsedLanguages_.begin();
1377         LanguageList::const_iterator end = UsedLanguages_.end();
1378         for (; it != end; ++it)
1379                 if ((*it)->asBabelOptions())
1380                         return true;
1381
1382         return false;
1383 }
1384
1385
1386 string const LaTeXFeatures::loadAMSPackages() const
1387 {
1388         ostringstream tmp;
1389
1390         if (mustProvide("amsmath")
1391             && params_.use_package("amsmath") != BufferParams::package_off) {
1392                 tmp << "\\usepackage{amsmath}\n";
1393         } else {
1394                 // amsbsy and amstext are already provided by amsmath
1395                 if (mustProvide("amsbsy"))
1396                         tmp << "\\usepackage{amsbsy}\n";
1397                 if (mustProvide("amstext"))
1398                         tmp << "\\usepackage{amstext}\n";
1399         }
1400
1401         if (mustProvide("amsthm"))
1402                 tmp << "\\usepackage{amsthm}\n";
1403
1404         if (mustProvide("amssymb")
1405             && params_.use_package("amssymb") != BufferParams::package_off)
1406                 tmp << "\\usepackage{amssymb}\n";
1407
1408         return tmp.str();
1409 }
1410
1411
1412 docstring const LaTeXFeatures::getTClassPreamble() const
1413 {
1414         // the text class specific preamble
1415         DocumentClass const & tclass = params_.documentClass();
1416         odocstringstream tcpreamble;
1417
1418         tcpreamble << tclass.preamble();
1419
1420         list<docstring>::const_iterator cit = usedLayouts_.begin();
1421         list<docstring>::const_iterator end = usedLayouts_.end();
1422         for (; cit != end; ++cit)
1423                 tcpreamble << tclass[*cit].preamble();
1424
1425         cit = usedInsetLayouts_.begin();
1426         end = usedInsetLayouts_.end();
1427         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1428         for (; cit != end; ++cit) {
1429                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1430                 if (it == ils.end())
1431                         continue;
1432                 tcpreamble << it->second.preamble();
1433         }
1434
1435         return tcpreamble.str();
1436 }
1437
1438
1439 docstring const LaTeXFeatures::getTClassHTMLPreamble() const
1440 {
1441         DocumentClass const & tclass = params_.documentClass();
1442         odocstringstream tcpreamble;
1443
1444         tcpreamble << tclass.htmlpreamble();
1445
1446         list<docstring>::const_iterator cit = usedLayouts_.begin();
1447         list<docstring>::const_iterator end = usedLayouts_.end();
1448         for (; cit != end; ++cit)
1449                 tcpreamble << tclass[*cit].htmlpreamble();
1450
1451         cit = usedInsetLayouts_.begin();
1452         end = usedInsetLayouts_.end();
1453         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1454         for (; cit != end; ++cit) {
1455                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1456                 if (it == ils.end())
1457                         continue;
1458                 tcpreamble << it->second.htmlpreamble();
1459         }
1460
1461         return tcpreamble.str();
1462 }
1463
1464
1465 docstring const LaTeXFeatures::getTClassHTMLStyles() const
1466 {
1467         DocumentClass const & tclass = params_.documentClass();
1468         odocstringstream tcpreamble;
1469
1470         if (mustProvide("noun"))
1471                 tcpreamble << lyxnoun_style;
1472         // this isn't exact, but it won't hurt that much if it
1473         // wasn't for this.
1474         if (mustProvide("ulem"))
1475                 tcpreamble << lyxstrikeout_style;
1476
1477         tcpreamble << tclass.htmlstyles();
1478
1479         list<docstring>::const_iterator cit = usedLayouts_.begin();
1480         list<docstring>::const_iterator end = usedLayouts_.end();
1481         for (; cit != end; ++cit)
1482                 tcpreamble << tclass[*cit].htmlstyle();
1483
1484         cit = usedInsetLayouts_.begin();
1485         end = usedInsetLayouts_.end();
1486         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1487         for (; cit != end; ++cit) {
1488                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1489                 if (it == ils.end())
1490                         continue;
1491                 tcpreamble << it->second.htmlstyle();
1492         }
1493
1494         return tcpreamble.str();
1495 }
1496
1497
1498 namespace {
1499
1500 docstring const getFloatI18nPreamble(docstring const & type,
1501                         docstring const & name, Language const * lang,
1502                         Encoding const & enc, bool const polyglossia)
1503 {
1504         // Check whether name can be encoded in the buffer encoding
1505         bool encodable = true;
1506         for (size_t i = 0; i < name.size(); ++i) {
1507                 if (!enc.encodable(name[i])) {
1508                         encodable = false;
1509                         break;
1510                 }
1511         }
1512
1513         docstring const language = polyglossia ? from_ascii(lang->polyglossia())
1514                                                : from_ascii(lang->babel());
1515         docstring const langenc = from_ascii(lang->encoding()->iconvName());
1516         docstring const texenc = from_ascii(lang->encoding()->latexName());
1517         docstring const bufenc = from_ascii(enc.iconvName());
1518         docstring const s1 = docstring(1, 0xF0000);
1519         docstring const s2 = docstring(1, 0xF0001);
1520         docstring const translated = encodable ? name
1521                 : from_ascii("\\inputencoding{") + texenc + from_ascii("}")
1522                         + s1 + langenc + s2 + name + s1 + bufenc + s2;
1523
1524         odocstringstream os;
1525         os << "\\addto\\captions" << language
1526            << "{\\renewcommand{\\" << type << "name}{" << translated << "}}\n";
1527         return os.str();
1528 }
1529
1530
1531 docstring const i18npreamble(docstring const & templ, Language const * lang,
1532                              Encoding const & enc, bool const polyglossia,
1533                              bool const need_fixedwidth)
1534 {
1535         if (templ.empty())
1536                 return templ;
1537
1538         string preamble = polyglossia ?
1539                 subst(to_utf8(templ), "$$lang", lang->polyglossia()) :
1540                 subst(to_utf8(templ), "$$lang", lang->babel());
1541
1542         string const langenc = lang->encoding()->iconvName();
1543         string const texenc = lang->encoding()->latexName();
1544         string const bufenc = enc.iconvName();
1545         Encoding const * testenc(&enc);
1546         bool lang_fallback = false;
1547         bool ascii_fallback = false;
1548         if (need_fixedwidth && !enc.hasFixedWidth()) {
1549                 if (lang->encoding()->hasFixedWidth()) {
1550                         testenc = lang->encoding();
1551                         lang_fallback = true;
1552                 } else {
1553                         // We need a fixed width encoding, but both the buffer
1554                         // encoding and the language encoding are variable
1555                         // width. As a last fallback, try to convert to pure
1556                         // ASCII using the LaTeX commands defined in unicodesymbols.
1557                         testenc = encodings.fromLyXName("ascii");
1558                         if (!testenc)
1559                                 return docstring();
1560                         ascii_fallback = true;
1561                 }
1562         }
1563         // First and second character of plane 15 (Private Use Area)
1564         string const s1 = "\xf3\xb0\x80\x80"; // U+F0000
1565         string const s2 = "\xf3\xb0\x80\x81"; // U+F0001
1566         // FIXME UNICODE
1567         // lyx::regex is not unicode-safe.
1568         // Should use QRegExp or (boost::u32regex, but that requires ICU)
1569         static regex const reg("_\\(([^\\)]+)\\)");
1570         smatch sub;
1571         while (regex_search(preamble, sub, reg)) {
1572                 string const key = sub.str(1);
1573                 docstring const name = lang->translateLayout(key);
1574                 // Check whether name can be encoded in the buffer encoding
1575                 bool encodable = true;
1576                 for (size_t i = 0; i < name.size() && encodable; ++i)
1577                         if (!testenc->encodable(name[i]))
1578                                 encodable = false;
1579                 string translated;
1580                 if (encodable && !lang_fallback)
1581                         translated = to_utf8(name);
1582                 else if (ascii_fallback)
1583                         translated = to_ascii(testenc->latexString(name).first);
1584                 else
1585                         translated = "\\inputencoding{" + texenc + "}"
1586                                 + s1 + langenc + s2 + to_utf8(name)
1587                                 + s1 + bufenc + s2;
1588                 preamble = subst(preamble, sub.str(), translated);
1589         }
1590         return from_utf8(preamble);
1591 }
1592
1593 }
1594
1595
1596 docstring const LaTeXFeatures::getTClassI18nPreamble(bool use_babel, bool use_polyglossia) const
1597 {
1598         DocumentClass const & tclass = params_.documentClass();
1599         // collect preamble snippets in a set to prevent multiple identical
1600         // commands (would happen if e.g. both theorem and theorem* are used)
1601         set<docstring> snippets;
1602         typedef LanguageList::const_iterator lang_it;
1603         lang_it const lbeg = UsedLanguages_.begin();
1604         lang_it const lend =  UsedLanguages_.end();
1605         list<docstring>::const_iterator cit = usedLayouts_.begin();
1606         list<docstring>::const_iterator end = usedLayouts_.end();
1607         for (; cit != end; ++cit) {
1608                 // language dependent commands (once per document)
1609                 snippets.insert(i18npreamble(tclass[*cit].langpreamble(),
1610                                                 buffer().language(),
1611                                                 buffer().params().encoding(),
1612                                                 use_polyglossia, false));
1613                 // commands for language changing (for multilanguage documents)
1614                 if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
1615                         snippets.insert(i18npreamble(
1616                                                 tclass[*cit].babelpreamble(),
1617                                                 buffer().language(),
1618                                                 buffer().params().encoding(),
1619                                                 use_polyglossia, false));
1620                         for (lang_it lit = lbeg; lit != lend; ++lit)
1621                                 snippets.insert(i18npreamble(
1622                                                 tclass[*cit].babelpreamble(),
1623                                                 *lit,
1624                                                 buffer().params().encoding(),
1625                                                 use_polyglossia, false));
1626                 }
1627         }
1628         if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
1629                 FloatList const & floats = params_.documentClass().floats();
1630                 UsedFloats::const_iterator fit = usedFloats_.begin();
1631                 UsedFloats::const_iterator fend = usedFloats_.end();
1632                 for (; fit != fend; ++fit) {
1633                         Floating const & fl = floats.getType(fit->first);
1634                         // we assume builtin floats are translated
1635                         if (fl.isPredefined())
1636                                 continue;
1637                         docstring const type = from_ascii(fl.floattype());
1638                         docstring const flname = from_utf8(fl.name());
1639                         docstring name = buffer().language()->translateLayout(fl.name());
1640                         // only request translation if we have a real translation
1641                         // (that differs from the source)
1642                         if (flname != name)
1643                                 snippets.insert(getFloatI18nPreamble(
1644                                                 type, name, buffer().language(),
1645                                                 buffer().params().encoding(),
1646                                                 use_polyglossia));
1647                         for (lang_it lit = lbeg; lit != lend; ++lit) {
1648                                 string const code = (*lit)->code();
1649                                 name = (*lit)->translateLayout(fl.name());
1650                                 // we assume we have a suitable translation if
1651                                 // either the language is English (we need to
1652                                 // translate into English if English is a secondary
1653                                 // language) or if translateIfPossible returns
1654                                 // something different to the English source.
1655                                 bool const have_translation =
1656                                         (flname != name || contains(code, "en"));
1657                                 if (have_translation)
1658                                         snippets.insert(getFloatI18nPreamble(
1659                                                 type, name, *lit,
1660                                                 buffer().params().encoding(),
1661                                                 use_polyglossia));
1662                         }
1663                 }
1664         }
1665
1666         cit = usedInsetLayouts_.begin();
1667         end = usedInsetLayouts_.end();
1668         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1669         for (; cit != end; ++cit) {
1670                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1671                 if (it == ils.end())
1672                         continue;
1673                 // The listings package does not work with variable width
1674                 // encodings, only with fixed width encodings. Therefore we
1675                 // need to force a fixed width encoding for
1676                 // \lstlistlistingname and \lstlistingname (bug 9382).
1677                 // This needs to be consistent with InsetListings::latex().
1678                 bool const need_fixedwidth = !runparams_.isFullUnicode() &&
1679                                 it->second.fixedwidthpreambleencoding();
1680                 // language dependent commands (once per document)
1681                 snippets.insert(i18npreamble(it->second.langpreamble(),
1682                                                 buffer().language(),
1683                                                 buffer().params().encoding(),
1684                                                 use_polyglossia, need_fixedwidth));
1685                 // commands for language changing (for multilanguage documents)
1686                 if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
1687                         snippets.insert(i18npreamble(
1688                                                 it->second.babelpreamble(),
1689                                                 buffer().language(),
1690                                                 buffer().params().encoding(),
1691                                                 use_polyglossia, need_fixedwidth));
1692                         for (lang_it lit = lbeg; lit != lend; ++lit)
1693                                 snippets.insert(i18npreamble(
1694                                                 it->second.babelpreamble(),
1695                                                 *lit,
1696                                                 buffer().params().encoding(),
1697                                                 use_polyglossia, need_fixedwidth));
1698                 }
1699         }
1700
1701         odocstringstream tcpreamble;
1702         set<docstring>::const_iterator const send = snippets.end();
1703         set<docstring>::const_iterator it = snippets.begin();
1704         for (; it != send; ++it)
1705                 tcpreamble << *it;
1706         return tcpreamble.str();
1707 }
1708
1709
1710 docstring const LaTeXFeatures::getLyXSGMLEntities() const
1711 {
1712         // Definition of entities used in the document that are LyX related.
1713         odocstringstream entities;
1714
1715         if (mustProvide("lyxarrow")) {
1716                 entities << "<!ENTITY lyxarrow \"-&gt;\">" << '\n';
1717         }
1718
1719         return entities.str();
1720 }
1721
1722
1723 docstring const LaTeXFeatures::getIncludedFiles(string const & fname) const
1724 {
1725         odocstringstream sgmlpreamble;
1726         // FIXME UNICODE
1727         docstring const basename(from_utf8(onlyPath(fname)));
1728
1729         FileMap::const_iterator end = IncludedFiles_.end();
1730         for (FileMap::const_iterator fi = IncludedFiles_.begin();
1731              fi != end; ++fi)
1732                 // FIXME UNICODE
1733                 sgmlpreamble << "\n<!ENTITY " << fi->first
1734                              << (isSGMLFileName(fi->second) ? " SYSTEM \"" : " \"")
1735                              << makeRelPath(from_utf8(fi->second), basename) << "\">";
1736
1737         return sgmlpreamble.str();
1738 }
1739
1740
1741 void LaTeXFeatures::showStruct() const
1742 {
1743         lyxerr << "LyX needs the following commands when LaTeXing:"
1744                << "\n***** Packages:" << getPackages()
1745                << "\n***** Macros:" << to_utf8(getMacros())
1746                << "\n***** Textclass stuff:" << to_utf8(getTClassPreamble())
1747                << "\n***** done." << endl;
1748 }
1749
1750
1751 Buffer const & LaTeXFeatures::buffer() const
1752 {
1753         return *buffer_;
1754 }
1755
1756
1757 void LaTeXFeatures::setBuffer(Buffer const & buffer)
1758 {
1759         buffer_ = &buffer;
1760 }
1761
1762
1763 BufferParams const & LaTeXFeatures::bufferParams() const
1764 {
1765         return params_;
1766 }
1767
1768
1769 void LaTeXFeatures::getFloatDefinitions(odocstream & os) const
1770 {
1771         FloatList const & floats = params_.documentClass().floats();
1772
1773         // Here we will output the code to create the needed float styles.
1774         // We will try to do this as minimal as possible.
1775         // \floatstyle{ruled}
1776         // \newfloat{algorithm}{htbp}{loa}
1777         // \providecommand{\algorithmname}{Algorithm}
1778         // \floatname{algorithm}{\protect\algorithmname}
1779         UsedFloats::const_iterator cit = usedFloats_.begin();
1780         UsedFloats::const_iterator end = usedFloats_.end();
1781         for (; cit != end; ++cit) {
1782                 Floating const & fl = floats.getType(cit->first);
1783
1784                 // For builtin floats we do nothing.
1785                 if (fl.isPredefined())
1786                         continue;
1787
1788                 // We have to special case "table" and "figure"
1789                 if (fl.floattype() == "tabular" || fl.floattype() == "figure") {
1790                         // Output code to modify "table" or "figure"
1791                         // but only if builtin == false
1792                         // and that have to be true at this point in the
1793                         // function.
1794                         docstring const type = from_ascii(fl.floattype());
1795                         docstring const placement = from_ascii(fl.placement());
1796                         docstring const style = from_ascii(fl.style());
1797                         if (!style.empty()) {
1798                                 os << "\\floatstyle{" << style << "}\n"
1799                                    << "\\restylefloat{" << type << "}\n";
1800                         }
1801                         if (!placement.empty()) {
1802                                 os << "\\floatplacement{" << type << "}{"
1803                                    << placement << "}\n";
1804                         }
1805                 } else {
1806                         // The other non builtin floats.
1807
1808                         docstring const type = from_ascii(fl.floattype());
1809                         docstring const placement = from_ascii(fl.placement());
1810                         docstring const ext = from_ascii(fl.ext());
1811                         docstring const within = from_ascii(fl.within());
1812                         docstring const style = from_ascii(fl.style());
1813                         docstring const name =
1814                                 buffer().language()->translateLayout(fl.name());
1815                         os << "\\floatstyle{" << style << "}\n"
1816                            << "\\newfloat{" << type << "}{" << placement
1817                            << "}{" << ext << '}';
1818                         if (!within.empty())
1819                                 os << '[' << within << ']';
1820                         os << '\n'
1821                            << "\\providecommand{\\" << type << "name}{"
1822                            << name << "}\n"
1823                            << "\\floatname{" << type << "}{\\protect\\"
1824                            << type << "name}\n";
1825
1826                         // What missing here is to code to minimalize the code
1827                         // output so that the same floatstyle will not be
1828                         // used several times, when the same style is still in
1829                         // effect. (Lgb)
1830                 }
1831                 if (cit->second)
1832                         // The subfig package is loaded later
1833                         os << "\n\\AtBeginDocument{\\newsubfloat{" << from_ascii(fl.floattype()) << "}}\n";
1834         }
1835 }
1836
1837
1838 void LaTeXFeatures::resolveAlternatives()
1839 {
1840         for (Features::iterator it = features_.begin(); it != features_.end();) {
1841                 if (contains(*it, '|')) {
1842                         vector<string> const alternatives = getVectorFromString(*it, "|");
1843                         vector<string>::const_iterator const end = alternatives.end();
1844                         vector<string>::const_iterator ita = alternatives.begin();
1845                         // Is any alternative already required? => use that
1846                         for (; ita != end; ++ita) {
1847                                 if (isRequired(*ita))
1848                                         break;
1849                         }
1850                         // Is any alternative available? => use the first one
1851                         // (bug 9498)
1852                         if (ita == end) {
1853                                 for (ita = alternatives.begin(); ita != end; ++ita) {
1854                                         if (isAvailable(*ita)) {
1855                                                 require(*ita);
1856                                                 break;
1857                                         }
1858                                 }
1859                         }
1860                         // This will not work, but not requiring something
1861                         // would be more confusing
1862                         if (ita == end)
1863                                 require(alternatives.front());
1864                         features_.erase(it);
1865                         it = features_.begin();
1866                 } else
1867                         ++it;
1868         }
1869 }
1870
1871
1872 } // namespace lyx