]> git.lyx.org Git - lyx.git/blob - src/LaTeXFeatures.cpp
562f9b1150c12d64c39b7001da9a77ee7f4b8fe0
[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
34 #include "insets/InsetLayout.h"
35
36 #include "support/debug.h"
37 #include "support/docstream.h"
38 #include "support/FileName.h"
39 #include "support/filetools.h"
40 #include "support/gettext.h"
41 #include "support/lstrings.h"
42 #include "support/regex.h"
43
44 #include <algorithm>
45
46
47 using namespace std;
48 using namespace lyx::support;
49
50
51 namespace lyx {
52
53 /////////////////////////////////////////////////////////////////////
54 //
55 // Strings
56 //
57 /////////////////////////////////////////////////////////////////////
58
59 //\NeedsTeXFormat{LaTeX2e}
60 //\ProvidesPackage{lyx}[1996/01/11 LLE v0.2 (LyX LaTeX Extensions)]
61 //\message{LyX LaTeX Extensions (LLE v0.2) of 11-Jan-1996.}
62
63 static docstring const lyx_def = from_ascii(
64         "\\providecommand{\\LyX}{L\\kern-.1667em\\lower.25em\\hbox{Y}\\kern-.125emX\\@}");
65
66 static docstring const lyx_hyperref_def = from_ascii(
67         "\\providecommand{\\LyX}{\\texorpdfstring%\n"
68         "  {L\\kern-.1667em\\lower.25em\\hbox{Y}\\kern-.125emX\\@}\n"
69         "  {LyX}}");
70
71 static docstring const noun_def = from_ascii(
72         "\\newcommand{\\noun}[1]{\\textsc{#1}}");
73
74 static docstring const lyxarrow_def = from_ascii(
75         "\\DeclareRobustCommand*{\\lyxarrow}{%\n"
76         "\\@ifstar\n"
77         "{\\leavevmode\\,$\\triangleleft$\\,\\allowbreak}\n"
78         "{\\leavevmode\\,$\\triangleright$\\,\\allowbreak}}");
79
80 // for quotes without babel. This does not give perfect results, but
81 // anybody serious about non-english quotes should use babel (JMarc).
82
83 static docstring const quotedblbase_def = from_ascii(
84         "\\ProvideTextCommandDefault{\\quotedblbase}{%\n"
85         "  \\raisebox{-1.4ex}[1ex][.5ex]{\\textquotedblright}%\n"
86         "  \\penalty10000\\hskip0em\\relax%\n"
87         "}");
88
89 static docstring const quotesinglbase_def = from_ascii(
90         "\\ProvideTextCommandDefault{\\quotesinglbase}{%\n"
91         "  \\raisebox{-1.4ex}[1ex][.5ex]{\\textquoteright}%\n"
92         "  \\penalty10000\\hskip0em\\relax%\n"
93         "}");
94
95 static docstring const guillemotleft_def = from_ascii(
96         "\\ProvideTextCommandDefault{\\guillemotleft}{%\n"
97         "  {\\usefont{U}{lasy}{m}{n}\\char'50\\kern-.15em\\char'50}%\n"
98         "\\penalty10000\\hskip0pt\\relax%\n"
99         "}");
100
101 static docstring const guillemotright_def = from_ascii(
102         "\\ProvideTextCommandDefault{\\guillemotright}{%\n"
103         "  \\penalty10000\\hskip0pt%\n"
104         "  {\\usefont{U}{lasy}{m}{n}\\char'51\\kern-.15em\\char'51}%\n"
105         "}");
106
107 static docstring const guilsinglleft_def = from_ascii(
108         "\\ProvideTextCommandDefault{\\guilsinglleft}{%\n"
109         "  {\\usefont{U}{lasy}{m}{n}\\char'50}%\n"
110         "  \\penalty10000\\hskip0pt\\relax%\n"
111         "}");
112
113 static docstring const guilsinglright_def = from_ascii(
114         "\\ProvideTextCommandDefault{\\guilsinglright}{%\n"
115         "  \\penalty10000\\hskip0pt%\n"
116         "  {\\usefont{U}{lasy}{m}{n}\\char'51}%\n"
117         "}");
118
119 static docstring const paragraphleftindent_def = from_ascii(
120         "\\newenvironment{LyXParagraphLeftIndent}[1]%\n"
121         "{\n"
122         "  \\begin{list}{}{%\n"
123         "    \\setlength{\\topsep}{0pt}%\n"
124         "    \\addtolength{\\leftmargin}{#1}\n"
125 // ho hum, yet more things commented out with no hint as to why they
126 // weren't just removed
127 //      "%%    \\addtolength{\\leftmargin}{#1\\textwidth}\n"
128 //      "%%    \\setlength{\\textwidth}{#2\\textwidth}\n"
129 //      "%%    \\setlength\\listparindent\\parindent%\n"
130 //      "%%    \\setlength\\itemindent\\parindent%\n"
131         "    \\setlength{\\parsep}{0pt plus 1pt}%\n"
132         "  }\n"
133         "  \\item[]\n"
134         "}\n"
135         "{\\end{list}}\n");
136
137 static docstring const floatingfootnote_def = from_ascii(
138         "%% Special footnote code from the package 'stblftnt.sty'\n"
139         "%% Author: Robin Fairbairns -- Last revised Dec 13 1996\n"
140         "\\let\\SF@@footnote\\footnote\n"
141         "\\def\\footnote{\\ifx\\protect\\@typeset@protect\n"
142         "    \\expandafter\\SF@@footnote\n"
143         "  \\else\n"
144         "    \\expandafter\\SF@gobble@opt\n"
145         "  \\fi\n"
146         "}\n"
147         "\\expandafter\\def\\csname SF@gobble@opt \\endcsname{\\@ifnextchar[%]\n"
148         "  \\SF@gobble@twobracket\n"
149         "  \\@gobble\n"
150         "}\n"
151         "\\edef\\SF@gobble@opt{\\noexpand\\protect\n"
152         "  \\expandafter\\noexpand\\csname SF@gobble@opt \\endcsname}\n"
153         "\\def\\SF@gobble@twobracket[#1]#2{}\n");
154
155 static docstring const binom_def = from_ascii(
156         "%% Binom macro for standard LaTeX users\n"
157         "\\newcommand{\\binom}[2]{{#1 \\choose #2}}\n");
158
159 static docstring const mathcircumflex_def = from_ascii(
160         "%% For printing a cirumflex inside a formula\n"
161         "\\newcommand{\\mathcircumflex}[0]{\\mbox{\\^{}}}\n");
162
163 static docstring const tabularnewline_def = from_ascii(
164         "%% Because html converters don't know tabularnewline\n"
165         "\\providecommand{\\tabularnewline}{\\\\}\n");
166
167 static docstring const lyxgreyedout_def = from_ascii(
168         "%% The greyedout annotation environment\n"
169         "\\newenvironment{lyxgreyedout}\n"
170         "  {\\textcolor{note_fontcolor}\\bgroup\\ignorespaces}\n"
171         "  {\\ignorespacesafterend\\egroup}\n");
172
173 // We want to omit the file extension for includegraphics, but this does not
174 // work when the filename contains other dots.
175 // Idea from http://www.tex.ac.uk/cgi-bin/texfaq2html?label=unkgrfextn
176 static docstring const lyxdot_def = from_ascii(
177         "%% A simple dot to overcome graphicx limitations\n"
178         "\\newcommand{\\lyxdot}{.}\n");
179
180 static docstring const changetracking_dvipost_def = from_ascii(
181         "%% Change tracking with dvipost\n"
182         "\\dvipostlayout\n"
183         "\\dvipost{osstart color push Red}\n"
184         "\\dvipost{osend color pop}\n"
185         "\\dvipost{cbstart color push Blue}\n"
186         "\\dvipost{cbend color pop}\n"
187         "\\DeclareRobustCommand{\\lyxadded}[3]{\\changestart#3\\changeend}\n"
188         "\\DeclareRobustCommand{\\lyxdeleted}[3]{%\n"
189         "\\changestart\\overstrikeon#3\\overstrikeoff\\changeend}\n");
190
191 static docstring const changetracking_xcolor_ulem_def = from_ascii(
192         "%% Change tracking with ulem\n"
193         "\\DeclareRobustCommand{\\lyxadded}[3]{{\\color{lyxadded}{}#3}}\n"
194         "\\DeclareRobustCommand{\\lyxdeleted}[3]{{\\color{lyxdeleted}\\sout{#3}}}\n");
195
196 static docstring const changetracking_xcolor_ulem_hyperref_def = from_ascii(
197         "%% Change tracking with ulem\n"
198         "\\DeclareRobustCommand{\\lyxadded}[3]{{\\texorpdfstring{\\color{lyxadded}{}}{}#3}}\n"
199         "\\DeclareRobustCommand{\\lyxdeleted}[3]{{\\texorpdfstring{\\color{lyxdeleted}\\sout{#3}}{}}}\n");
200
201 static docstring const changetracking_none_def = from_ascii(
202         "\\newcommand{\\lyxadded}[3]{#3}\n"
203         "\\newcommand{\\lyxdeleted}[3]{}\n");
204
205 static docstring const textgreek_def = from_ascii(
206         "\\DeclareRobustCommand{\\greektext}{%\n"
207         "  \\fontencoding{LGR}\\selectfont\\def\\encodingdefault{LGR}}\n"
208         "\\DeclareRobustCommand{\\textgreek}[1]{\\leavevmode{\\greektext #1}}\n"
209         "\\DeclareFontEncoding{LGR}{}{}\n"
210         "\\DeclareTextSymbol{\\~}{LGR}{126}");
211
212 static docstring const textcyr_def = from_ascii(
213         "\\DeclareRobustCommand{\\cyrtext}{%\n"
214         "  \\fontencoding{T2A}\\selectfont\\def\\encodingdefault{T2A}}\n"
215         "\\DeclareRobustCommand{\\textcyr}[1]{\\leavevmode{\\cyrtext #1}}\n"
216         "\\AtBeginDocument{\\DeclareFontEncoding{T2A}{}{}}\n");
217
218 static docstring const lyxmathsym_def = from_ascii(
219         "\\newcommand{\\lyxmathsym}[1]{\\ifmmode\\begingroup\\def\\b@ld{bold}\n"
220         "  \\text{\\ifx\\math@version\\b@ld\\bfseries\\fi#1}\\endgroup\\else#1\\fi}\n");
221
222 static docstring const papersizedvi_def = from_ascii(
223         "\\special{papersize=\\the\\paperwidth,\\the\\paperheight}\n");
224
225 static docstring const papersizepdf_def = from_ascii(
226         "\\pdfpageheight\\paperheight\n"
227         "\\pdfpagewidth\\paperwidth\n");
228
229 static docstring const cedilla_def = from_ascii(
230         "\\newcommand{\\docedilla}[2]{\\underaccent{#1\\mathchar'30}{#2}}\n"
231         "\\newcommand{\\cedilla}[1]{\\mathpalette\\docedilla{#1}}\n");
232
233 static docstring const subring_def = from_ascii(
234         "\\newcommand{\\dosubring}[2]{\\underaccent{#1\\mathchar'27}{#2}}\n"
235         "\\newcommand{\\subring}[1]{\\mathpalette\\dosubring{#1}}\n");
236
237 static docstring const subdot_def = from_ascii(
238         "\\newcommand{\\dosubdot}[2]{\\underaccent{#1.}{#2}}\n"
239         "\\newcommand{\\subdot}[1]{\\mathpalette\\dosubdot{#1}}\n");
240
241 static docstring const subhat_def = from_ascii(
242         "\\newcommand{\\dosubhat}[2]{\\underaccent{#1\\mathchar'136}{#2}}\n"
243         "\\newcommand{\\subhat}[1]{\\mathpalette\\dosubhat{#1}}\n");
244
245 static docstring const subtilde_def = from_ascii(
246         "\\newcommand{\\dosubtilde}[2]{\\underaccent{#1\\mathchar'176}{#2}}\n"
247         "\\newcommand{\\subtilde}[1]{\\mathpalette\\dosubtilde{#1}}\n");
248
249 static docstring const dacute_def = from_ascii(
250         "\\DeclareMathAccent{\\dacute}{\\mathalpha}{operators}{'175}\n");
251
252 static docstring const tipasymb_def = from_ascii(
253         "\\DeclareFontEncoding{T3}{}{}\n"
254         "\\DeclareSymbolFont{tipasymb}{T3}{cmr}{m}{n}\n");
255
256 static docstring const dgrave_def = from_ascii(
257         "\\DeclareMathAccent{\\dgrave}{\\mathord}{tipasymb}{'15}\n");
258
259 static docstring const rcap_def = from_ascii(
260         "\\DeclareMathAccent{\\rcap}{\\mathord}{tipasymb}{'20}\n");
261
262 static docstring const ogonek_def = from_ascii(
263         "\\newcommand{\\doogonek}[2]{\\setbox0=\\hbox{$#1#2$}\\underaccent{#1\\mkern-6mu\n"
264         "  \\ifx#2O\\hskip0.5\\wd0\\else\\ifx#2U\\hskip0.5\\wd0\\else\\hskip\\wd0\\fi\\fi\n"
265         "  \\ifx#2o\\mkern-2mu\\else\\ifx#2e\\mkern-1mu\\fi\\fi\n"
266         "  \\mathchar\"0\\hexnumber@\\symtipasymb0C}{#2}}\n"
267         "\\newcommand{\\ogonek}[1]{\\mathpalette\\doogonek{#1}}\n");
268
269 static docstring const lyxref_def = from_ascii(
270                 "\\RS@ifundefined{subref}\n"
271                 "  {\\def\\RSsubtxt{section~}\\newref{sub}{name = \\RSsubtxt}}\n"
272                 "  {}\n"
273                 "\\RS@ifundefined{thmref}\n"
274                 "  {\\def\\RSthmtxt{theorem~}\\newref{thm}{name = \\RSthmtxt}}\n"
275                 "  {}\n"
276                 "\\RS@ifundefined{lemref}\n"
277                 "  {\\def\\RSlemtxt{lemma~}\\newref{lem}{name = \\RSlemtxt}}\n" 
278                 "  {}\n");
279
280 // Make sure the columns are also outputed as rtl
281 static docstring const rtloutputdblcol_def = from_ascii(
282         "\\def\\@outputdblcol{%\n"
283         "  \\if@firstcolumn\n"
284         "    \\global \\@firstcolumnfalse\n"
285         "    \\global \\setbox\\@leftcolumn \\box\\@outputbox\n"
286         "  \\else\n"
287         "    \\global \\@firstcolumntrue\n"
288         "    \\setbox\\@outputbox \\vbox {%\n"
289         "      \\hb@xt@\\textwidth {%\n"
290         "      \\kern\\textwidth \\kern-\\columnwidth %**\n"
291         "      \\hb@xt@\\columnwidth {%\n"
292         "         \\box\\@leftcolumn \\hss}%\n"
293         "      \\kern-\\textwidth %**\n"
294         "      \\hfil\n"
295         "      {\\normalcolor\\vrule \\@width\\columnseprule}%\n"
296         "      \\hfil\n"
297         "      \\kern-\\textwidth  %**\n"
298         "      \\hb@xt@\\columnwidth {%\n"
299         "         \\box\\@outputbox \\hss}%\n"
300         "      \\kern-\\columnwidth \\kern\\textwidth %**\n"
301         "    }%\n"
302         "  }%\n"
303         "  \\@combinedblfloats\n"
304         "  \\@outputpage\n"
305         "  \\begingroup\n"
306         "  \\@dblfloatplacement\n"
307         "  \\@startdblcolumn\n"
308         "  \\@whilesw\\if@fcolmade \\fi\n"
309         "  {\\@outputpage\n"
310         "    \\@startdblcolumn}%\n"
311         "  \\endgroup\n"
312         "  \\fi\n"
313         "}\n"
314         "\\@mparswitchtrue\n");
315
316
317 /////////////////////////////////////////////////////////////////////
318 //
319 // LaTeXFeatures
320 //
321 /////////////////////////////////////////////////////////////////////
322
323
324 LaTeXFeatures::LaTeXFeatures(Buffer const & b, BufferParams const & p,
325                              OutputParams const & r)
326         : buffer_(&b), params_(p), runparams_(r), in_float_(false)
327 {}
328
329
330 LaTeXFeatures::LangPackage LaTeXFeatures::langPackage() const
331 {
332         string const local_lp = bufferParams().lang_package;
333
334         // Locally, custom is just stored as a string
335         // in bufferParams().lang_package.
336         if (local_lp != "auto"
337             && local_lp != "babel"
338             && local_lp != "default"
339             && local_lp != "none")
340                  return LANG_PACK_CUSTOM;
341
342         if (local_lp == "none")
343                 return LANG_PACK_NONE;
344
345         /* If "auto" is selected, we load polyglossia if required,
346          * else we select babel.
347          * If babel is selected (either directly or via the "auto"
348          * mechanism), we really do only require it if we have
349          * a language that needs it.
350          */
351         bool const polyglossia_required =
352                 isRequired("polyglossia")
353                 && isAvailable("polyglossia")
354                 && !isProvided("babel")
355                 && this->hasOnlyPolyglossiaLanguages();
356         bool const babel_required = 
357                 !bufferParams().language->babel().empty()
358                 || !this->getBabelLanguages().empty();
359
360         if (local_lp == "auto") {
361                 // polyglossia requirement has priority over babel
362                 if (polyglossia_required)
363                         return LANG_PACK_POLYGLOSSIA;
364                 else if (babel_required)
365                         return LANG_PACK_BABEL;
366         }
367
368         if (local_lp == "babel") {
369                 if (babel_required)
370                         return LANG_PACK_BABEL;
371         }
372
373         if (local_lp == "default") {
374                 switch (lyxrc.language_package_selection) {
375                 case LyXRC::LP_AUTO:
376                         // polyglossia requirement has priority over babel
377                         if (polyglossia_required)
378                                 return LANG_PACK_POLYGLOSSIA;
379                         else if (babel_required)
380                                 return LANG_PACK_BABEL;
381                         break;
382                 case LyXRC::LP_BABEL:
383                         if (babel_required)
384                                 return LANG_PACK_BABEL;
385                         break;
386                 case LyXRC::LP_CUSTOM:
387                         return LANG_PACK_CUSTOM;
388                 case LyXRC::LP_NONE:
389                         return LANG_PACK_NONE;
390                 }
391         }
392
393         return LANG_PACK_NONE;
394 }
395
396
397 void LaTeXFeatures::require(string const & name)
398 {
399         features_.insert(name);
400 }
401
402
403 void LaTeXFeatures::require(set<string> const & names)
404 {
405         features_.insert(names.begin(), names.end());
406 }
407
408
409 void LaTeXFeatures::useLayout(docstring const & layoutname)
410 {
411         // Some code to avoid loops in dependency definition
412         static int level = 0;
413         const int maxlevel = 30;
414         if (level > maxlevel) {
415                 lyxerr << "LaTeXFeatures::useLayout: maximum level of "
416                        << "recursion attained by layout "
417                        << to_utf8(layoutname) << endl;
418                 return;
419         }
420
421         DocumentClass const & tclass = params_.documentClass();
422         if (tclass.hasLayout(layoutname)) {
423                 // Is this layout already in usedLayouts?
424                 if (find(usedLayouts_.begin(), usedLayouts_.end(), layoutname)
425                     != usedLayouts_.end())
426                         return;
427
428                 Layout const & layout = tclass[layoutname];
429                 require(layout.requires());
430
431                 if (!layout.depends_on().empty()) {
432                         ++level;
433                         useLayout(layout.depends_on());
434                         --level;
435                 }
436                 usedLayouts_.push_back(layoutname);
437         } else {
438                 lyxerr << "LaTeXFeatures::useLayout: layout `"
439                        << to_utf8(layoutname) << "' does not exist in this class"
440                        << endl;
441         }
442
443         --level;
444 }
445
446
447 void LaTeXFeatures::useInsetLayout(InsetLayout const & lay)
448 {
449         docstring const & lname = lay.name();
450         DocumentClass const & tclass = params_.documentClass();
451
452         // this is a default inset layout, nothing useful here
453         if (!tclass.hasInsetLayout(lname))
454                 return;
455         // Is this layout already in usedInsetLayouts?
456         if (find(usedInsetLayouts_.begin(), usedInsetLayouts_.end(), lname)
457                         != usedInsetLayouts_.end())
458                 return;
459
460         require(lay.requires());
461         usedInsetLayouts_.push_back(lname);
462 }
463
464
465 bool LaTeXFeatures::isRequired(string const & name) const
466 {
467         return features_.find(name) != features_.end();
468 }
469
470
471 bool LaTeXFeatures::isProvided(string const & name) const
472 {
473         if (params_.useNonTeXFonts)
474                 return params_.documentClass().provides(name);
475
476         bool const ot1 = (params_.font_encoding() == "default"
477                 || params_.font_encoding() == "OT1");
478         bool const complete = (params_.fonts_sans == "default")
479                 && (params_.fonts_typewriter == "default");
480         bool const nomath = (params_.fonts_math == "default");
481         return params_.documentClass().provides(name)
482                 || theLaTeXFonts().getLaTeXFont(
483                         from_ascii(params_.fonts_roman)).provides(name, ot1,
484                                                                   complete,
485                                                                   nomath)
486                 || theLaTeXFonts().getLaTeXFont(
487                         from_ascii(params_.fonts_sans)).provides(name, ot1,
488                                                                  complete,
489                                                                  nomath)
490                 || theLaTeXFonts().getLaTeXFont(
491                         from_ascii(params_.fonts_typewriter)).provides(name, ot1,
492                                                                        complete,
493                                                                        nomath)
494                 || theLaTeXFonts().getLaTeXFont(
495                         from_ascii(params_.fonts_math)).provides(name, ot1,
496                                                                        complete,
497                                                                        nomath);
498 }
499
500
501 bool LaTeXFeatures::mustProvide(string const & name) const
502 {
503         return isRequired(name) && !isProvided(name);
504 }
505
506
507 bool LaTeXFeatures::isAvailable(string const & name)
508 {
509         string::size_type const i = name.find("->");
510         if (i != string::npos) {
511                 string const from = name.substr(0,i);
512                 string const to = name.substr(i+2);
513                 //LYXERR0("from=[" << from << "] to=[" << to << "]");
514                 return theConverters().isReachable(from, to);
515         }
516         return LaTeXPackages::isAvailable(name);
517 }
518
519
520 void LaTeXFeatures::addPreambleSnippet(string const & preamble)
521 {
522         SnippetList::const_iterator begin = preamble_snippets_.begin();
523         SnippetList::const_iterator end   = preamble_snippets_.end();
524         if (find(begin, end, preamble) == end)
525                 preamble_snippets_.push_back(preamble);
526 }
527
528
529 void LaTeXFeatures::addCSSSnippet(std::string const & snippet)
530 {
531         SnippetList::const_iterator begin = css_snippets_.begin();
532         SnippetList::const_iterator end   = css_snippets_.end();
533         if (find(begin, end, snippet) == end)
534                 css_snippets_.push_back(snippet);
535 }
536
537
538 void LaTeXFeatures::useFloat(string const & name, bool subfloat)
539 {
540         if (!usedFloats_[name])
541                 usedFloats_[name] = subfloat;
542         if (subfloat)
543                 require("subfig");
544         // We only need float.sty if we use non builtin floats, or if we
545         // use the "H" modifier. This includes modified table and
546         // figure floats. (Lgb)
547         Floating const & fl = params_.documentClass().floats().getType(name);
548         if (!fl.floattype().empty() && fl.usesFloatPkg()) {
549                 require("float");
550         }
551 }
552
553
554 void LaTeXFeatures::useLanguage(Language const * lang)
555 {
556         if (!lang->babel().empty() || !lang->polyglossia().empty())
557                 UsedLanguages_.insert(lang);
558         if (!lang->requires().empty())
559                 require(lang->requires());
560         // CJK languages do not have a babel name.
561         // They use the CJK package
562         if (lang->encoding()->package() == Encoding::CJK)
563                 require("CJK");
564         // japanese package is special
565         if (lang->encoding()->package() == Encoding::japanese)
566                 require("japanese");
567 }
568
569
570 void LaTeXFeatures::includeFile(docstring const & key, string const & name)
571 {
572         IncludedFiles_[key] = name;
573 }
574
575
576 bool LaTeXFeatures::hasLanguages() const
577 {
578         return !UsedLanguages_.empty();
579 }
580
581
582 bool LaTeXFeatures::hasOnlyPolyglossiaLanguages() const
583 {
584         LanguageList::const_iterator const begin = UsedLanguages_.begin();
585         for (LanguageList::const_iterator cit = begin;
586              cit != UsedLanguages_.end();
587              ++cit) {
588                 if ((*cit)->polyglossia().empty())
589                         return false;
590         }
591         return true;
592 }
593
594
595 bool LaTeXFeatures::hasPolyglossiaExclusiveLanguages() const
596 {
597         LanguageList::const_iterator const begin = UsedLanguages_.begin();
598         for (LanguageList::const_iterator cit = begin;
599              cit != UsedLanguages_.end();
600              ++cit) {
601                 if ((*cit)->babel().empty() && !(*cit)->polyglossia().empty() && (*cit)->requires().empty())
602                         return true;
603         }
604         return false;
605 }
606
607
608 string LaTeXFeatures::getBabelLanguages() const
609 {
610         ostringstream languages;
611
612         bool first = true;
613         LanguageList::const_iterator const begin = UsedLanguages_.begin();
614         for (LanguageList::const_iterator cit = begin;
615              cit != UsedLanguages_.end();
616              ++cit) {
617                 if ((*cit)->babel().empty())
618                         continue;
619                 if (!first)
620                         languages << ',';
621                 else
622                         first = false;
623                 languages << (*cit)->babel();
624         }
625         return languages.str();
626 }
627
628
629 std::map<std::string, std::string> LaTeXFeatures::getPolyglossiaLanguages() const
630 {
631         std::map<std::string, std::string> languages;
632
633         LanguageList::const_iterator const begin = UsedLanguages_.begin();
634         for (LanguageList::const_iterator cit = begin;
635              cit != UsedLanguages_.end();
636              ++cit) {
637                 languages[(*cit)->polyglossia()] = (*cit)->polyglossiaOpts();
638         }
639         return languages;
640 }
641
642
643 set<string> LaTeXFeatures::getEncodingSet(string const & doc_encoding) const
644 {
645         // This does only find encodings of languages supported by babel, but
646         // that does not matter since we don't have a language with an
647         // encoding supported by inputenc but without babel support.
648         set<string> encodings;
649         LanguageList::const_iterator it  = UsedLanguages_.begin();
650         LanguageList::const_iterator end = UsedLanguages_.end();
651         for (; it != end; ++it)
652                 if ((*it)->encoding()->latexName() != doc_encoding &&
653                     ((*it)->encoding()->package() == Encoding::inputenc
654                      || (*it)->encoding()->package() == Encoding::japanese))
655                         encodings.insert((*it)->encoding()->latexName());
656         return encodings;
657 }
658
659 namespace {
660
661 char const * simplefeatures[] = {
662 // note that the package order here will be the same in the LaTeX-output
663         "array",
664         "verbatim",
665         "longtable",
666         "rotating",
667         "latexsym",
668         "pifont",
669         // subfig is handled in BufferParams.cpp
670         "varioref",
671         "prettyref",
672         "refstyle",
673         /*For a successful cooperation of the `wrapfig' package with the
674           `float' package you should load the `wrapfig' package *after*
675           the `float' package. See the caption package documentation
676           for explanation.*/
677         "float",
678         "rotfloat",
679         "wrapfig",
680         "booktabs",
681         "dvipost",
682         "fancybox",
683         "calc",
684         "units",
685         "tipa",
686         "tipx",
687         "tone",
688         "framed",
689         "soul",
690         "textcomp",
691         "pmboxdraw",
692         "bbding",
693         "ifsym",
694         "marvosym",
695         "txfonts",
696         "pxfonts",
697         "mathdesign",
698         "mathrsfs",
699         "mathabx",
700         "mathtools",
701         "cancel",
702         "ascii",
703         "url",
704         "covington",
705         "csquotes",
706         "enumitem",
707         "endnotes",
708         "hhline",
709         "ifthen",
710         // listings is handled in BufferParams.cpp
711         "bm",
712         "pdfpages",
713         "amscd",
714         "slashed",
715         "multirow",
716         "tfrupee"
717 };
718
719 char const * bibliofeatures[] = {
720         // Known bibliography packages (will be loaded before natbib)
721         "achicago",
722         "apacite",
723         "apalike",
724         "astron",
725         "authordate1-4",
726         "chicago",
727         "harvard",
728         "mslapa",
729         "named"
730 };
731
732 int const nb_bibliofeatures = sizeof(bibliofeatures) / sizeof(char const *);
733
734 int const nb_simplefeatures = sizeof(simplefeatures) / sizeof(char const *);
735
736 }
737
738
739 string const LaTeXFeatures::getColorOptions() const
740 {
741         ostringstream colors;
742
743         // Handling the color packages separately is needed to be able to load them
744         // before babel when hyperref is loaded with the colorlinks option
745         // for more info see Bufferparams.cpp
746
747         // [x]color.sty
748         if (mustProvide("color") || mustProvide("xcolor")) {
749                 string const package =
750                         (mustProvide("xcolor") ? "xcolor" : "color");
751                 if (params_.graphics_driver == "default"
752                         || params_.graphics_driver == "none")
753                         colors << "\\usepackage{" << package << "}\n";
754                 else
755                         colors << "\\usepackage["
756                                  << params_.graphics_driver
757                                  << "]{" << package << "}\n";
758         }
759
760         // pdfcolmk must be loaded after color
761         if (mustProvide("pdfcolmk"))
762                 colors << "\\usepackage{pdfcolmk}\n";
763
764         // the following 3 color commands must be set after color
765         // is loaded and before pdfpages, therefore add the command
766         // here define the set color
767         if (mustProvide("pagecolor")) {
768                 colors << "\\definecolor{page_backgroundcolor}{rgb}{";
769                 colors << outputLaTeXColor(params_.backgroundcolor) << "}\n";
770                 // set the page color
771                 colors << "\\pagecolor{page_backgroundcolor}\n";
772         }
773
774         if (mustProvide("fontcolor")) {
775                 colors << "\\definecolor{document_fontcolor}{rgb}{";
776                 colors << outputLaTeXColor(params_.fontcolor) << "}\n";
777                 // set the color
778                 colors << "\\color{document_fontcolor}\n";
779         }
780
781         if (mustProvide("lyxgreyedout")) {
782                 colors << "\\definecolor{note_fontcolor}{rgb}{";
783                 colors << outputLaTeXColor(params_.notefontcolor) << "}\n";
784                 // the color will be set together with the definition of
785                 // the lyxgreyedout environment (see lyxgreyedout_def)
786         }
787
788         // color for shaded boxes
789         if (isRequired("framed") && mustProvide("color")) {
790                 colors << "\\definecolor{shadecolor}{rgb}{";
791                 colors << outputLaTeXColor(params_.boxbgcolor) << "}\n";
792                 // this color is automatically used by the LaTeX-package "framed"
793         }
794
795         return colors.str();
796 }
797
798
799 string const LaTeXFeatures::getPackages() const
800 {
801         ostringstream packages;
802
803         // FIXME: currently, we can only load packages and macros known
804         // to LyX.
805         // However, with the Require tag of layouts/custom insets,
806         // also unknown packages can be requested. They are silently
807         // swallowed now. We should change this eventually.
808
809         //
810         //  These are all the 'simple' includes.  i.e
811         //  packages which we just \usepackage{package}
812         //
813         for (int i = 0; i < nb_simplefeatures; ++i) {
814                 if (mustProvide(simplefeatures[i]))
815                         packages << "\\usepackage{"
816                                  << simplefeatures[i] << "}\n";
817         }
818
819         //
820         // The rest of these packages are somewhat more complicated
821         // than those above.
822         //
823
824         // if fontspec is used, AMS packages have to be loaded before
825         // fontspec (in BufferParams)
826         string const amsPackages = loadAMSPackages();
827         if (!params_.useNonTeXFonts && !amsPackages.empty())
828                 packages << amsPackages;
829
830         // fixltx2e must be loaded after amsthm, since amsthm produces an error with
831         // the redefined \[ command (bug 7233). Load it as early as possible, since
832         // other packages might profit from it.
833         if (mustProvide("fixltx2e"))
834                 packages << "\\usepackage{fixltx2e}\n";
835
836         // wasysym is a simple feature, but it must be after amsmath if both
837         // are used
838         // wasysym redefines some integrals (e.g. iint) from amsmath. That
839         // leads to inconsistent integrals. We only load this package if
840         // the document does not contain integrals (then isRequired("esint")
841         // is false) or if esint is used, since esint redefines all relevant
842         // integral symbols from wasysym and amsmath.
843         // See http://www.lyx.org/trac/ticket/1942
844         if (mustProvide("wasysym") &&
845             params_.use_package("wasysym") != BufferParams::package_off &&
846             (params_.use_package("esint") != BufferParams::package_off || !isRequired("esint")))
847                 packages << "\\usepackage{wasysym}\n";
848
849         // accents must be loaded after amsmath
850         if (mustProvide("accents") &&
851             params_.use_package("accents") != BufferParams::package_off)
852                 packages << "\\usepackage{accents}\n";
853
854         // mathdots must be loaded after amsmath
855         if (mustProvide("mathdots") &&
856                 params_.use_package("mathdots") != BufferParams::package_off)
857                 packages << "\\usepackage{mathdots}\n";
858
859         // yhmath must be loaded after amsmath
860         if (mustProvide("yhmath") &&
861             params_.use_package("yhmath") != BufferParams::package_off)
862                 packages << "\\usepackage{yhmath}\n";
863
864         // stmaryrd must be loaded after amsmath
865         if (mustProvide("stmaryrd") &&
866             params_.use_package("stmaryrd") != BufferParams::package_off)
867                 packages << "\\usepackage{stmaryrd}\n";
868
869         if (mustProvide("stackrel") &&
870             params_.use_package("stackrel") != BufferParams::package_off)
871                 packages << "\\usepackage{stackrel}\n";
872
873         if (mustProvide("undertilde") &&
874                 params_.use_package("undertilde") != BufferParams::package_off)
875                 packages << "\\usepackage{undertilde}\n";
876
877         // [x]color and pdfcolmk are handled in getColorOptions() above
878
879         // makeidx.sty
880         if (isRequired("makeidx") || isRequired("splitidx")) {
881                 if (!isProvided("makeidx") && !isRequired("splitidx"))
882                         packages << "\\usepackage{makeidx}\n";
883                 if (mustProvide("splitidx"))
884                         packages << "\\usepackage{splitidx}\n";
885                 packages << "\\makeindex\n";
886         }
887
888         // graphicx.sty
889         if (mustProvide("graphicx") && params_.graphics_driver != "none") {
890                 if (params_.graphics_driver == "default")
891                         packages << "\\usepackage{graphicx}\n";
892                 else
893                         packages << "\\usepackage["
894                                  << params_.graphics_driver
895                                  << "]{graphicx}\n";
896         }
897
898         // lyxskak.sty --- newer chess support based on skak.sty
899         if (mustProvide("chess"))
900                 packages << "\\usepackage[ps,mover]{lyxskak}\n";
901
902         // setspace.sty
903         if (mustProvide("setspace") && !isProvided("SetSpace"))
904                 packages << "\\usepackage{setspace}\n";
905
906         // esint must be after amsmath and wasysym, since it will redeclare
907         // inconsistent integral symbols
908         if (mustProvide("esint") &&
909             params_.use_package("esint") != BufferParams::package_off)
910                 packages << "\\usepackage{esint}\n";
911
912         // Known bibliography packages (simple \usepackage{package})
913         for (int i = 0; i < nb_bibliofeatures; ++i) {
914                 if (mustProvide(bibliofeatures[i]))
915                         packages << "\\usepackage{"
916                                  << bibliofeatures[i] << "}\n";
917         }
918
919         // Compatibility between achicago and natbib
920         if (mustProvide("achicago") && mustProvide("natbib"))
921                 packages << "\\let\\achicagobib\\thebibliography\n";
922
923         // natbib.sty
924         // Some classes load natbib themselves, but still allow (or even require)
925         // plain numeric citations (ReVTeX is such a case, see bug 5182).
926         // This special case is indicated by the "natbib-internal" key.
927         if (mustProvide("natbib") && !isProvided("natbib-internal")) {
928                 packages << "\\usepackage[";
929                 if (params_.citeEngineType() == ENGINE_TYPE_NUMERICAL)
930                         packages << "numbers";
931                 else
932                         packages << "authoryear";
933                 packages << "]{natbib}\n";
934         }
935
936         // Compatibility between achicago and natbib
937         if (mustProvide("achicago") && mustProvide("natbib")) {
938                 packages << "\\let\\thebibliography\\achicagobib\n";
939                 packages << "\\let\\SCcite\\astroncite\n";
940                 packages << "\\let\\UnexpandableProtect\\protect\n";
941         }
942
943         // jurabib -- we need version 0.6 at least.
944         if (mustProvide("jurabib"))
945                 packages << "\\usepackage{jurabib}[2004/01/25]\n";
946
947         // xargs -- we need version 1.09 at least
948         if (mustProvide("xargs"))
949                 packages << "\\usepackage{xargs}[2008/03/08]\n";
950
951         if (mustProvide("xy"))
952                 packages << "\\usepackage[all]{xy}\n";
953
954         if (mustProvide("feyn"))
955                 packages << "\\usepackage{feyn}\n"; //Diagram
956
957         if (mustProvide("ulem"))
958                 packages << "\\PassOptionsToPackage{normalem}{ulem}\n"
959                             "\\usepackage{ulem}\n";
960
961         if (mustProvide("mhchem") &&
962             params_.use_package("mhchem") != BufferParams::package_off)
963                 packages << "\\PassOptionsToPackage{version=3}{mhchem}\n"
964                             "\\usepackage{mhchem}\n";
965
966         if (mustProvide("nomencl")) {
967                 // Make it work with the new and old version of the package,
968                 // but don't use the compatibility option since it is
969                 // incompatible to other packages.
970                 packages << "\\usepackage{nomencl}\n"
971                             "% the following is useful when we have the old nomencl.sty package\n"
972                             "\\providecommand{\\printnomenclature}{\\printglossary}\n"
973                             "\\providecommand{\\makenomenclature}{\\makeglossary}\n"
974                             "\\makenomenclature\n";
975         }
976
977         // fixltx2e provides subscript
978         if (mustProvide("subscript") && !isRequired("fixltx2e"))
979                 packages << "\\usepackage{subscript}\n";
980
981         return packages.str();
982 }
983
984
985 string LaTeXFeatures::getPreambleSnippets() const
986 {
987         ostringstream snip;
988         SnippetList::const_iterator pit  = preamble_snippets_.begin();
989         SnippetList::const_iterator pend = preamble_snippets_.end();
990         for (; pit != pend; ++pit)
991                 snip << *pit << '\n';
992         return snip.str();
993 }
994
995
996 std::string LaTeXFeatures::getCSSSnippets() const
997 {
998         ostringstream snip;
999         SnippetList::const_iterator pit  = css_snippets_.begin();
1000         SnippetList::const_iterator pend = css_snippets_.end();
1001         for (; pit != pend; ++pit)
1002                 snip << *pit << '\n';
1003         return snip.str();
1004 }
1005
1006
1007 docstring const LaTeXFeatures::getMacros() const
1008 {
1009         odocstringstream macros;
1010
1011         if (!preamble_snippets_.empty()) {
1012                 macros << '\n';
1013                 macros << from_utf8(getPreambleSnippets());
1014         }
1015
1016         if (mustProvide("papersize")) {
1017                 if (runparams_.flavor == OutputParams::LATEX)
1018                         macros << papersizedvi_def << '\n';
1019                 else
1020                         macros << papersizepdf_def << '\n';
1021         }
1022
1023         if (mustProvide("LyX")) {
1024                 if (isRequired("hyperref"))
1025                         macros << lyx_hyperref_def << '\n';
1026                 else
1027                         macros << lyx_def << '\n';
1028         }
1029
1030         if (mustProvide("noun"))
1031                 macros << noun_def << '\n';
1032
1033         if (mustProvide("lyxarrow"))
1034                 macros << lyxarrow_def << '\n';
1035
1036         if (!usePolyglossia() && mustProvide("textgreek")) {
1037                 // Avoid a LaTeX error if times fonts are used and the grtimes
1038                 // package is installed but actual fonts are not (bug 6469).
1039                 if (params_.fonts_roman == "times")
1040                         macros << subst(textgreek_def,
1041                                         from_ascii("\\greektext #1"),
1042                                         from_ascii("%\n  \\IfFileExists"
1043                                                    "{grtm10.tfm}{}{\\fontfamily"
1044                                                    "{cmr}}\\greektext #1"))
1045                                << '\n';
1046                 else
1047                         macros << textgreek_def << '\n';
1048         }
1049
1050         if (!usePolyglossia() && mustProvide("textcyr"))
1051                 macros << textcyr_def << '\n';
1052
1053         if (mustProvide("lyxmathsym"))
1054                 macros << lyxmathsym_def << '\n';
1055
1056         if (mustProvide("cedilla"))
1057                 macros << cedilla_def << '\n';
1058
1059         if (mustProvide("subring"))
1060                 macros << subring_def << '\n';
1061
1062         if (mustProvide("subdot"))
1063                 macros << subdot_def << '\n';
1064
1065         if (mustProvide("subhat"))
1066                 macros << subhat_def << '\n';
1067
1068         if (mustProvide("subtilde"))
1069                 macros << subtilde_def << '\n';
1070
1071         if (mustProvide("dacute"))
1072                 macros << dacute_def << '\n';
1073
1074         if (mustProvide("tipasymb"))
1075                 macros << tipasymb_def << '\n';
1076
1077         if (mustProvide("dgrave"))
1078                 macros << dgrave_def << '\n';
1079
1080         if (mustProvide("rcap"))
1081                 macros << rcap_def << '\n';
1082
1083         if (mustProvide("ogonek"))
1084                 macros << ogonek_def << '\n';
1085
1086         // quotes.
1087         if (mustProvide("quotesinglbase"))
1088                 macros << quotesinglbase_def << '\n';
1089         if (mustProvide("quotedblbase"))
1090                 macros << quotedblbase_def << '\n';
1091         if (mustProvide("guilsinglleft"))
1092                 macros << guilsinglleft_def << '\n';
1093         if (mustProvide("guilsinglright"))
1094                 macros << guilsinglright_def << '\n';
1095         if (mustProvide("guillemotleft"))
1096                 macros << guillemotleft_def << '\n';
1097         if (mustProvide("guillemotright"))
1098                 macros << guillemotright_def << '\n';
1099
1100         // Math mode
1101         if (mustProvide("binom") && !isRequired("amsmath"))
1102                 macros << binom_def << '\n';
1103         if (mustProvide("mathcircumflex"))
1104                 macros << mathcircumflex_def << '\n';
1105
1106         // other
1107         if (mustProvide("ParagraphLeftIndent"))
1108                 macros << paragraphleftindent_def;
1109         if (mustProvide("NeedLyXFootnoteCode"))
1110                 macros << floatingfootnote_def;
1111
1112         // some problems with tex->html converters
1113         if (mustProvide("NeedTabularnewline"))
1114                 macros << tabularnewline_def;
1115
1116         // greyed-out environment (note inset)
1117         // the color is specified in the routine
1118         // getColorOptions() to avoid LaTeX-package clashes
1119         if (mustProvide("lyxgreyedout"))
1120                 macros << lyxgreyedout_def;
1121
1122         if (mustProvide("lyxdot"))
1123                 macros << lyxdot_def << '\n';
1124
1125         // floats
1126         getFloatDefinitions(macros);
1127
1128         if (mustProvide("refstyle"))
1129                 macros << lyxref_def << '\n';
1130
1131         // change tracking
1132         if (mustProvide("ct-dvipost"))
1133                 macros << changetracking_dvipost_def;
1134
1135         if (mustProvide("ct-xcolor-ulem")) {
1136                 streamsize const prec = macros.precision(2);
1137
1138                 RGBColor cadd = rgbFromHexName(lcolor.getX11Name(Color_addedtext));
1139                 macros << "\\providecolor{lyxadded}{rgb}{"
1140                        << cadd.r / 255.0 << ',' << cadd.g / 255.0 << ',' << cadd.b / 255.0 << "}\n";
1141
1142                 RGBColor cdel = rgbFromHexName(lcolor.getX11Name(Color_deletedtext));
1143                 macros << "\\providecolor{lyxdeleted}{rgb}{"
1144                        << cdel.r / 255.0 << ',' << cdel.g / 255.0 << ',' << cdel.b / 255.0 << "}\n";
1145
1146                 macros.precision(prec);
1147
1148                 if (isRequired("hyperref"))
1149                         macros << changetracking_xcolor_ulem_hyperref_def;
1150                 else
1151                         macros << changetracking_xcolor_ulem_def;
1152         }
1153
1154         if (mustProvide("ct-none"))
1155                 macros << changetracking_none_def;
1156
1157         if (mustProvide("rtloutputdblcol"))
1158                 macros << rtloutputdblcol_def;
1159
1160         return macros.str();
1161 }
1162
1163
1164 string const LaTeXFeatures::getBabelPresettings() const
1165 {
1166         ostringstream tmp;
1167
1168         LanguageList::const_iterator it  = UsedLanguages_.begin();
1169         LanguageList::const_iterator end = UsedLanguages_.end();
1170         for (; it != end; ++it)
1171                 if (!(*it)->babel_presettings().empty())
1172                         tmp << (*it)->babel_presettings() << '\n';
1173         if (!params_.language->babel_presettings().empty())
1174                 tmp << params_.language->babel_presettings() << '\n';
1175
1176         if (!contains(tmp.str(), '@'))
1177                 return tmp.str();
1178
1179         return "\\makeatletter\n" + tmp.str() + "\\makeatother\n";
1180 }
1181
1182
1183 string const LaTeXFeatures::getBabelPostsettings() const
1184 {
1185         ostringstream tmp;
1186
1187         LanguageList::const_iterator it  = UsedLanguages_.begin();
1188         LanguageList::const_iterator end = UsedLanguages_.end();
1189         for (; it != end; ++it)
1190                 if (!(*it)->babel_postsettings().empty())
1191                         tmp << (*it)->babel_postsettings() << '\n';
1192         if (!params_.language->babel_postsettings().empty())
1193                 tmp << params_.language->babel_postsettings() << '\n';
1194
1195         if (!contains(tmp.str(), '@'))
1196                 return tmp.str();
1197
1198         return "\\makeatletter\n" + tmp.str() + "\\makeatother\n";
1199 }
1200
1201
1202 bool LaTeXFeatures::needBabelLangOptions() const
1203 {
1204         if (!lyxrc.language_global_options || params_.language->asBabelOptions())
1205                 return true;
1206
1207         LanguageList::const_iterator it  = UsedLanguages_.begin();
1208         LanguageList::const_iterator end = UsedLanguages_.end();
1209         for (; it != end; ++it)
1210                 if ((*it)->asBabelOptions())
1211                         return true;
1212
1213         return false;
1214 }
1215
1216
1217 string const LaTeXFeatures::loadAMSPackages() const
1218 {
1219         ostringstream tmp;
1220         if (mustProvide("amsthm"))
1221                 tmp << "\\usepackage{amsthm}\n";
1222
1223         if (mustProvide("amsmath")
1224             && params_.use_package("amsmath") != BufferParams::package_off) {
1225                 tmp << "\\usepackage{amsmath}\n";
1226         } else {
1227                 // amsbsy and amstext are already provided by amsmath
1228                 if (mustProvide("amsbsy"))
1229                         tmp << "\\usepackage{amsbsy}\n";
1230                 if (mustProvide("amstext"))
1231                         tmp << "\\usepackage{amstext}\n";
1232         }
1233
1234         if (mustProvide("amssymb")
1235             && params_.use_package("amssymb") != BufferParams::package_off)
1236                 tmp << "\\usepackage{amssymb}\n";
1237
1238         return tmp.str();
1239 }
1240
1241
1242 docstring const LaTeXFeatures::getTClassPreamble() const
1243 {
1244         // the text class specific preamble
1245         DocumentClass const & tclass = params_.documentClass();
1246         odocstringstream tcpreamble;
1247
1248         tcpreamble << tclass.preamble();
1249
1250         list<docstring>::const_iterator cit = usedLayouts_.begin();
1251         list<docstring>::const_iterator end = usedLayouts_.end();
1252         for (; cit != end; ++cit)
1253                 tcpreamble << tclass[*cit].preamble();
1254
1255         cit = usedInsetLayouts_.begin();
1256         end = usedInsetLayouts_.end();
1257         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1258         for (; cit != end; ++cit) {
1259                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1260                 if (it == ils.end())
1261                         continue;
1262                 tcpreamble << it->second.preamble();
1263         }
1264
1265         return tcpreamble.str();
1266 }
1267
1268
1269 docstring const LaTeXFeatures::getTClassHTMLPreamble() const
1270 {
1271         DocumentClass const & tclass = params_.documentClass();
1272         odocstringstream tcpreamble;
1273
1274         tcpreamble << tclass.htmlpreamble();
1275
1276         list<docstring>::const_iterator cit = usedLayouts_.begin();
1277         list<docstring>::const_iterator end = usedLayouts_.end();
1278         for (; cit != end; ++cit)
1279                 tcpreamble << tclass[*cit].htmlpreamble();
1280
1281         cit = usedInsetLayouts_.begin();
1282         end = usedInsetLayouts_.end();
1283         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1284         for (; cit != end; ++cit) {
1285                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1286                 if (it == ils.end())
1287                         continue;
1288                 tcpreamble << it->second.htmlpreamble();
1289         }
1290
1291         return tcpreamble.str();
1292 }
1293
1294
1295 docstring const LaTeXFeatures::getTClassHTMLStyles() const
1296 {
1297         DocumentClass const & tclass = params_.documentClass();
1298         odocstringstream tcpreamble;
1299
1300         tcpreamble << tclass.htmlstyles();
1301
1302         list<docstring>::const_iterator cit = usedLayouts_.begin();
1303         list<docstring>::const_iterator end = usedLayouts_.end();
1304         for (; cit != end; ++cit)
1305                 tcpreamble << tclass[*cit].htmlstyle();
1306
1307         cit = usedInsetLayouts_.begin();
1308         end = usedInsetLayouts_.end();
1309         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1310         for (; cit != end; ++cit) {
1311                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1312                 if (it == ils.end())
1313                         continue;
1314                 tcpreamble << it->second.htmlstyle();
1315         }
1316
1317         return tcpreamble.str();
1318 }
1319
1320
1321 namespace {
1322
1323 docstring const getFloatI18nPreamble(docstring const & type,
1324                         docstring const & name, Language const * lang,
1325                         Encoding const & enc, bool const polyglossia)
1326 {
1327         // Check whether name can be encoded in the buffer encoding
1328         bool encodable = true;
1329         for (size_t i = 0; i < name.size(); ++i) {
1330                 if (!enc.encodable(name[i])) {
1331                         encodable = false;
1332                         break;
1333                 }
1334         }
1335
1336         docstring const language = polyglossia ? from_ascii(lang->polyglossia())
1337                                                : from_ascii(lang->babel());
1338         docstring const langenc = from_ascii(lang->encoding()->iconvName());
1339         docstring const texenc = from_ascii(lang->encoding()->latexName());
1340         docstring const bufenc = from_ascii(enc.iconvName());
1341         docstring const s1 = docstring(1, 0xF0000);
1342         docstring const s2 = docstring(1, 0xF0001);
1343         docstring const translated = encodable ? name
1344                 : from_ascii("\\inputencoding{") + texenc + from_ascii("}")
1345                         + s1 + langenc + s2 + name + s1 + bufenc + s2;
1346
1347         odocstringstream os;
1348         os << "\\addto\\captions" << language
1349            << "{\\renewcommand{\\" << type << "name}{" << translated << "}}\n";
1350         return os.str();
1351 }
1352
1353
1354 docstring const i18npreamble(docstring const & templ, Language const * lang,
1355                 Encoding const & enc, bool const polyglossia)
1356 {
1357         if (templ.empty())
1358                 return templ;
1359
1360         string preamble = polyglossia ?
1361                 subst(to_utf8(templ), "$$lang", lang->polyglossia()) :
1362                 subst(to_utf8(templ), "$$lang", lang->babel());
1363
1364         string const langenc = lang->encoding()->iconvName();
1365         string const texenc = lang->encoding()->latexName();
1366         string const bufenc = enc.iconvName();
1367         // First and second character of plane 15 (Private Use Area)
1368         string const s1 = "\xf3\xb0\x80\x80"; // U+F0000
1369         string const s2 = "\xf3\xb0\x80\x81"; // U+F0001
1370         // FIXME UNICODE
1371         // lyx::regex is not unicode-safe.
1372         // Should use QRegExp or (boost::u32regex, but that requires ICU)
1373         static regex const reg("_\\(([^\\)]+)\\)");
1374         smatch sub;
1375         while (regex_search(preamble, sub, reg)) {
1376                 string const key = sub.str(1);
1377                 docstring const name = lang->translateLayout(key);
1378                 // Check whether name can be encoded in the buffer encoding
1379                 bool encodable = true;
1380                 for (size_t i = 0; i < name.size(); ++i) {
1381                         if (!enc.encodable(name[i])) {
1382                                 encodable = false;
1383                                 break;
1384                         }
1385                 }
1386                 string const translated = encodable ? to_utf8(name)
1387                         : "\\inputencoding{" + texenc + "}"
1388                         + s1 + langenc + s2 + to_utf8(name)
1389                         + s1 + bufenc + s2;
1390                 preamble = subst(preamble, sub.str(), translated);
1391         }
1392         return from_utf8(preamble);
1393 }
1394
1395 }
1396
1397
1398 docstring const LaTeXFeatures::getTClassI18nPreamble(bool use_babel, bool use_polyglossia) const
1399 {
1400         DocumentClass const & tclass = params_.documentClass();
1401         // collect preamble snippets in a set to prevent multiple identical
1402         // commands (would happen if e.g. both theorem and theorem* are used)
1403         set<docstring> snippets;
1404         typedef LanguageList::const_iterator lang_it;
1405         lang_it const lbeg = UsedLanguages_.begin();
1406         lang_it const lend =  UsedLanguages_.end();
1407         list<docstring>::const_iterator cit = usedLayouts_.begin();
1408         list<docstring>::const_iterator end = usedLayouts_.end();
1409         for (; cit != end; ++cit) {
1410                 // language dependent commands (once per document)
1411                 snippets.insert(i18npreamble(tclass[*cit].langpreamble(),
1412                                                 buffer().language(),
1413                                                 buffer().params().encoding(),
1414                                                 use_polyglossia));
1415                 // commands for language changing (for multilanguage documents)
1416                 if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
1417                         snippets.insert(i18npreamble(
1418                                                 tclass[*cit].babelpreamble(),
1419                                                 buffer().language(),
1420                                                 buffer().params().encoding(),
1421                                                 use_polyglossia));
1422                         for (lang_it lit = lbeg; lit != lend; ++lit)
1423                                 snippets.insert(i18npreamble(
1424                                                 tclass[*cit].babelpreamble(),
1425                                                 *lit,
1426                                                 buffer().params().encoding(),
1427                                                 use_polyglossia));
1428                 }
1429         }
1430         if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
1431                 FloatList const & floats = params_.documentClass().floats();
1432                 UsedFloats::const_iterator fit = usedFloats_.begin();
1433                 UsedFloats::const_iterator fend = usedFloats_.end();
1434                 for (; fit != fend; ++fit) {
1435                         Floating const & fl = floats.getType(fit->first);
1436                         // we assume builtin floats are translated
1437                         if (fl.isPredefined())
1438                                 continue;
1439                         docstring const type = from_ascii(fl.floattype());
1440                         docstring const flname = from_utf8(fl.name());
1441                         docstring name = buffer().language()->translateLayout(fl.name());
1442                         // only request translation if we have a real translation
1443                         // (that differs from the source)
1444                         if (flname != name)
1445                                 snippets.insert(getFloatI18nPreamble(
1446                                                 type, name, buffer().language(),
1447                                                 buffer().params().encoding(),
1448                                                 use_polyglossia));
1449                         for (lang_it lit = lbeg; lit != lend; ++lit) {
1450                                 string const code = (*lit)->code();
1451                                 name = (*lit)->translateLayout(fl.name());
1452                                 // we assume we have a suitable translation if
1453                                 // either the language is English (we need to
1454                                 // translate into English if English is a secondary
1455                                 // language) or if translateIfPossible returns
1456                                 // something different to the English source.
1457                                 bool const have_translation =
1458                                         (flname != name || contains(code, "en"));
1459                                 if (have_translation)
1460                                         snippets.insert(getFloatI18nPreamble(
1461                                                 type, name, *lit,
1462                                                 buffer().params().encoding(),
1463                                                 use_polyglossia));
1464                         }
1465                 }
1466         }
1467
1468         cit = usedInsetLayouts_.begin();
1469         end = usedInsetLayouts_.end();
1470         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1471         for (; cit != end; ++cit) {
1472                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1473                 if (it == ils.end())
1474                         continue;
1475                 // language dependent commands (once per document)
1476                 snippets.insert(i18npreamble(it->second.langpreamble(),
1477                                                 buffer().language(),
1478                                                 buffer().params().encoding(),
1479                                                 use_polyglossia));
1480                 // commands for language changing (for multilanguage documents)
1481                 if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
1482                         snippets.insert(i18npreamble(
1483                                                 it->second.babelpreamble(),
1484                                                 buffer().language(),
1485                                                 buffer().params().encoding(),
1486                                                 use_polyglossia));
1487                         for (lang_it lit = lbeg; lit != lend; ++lit)
1488                                 snippets.insert(i18npreamble(
1489                                                 it->second.babelpreamble(),
1490                                                 *lit,
1491                                                 buffer().params().encoding(),
1492                                                 use_polyglossia));
1493                 }
1494         }
1495
1496         odocstringstream tcpreamble;
1497         set<docstring>::const_iterator const send = snippets.end();
1498         set<docstring>::const_iterator it = snippets.begin();
1499         for (; it != send; ++it)
1500                 tcpreamble << *it;
1501         return tcpreamble.str();
1502 }
1503
1504
1505 docstring const LaTeXFeatures::getLyXSGMLEntities() const
1506 {
1507         // Definition of entities used in the document that are LyX related.
1508         odocstringstream entities;
1509
1510         if (mustProvide("lyxarrow")) {
1511                 entities << "<!ENTITY lyxarrow \"-&gt;\">" << '\n';
1512         }
1513
1514         return entities.str();
1515 }
1516
1517
1518 docstring const LaTeXFeatures::getIncludedFiles(string const & fname) const
1519 {
1520         odocstringstream sgmlpreamble;
1521         // FIXME UNICODE
1522         docstring const basename(from_utf8(onlyPath(fname)));
1523
1524         FileMap::const_iterator end = IncludedFiles_.end();
1525         for (FileMap::const_iterator fi = IncludedFiles_.begin();
1526              fi != end; ++fi)
1527                 // FIXME UNICODE
1528                 sgmlpreamble << "\n<!ENTITY " << fi->first
1529                              << (isSGMLFileName(fi->second) ? " SYSTEM \"" : " \"")
1530                              << makeRelPath(from_utf8(fi->second), basename) << "\">";
1531
1532         return sgmlpreamble.str();
1533 }
1534
1535
1536 void LaTeXFeatures::showStruct() const
1537 {
1538         lyxerr << "LyX needs the following commands when LaTeXing:"
1539                << "\n***** Packages:" << getPackages()
1540                << "\n***** Macros:" << to_utf8(getMacros())
1541                << "\n***** Textclass stuff:" << to_utf8(getTClassPreamble())
1542                << "\n***** done." << endl;
1543 }
1544
1545
1546 Buffer const & LaTeXFeatures::buffer() const
1547 {
1548         return *buffer_;
1549 }
1550
1551
1552 void LaTeXFeatures::setBuffer(Buffer const & buffer)
1553 {
1554         buffer_ = &buffer;
1555 }
1556
1557
1558 BufferParams const & LaTeXFeatures::bufferParams() const
1559 {
1560         return params_;
1561 }
1562
1563
1564 void LaTeXFeatures::getFloatDefinitions(odocstream & os) const
1565 {
1566         FloatList const & floats = params_.documentClass().floats();
1567
1568         // Here we will output the code to create the needed float styles.
1569         // We will try to do this as minimal as possible.
1570         // \floatstyle{ruled}
1571         // \newfloat{algorithm}{htbp}{loa}
1572         // \providecommand{\algorithmname}{Algorithm}
1573         // \floatname{algorithm}{\protect\algorithmname}
1574         UsedFloats::const_iterator cit = usedFloats_.begin();
1575         UsedFloats::const_iterator end = usedFloats_.end();
1576         for (; cit != end; ++cit) {
1577                 Floating const & fl = floats.getType(cit->first);
1578
1579                 // For builtin floats we do nothing.
1580                 if (fl.isPredefined())
1581                         continue;
1582
1583                 // We have to special case "table" and "figure"
1584                 if (fl.floattype() == "tabular" || fl.floattype() == "figure") {
1585                         // Output code to modify "table" or "figure"
1586                         // but only if builtin == false
1587                         // and that have to be true at this point in the
1588                         // function.
1589                         docstring const type = from_ascii(fl.floattype());
1590                         docstring const placement = from_ascii(fl.placement());
1591                         docstring const style = from_ascii(fl.style());
1592                         if (!style.empty()) {
1593                                 os << "\\floatstyle{" << style << "}\n"
1594                                    << "\\restylefloat{" << type << "}\n";
1595                         }
1596                         if (!placement.empty()) {
1597                                 os << "\\floatplacement{" << type << "}{"
1598                                    << placement << "}\n";
1599                         }
1600                 } else {
1601                         // The other non builtin floats.
1602
1603                         docstring const type = from_ascii(fl.floattype());
1604                         docstring const placement = from_ascii(fl.placement());
1605                         docstring const ext = from_ascii(fl.ext());
1606                         docstring const within = from_ascii(fl.within());
1607                         docstring const style = from_ascii(fl.style());
1608                         docstring const name =
1609                                 buffer().language()->translateLayout(fl.name());
1610                         os << "\\floatstyle{" << style << "}\n"
1611                            << "\\newfloat{" << type << "}{" << placement
1612                            << "}{" << ext << '}';
1613                         if (!within.empty())
1614                                 os << '[' << within << ']';
1615                         os << '\n'
1616                            << "\\providecommand{\\" << type << "name}{"
1617                            << name << "}\n"
1618                            << "\\floatname{" << type << "}{\\protect\\"
1619                            << type << "name}\n";
1620
1621                         // What missing here is to code to minimalize the code
1622                         // output so that the same floatstyle will not be
1623                         // used several times, when the same style is still in
1624                         // effect. (Lgb)
1625                 }
1626                 if (cit->second)
1627                         os << "\n\\newsubfloat{" << from_ascii(fl.floattype()) << "}\n";
1628         }
1629 }
1630
1631
1632 void LaTeXFeatures::resolveAlternatives()
1633 {
1634         for (Features::iterator it = features_.begin(); it != features_.end();) {
1635                 if (contains(*it, '|')) {
1636                         vector<string> const alternatives = getVectorFromString(*it, "|");
1637                         vector<string>::const_iterator const end = alternatives.end();
1638                         vector<string>::const_iterator ita = alternatives.begin();
1639                         for (; ita != end; ++ita) {
1640                                 if (isRequired(*ita))
1641                                         break;
1642                         }
1643                         if (ita == end)
1644                                 require(alternatives.front());
1645                         features_.erase(it);
1646                         it = features_.begin();
1647                 } else
1648                         ++it;
1649         }
1650 }
1651
1652
1653 } // namespace lyx