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