]> git.lyx.org Git - features.git/blob - src/insets/InsetERT.cpp
DocBook: in ERTs, allow the use of \string.
[features.git] / src / insets / InsetERT.cpp
1 /**
2  * \file InsetERT.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Jürgen Vigna
7  * \author Lars Gullik Bjønnes
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "InsetERT.h"
15
16 #include "Cursor.h"
17 #include "FuncRequest.h"
18 #include "FuncStatus.h"
19 #include "InsetLayout.h"
20 #include "Language.h"
21 #include "Lexer.h"
22 #include "xml.h"
23 #include "ParagraphParameters.h"
24 #include "Paragraph.h"
25 #include "output_docbook.h"
26
27 #include "support/docstream.h"
28 #include "support/gettext.h"
29 #include "support/lstrings.h"
30 #include "support/TempFile.h"
31
32 #include <sstream>
33 #include <regex>
34 #include <iostream>
35
36 using namespace std;
37 using namespace lyx::support;
38
39 namespace lyx {
40
41 InsetERT::InsetERT(Buffer * buf, CollapseStatus status)
42         : InsetCollapsible(buf)
43 {
44         status_ = status;
45 }
46
47
48 InsetERT::InsetERT(InsetERT const & old)
49         : InsetCollapsible(old)
50 {}
51
52
53 void InsetERT::write(ostream & os) const
54 {
55         os << "ERT" << "\n";
56         InsetCollapsible::write(os);
57 }
58
59
60 int InsetERT::plaintext(odocstringstream & os,
61         OutputParams const & rp, size_t max_length) const
62 {
63         if (!rp.inIndexEntry)
64                 // do not output TeX code
65                 return 0;
66
67         ParagraphList::const_iterator par = paragraphs().begin();
68         ParagraphList::const_iterator end = paragraphs().end();
69
70         while (par != end && os.str().size() <= max_length) {
71                 pos_type siz = par->size();
72                 for (pos_type i = 0; i < siz; ++i) {
73                         char_type const c = par->getChar(i);
74                         // output the active characters
75                         switch (c) {
76                         case '|':
77                         case '!':
78                         case '@':
79                                 os.put(c);
80                                 break;
81                         default:
82                                 break;
83                         }
84                 }
85                 ++par;
86         }
87         return 0;
88 }
89
90
91 static const std::map<docstring, docstring> raw_latex_encoding_to_unicode_xml{
92                 // Punctuation.
93                 {from_ascii("\\textquotesingle"), from_ascii("'")},
94                 {from_ascii("!`"), from_ascii("&#161;")}, // inverted exclamation mark
95                 {from_ascii("?`"), from_ascii("&#191;")}, // inverted interrogation mark
96
97                 // Logos.
98                 {from_ascii("\\LaTeX"), from_ascii("LaTeX")},
99                 {from_ascii("\\LaTeXe"), from_ascii("LaTeX2&#x03b5;")}, // LaTeX 2 epsilon
100                 {from_ascii("\\LyX"), from_ascii("LyX")},
101                 {from_ascii("\\TeX"), from_ascii("TeX")},
102
103                 // Accentuated letters (alphabetical order of description, ligatures after accents).
104                 // Missing letters are only indicated for vowels (only few consonants have diacritics).
105                 // Only symbols that can be expressed as one Unicode characters are present; symbols with more than one
106                 // diacritic are also omitted.
107                 {from_ascii("\\`{a}"), from_ascii("&#225;")}, // a acute
108                 {from_ascii("\\` a"), from_ascii("&#225;")},
109                 {from_ascii("\\`{A}"), from_ascii("&#193;")}, // A acute
110                 {from_ascii("\\` A"), from_ascii("&#193;")},
111                 {from_ascii("\\u{a}"), from_ascii("&#259;")}, // a breve
112                 {from_ascii("\\u a"), from_ascii("&#259;")},
113                 {from_ascii("\\u{A}"), from_ascii("&#258;")}, // A breve
114                 {from_ascii("\\u A"), from_ascii("&#258;")},
115                 {from_ascii("\\v{a}"), from_ascii("&#462;")}, // a caron
116                 {from_ascii("\\v a"), from_ascii("&#462;")},
117                 {from_ascii("\\v{A}"), from_ascii("&#461;")}, // A caron
118                 {from_ascii("\\v A"), from_ascii("&#461;")},
119                 // No a cedilla.
120                 {from_ascii("\\^{a}"), from_ascii("&#226;")}, // a circumflex
121                 {from_ascii("\\^ a"), from_ascii("&#226;")},
122                 {from_ascii("\\^{A}"), from_ascii("&#194;")}, // A circumflex
123                 {from_ascii("\\^ A"), from_ascii("&#194;")},
124                 {from_ascii("\\\"{a}"), from_ascii("&#228;")}, // a diaeresis
125                 {from_ascii("\\\" a"), from_ascii("&#228;")},
126                 {from_ascii("\\\"{A}"), from_ascii("&#196;")}, // A diaeresis
127                 {from_ascii("\\\" A"), from_ascii("&#196;")},
128                 // No a double acute.
129                 {from_ascii("\\`{a}"), from_ascii("&#224;")}, // a grave
130                 {from_ascii("\\` a"), from_ascii("&#224;")},
131                 {from_ascii("\\`{A}"), from_ascii("&#192;")}, // A grave
132                 {from_ascii("\\` A"), from_ascii("&#192;")},
133                 {from_ascii("\\~{a}"), from_ascii("&#227;")}, // a tilde
134                 {from_ascii("\\~ a"), from_ascii("&#227;")},
135                 {from_ascii("\\~{A}"), from_ascii("&#195;")}, // A tilde
136                 {from_ascii("\\~ A"), from_ascii("&#195;")},
137                 {from_ascii("\\aa"), from_ascii("&#229;")}, // a ring
138                 {from_ascii("\\r{a}"), from_ascii("&#229;")},
139                 {from_ascii("\\r a"), from_ascii("&#229;")},
140                 {from_ascii("\\AA"), from_ascii("&#197;")}, // A ring
141                 {from_ascii("\\r{A}"), from_ascii("&#197;")},
142                 {from_ascii("\\r A"), from_ascii("&#197;")},
143                 {from_ascii("\\ae"), from_ascii("&#230;")}, // ae ligature
144                 {from_ascii("\\AE"), from_ascii("&#198;")}, // AE ligature
145                 {from_ascii("\\v{c}"), from_ascii("&#269;")}, // c caron
146                 {from_ascii("\\v c"), from_ascii("&#269;")},
147                 {from_ascii("\\v{C}"), from_ascii("&#268;")}, // C caron
148                 {from_ascii("\\v C"), from_ascii("&#268;")},
149                 {from_ascii("\\c{c}"), from_ascii("&#199;")}, // c cedilla
150                 {from_ascii("\\c c"), from_ascii("&#199;")},
151                 {from_ascii("\\c{C}"), from_ascii("&#231;")}, // C cedilla
152                 {from_ascii("\\c C"), from_ascii("&#231;")},
153                 {from_ascii("\\v{d}"), from_ascii("&#271;")}, // d caron
154                 {from_ascii("\\v d"), from_ascii("&#271;")},
155                 {from_ascii("\\v{D}"), from_ascii("&#270;")}, // D caron
156                 {from_ascii("\\v D"), from_ascii("&#270;")},
157                 {from_ascii("\\`{e}"), from_ascii("&#233;")}, // e acute
158                 {from_ascii("\\` e"), from_ascii("&#233;")},
159                 {from_ascii("\\`{E}"), from_ascii("&#201;")}, // E acute
160                 {from_ascii("\\` E"), from_ascii("&#201;")},
161                 {from_ascii("\\u{e}"), from_ascii("&#277;")}, // e breve
162                 {from_ascii("\\u e"), from_ascii("&#277;")},
163                 {from_ascii("\\u{E}"), from_ascii("&#276;")}, // E breve
164                 {from_ascii("\\u E"), from_ascii("&#276;")},
165                 {from_ascii("\\v{e}"), from_ascii("&#283;")}, // e caron
166                 {from_ascii("\\v e"), from_ascii("&#283;")},
167                 {from_ascii("\\v{E}"), from_ascii("&#282;")}, // E caron
168                 {from_ascii("\\v E"), from_ascii("&#282;")},
169                 {from_ascii("\\c{e}"), from_ascii("&#553;")}, // e cedilla
170                 {from_ascii("\\c e"), from_ascii("&#553;")},
171                 {from_ascii("\\c{E}"), from_ascii("&#552;")}, // E cedilla
172                 {from_ascii("\\c E"), from_ascii("&#552;")},
173                 {from_ascii("\\^{e}"), from_ascii("&#234;")}, // e circumflex
174                 {from_ascii("\\^ e"), from_ascii("&#234;")},
175                 {from_ascii("\\^{E}"), from_ascii("&#202;")}, // E circumflex
176                 {from_ascii("\\^ E"), from_ascii("&#202;")},
177                 {from_ascii("\\\"{e}"), from_ascii("&#235;")}, // e diaeresis
178                 {from_ascii("\\\" e"), from_ascii("&#235;")},
179                 {from_ascii("\\\"{E}"), from_ascii("&#203;")}, // E diaeresis
180                 {from_ascii("\\\" E"), from_ascii("&#203;")},
181                 // No e double acute.
182                 {from_ascii("\\`{e}"), from_ascii("&#232;")}, // e grave
183                 {from_ascii("\\` e"), from_ascii("&#232;")},
184                 {from_ascii("\\`{E}"), from_ascii("&#200;")}, // E grave
185                 {from_ascii("\\` E"), from_ascii("&#200;")},
186                 {from_ascii("\\~{e}"), from_ascii("&#7869;")}, // e tilde
187                 {from_ascii("\\~ e"), from_ascii("&#7869;")},
188                 {from_ascii("\\~{E}"), from_ascii("&#7868;")}, // E tilde
189                 {from_ascii("\\~ E"), from_ascii("&#7868;")},
190                 // No e ring.
191                 {from_ascii("\\u{g}"), from_ascii("&#287;")}, // g breve
192                 {from_ascii("\\u g"), from_ascii("&#287;")},
193                 {from_ascii("\\u{G}"), from_ascii("&#286;")}, // G breve
194                 {from_ascii("\\u G"), from_ascii("&#286;")},
195                 {from_ascii("\\v{g}"), from_ascii("&#487;")}, // g caron
196                 {from_ascii("\\v g"), from_ascii("&#487;")},
197                 {from_ascii("\\v{G}"), from_ascii("&#486;")}, // G caron
198                 {from_ascii("\\v G"), from_ascii("&#486;")},
199                 {from_ascii("\\c{g}"), from_ascii("&#291;")}, // g cedilla
200                 {from_ascii("\\c g"), from_ascii("&#291;")},
201                 {from_ascii("\\c{G}"), from_ascii("&#290;")}, // G cedilla
202                 {from_ascii("\\c G"), from_ascii("&#290;")},
203                 {from_ascii("\\i"), from_ascii("&#305;")}, // i dotless
204                 {from_ascii("\\`{i}"), from_ascii("&#237;")}, // i acute
205                 {from_ascii("\\` i"), from_ascii("&#237;")},
206                 {from_ascii("\\`{I}"), from_ascii("&#205;")}, // I acute
207                 {from_ascii("\\` I"), from_ascii("&#205;")},
208                 {from_ascii("\\u{i}"), from_ascii("&#301;")}, // i breve
209                 {from_ascii("\\u i"), from_ascii("&#301;")},
210                 {from_ascii("\\u{I}"), from_ascii("&#300;")}, // I breve
211                 {from_ascii("\\u I"), from_ascii("&#300;")},
212                 {from_ascii("\\v{i}"), from_ascii("&#464;")}, // i caron
213                 {from_ascii("\\v i"), from_ascii("&#464;")},
214                 {from_ascii("\\v{I}"), from_ascii("&#463;")}, // I caron
215                 {from_ascii("\\v I"), from_ascii("&#463;")},
216                 // No i cedilla.
217                 {from_ascii("\\^{i}"), from_ascii("&#238;")}, // i circumflex
218                 {from_ascii("\\^ i"), from_ascii("&#238;")},
219                 {from_ascii("\\^{I}"), from_ascii("&#206;")}, // I circumflex
220                 {from_ascii("\\^ I"), from_ascii("&#239;")},
221                 {from_ascii("\\\"{i}"), from_ascii("&#239;")}, // i diaeresis
222                 {from_ascii("\\\" i"), from_ascii("&#235;")},
223                 {from_ascii("\\\"{I}"), from_ascii("&#235;")}, // I diaeresis
224                 {from_ascii("\\\" I"), from_ascii("&#207;")},
225                 // No i double acute.
226                 {from_ascii("\\`{i}"), from_ascii("&#236;")}, // i grave
227                 {from_ascii("\\` i"), from_ascii("&#236;")},
228                 {from_ascii("\\`{I}"), from_ascii("&#204;")}, // I grave
229                 {from_ascii("\\` I"), from_ascii("&#204;")},
230                 {from_ascii("\\~{i}"), from_ascii("&#297;")}, // i tilde
231                 {from_ascii("\\~ i"), from_ascii("&#297;")},
232                 {from_ascii("\\~{I}"), from_ascii("&#296;")}, // I tilde
233                 {from_ascii("\\~ I"), from_ascii("&#296;")},
234                 // No i ring.
235                 {from_ascii("\\j"), from_ascii("&#567;")}, // j dotless
236                 {from_ascii("\\v{k}"), from_ascii("&#488;")}, // k caron
237                 {from_ascii("\\v k"), from_ascii("&#488;")},
238                 {from_ascii("\\v{K}"), from_ascii("&#489;")}, // K caron
239                 {from_ascii("\\v K"), from_ascii("&#489;")},
240                 {from_ascii("\\c{k}"), from_ascii("&#311;")}, // k cedilla
241                 {from_ascii("\\c k"), from_ascii("&#311;")},
242                 {from_ascii("\\c{K}"), from_ascii("&#310;")}, // K cedilla
243                 {from_ascii("\\c K"), from_ascii("&#310;")},
244                 {from_ascii("\\v{l}"), from_ascii("&#318;")}, // l caron
245                 {from_ascii("\\v l"), from_ascii("&#318;")},
246                 {from_ascii("\\v{L}"), from_ascii("&#317;")}, // L caron
247                 {from_ascii("\\v L"), from_ascii("&#317;")},
248                 {from_ascii("\\c{l}"), from_ascii("&#316;")}, // l cedilla
249                 {from_ascii("\\c l"), from_ascii("&#316;")},
250                 {from_ascii("\\c{L}"), from_ascii("&#315;")}, // L cedilla
251                 {from_ascii("\\c L"), from_ascii("&#315;")},
252                 {from_ascii("\\l"), from_ascii("&#322;")}, // l stroke
253                 {from_ascii("\\L"), from_ascii("&#321;")}, // L stroke
254                 {from_ascii("\\v{n}"), from_ascii("&#328;")}, // n caron
255                 {from_ascii("\\v n"), from_ascii("&#328;")},
256                 {from_ascii("\\v{N}"), from_ascii("&#327;")}, // N caron
257                 {from_ascii("\\v N"), from_ascii("&#327;")},
258                 {from_ascii("\\c{n}"), from_ascii("&#326;")}, // n cedilla
259                 {from_ascii("\\c n"), from_ascii("&#326;")},
260                 {from_ascii("\\c{N}"), from_ascii("&#325;")}, // N cedilla
261                 {from_ascii("\\c N"), from_ascii("&#325;")},
262                 {from_ascii("\\~{n}"), from_ascii("&#241;")}, // n tilde
263                 {from_ascii("\\~ n"), from_ascii("&#241;")},
264                 {from_ascii("\\~{N}"), from_ascii("&#209;")}, // N tilde
265                 {from_ascii("\\~ N"), from_ascii("&#209;")},
266                 {from_ascii("\\`{o}"), from_ascii("&#243;")}, // o acute
267                 {from_ascii("\\` o"), from_ascii("&#243;")},
268                 {from_ascii("\\`{O}"), from_ascii("&#211;")}, // O acute
269                 {from_ascii("\\` O"), from_ascii("&#211;")},
270                 {from_ascii("\\u{o}"), from_ascii("&#335;")}, // o breve
271                 {from_ascii("\\u o"), from_ascii("&#335;")},
272                 {from_ascii("\\u{O}"), from_ascii("&#334;")}, // O breve
273                 {from_ascii("\\u O"), from_ascii("&#334;")},
274                 {from_ascii("\\v{o}"), from_ascii("&#466;")}, // o caron
275                 {from_ascii("\\v o"), from_ascii("&#466;")},
276                 {from_ascii("\\v{O}"), from_ascii("&#465;")}, // O caron
277                 {from_ascii("\\v O"), from_ascii("&#465;")},
278                 // No o cedilla.
279                 {from_ascii("\\^{o}"), from_ascii("&#244;")}, // o circumflex
280                 {from_ascii("\\^ o"), from_ascii("&#244;")},
281                 {from_ascii("\\^{O}"), from_ascii("&#212;")}, // O circumflex
282                 {from_ascii("\\^ O"), from_ascii("&#212;")},
283                 {from_ascii("\\\"{o}"), from_ascii("&#246;")}, // o diaeresis
284                 {from_ascii("\\\" o"), from_ascii("&#246;")},
285                 {from_ascii("\\\"{O}"), from_ascii("&#214;")}, // O diaeresis
286                 {from_ascii("\\\" O"), from_ascii("&#214;")},
287                 {from_ascii("\\H{o}"), from_ascii("&#337;")}, // o double acute
288                 {from_ascii("\\H o"), from_ascii("&#337;")},
289                 {from_ascii("\\H{O}"), from_ascii("&#336;")}, // O double acute
290                 {from_ascii("\\H O"), from_ascii("&#336;")},
291                 {from_ascii("\\`{o}"), from_ascii("&#242;")}, // o grave
292                 {from_ascii("\\` o"), from_ascii("&#242;")},
293                 {from_ascii("\\`{O}"), from_ascii("&#210;")}, // O grave
294                 {from_ascii("\\` O"), from_ascii("&#210;")},
295                 {from_ascii("\\o"), from_ascii("&#248;")}, // o stroke
296                 {from_ascii("\\O"), from_ascii("&#216;")}, // O stroke
297                 {from_ascii("\\~{o}"), from_ascii("&#245;")}, // o tilde
298                 {from_ascii("\\~ o"), from_ascii("&#245;")},
299                 {from_ascii("\\~{O}"), from_ascii("&#213;")}, // O tilde
300                 {from_ascii("\\~ O"), from_ascii("&#213;")},
301                 // No o ring.
302                 {from_ascii("\\oe"), from_ascii("&#339;")}, // oe ligature
303                 {from_ascii("\\OE"), from_ascii("&#338;")}, // OE ligature
304                 {from_ascii("\\v{r}"), from_ascii("&#345;")}, // r caron
305                 {from_ascii("\\v r"), from_ascii("&#345;")},
306                 {from_ascii("\\v{R}"), from_ascii("&#344;")}, // R caron
307                 {from_ascii("\\v R"), from_ascii("&#344;")},
308                 {from_ascii("\\c{r}"), from_ascii("&#343;")}, // r cedilla
309                 {from_ascii("\\c r"), from_ascii("&#343;")},
310                 {from_ascii("\\c{R}"), from_ascii("&#342;")}, // R cedilla
311                 {from_ascii("\\c R"), from_ascii("&#342;")},
312                 {from_ascii("\\v{s}"), from_ascii("&#353;")}, // s caron
313                 {from_ascii("\\v s"), from_ascii("&#353;")},
314                 {from_ascii("\\v{S}"), from_ascii("&#352;")}, // S caron
315                 {from_ascii("\\v S"), from_ascii("&#352;")},
316                 {from_ascii("\\c{s}"), from_ascii("&#351;")}, // s cedilla
317                 {from_ascii("\\c s"), from_ascii("&#351;")},
318                 {from_ascii("\\c{S}"), from_ascii("&#350;")}, // S cedilla
319                 {from_ascii("\\c S"), from_ascii("&#350;")},
320                 {from_ascii("\\v{t}"), from_ascii("&#357;")}, // t caron
321                 {from_ascii("\\v t"), from_ascii("&#357;")},
322                 {from_ascii("\\v{T}"), from_ascii("&#356;")}, // T caron
323                 {from_ascii("\\v T"), from_ascii("&#356;")},
324                 {from_ascii("\\c{t}"), from_ascii("&#355;")}, // t cedilla
325                 {from_ascii("\\c t"), from_ascii("&#355;")},
326                 {from_ascii("\\c{T}"), from_ascii("&#354;")}, // T cedilla
327                 {from_ascii("\\c T"), from_ascii("&#354;")},
328                 {from_ascii("\\`{u}"), from_ascii("&#250;")}, // u acute
329                 {from_ascii("\\` u"), from_ascii("&#250;")},
330                 {from_ascii("\\`{U}"), from_ascii("&#218;")}, // U acute
331                 {from_ascii("\\` U"), from_ascii("&#218;")},
332                 {from_ascii("\\u{u}"), from_ascii("&#365;")}, // u breve
333                 {from_ascii("\\u u"), from_ascii("&#365;")},
334                 {from_ascii("\\u{U}"), from_ascii("&#364;")}, // U breve
335                 {from_ascii("\\u U"), from_ascii("&#364;")},
336                 {from_ascii("\\v{u}"), from_ascii("&#468;")}, // u caron
337                 {from_ascii("\\v u"), from_ascii("&#468;")},
338                 {from_ascii("\\v{U}"), from_ascii("&#467;")}, // U caron
339                 {from_ascii("\\v U"), from_ascii("&#467;")},
340                 // No u cedilla.
341                 {from_ascii("\\^{u}"), from_ascii("&#251;")}, // u circumflex
342                 {from_ascii("\\^ u"), from_ascii("&#251;")},
343                 {from_ascii("\\^{U}"), from_ascii("&#219;")}, // U circumflex
344                 {from_ascii("\\^ U"), from_ascii("&#219;")},
345                 {from_ascii("\\\"{u}"), from_ascii("&#252;")}, // u diaeresis
346                 {from_ascii("\\\" u"), from_ascii("&#252;")},
347                 {from_ascii("\\\"{U}"), from_ascii("&#220;")}, // U diaeresis
348                 {from_ascii("\\\" U"), from_ascii("&#220;")},
349                 {from_ascii("\\H{u}"), from_ascii("&#369;")}, // u double acute
350                 {from_ascii("\\H u"), from_ascii("&#369;")},
351                 {from_ascii("\\H{U}"), from_ascii("&#368;")}, // U double acute
352                 {from_ascii("\\H U"), from_ascii("&#368;")},
353                 {from_ascii("\\`{u}"), from_ascii("&#249;")}, // u grave
354                 {from_ascii("\\` u"), from_ascii("&#249;")},
355                 {from_ascii("\\`{U}"), from_ascii("&#217;")}, // U grave
356                 {from_ascii("\\` U"), from_ascii("&#217;")},
357                 {from_ascii("\\~{u}"), from_ascii("&#361;")}, // u tilde
358                 {from_ascii("\\~ u"), from_ascii("&#361;")},
359                 {from_ascii("\\~{U}"), from_ascii("&#360;")}, // U tilde
360                 {from_ascii("\\~ U"), from_ascii("&#360;")},
361                 {from_ascii("\\r{u}"), from_ascii("&#229;")}, // u ring
362                 {from_ascii("\\r u"), from_ascii("&#367;")},
363                 {from_ascii("\\r{U}"), from_ascii("&#367;")}, // U ring
364                 {from_ascii("\\r U"), from_ascii("&#366;")},
365                 {from_ascii("\\`{y}"), from_ascii("&#253;")}, // y acute
366                 {from_ascii("\\` y"), from_ascii("&#253;")},
367                 {from_ascii("\\`{Y}"), from_ascii("&#221;")}, // Y acute
368                 {from_ascii("\\` Y"), from_ascii("&#221;")},
369                 {from_ascii("\\v{z}"), from_ascii("&#382;")}, // z caron
370                 {from_ascii("\\v z"), from_ascii("&#382;")},
371                 {from_ascii("\\v{Z}"), from_ascii("&#381;")}, // Z caron
372                 {from_ascii("\\v Z"), from_ascii("&#381;")},
373                 // No y breve.
374                 // No y cedilla.
375                 {from_ascii("\\^{y}"), from_ascii("&#375;")}, // y circumflex
376                 {from_ascii("\\^ y"), from_ascii("&#375;")},
377                 {from_ascii("\\^{Y}"), from_ascii("&#374;")}, // Y circumflex
378                 {from_ascii("\\^ Y"), from_ascii("&#374;")},
379                 {from_ascii("\\\"{y}"), from_ascii("&#255;")}, // y diaeresis
380                 {from_ascii("\\\" y"), from_ascii("&#255;")},
381                 {from_ascii("\\\"{Y}"), from_ascii("&#376;")}, // Y diaeresis
382                 {from_ascii("\\\" Y"), from_ascii("&#376;")},
383                 // No y double acute.
384                 {from_ascii("\\`{y}"), from_ascii("&#7923;")}, // y grave
385                 {from_ascii("\\` y"), from_ascii("&#7923;")},
386                 {from_ascii("\\`{Y}"), from_ascii("&#7922;")}, // Y grave
387                 {from_ascii("\\` Y"), from_ascii("&#7922;")},
388                 {from_ascii("\\~{y}"), from_ascii("&#7929;")}, // y tilde
389                 {from_ascii("\\~ y"), from_ascii("&#7929;")},
390                 {from_ascii("\\~{Y}"), from_ascii("&#7928;")}, // Y tilde
391                 {from_ascii("\\~ Y"), from_ascii("&#7928;")},
392                 // No y ring.
393 };
394
395
396 void InsetERT::docbook(XMLStream & xs, OutputParams const & runparams) const
397 {
398         auto const begin = paragraphs().begin();
399         auto par = begin;
400         auto const end = paragraphs().end();
401
402         odocstringstream os; // No need for XML handling here.
403
404         // Recreate the logic of makeParagraph in output_docbook.cpp, but much simplified: never open <para>
405         // in an ERT, use simple line breaks.
406         // New line after each paragraph of the ERT, save the last one.
407         while (true) { // For each paragraph in the ERT...
408         std::vector<docstring> pars_prepend;
409         std::vector<docstring> pars;
410         std::vector<docstring> pars_append;
411         tie(pars_prepend, pars, pars_append) = par->simpleDocBookOnePar(buffer(), runparams, text().outerFont(distance(begin, par)), 0, false, true);
412
413         for (docstring const & parXML : pars_prepend)
414             xs << XMLStream::ESCAPE_NONE << parXML;
415                 auto p = pars.begin();
416                 while (true) { // For each line of this ERT paragraph...
417                         os << *p;
418                         ++p;
419                         if (p != pars.end())
420                                 os << "\n";
421                         else
422                                 break;
423                 }
424         for (docstring const & parXML : pars_append)
425             xs << XMLStream::ESCAPE_NONE << parXML;
426
427                 ++par;
428                 if (par != end)
429                         os << "\n";
430                 else
431                         break;
432         }
433
434 //      // Implement the special case of \and: split the current item.
435 //      if (os.str() == "\\and" || os.str() == "\\and ") {
436 //              auto lay = getLayout();
437 //      }
438
439         // Try to recognise some commands to have a nicer DocBook output.
440         bool output_as_comment = true;
441
442         // First step: some commands have a direct mapping to DocBook, mostly because the mapping is simply text or
443         // an XML entity.
444         {
445                 docstring os_trimmed = trim(os.str());
446
447                 auto command_raw_translation = raw_latex_encoding_to_unicode_xml.find(os_trimmed);
448                 if (command_raw_translation != raw_latex_encoding_to_unicode_xml.end()) {
449                         xs << command_raw_translation->second;
450                         output_as_comment = false;
451                 } else {
452                         // If the trimmed ERT ends with {}, try a mapping without it.
453                         auto os_braces = os_trimmed.find(from_ascii("{}"));
454
455                         if (os_braces != lyx::docstring::npos) {
456                                 auto key = os_trimmed.substr(0, os_braces);
457                                 auto command_braces_translation = raw_latex_encoding_to_unicode_xml.find(key);
458
459                                 if (command_braces_translation != raw_latex_encoding_to_unicode_xml.end()) {
460                                         xs << command_braces_translation->second;
461                                         output_as_comment = false;
462                                 }
463                         }
464                 }
465         }
466
467         // Second step: the command \string can be ignored. If that's the only command in the ERT, then done.
468         // There may be several occurrences. (\string is 7 characters long.)
469         if (os.str().length() >= 7) {
470                 docstring os_str = os.str();
471
472                 while (os_str.length() >= 7) {
473                         auto os_text = os_str.find(from_ascii("\\string"));
474
475                         if (os_text != lyx::docstring::npos && !std::isalpha(static_cast<int>(os_str[os_text + 7]))) {
476                                 os_str = os_str.substr(0, os_text) + os_str.substr(os_text + 7, os_str.length());
477
478                                 if (os_str.find('\\') == std::string::npos) {
479                                         xs << os_str;
480                                         output_as_comment = false;
481                                         break;
482                                 }
483                         } else {
484                                 break;
485                         }
486                 }
487         }
488
489         // Otherwise, output the ERT as a comment with the appropriate escaping if the command is not recognised.
490         if (output_as_comment) {
491                 xs << XMLStream::ESCAPE_NONE << "<!-- ";
492                 xs << XMLStream::ESCAPE_COMMENTS << os.str();
493                 xs << XMLStream::ESCAPE_NONE << " -->";
494         }
495 }
496
497
498 void InsetERT::doDispatch(Cursor & cur, FuncRequest & cmd)
499 {
500         switch (cmd.action()) {
501         case LFUN_INSET_MODIFY:
502                 if (cmd.getArg(0) == "ert") {
503                         cur.recordUndoInset(this);
504                         setStatus(cur, string2params(to_utf8(cmd.argument())));
505                         break;
506                 }
507                 //fall-through
508         default:
509                 InsetCollapsible::doDispatch(cur, cmd);
510                 break;
511         }
512
513 }
514
515
516 bool InsetERT::getStatus(Cursor & cur, FuncRequest const & cmd,
517         FuncStatus & status) const
518 {
519         switch (cmd.action()) {
520         case LFUN_INSET_INSERT:
521                 status.setEnabled(false);
522                 return true;
523         case LFUN_INSET_MODIFY:
524                 if (cmd.getArg(0) == "ert") {
525                         status.setEnabled(true);
526                         return true;
527                 }
528                 //fall through
529
530         default:
531                 return InsetCollapsible::getStatus(cur, cmd, status);
532         }
533 }
534
535
536
537 docstring const InsetERT::buttonLabel(BufferView const & bv) const
538 {
539         // U+1F512 LOCK
540         docstring const locked = tempfile_ ? docstring(1, 0x1F512) : docstring();
541         if (decoration() == InsetDecoration::CLASSIC)
542                 return locked + (isOpen(bv) ? _("ERT") : getNewLabel(_("ERT")));
543         return locked + getNewLabel(_("ERT"));
544 }
545
546
547 InsetCollapsible::CollapseStatus InsetERT::string2params(string const & in)
548 {
549         if (in.empty())
550                 return Collapsed;
551         istringstream data(in);
552         Lexer lex;
553         lex.setStream(data);
554         lex.setContext("InsetERT::string2params");
555         lex >> "ert";
556         int s;
557         lex >> s;
558         return static_cast<CollapseStatus>(s);
559 }
560
561
562 string InsetERT::params2string(CollapseStatus status)
563 {
564         ostringstream data;
565         data << "ert" << ' ' << status;
566         return data.str();
567 }
568
569
570 docstring InsetERT::xhtml(XMLStream &, OutputParams const &) const
571 {
572         return docstring();
573 }
574
575 } // namespace lyx