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