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