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