]> git.lyx.org Git - lyx.git/blob - src/insets/InsetSpecialChar.cpp
Fix bug #8580: Do not include material in the XHTML TOC that is not
[lyx.git] / src / insets / InsetSpecialChar.cpp
1 /**
2  * \file InsetSpecialChar.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Asger Alstrup Nielsen
7  * \author Jean-Marc Lasgouttes
8  * \author Lars Gullik Bjønnes
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "InsetSpecialChar.h"
16
17 #include "Dimension.h"
18 #include "Font.h"
19 #include "LaTeXFeatures.h"
20 #include "Lexer.h"
21 #include "MetricsInfo.h"
22 #include "output_xhtml.h"
23
24 #include "frontends/FontMetrics.h"
25 #include "frontends/Painter.h"
26
27 #include "support/debug.h"
28 #include "support/docstream.h"
29
30 using namespace std;
31
32 namespace lyx {
33
34
35 InsetSpecialChar::InsetSpecialChar(Kind k)
36         : Inset(0), kind_(k)
37 {}
38
39
40 InsetSpecialChar::Kind InsetSpecialChar::kind() const
41 {
42         return kind_;
43 }
44
45
46 void InsetSpecialChar::metrics(MetricsInfo & mi, Dimension & dim) const
47 {
48         frontend::FontMetrics const & fm =
49                 theFontMetrics(mi.base.font);
50         dim.asc = fm.maxAscent();
51         dim.des = fm.maxDescent();
52
53         string s;
54         switch (kind_) {
55                 case LIGATURE_BREAK:
56                         s = "|";
57                         break;
58                 case END_OF_SENTENCE:
59                         s = ".";
60                         break;
61                 case LDOTS:
62                         s = ". . .";
63                         break;
64                 case MENU_SEPARATOR:
65                         s = " x ";
66                         break;
67                 case HYPHENATION:
68                         s = "-";
69                         break;
70                 case SLASH:
71                         s = "/";
72                         break;
73                 case NOBREAKDASH:
74                         s = "-";
75                         break;
76         }
77         docstring ds(s.begin(), s.end());
78         dim.wid = fm.width(ds);
79         if (kind_ == HYPHENATION && dim.wid > 5)
80                 dim.wid -= 2; // to make it look shorter
81         
82         setDimCache(mi, dim);
83 }
84
85
86 void InsetSpecialChar::draw(PainterInfo & pi, int x, int y) const
87 {
88         FontInfo font = pi.base.font;
89
90         switch (kind_) {
91         case HYPHENATION:
92         {
93                 font.setColor(Color_special);
94                 pi.pain.text(x, y, char_type('-'), font);
95                 break;
96         }
97         case LIGATURE_BREAK:
98         {
99                 font.setColor(Color_special);
100                 pi.pain.text(x, y, char_type('|'), font);
101                 break;
102         }
103         case END_OF_SENTENCE:
104         {
105                 font.setColor(Color_special);
106                 pi.pain.text(x, y, char_type('.'), font);
107                 break;
108         }
109         case LDOTS:
110         {
111                 font.setColor(Color_special);
112                 string ell = ". . . ";
113                 docstring dell(ell.begin(), ell.end());
114                 pi.pain.text(x, y, dell, font);
115                 break;
116         }
117         case MENU_SEPARATOR:
118         {
119                 frontend::FontMetrics const & fm =
120                         theFontMetrics(font);
121
122                 // A triangle the width and height of an 'x'
123                 int w = fm.width(char_type('x'));
124                 int ox = fm.width(char_type(' ')) + x;
125                 int h = fm.ascent(char_type('x'));
126                 int xp[4], yp[4];
127
128                 xp[0] = ox;     yp[0] = y;
129                 xp[1] = ox;     yp[1] = y - h;
130                 xp[2] = ox + w; yp[2] = y - h/2;
131                 xp[3] = ox;     yp[3] = y;
132
133                 pi.pain.lines(xp, yp, 4, Color_special);
134                 break;
135         }
136         case SLASH:
137         {
138                 font.setColor(Color_special);
139                 pi.pain.text(x, y, char_type('/'), font);
140                 break;
141         }
142         case NOBREAKDASH:
143         {
144                 font.setColor(Color_latex);
145                 pi.pain.text(x, y, char_type('-'), font);
146                 break;
147         }
148         }
149 }
150
151
152 // In lyxf3 this will be just LaTeX
153 void InsetSpecialChar::write(ostream & os) const
154 {
155         string command;
156         switch (kind_) {
157         case HYPHENATION:
158                 command = "\\-";
159                 break;
160         case LIGATURE_BREAK:
161                 command = "\\textcompwordmark{}";
162                 break;
163         case END_OF_SENTENCE:
164                 command = "\\@.";
165                 break;
166         case LDOTS:
167                 command = "\\ldots{}";
168                 break;
169         case MENU_SEPARATOR:
170                 command = "\\menuseparator";
171                 break;
172         case SLASH:
173                 command = "\\slash{}";
174                 break;
175         case NOBREAKDASH:
176                 command = "\\nobreakdash-";
177                 break;
178         }
179         os << "\\SpecialChar " << command << "\n";
180 }
181
182
183 // This function will not be necessary when lyx3
184 void InsetSpecialChar::read(Lexer & lex)
185 {
186         lex.next();
187         string const command = lex.getString();
188
189         if (command == "\\-")
190                 kind_ = HYPHENATION;
191         else if (command == "\\textcompwordmark{}")
192                 kind_ = LIGATURE_BREAK;
193         else if (command == "\\@.")
194                 kind_ = END_OF_SENTENCE;
195         else if (command == "\\ldots{}")
196                 kind_ = LDOTS;
197         else if (command == "\\menuseparator")
198                 kind_ = MENU_SEPARATOR;
199         else if (command == "\\slash{}")
200                 kind_ = SLASH;
201         else if (command == "\\nobreakdash-")
202                 kind_ = NOBREAKDASH;
203         else
204                 lex.printError("InsetSpecialChar: Unknown kind: `$$Token'");
205 }
206
207
208 void InsetSpecialChar::latex(otexstream & os,
209                              OutputParams const & rp) const
210 {
211         switch (kind_) {
212         case HYPHENATION:
213                 os << "\\-";
214                 break;
215         case LIGATURE_BREAK:
216                 os << "\\textcompwordmark{}";
217                 break;
218         case END_OF_SENTENCE:
219                 os << "\\@.";
220                 break;
221         case LDOTS:
222                 os << "\\ldots{}";
223                 break;
224         case MENU_SEPARATOR:
225                 if (rp.local_font->isRightToLeft())
226                         os << "\\lyxarrow*{}";
227                 else
228                         os << "\\lyxarrow{}";
229                 break;
230         case SLASH:
231                 os << "\\slash{}";
232                 break;
233         case NOBREAKDASH:
234                 if (rp.moving_arg)
235                         os << "\\protect";
236                 os << "\\nobreakdash-";
237                 break;
238         }
239 }
240
241
242 int InsetSpecialChar::plaintext(odocstringstream & os,
243         OutputParams const &, size_t) const
244 {
245         switch (kind_) {
246         case HYPHENATION:
247                 return 0;
248         case LIGATURE_BREAK:
249                 os.put(0x200c);
250                 return 1;
251         case END_OF_SENTENCE:
252                 os << '.';
253                 return 1;
254         case LDOTS:
255                 os << "...";
256                 return 3;
257         case MENU_SEPARATOR:
258                 os << "->";
259                 return 2;
260         case SLASH:
261                 os << '/';
262                 return 1;
263         case NOBREAKDASH:
264                 os.put(0x2011);
265                 return 1;
266         }
267         return 0;
268 }
269
270
271 int InsetSpecialChar::docbook(odocstream & os, OutputParams const &) const
272 {
273         switch (kind_) {
274         case HYPHENATION:
275         case LIGATURE_BREAK:
276                 break;
277         case END_OF_SENTENCE:
278                 os << '.';
279                 break;
280         case LDOTS:
281                 os << "...";
282                 break;
283         case MENU_SEPARATOR:
284                 os << "&lyxarrow;";
285                 break;
286         case SLASH:
287                 os << '/';
288                 break;
289         case NOBREAKDASH:
290                 os << '-';
291                 break;
292         }
293         return 0;
294 }
295
296
297 docstring InsetSpecialChar::xhtml(XHTMLStream & xs, OutputParams const &) const
298 {
299         switch (kind_) {
300         case HYPHENATION:
301                 break;
302         case LIGATURE_BREAK:
303                 xs << XHTMLStream::ESCAPE_NONE << "&#8204;";
304                 break;
305         case END_OF_SENTENCE:
306                 xs << '.';
307                 break;
308         case LDOTS:
309                 xs << XHTMLStream::ESCAPE_NONE << "&hellip;";
310                 break;
311         case MENU_SEPARATOR:
312                 xs << XHTMLStream::ESCAPE_NONE << "&rArr;";
313                 break;
314         case SLASH:
315                 xs << XHTMLStream::ESCAPE_NONE << "&frasl;";
316                 break;
317         case NOBREAKDASH:
318                 xs << XHTMLStream::ESCAPE_NONE << "&#8209;";
319                 break;
320         }
321         return docstring();
322 }
323
324
325 void InsetSpecialChar::toString(odocstream & os) const
326 {
327         switch (kind_) {
328         case LIGATURE_BREAK:
329                 // Do not output ZERO WIDTH NON JOINER here
330                 // Spell checker would choke on it.
331                 return;
332         default:
333                 break;
334         }
335         odocstringstream ods;
336         plaintext(ods, OutputParams(0));
337         os << ods.str();
338 }
339
340
341 void InsetSpecialChar::forToc(docstring & os, size_t) const
342 {
343         odocstringstream ods;
344         plaintext(ods, OutputParams(0));
345         os += ods.str();
346 }
347
348
349 void InsetSpecialChar::validate(LaTeXFeatures & features) const
350 {
351         if (kind_ == MENU_SEPARATOR)
352                 features.require("lyxarrow");
353         if (kind_ == NOBREAKDASH)
354                 features.require("amsmath");
355 }
356
357
358 bool InsetSpecialChar::isLetter() const
359 {
360         return kind_ == HYPHENATION || kind_ == LIGATURE_BREAK
361                 || kind_ == NOBREAKDASH;
362 }
363
364
365 bool InsetSpecialChar::isLineSeparator() const
366 {
367 #if 0
368         // this would be nice, but it does not work, since
369         // Paragraph::stripLeadingSpaces nukes the characters which
370         // have this property. I leave the code here, since it should
371         // eventually be made to work. (JMarc 20020327)
372         return kind_ == HYPHENATION || kind_ == MENU_SEPARATOR
373                 || kind_ == SLASH;
374 #else
375         return false;
376 #endif
377 }
378
379
380 } // namespace lyx