]> git.lyx.org Git - lyx.git/blob - src/LaTeXFeatures.cpp
eb31dbab66fcabf739b2f28c1b307ff5f6223415
[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         "covington",
975         "csquotes",
976         "enumitem",
977         "endnotes",
978         "hhline",
979         "ifthen",
980         // listings is handled in BufferParams.cpp
981         "bm",
982         "pdfpages",
983         "amscd",
984         "slashed",
985         "multicol",
986         "multirow",
987         "tfrupee",
988         "shapepar",
989         "rsphrase",
990         "hpstatement",
991         "algorithm2e",
992         "sectionbox",
993         "tcolorbox",
994         "pdfcomment",
995         "fixme",
996         "todonotes",
997         "forest",
998         "varwidth",
999         "tablefootnote",
1000         "afterpage",
1001         "tabularx",
1002         "xltabular",
1003         "chessboard",
1004         "xskak"
1005 };
1006
1007 char const * bibliofeatures[] = {
1008         // Known bibliography packages (will be loaded before natbib)
1009         "achicago",
1010         "apacite",
1011         "apalike",
1012         "astron",
1013         "authordate1-4",
1014         "babelbib",
1015         "bibgerm",
1016         "chapterbib",
1017         "chicago",
1018         "chscite",
1019         "harvard",
1020         "mslapa",
1021         "named"
1022 };
1023
1024 int const nb_bibliofeatures = sizeof(bibliofeatures) / sizeof(char const *);
1025
1026 int const nb_simplefeatures = sizeof(simplefeatures) / sizeof(char const *);
1027
1028 } // namespace
1029
1030
1031 string const LaTeXFeatures::getColorOptions() const
1032 {
1033         ostringstream colors;
1034
1035         // Handling the color packages separately is needed to be able to load them
1036         // before babel when hyperref is loaded with the colorlinks option
1037         // for more info see Bufferparams.cpp
1038
1039         // [x]color.sty
1040         if (mustProvide("color") || mustProvide("xcolor")) {
1041                 string const package =
1042                         (mustProvide("xcolor") ? "xcolor" : "color");
1043                 if (params_.graphics_driver == "default"
1044                         || params_.graphics_driver == "none")
1045                         colors << "\\usepackage{" << package << "}\n";
1046                 else
1047                         colors << "\\usepackage["
1048                                  << params_.graphics_driver
1049                                  << "]{" << package << "}\n";
1050         }
1051
1052         // pdfcolmk must be loaded after color
1053         if (mustProvide("pdfcolmk"))
1054                 colors << "\\usepackage{pdfcolmk}\n";
1055
1056         // the following 3 color commands must be set after color
1057         // is loaded and before pdfpages, therefore add the command
1058         // here define the set color
1059         if (mustProvide("pagecolor")) {
1060                 colors << "\\definecolor{page_backgroundcolor}{rgb}{";
1061                 colors << outputLaTeXColor(params_.backgroundcolor) << "}\n";
1062                 // set the page color
1063                 colors << "\\pagecolor{page_backgroundcolor}\n";
1064         }
1065
1066         if (mustProvide("fontcolor")) {
1067                 colors << "\\definecolor{document_fontcolor}{rgb}{";
1068                 colors << outputLaTeXColor(params_.fontcolor) << "}\n";
1069                 // set the color
1070                 colors << "\\color{document_fontcolor}\n";
1071         }
1072
1073         if (mustProvide("lyxgreyedout")) {
1074                 colors << "\\definecolor{note_fontcolor}{rgb}{";
1075                 colors << outputLaTeXColor(params_.notefontcolor) << "}\n";
1076                 // the color will be set together with the definition of
1077                 // the lyxgreyedout environment (see lyxgreyedout_def)
1078         }
1079
1080         // color for shaded boxes
1081         if (isRequired("framed") && mustProvide("color")) {
1082                 colors << "\\definecolor{shadecolor}{rgb}{";
1083                 colors << outputLaTeXColor(params_.boxbgcolor) << "}\n";
1084                 // this color is automatically used by the LaTeX-package "framed"
1085         }
1086
1087         return colors.str();
1088 }
1089
1090
1091 string const LaTeXFeatures::getPackageOptions() const
1092 {
1093         ostringstream packageopts;
1094         // Output all the package option stuff we have been asked to do.
1095         map<string, string>::const_iterator it =
1096                 params_.documentClass().packageOptions().begin();
1097         map<string, string>::const_iterator en =
1098                 params_.documentClass().packageOptions().end();
1099         for (; it != en; ++it)
1100                 if (mustProvide(it->first))
1101                         packageopts << "\\PassOptionsToPackage{" << it->second << "}"
1102                                  << "{" << it->first << "}\n";
1103         return packageopts.str();
1104 }
1105
1106
1107 string const LaTeXFeatures::getPackages() const
1108 {
1109         ostringstream packages;
1110
1111         // FIXME: currently, we can only load packages and macros known
1112         // to LyX.
1113         // However, with the Require tag of layouts/custom insets,
1114         // also unknown packages can be requested. They are silently
1115         // swallowed now. We should change this eventually.
1116
1117         //  These are all the 'simple' includes.  i.e
1118         //  packages which we just \usepackage{package}
1119         for (int i = 0; i < nb_simplefeatures; ++i) {
1120                 if (mustProvide(simplefeatures[i]))
1121                         packages << "\\usepackage{" << simplefeatures[i] << "}\n";
1122         }
1123
1124         // The rest of these packages are somewhat more complicated
1125         // than those above.
1126
1127         if (mustProvide("footnote")) {
1128                 if (isRequired("hyperref"))
1129                         packages << "\\usepackage{footnotehyper}\n";
1130                 else
1131                         packages << "\\usepackage{footnote}\n";
1132         }
1133
1134         // [pdf]lscape is used to rotate longtables
1135         if (mustProvide("lscape")) {
1136                 if (runparams_.flavor == OutputParams::LATEX
1137                     || runparams_.flavor == OutputParams::DVILUATEX)
1138                         packages << "\\usepackage{lscape}\n";
1139                 else
1140                         packages << "\\usepackage{pdflscape}\n";
1141         }
1142
1143         // The tipa package and its extensions (tipx, tone) must not
1144         // be loaded with non-TeX fonts, since fontspec includes the
1145         // respective macros
1146         if (mustProvide("tipa") && !params_.useNonTeXFonts)
1147                 packages << "\\usepackage{tipa}\n";
1148         if (mustProvide("tipx") && !params_.useNonTeXFonts)
1149                 packages << "\\usepackage{tipx}\n";
1150         if (mustProvide("extraipa") && !params_.useNonTeXFonts)
1151                 packages << "\\usepackage{extraipa}\n";
1152         if (mustProvide("tone") && !params_.useNonTeXFonts)
1153                 packages << "\\usepackage{tone}\n";
1154
1155         // if fontspec or newtxmath is used, AMS packages have to be loaded
1156         // before fontspec (in BufferParams)
1157         string const amsPackages = loadAMSPackages();
1158         bool const ot1 = (params_.main_font_encoding() == "default"
1159                           || params_.main_font_encoding() == "OT1");
1160         bool const use_newtxmath =
1161                 theLaTeXFonts().getLaTeXFont(from_ascii(params_.fontsMath())).getUsedPackage(
1162                         ot1, false, false) == "newtxmath";
1163
1164         if (!params_.useNonTeXFonts && !use_newtxmath && !amsPackages.empty())
1165                 packages << amsPackages;
1166
1167         if (mustProvide("cancel") &&
1168             params_.use_package("cancel") != BufferParams::package_off)
1169                 packages << "\\usepackage{cancel}\n";
1170
1171         // marvosym and bbding both define the \Cross macro
1172         if (mustProvide("marvosym")) {
1173             if (mustProvide("bbding"))
1174                 packages << "\\let\\Cross\\relax\n";
1175             packages << "\\usepackage{marvosym}\n";
1176         }
1177
1178         // accents must be loaded after amsmath
1179         if (mustProvide("accents") &&
1180             params_.use_package("accents") != BufferParams::package_off)
1181                 packages << "\\usepackage{accents}\n";
1182
1183         // mathdots must be loaded after amsmath
1184         if (mustProvide("mathdots") &&
1185                 params_.use_package("mathdots") != BufferParams::package_off)
1186                 packages << "\\usepackage{mathdots}\n";
1187
1188         // yhmath must be loaded after amsmath
1189         if (mustProvide("yhmath") &&
1190             params_.use_package("yhmath") != BufferParams::package_off)
1191                 packages << "\\usepackage{yhmath}\n";
1192
1193         // stmaryrd must be loaded after amsmath
1194         if (mustProvide("stmaryrd") &&
1195             params_.use_package("stmaryrd") != BufferParams::package_off)
1196                 packages << "\\usepackage{stmaryrd}\n";
1197
1198         if (mustProvide("stackrel") &&
1199             params_.use_package("stackrel") != BufferParams::package_off)
1200                 packages << "\\usepackage{stackrel}\n";
1201
1202         if (mustProvide("undertilde") &&
1203                 params_.use_package("undertilde") != BufferParams::package_off)
1204                 packages << "\\usepackage{undertilde}\n";
1205
1206         // [x]color and pdfcolmk are handled in getColorOptions() above
1207
1208         // makeidx.sty
1209         if (isRequired("makeidx") || isRequired("splitidx")) {
1210                 if (!isProvided("makeidx") && !isRequired("splitidx"))
1211                         packages << "\\usepackage{makeidx}\n";
1212                 if (mustProvide("splitidx"))
1213                         packages << "\\usepackage{splitidx}\n";
1214                 packages << "\\makeindex\n";
1215         }
1216
1217         // graphicx.sty
1218         if (mustProvide("graphicx") && params_.graphics_driver != "none") {
1219                 if (params_.graphics_driver == "default")
1220                         packages << "\\usepackage{graphicx}\n";
1221                 else
1222                         packages << "\\usepackage["
1223                                  << params_.graphics_driver
1224                                  << "]{graphicx}\n";
1225         }
1226
1227         // lyxskak.sty --- newer chess support based on skak.sty
1228         if (mustProvide("chess"))
1229                 packages << "\\usepackage[ps,mover]{lyxskak}\n";
1230
1231         // setspace.sty
1232         if (mustProvide("setspace") && !isProvided("SetSpace"))
1233                 packages << "\\usepackage{setspace}\n";
1234
1235         // we need to assure that mhchem is loaded before esint and every other
1236         // package that redefines command of amsmath because mhchem loads amlatex
1237         // (this info is from the author of mhchem from June 2013)
1238         if (mustProvide("mhchem") &&
1239             params_.use_package("mhchem") != BufferParams::package_off)
1240                 packages << "\\PassOptionsToPackage{version=3}{mhchem}\n"
1241                             "\\usepackage{mhchem}\n";
1242
1243         // wasysym is a simple feature, but it must be after amsmath if both
1244         // are used
1245         // wasysym redefines some integrals (e.g. iint) from amsmath. That
1246         // leads to inconsistent integrals. We only load this package if
1247         // the document does not contain integrals (then isRequired("esint")
1248         // is false) or if esint is used, since esint redefines all relevant
1249         // integral symbols from wasysym and amsmath.
1250         // See http://www.lyx.org/trac/ticket/1942
1251         if (mustProvide("wasysym") &&
1252             params_.use_package("wasysym") != BufferParams::package_off &&
1253             (params_.use_package("esint") != BufferParams::package_off || !isRequired("esint")))
1254                 packages << "\\usepackage{wasysym}\n";
1255
1256         // esint must be after amsmath (and packages requiring amsmath, like mhchem)
1257         // and wasysym, since it will redeclare inconsistent integral symbols
1258         if (mustProvide("esint") &&
1259             params_.use_package("esint") != BufferParams::package_off)
1260                 packages << "\\usepackage{esint}\n";
1261
1262         // Known bibliography packages (simple \usepackage{package})
1263         for (int i = 0; i < nb_bibliofeatures; ++i) {
1264                 if (mustProvide(bibliofeatures[i]))
1265                         packages << "\\usepackage{"
1266                                  << bibliofeatures[i] << "}\n";
1267         }
1268
1269         // Compatibility between achicago and natbib
1270         if (mustProvide("achicago") && mustProvide("natbib"))
1271                 packages << "\\let\\achicagobib\\thebibliography\n";
1272
1273         // natbib.sty
1274         // Some classes load natbib themselves, but still allow (or even require)
1275         // plain numeric citations (ReVTeX is such a case, see bug 5182).
1276         // This special case is indicated by the "natbib-internal" key.
1277         if (mustProvide("natbib")
1278             && !isProvided("natbib-internal")
1279             && !isProvided("biblatex")
1280             && !isProvided("biblatex-natbib")
1281             && !isProvided("jurabib")) {
1282                 packages << "\\usepackage[";
1283                 if (params_.citeEngineType() == ENGINE_TYPE_NUMERICAL)
1284                         packages << "numbers";
1285                 else
1286                         packages << "authoryear";
1287                 if (!params_.biblio_opts.empty())
1288                         packages << ',' << params_.biblio_opts;
1289                 packages << "]{natbib}\n";
1290         }
1291
1292         // Compatibility between achicago and natbib
1293         if (mustProvide("achicago") && mustProvide("natbib")) {
1294                 packages << "\\let\\thebibliography\\achicagobib\n";
1295                 packages << "\\let\\SCcite\\astroncite\n";
1296                 packages << "\\let\\UnexpandableProtect\\protect\n";
1297         }
1298
1299         // jurabib -- we need version 0.6 at least.
1300         if (mustProvide("jurabib")
1301             && !isProvided("natbib-internal")
1302             && !isProvided("natbib")
1303             && !isProvided("biblatex")
1304             && !isProvided("biblatex-natbib")) {
1305                 packages << "\\usepackage";
1306                 if (!params_.biblio_opts.empty())
1307                         packages << '[' << params_.biblio_opts << ']';
1308                 packages << "{jurabib}[2004/01/25]\n";
1309         }
1310
1311         // opcit -- we pass custombst as we output \bibliographystyle ourselves
1312         if (mustProvide("opcit")) {
1313                 if (isRequired("hyperref"))
1314                         packages << "\\usepackage[custombst,hyperref]{opcit}\n";
1315                 else
1316                         packages << "\\usepackage[custombst]{opcit}\n";
1317         }
1318
1319         // xargs -- we need version 1.09 at least
1320         if (mustProvide("xargs"))
1321                 packages << "\\usepackage{xargs}[2008/03/08]\n";
1322
1323         if (mustProvide("xy"))
1324                 packages << "\\usepackage[all]{xy}\n";
1325
1326         if (mustProvide("feyn"))
1327                 packages << "\\usepackage{feyn}\n"; //Diagram
1328
1329         if (mustProvide("ulem"))
1330                 packages << "\\PassOptionsToPackage{normalem}{ulem}\n"
1331                             "\\usepackage{ulem}\n";
1332
1333         if (mustProvide("nomencl")) {
1334                 // Make it work with the new and old version of the package,
1335                 // but don't use the compatibility option since it is
1336                 // incompatible to other packages.
1337                 packages << "\\usepackage{nomencl}\n"
1338                             "% the following is useful when we have the old nomencl.sty package\n"
1339                             "\\providecommand{\\printnomenclature}{\\printglossary}\n"
1340                             "\\providecommand{\\makenomenclature}{\\makeglossary}\n"
1341                             "\\makenomenclature\n";
1342         }
1343
1344         // fixltx2e provides subscript
1345         if (mustProvide("subscript") && !isRequired("fixltx2e"))
1346                 packages << "\\usepackage{subscript}\n";
1347
1348         // footmisc must be loaded after setspace
1349         // Set options here, load the package after the user preamble to
1350         // avoid problems with manual loaded footmisc.
1351         if (mustProvide("footmisc"))
1352                 packages << "\\PassOptionsToPackage{stable}{footmisc}\n";
1353
1354         if (mustProvide("microtype")){
1355                 packages << "\\usepackage{microtype}\n";
1356         }
1357
1358         return packages.str();
1359 }
1360
1361
1362 TexString LaTeXFeatures::getMacros() const
1363 {
1364         otexstringstream macros;
1365
1366         if (!preamble_snippets_.empty()) {
1367                 macros << '\n';
1368                 macros << getPreambleSnippets();
1369         }
1370
1371         if (mustProvide("xetexdashbreakstate"))
1372                 macros << "\\XeTeXdashbreakstate 0" << '\n';
1373
1374         if (mustProvide("papersize")) {
1375                 if (runparams_.flavor == OutputParams::LATEX
1376                     || runparams_.flavor == OutputParams::DVILUATEX)
1377                         macros << papersizedvi_def << '\n';
1378                 else if  (runparams_.flavor == OutputParams::LUATEX)
1379                         macros << papersizepdflua_def << '\n';
1380                 else
1381                         macros << papersizepdf_def << '\n';
1382         }
1383
1384         if (mustProvide("LyX")) {
1385                 if (isRequired("hyperref"))
1386                         macros << lyx_hyperref_def << '\n';
1387                 else
1388                         macros << lyx_def << '\n';
1389                 if (runparams_.use_polyglossia && hasRTLLanguage())
1390                         macros << lyx_rtl_def << '\n';
1391         }
1392
1393         if (mustProvide("noun"))
1394                 macros << noun_def << '\n';
1395
1396         if (mustProvide("lyxarrow"))
1397                 macros << lyxarrow_def << '\n';
1398
1399         if (mustProvide("lyxzerowidthspace"))
1400                 macros << lyxZWSP_def << '\n';
1401
1402         if (!usePolyglossia() && mustProvide("textgreek")) {
1403             // ensure LGR font encoding is defined also if fontenc is not loaded by LyX
1404                 if (params_.main_font_encoding() == "default")
1405                         macros << textgreek_LGR_def;
1406                 macros << textgreek_def << '\n';
1407         }
1408
1409         if (!usePolyglossia() && mustProvide("textcyrillic")) {
1410                 // ensure T2A font encoding is set up also if fontenc is not loaded by LyX
1411                 if (params_.main_font_encoding() == "default")
1412                         macros << textcyr_T2A_def;
1413                 macros << textcyr_def << '\n';
1414         }
1415
1416         // non-standard text accents:
1417         if (mustProvide("textcommaabove") || mustProvide("textcommaaboveright") ||
1418             mustProvide("textcommabelow") || mustProvide("textbaltic"))
1419                 macros << lyxaccent_def;
1420
1421         if (mustProvide("textcommabelow") || mustProvide("textbaltic"))
1422                 macros << textcommabelow_def << '\n';
1423
1424         if (mustProvide("textcommaabove") || mustProvide("textbaltic"))
1425                 macros << textcommaabove_def << '\n';
1426
1427         if (mustProvide("textcommaaboveright"))
1428                 macros << textcommaaboveright_def << '\n';
1429
1430         if (mustProvide("textbaltic"))
1431                 macros << textbaltic_def << '\n';
1432
1433         // split-level fractions
1434         if (mustProvide("xfrac") || mustProvide("smallLetterFrac"))
1435                 macros << xfrac_def << '\n';
1436
1437         if (mustProvide("smallLetterFrac"))
1438                 macros << smallLetterFrac_def << '\n';
1439
1440         if (mustProvide("lyxmathsym"))
1441                 macros << lyxmathsym_def << '\n';
1442
1443         if (mustProvide("cedilla"))
1444                 macros << cedilla_def << '\n';
1445
1446         if (mustProvide("subring"))
1447                 macros << subring_def << '\n';
1448
1449         if (mustProvide("subdot"))
1450                 macros << subdot_def << '\n';
1451
1452         if (mustProvide("subhat"))
1453                 macros << subhat_def << '\n';
1454
1455         if (mustProvide("subtilde"))
1456                 macros << subtilde_def << '\n';
1457
1458         if (mustProvide("dacute"))
1459                 macros << dacute_def << '\n';
1460
1461         if (mustProvide("tipasymb"))
1462                 macros << tipasymb_def << '\n';
1463
1464         if (mustProvide("dgrave"))
1465                 macros << dgrave_def << '\n';
1466
1467         if (mustProvide("rcap"))
1468                 macros << rcap_def << '\n';
1469
1470         if (mustProvide("ogonek"))
1471                 macros << ogonek_def << '\n';
1472
1473         // quotes.
1474         if (mustProvide("quotesinglbase"))
1475                 macros << quotesinglbase_def << '\n';
1476         if (mustProvide("quotedblbase"))
1477                 macros << quotedblbase_def << '\n';
1478         if (mustProvide("guilsinglleft"))
1479                 macros << guilsinglleft_def << '\n';
1480         if (mustProvide("guilsinglright"))
1481                 macros << guilsinglright_def << '\n';
1482         if (mustProvide("guillemotleft"))
1483                 macros << guillemotleft_def << '\n';
1484         if (mustProvide("guillemotright"))
1485                 macros << guillemotright_def << '\n';
1486         if (mustProvide("textquotedbl"))
1487                 macros << textquotedbl_def << '\n';
1488         if (mustProvide("textquotesinglep")) {
1489                 if (runparams_.flavor == OutputParams::XETEX)
1490                         macros << textquotesinglep_xetex_def << '\n';
1491                 else
1492                         macros << textquotesinglep_luatex_def << '\n';
1493         }
1494         if (mustProvide("textquotedblp")) {
1495                 if (runparams_.flavor == OutputParams::XETEX)
1496                         macros << textquotedblp_xetex_def << '\n';
1497                 else
1498                         macros << textquotedblp_luatex_def << '\n';
1499         }
1500
1501         // Math mode
1502         if (mustProvide("binom") && !isRequired("amsmath"))
1503                 macros << binom_def << '\n';
1504         if (mustProvide("mathcircumflex"))
1505                 macros << mathcircumflex_def << '\n';
1506
1507         // other
1508         if (mustProvide("ParagraphLeftIndent"))
1509                 macros << paragraphleftindent_def;
1510         if (mustProvide("NeedLyXFootnoteCode"))
1511                 macros << floatingfootnote_def;
1512
1513         // some problems with tex->html converters
1514         if (mustProvide("NeedTabularnewline"))
1515                 macros << tabularnewline_def;
1516
1517         // greyed-out environment (note inset)
1518         // the color is specified in the routine
1519         // getColorOptions() to avoid LaTeX-package clashes
1520         if (mustProvide("lyxgreyedout"))
1521                 macros << lyxgreyedout_def;
1522
1523         if (mustProvide("lyxdot"))
1524                 macros << lyxdot_def << '\n';
1525
1526         // floats
1527         getFloatDefinitions(macros);
1528
1529         if (mustProvide("refstyle"))
1530                 macros << lyxref_def << '\n';
1531
1532         // change tracking
1533         if (mustProvide("ct-dvipost"))
1534                 macros << changetracking_dvipost_def;
1535
1536         if (mustProvide("ct-xcolor-ulem")) {
1537                 streamsize const prec = macros.os().precision(2);
1538
1539                 RGBColor cadd = rgbFromHexName(lcolor.getX11Name(Color_addedtext));
1540                 macros << "\\providecolor{lyxadded}{rgb}{"
1541                        << cadd.r / 255.0 << ',' << cadd.g / 255.0 << ',' << cadd.b / 255.0 << "}\n";
1542
1543                 RGBColor cdel = rgbFromHexName(lcolor.getX11Name(Color_deletedtext));
1544                 macros << "\\providecolor{lyxdeleted}{rgb}{"
1545                        << cdel.r / 255.0 << ',' << cdel.g / 255.0 << ',' << cdel.b / 255.0 << "}\n";
1546
1547                 macros.os().precision(prec);
1548
1549                 if (isRequired("hyperref"))
1550                         macros << changetracking_xcolor_ulem_hyperref_def;
1551                 else
1552                         macros << changetracking_xcolor_ulem_def;
1553         }
1554
1555         if (mustProvide("ct-tikz-math-sout"))
1556                         macros << changetracking_tikz_math_sout_def;
1557
1558         if (mustProvide("ct-none"))
1559                 macros << changetracking_none_def;
1560
1561         if (mustProvide("rtloutputdblcol"))
1562                 macros << rtloutputdblcol_def;
1563
1564         if (mustProvide("lyxmintcaption"))
1565                 macros << lyxmintcaption_def;
1566
1567         return macros.release();
1568 }
1569
1570
1571 docstring const LaTeXFeatures::getBabelPresettings() const
1572 {
1573         odocstringstream tmp;
1574
1575         for (Language const * lang : UsedLanguages_)
1576                 if (!lang->babel_presettings().empty())
1577                         tmp << lang->babel_presettings() << '\n';
1578         if (!params_.language->babel_presettings().empty())
1579                 tmp << params_.language->babel_presettings() << '\n';
1580
1581         if (!contains(tmp.str(), '@'))
1582                 return tmp.str();
1583
1584         return "\\makeatletter\n" + tmp.str() + "\\makeatother\n";
1585 }
1586
1587
1588 docstring const LaTeXFeatures::getBabelPostsettings() const
1589 {
1590         odocstringstream tmp;
1591
1592         for (Language const * lang : UsedLanguages_)
1593                 if (!lang->babel_postsettings().empty())
1594                         tmp << lang->babel_postsettings() << '\n';
1595         if (!params_.language->babel_postsettings().empty())
1596                 tmp << params_.language->babel_postsettings() << '\n';
1597
1598         if (!contains(tmp.str(), '@'))
1599                 return tmp.str();
1600
1601         return "\\makeatletter\n" + tmp.str() + "\\makeatother\n";
1602 }
1603
1604
1605 bool LaTeXFeatures::needBabelLangOptions() const
1606 {
1607         if (!lyxrc.language_global_options || params_.language->asBabelOptions())
1608                 return true;
1609
1610         LanguageList::const_iterator it  = UsedLanguages_.begin();
1611         LanguageList::const_iterator end = UsedLanguages_.end();
1612         for (; it != end; ++it)
1613                 if ((*it)->asBabelOptions())
1614                         return true;
1615
1616         return false;
1617 }
1618
1619
1620 string const LaTeXFeatures::loadAMSPackages() const
1621 {
1622         ostringstream tmp;
1623
1624         if (mustProvide("amsmath")
1625             && params_.use_package("amsmath") != BufferParams::package_off) {
1626                 tmp << "\\usepackage{amsmath}\n";
1627         } else {
1628                 // amsbsy and amstext are already provided by amsmath
1629                 if (mustProvide("amsbsy"))
1630                         tmp << "\\usepackage{amsbsy}\n";
1631                 if (mustProvide("amstext"))
1632                         tmp << "\\usepackage{amstext}\n";
1633         }
1634
1635         if (mustProvide("amsthm"))
1636                 tmp << "\\usepackage{amsthm}\n";
1637
1638         if (mustProvide("amssymb")
1639             && params_.use_package("amssymb") != BufferParams::package_off)
1640                 tmp << "\\usepackage{amssymb}\n";
1641
1642         return tmp.str();
1643 }
1644
1645
1646 docstring const LaTeXFeatures::getTClassPreamble() const
1647 {
1648         // the text class specific preamble
1649         DocumentClass const & tclass = params_.documentClass();
1650         odocstringstream tcpreamble;
1651
1652         tcpreamble << tclass.preamble();
1653
1654         list<docstring>::const_iterator cit = usedLayouts_.begin();
1655         list<docstring>::const_iterator end = usedLayouts_.end();
1656         for (; cit != end; ++cit)
1657                 // For InPreamble layouts, we output the preamble stuff earlier
1658                 // (before the layouts). See Paragraph::Private::validate.
1659                 if (!tclass[*cit].inpreamble)
1660                         tcpreamble << tclass[*cit].preamble();
1661
1662         cit = usedInsetLayouts_.begin();
1663         end = usedInsetLayouts_.end();
1664         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1665         for (; cit != end; ++cit) {
1666                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1667                 if (it == ils.end())
1668                         continue;
1669                 tcpreamble << it->second.preamble();
1670         }
1671
1672         return tcpreamble.str();
1673 }
1674
1675
1676 docstring const LaTeXFeatures::getTClassHTMLPreamble() const
1677 {
1678         DocumentClass const & tclass = params_.documentClass();
1679         odocstringstream tcpreamble;
1680
1681         tcpreamble << tclass.htmlpreamble();
1682
1683         list<docstring>::const_iterator cit = usedLayouts_.begin();
1684         list<docstring>::const_iterator end = usedLayouts_.end();
1685         for (; cit != end; ++cit)
1686                 tcpreamble << tclass[*cit].htmlpreamble();
1687
1688         cit = usedInsetLayouts_.begin();
1689         end = usedInsetLayouts_.end();
1690         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1691         for (; cit != end; ++cit) {
1692                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1693                 if (it == ils.end())
1694                         continue;
1695                 tcpreamble << it->second.htmlpreamble();
1696         }
1697
1698         return tcpreamble.str();
1699 }
1700
1701
1702 docstring const LaTeXFeatures::getTClassHTMLStyles() const
1703 {
1704         DocumentClass const & tclass = params_.documentClass();
1705         odocstringstream tcpreamble;
1706
1707         if (mustProvide("noun"))
1708                 tcpreamble << lyxnoun_style;
1709         // this isn't exact, but it won't hurt that much if it
1710         // wasn't for this.
1711         if (mustProvide("ulem"))
1712                 tcpreamble << lyxstrikeout_style;
1713
1714         tcpreamble << tclass.htmlstyles();
1715
1716         list<docstring>::const_iterator cit = usedLayouts_.begin();
1717         list<docstring>::const_iterator end = usedLayouts_.end();
1718         for (; cit != end; ++cit)
1719                 tcpreamble << tclass[*cit].htmlstyle();
1720
1721         cit = usedInsetLayouts_.begin();
1722         end = usedInsetLayouts_.end();
1723         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1724         for (; cit != end; ++cit) {
1725                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1726                 if (it == ils.end())
1727                         continue;
1728                 tcpreamble << it->second.htmlstyle();
1729         }
1730
1731         return tcpreamble.str();
1732 }
1733
1734
1735 namespace {
1736
1737 docstring const getFloatI18nPreamble(docstring const & type,
1738                         docstring const & name, Language const * lang,
1739                         Encoding const & enc, bool const polyglossia)
1740 {
1741         // Check whether name can be encoded in the buffer encoding
1742         bool encodable = true;
1743         for (size_t i = 0; i < name.size(); ++i) {
1744                 if (!enc.encodable(name[i])) {
1745                         encodable = false;
1746                         break;
1747                 }
1748         }
1749
1750         docstring const language = polyglossia ? from_ascii(lang->polyglossia())
1751                                                : from_ascii(lang->babel());
1752         docstring const langenc = from_ascii(lang->encoding()->iconvName());
1753         docstring const texenc = from_ascii(lang->encoding()->latexName());
1754         docstring const bufenc = from_ascii(enc.iconvName());
1755         docstring const s1 = docstring(1, 0xF0000);
1756         docstring const s2 = docstring(1, 0xF0001);
1757         docstring const translated = encodable ? name
1758                 : from_ascii("\\inputencoding{") + texenc + from_ascii("}")
1759                         + s1 + langenc + s2 + name + s1 + bufenc + s2;
1760
1761         odocstringstream os;
1762         os << "\\addto\\captions" << language
1763            << "{\\renewcommand{\\" << type << "name}{" << translated << "}}\n";
1764         return os.str();
1765 }
1766
1767
1768 docstring const i18npreamble(docstring const & templ, Language const * lang,
1769                              Encoding const & enc, bool const polyglossia,
1770                              bool const need_fixedwidth)
1771 {
1772         if (templ.empty())
1773                 return templ;
1774
1775         string preamble = polyglossia ?
1776                 subst(to_utf8(templ), "$$lang", lang->polyglossia()) :
1777                 subst(to_utf8(templ), "$$lang", lang->babel());
1778
1779         string const langenc = lang->encoding()->iconvName();
1780         string const texenc = lang->encoding()->latexName();
1781         string const bufenc = enc.iconvName();
1782         Encoding const * testenc(&enc);
1783         bool lang_fallback = false;
1784         bool ascii_fallback = false;
1785         if (need_fixedwidth && !enc.hasFixedWidth()) {
1786                 if (lang->encoding()->hasFixedWidth()) {
1787                         testenc = lang->encoding();
1788                         lang_fallback = true;
1789                 } else {
1790                         // We need a fixed width encoding, but both the buffer
1791                         // encoding and the language encoding are variable
1792                         // width. As a last fallback, try to convert to pure
1793                         // ASCII using the LaTeX commands defined in unicodesymbols.
1794                         testenc = encodings.fromLyXName("ascii");
1795                         if (!testenc)
1796                                 return docstring();
1797                         ascii_fallback = true;
1798                 }
1799         }
1800         // First and second character of plane 15 (Private Use Area)
1801         string const s1 = "\xf3\xb0\x80\x80"; // U+F0000
1802         string const s2 = "\xf3\xb0\x80\x81"; // U+F0001
1803         // FIXME UNICODE
1804         // lyx::regex is not unicode-safe.
1805         // Should use QRegExp or (boost::u32regex, but that requires ICU)
1806         static regex const reg("_\\(([^\\)]+)\\)");
1807         smatch sub;
1808         while (regex_search(preamble, sub, reg)) {
1809                 string const key = sub.str(1);
1810                 docstring const name = lang->translateLayout(key);
1811                 // Check whether name can be encoded in the buffer encoding
1812                 bool encodable = true;
1813                 for (size_t i = 0; i < name.size() && encodable; ++i)
1814                         if (!testenc->encodable(name[i]))
1815                                 encodable = false;
1816                 string translated;
1817                 if (encodable && !lang_fallback)
1818                         translated = to_utf8(name);
1819                 else if (ascii_fallback)
1820                         translated = to_ascii(testenc->latexString(name).first);
1821                 else
1822                         translated = "\\inputencoding{" + texenc + "}"
1823                                 + s1 + langenc + s2 + to_utf8(name)
1824                                 + s1 + bufenc + s2;
1825                 preamble = subst(preamble, sub.str(), translated);
1826         }
1827         return from_utf8(preamble);
1828 }
1829
1830 } // namespace
1831
1832
1833 docstring const LaTeXFeatures::getTClassI18nPreamble(bool use_babel,
1834                                 bool use_polyglossia, bool use_minted) const
1835 {
1836         DocumentClass const & tclass = params_.documentClass();
1837         // collect preamble snippets in a set to prevent multiple identical
1838         // commands (would happen if e.g. both theorem and theorem* are used)
1839         set<docstring> snippets;
1840         typedef LanguageList::const_iterator lang_it;
1841         lang_it const lbeg = UsedLanguages_.begin();
1842         lang_it const lend =  UsedLanguages_.end();
1843         list<docstring>::const_iterator cit = usedLayouts_.begin();
1844         list<docstring>::const_iterator end = usedLayouts_.end();
1845         for (; cit != end; ++cit) {
1846                 // language dependent commands (once per document)
1847                 snippets.insert(i18npreamble(tclass[*cit].langpreamble(),
1848                                                 buffer().language(),
1849                                                 buffer().params().encoding(),
1850                                                 use_polyglossia, false));
1851                 // commands for language changing (for multilanguage documents)
1852                 if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
1853                         snippets.insert(i18npreamble(
1854                                                 tclass[*cit].babelpreamble(),
1855                                                 buffer().language(),
1856                                                 buffer().params().encoding(),
1857                                                 use_polyglossia, false));
1858                         for (lang_it lit = lbeg; lit != lend; ++lit)
1859                                 snippets.insert(i18npreamble(
1860                                                 tclass[*cit].babelpreamble(),
1861                                                 *lit,
1862                                                 buffer().params().encoding(),
1863                                                 use_polyglossia, false));
1864                 }
1865         }
1866         if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
1867                 FloatList const & floats = params_.documentClass().floats();
1868                 UsedFloats::const_iterator fit = usedFloats_.begin();
1869                 UsedFloats::const_iterator fend = usedFloats_.end();
1870                 for (; fit != fend; ++fit) {
1871                         Floating const & fl = floats.getType(fit->first);
1872                         // we assume builtin floats are translated
1873                         if (fl.isPredefined())
1874                                 continue;
1875                         docstring const type = from_ascii(fl.floattype());
1876                         docstring const flname = from_utf8(fl.name());
1877                         docstring name = buffer().language()->translateLayout(fl.name());
1878                         // only request translation if we have a real translation
1879                         // (that differs from the source)
1880                         if (flname != name)
1881                                 snippets.insert(getFloatI18nPreamble(
1882                                                 type, name, buffer().language(),
1883                                                 buffer().params().encoding(),
1884                                                 use_polyglossia));
1885                         for (lang_it lit = lbeg; lit != lend; ++lit) {
1886                                 string const code = (*lit)->code();
1887                                 name = (*lit)->translateLayout(fl.name());
1888                                 // we assume we have a suitable translation if
1889                                 // either the language is English (we need to
1890                                 // translate into English if English is a secondary
1891                                 // language) or if translateIfPossible returns
1892                                 // something different to the English source.
1893                                 bool const have_translation =
1894                                         (flname != name || contains(code, "en"));
1895                                 if (have_translation)
1896                                         snippets.insert(getFloatI18nPreamble(
1897                                                 type, name, *lit,
1898                                                 buffer().params().encoding(),
1899                                                 use_polyglossia));
1900                         }
1901                 }
1902         }
1903
1904         cit = usedInsetLayouts_.begin();
1905         end = usedInsetLayouts_.end();
1906         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1907         for (; cit != end; ++cit) {
1908                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1909                 if (it == ils.end())
1910                         continue;
1911                 // The listings package does not work with variable width
1912                 // encodings, only with fixed width encodings. Therefore we
1913                 // need to force a fixed width encoding for
1914                 // \lstlistlistingname and \lstlistingname (bug 9382).
1915                 // This needs to be consistent with InsetListings::latex().
1916                 bool const need_fixedwidth = !use_minted &&
1917                                         !runparams_.isFullUnicode() &&
1918                                         it->second.fixedwidthpreambleencoding();
1919                 // language dependent commands (once per document)
1920                 snippets.insert(i18npreamble(it->second.langpreamble(),
1921                                                 buffer().language(),
1922                                                 buffer().params().encoding(),
1923                                                 use_polyglossia, need_fixedwidth));
1924                 // commands for language changing (for multilanguage documents)
1925                 if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
1926                         snippets.insert(i18npreamble(
1927                                                 it->second.babelpreamble(),
1928                                                 buffer().language(),
1929                                                 buffer().params().encoding(),
1930                                                 use_polyglossia, need_fixedwidth));
1931                         for (lang_it lit = lbeg; lit != lend; ++lit)
1932                                 snippets.insert(i18npreamble(
1933                                                 it->second.babelpreamble(),
1934                                                 *lit,
1935                                                 buffer().params().encoding(),
1936                                                 use_polyglossia, need_fixedwidth));
1937                 }
1938         }
1939
1940         odocstringstream tcpreamble;
1941         set<docstring>::const_iterator const send = snippets.end();
1942         set<docstring>::const_iterator it = snippets.begin();
1943         for (; it != send; ++it)
1944                 tcpreamble << *it;
1945         return tcpreamble.str();
1946 }
1947
1948
1949 docstring const LaTeXFeatures::getLyXSGMLEntities() const
1950 {
1951         // Definition of entities used in the document that are LyX related.
1952         odocstringstream entities;
1953
1954         if (mustProvide("lyxarrow")) {
1955                 entities << "<!ENTITY lyxarrow \"-&gt;\">" << '\n';
1956         }
1957
1958         return entities.str();
1959 }
1960
1961
1962 docstring const LaTeXFeatures::getIncludedFiles(string const & fname) const
1963 {
1964         odocstringstream sgmlpreamble;
1965         // FIXME UNICODE
1966         docstring const basename(from_utf8(onlyPath(fname)));
1967
1968         FileMap::const_iterator end = IncludedFiles_.end();
1969         for (FileMap::const_iterator fi = IncludedFiles_.begin();
1970              fi != end; ++fi)
1971                 // FIXME UNICODE
1972                 sgmlpreamble << "\n<!ENTITY " << fi->first
1973                              << (isSGMLFileName(fi->second) ? " SYSTEM \"" : " \"")
1974                              << makeRelPath(from_utf8(fi->second), basename) << "\">";
1975
1976         return sgmlpreamble.str();
1977 }
1978
1979
1980 void LaTeXFeatures::showStruct() const
1981 {
1982         lyxerr << "LyX needs the following commands when LaTeXing:"
1983                << "\n***** Packages:" << getPackages()
1984                << "\n***** Macros:" << to_utf8(getMacros().str)
1985                << "\n***** Textclass stuff:" << to_utf8(getTClassPreamble())
1986                << "\n***** done." << endl;
1987 }
1988
1989
1990 Buffer const & LaTeXFeatures::buffer() const
1991 {
1992         return *buffer_;
1993 }
1994
1995
1996 void LaTeXFeatures::setBuffer(Buffer const & buffer)
1997 {
1998         buffer_ = &buffer;
1999 }
2000
2001
2002 BufferParams const & LaTeXFeatures::bufferParams() const
2003 {
2004         return params_;
2005 }
2006
2007
2008 void LaTeXFeatures::getFloatDefinitions(otexstream & os) const
2009 {
2010         FloatList const & floats = params_.documentClass().floats();
2011
2012         // Here we will output the code to create the needed float styles.
2013         // We will try to do this as minimal as possible.
2014         // \floatstyle{ruled}
2015         // \newfloat{algorithm}{htbp}{loa}
2016         // \providecommand{\algorithmname}{Algorithm}
2017         // \floatname{algorithm}{\protect\algorithmname}
2018         UsedFloats::const_iterator cit = usedFloats_.begin();
2019         UsedFloats::const_iterator end = usedFloats_.end();
2020         for (; cit != end; ++cit) {
2021                 Floating const & fl = floats.getType(cit->first);
2022
2023                 // For builtin floats we do nothing.
2024                 if (fl.isPredefined())
2025                         continue;
2026
2027                 // We have to special case "table" and "figure"
2028                 if (fl.floattype() == "tabular" || fl.floattype() == "figure") {
2029                         // Output code to modify "table" or "figure"
2030                         // but only if builtin == false
2031                         // and that have to be true at this point in the
2032                         // function.
2033                         docstring const type = from_ascii(fl.floattype());
2034                         docstring const placement = from_ascii(fl.placement());
2035                         docstring const style = from_ascii(fl.style());
2036                         if (!style.empty()) {
2037                                 os << "\\floatstyle{" << style << "}\n"
2038                                    << "\\restylefloat{" << type << "}\n";
2039                         }
2040                         if (!placement.empty()) {
2041                                 os << "\\floatplacement{" << type << "}{"
2042                                    << placement << "}\n";
2043                         }
2044                 } else {
2045                         // The other non builtin floats.
2046
2047                         docstring const type = from_ascii(fl.floattype());
2048                         docstring const placement = from_ascii(fl.placement());
2049                         docstring const ext = from_ascii(fl.ext());
2050                         docstring const within = from_ascii(fl.within());
2051                         docstring const style = from_ascii(fl.style());
2052                         docstring const name =
2053                                 buffer().language()->translateLayout(fl.name());
2054                         os << "\\floatstyle{" << style << "}\n"
2055                            << "\\newfloat{" << type << "}{" << placement
2056                            << "}{" << ext << '}';
2057                         if (!within.empty())
2058                                 os << '[' << within << ']';
2059                         os << '\n'
2060                            << "\\providecommand{\\" << type << "name}{"
2061                            << name << "}\n"
2062                            << "\\floatname{" << type << "}{\\protect\\"
2063                            << type << "name}\n";
2064
2065                         // What missing here is to code to minimalize the code
2066                         // output so that the same floatstyle will not be
2067                         // used several times, when the same style is still in
2068                         // effect. (Lgb)
2069                 }
2070                 if (cit->second)
2071                         // The subfig package is loaded later
2072                         os << "\n\\AtBeginDocument{\\newsubfloat{" << from_ascii(fl.floattype()) << "}}\n";
2073         }
2074 }
2075
2076
2077 void LaTeXFeatures::resolveAlternatives()
2078 {
2079         for (Features::iterator it = features_.begin(); it != features_.end();) {
2080                 if (contains(*it, '|')) {
2081                         vector<string> const alternatives = getVectorFromString(*it, "|");
2082                         vector<string>::const_iterator const end = alternatives.end();
2083                         vector<string>::const_iterator ita = alternatives.begin();
2084                         // Is any alternative already required? => use that
2085                         for (; ita != end; ++ita) {
2086                                 if (isRequired(*ita))
2087                                         break;
2088                         }
2089                         // Is any alternative available? => use the first one
2090                         // (bug 9498)
2091                         if (ita == end) {
2092                                 for (ita = alternatives.begin(); ita != end; ++ita) {
2093                                         if (isAvailable(*ita)) {
2094                                                 require(*ita);
2095                                                 break;
2096                                         }
2097                                 }
2098                         }
2099                         // This will not work, but not requiring something
2100                         // would be more confusing
2101                         if (ita == end)
2102                                 require(alternatives.front());
2103                         features_.erase(it);
2104                         it = features_.begin();
2105                 } else
2106                         ++it;
2107         }
2108 }
2109
2110
2111 void LaTeXFeatures::expandMultiples()
2112 {
2113         for (Features::iterator it = features_.begin(); it != features_.end();) {
2114                 if (contains(*it, ',')) {
2115                         vector<string> const multiples = getVectorFromString(*it, ",");
2116                         vector<string>::const_iterator const end = multiples.end();
2117                         vector<string>::const_iterator itm = multiples.begin();
2118                         // Do nothing if any multiple is already required
2119                         for (; itm != end; ++itm) {
2120                                 if (!isRequired(*itm))
2121                                         require(*itm);
2122                         }
2123                         features_.erase(it);
2124                         it = features_.begin();
2125                 } else
2126                         ++it;
2127         }
2128 }
2129
2130
2131 } // namespace lyx