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