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