]> git.lyx.org Git - lyx.git/blob - src/insets/InsetSpecialChar.cpp
This patch introduces an optional argument to Buffer::updateLabels(), so
[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 int InsetSpecialChar::latex(odocstream & 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         return 0;
240 }
241
242
243 int InsetSpecialChar::plaintext(odocstream & os, OutputParams const &) const
244 {
245         switch (kind_) {
246         case HYPHENATION:
247         case LIGATURE_BREAK:
248                 return 0;
249         case END_OF_SENTENCE:
250                 os << '.';
251                 return 1;
252         case LDOTS:
253                 os << "...";
254                 return 3;
255         case MENU_SEPARATOR:
256                 os << "->";
257                 return 2;
258         case SLASH:
259                 os << '/';
260                 return 1;
261         case NOBREAKDASH:
262                 os << '-';
263                 return 1;
264         }
265         return 0;
266 }
267
268
269 int InsetSpecialChar::docbook(odocstream & os, OutputParams const &) const
270 {
271         switch (kind_) {
272         case HYPHENATION:
273         case LIGATURE_BREAK:
274                 break;
275         case END_OF_SENTENCE:
276                 os << '.';
277                 break;
278         case LDOTS:
279                 os << "...";
280                 break;
281         case MENU_SEPARATOR:
282                 os << "&lyxarrow;";
283                 break;
284         case SLASH:
285                 os << '/';
286                 break;
287         case NOBREAKDASH:
288                 os << '-';
289                 break;
290         }
291         return 0;
292 }
293
294
295 docstring InsetSpecialChar::xhtml(XHTMLStream & xs, OutputParams const &) const
296 {
297         switch (kind_) {
298         case HYPHENATION:
299         case LIGATURE_BREAK:
300                 break;
301         case END_OF_SENTENCE:
302                 xs << '.';
303                 break;
304         case LDOTS:
305                 xs << XHTMLStream::NextRaw() << "&hellip;";
306                 break;
307         case MENU_SEPARATOR:
308                 xs << XHTMLStream::NextRaw() << "&rArr;";
309                 break;
310         case SLASH:
311                 xs << XHTMLStream::NextRaw() << "&frasl;";
312                 break;
313         case NOBREAKDASH:
314                 xs << '-';
315                 break;
316         }
317         return docstring();
318 }
319
320
321 void InsetSpecialChar::tocString(odocstream & os) const
322 {
323         plaintext(os, OutputParams(0));
324 }
325
326
327 void InsetSpecialChar::validate(LaTeXFeatures & features) const
328 {
329         if (kind_ == MENU_SEPARATOR)
330                 features.require("lyxarrow");
331         if (kind_ == NOBREAKDASH)
332                 features.require("amsmath");
333 }
334
335
336 bool InsetSpecialChar::isChar() const
337 {
338         return true;
339 }
340
341
342 bool InsetSpecialChar::isLetter() const
343 {
344         return kind_ == HYPHENATION || kind_ == LIGATURE_BREAK;
345 }
346
347
348 bool InsetSpecialChar::isLineSeparator() const
349 {
350 #if 0
351         // this would be nice, but it does not work, since
352         // Paragraph::stripLeadingSpaces nukes the characters which
353         // have this property. I leave the code here, since it should
354         // eventually be made to work. (JMarc 20020327)
355         return kind_ == HYPHENATION || kind_ == MENU_SEPARATOR;
356 #else
357         return false;
358 #endif
359 }
360
361
362 } // namespace lyx