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