]> git.lyx.org Git - lyx.git/blob - src/insets/insetspecialchar.C
Collapse all those LFUN_XYZ_APPLY to a single LFUN_INSET_APPLY.
[lyx.git] / src / insets / insetspecialchar.C
1 /**
2  * \file insetspecialchar.C
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
16 #include "insetspecialchar.h"
17 #include "debug.h"
18 #include "LaTeXFeatures.h"
19 #include "BufferView.h"
20 #include "frontends/Painter.h"
21 #include "frontends/font_metrics.h"
22 #include "lyxlex.h"
23 #include "lyxfont.h"
24
25 using std::ostream;
26 using std::max;
27
28 InsetSpecialChar::InsetSpecialChar(Kind k)
29         : kind_(k)
30 {}
31
32
33 InsetSpecialChar::Kind InsetSpecialChar::kind() const
34 {
35         return kind_;
36 }
37
38 int InsetSpecialChar::ascent(BufferView *, LyXFont const & font) const
39 {
40         return font_metrics::maxAscent(font);
41 }
42
43
44 int InsetSpecialChar::descent(BufferView *, LyXFont const & font) const
45 {
46         return font_metrics::maxDescent(font);
47 }
48
49
50 int InsetSpecialChar::width(BufferView *, LyXFont const & font) const
51 {
52         switch (kind_) {
53         case HYPHENATION:
54         {
55                 int w = font_metrics::width('-', font);
56                 if (w > 5)
57                         w -= 2; // to make it look shorter
58                 return w;
59         }
60         case LIGATURE_BREAK:
61         {
62                 return font_metrics::width('|', font);
63         }
64         case END_OF_SENTENCE:
65         {
66                 return font_metrics::width('.', font);
67         }
68         case LDOTS:
69         {
70                 return font_metrics::width(". . .", font);
71         }
72         case MENU_SEPARATOR:
73         {
74                 return font_metrics::width(" x ", font);
75         }
76         case PROTECTED_SEPARATOR:
77         {
78                 return font_metrics::width('x', font);
79         }
80
81         }
82         return 1; // To shut up gcc
83 }
84
85
86 void InsetSpecialChar::draw(BufferView * bv, LyXFont const & f,
87                             int baseline, float & x, bool) const
88 {
89         Painter & pain = bv->painter();
90         LyXFont font(f);
91
92         switch (kind_) {
93         case HYPHENATION:
94         {
95                 font.setColor(LColor::special);
96                 pain.text(int(x), baseline, '-', font);
97                 x += width(bv, font);
98                 break;
99         }
100         case LIGATURE_BREAK:
101         {
102                 font.setColor(LColor::special);
103                 pain.text(int(x), baseline, '|', font);
104                 x += width(bv, font);
105                 break;
106         }
107         case END_OF_SENTENCE:
108         {
109                 font.setColor(LColor::special);
110                 pain.text(int(x), baseline, '.', font);
111                 x += width(bv, font);
112                 break;
113         }
114         case LDOTS:
115         {
116                 font.setColor(LColor::special);
117                 pain.text(int(x), baseline, ". . .", font);
118                 x += width(bv, font);
119                 break;
120         }
121         case MENU_SEPARATOR:
122         {
123                 // A triangle the width and height of an 'x'
124                 int w = font_metrics::width('x', font);
125                 int ox = font_metrics::width(' ', font) + int(x);
126                 int h = font_metrics::ascent('x', font);
127                 int xp[4], yp[4];
128
129                 xp[0] = ox;     yp[0] = baseline;
130                 xp[1] = ox;     yp[1] = baseline - h;
131                 xp[2] = ox + w; yp[2] = baseline - h/2;
132                 xp[3] = ox;     yp[3] = baseline;
133
134                 pain.lines(xp, yp, 4, LColor::special);
135                 x += width(bv, font);
136                 break;
137         }
138         case PROTECTED_SEPARATOR:
139         {
140                 float w = width(bv, font);
141                 int h = font_metrics::ascent('x', font);
142                 int xp[4], yp[4];
143
144                 xp[0] = int(x);
145                 yp[0] = baseline - max(h / 4, 1);
146
147                 xp[1] = int(x);
148                 yp[1] = baseline;
149
150                 xp[2] = int(x + w);
151                 yp[2] = baseline;
152
153                 xp[3] = int(x + w);
154                 yp[3] = baseline - max(h / 4, 1);
155
156                 pain.lines(xp, yp, 4, LColor::special);
157                 x += w;
158                 break;
159         }
160         }
161 }
162
163
164 // In lyxf3 this will be just LaTeX
165 void InsetSpecialChar::write(Buffer const *, ostream & os) const
166 {
167         string command;
168         switch (kind_) {
169         case HYPHENATION:
170                 command = "\\-";
171                 break;
172         case LIGATURE_BREAK:
173                 command = "\\textcompwordmark{}";
174                 break;
175         case END_OF_SENTENCE:
176                 command = "\\@.";
177                 break;
178         case LDOTS:
179                 command = "\\ldots{}";
180                 break;
181         case MENU_SEPARATOR:
182                 command = "\\menuseparator";
183                 break;
184         case PROTECTED_SEPARATOR:
185                 command = "~";
186                 break;
187         }
188         os << "\\SpecialChar " << command << "\n";
189 }
190
191
192 // This function will not be necessary when lyx3
193 void InsetSpecialChar::read(Buffer const *, LyXLex & lex)
194 {
195         lex.nextToken();
196         string const command = lex.getString();
197
198         if (command == "\\-")
199                 kind_ = HYPHENATION;
200         else if (command == "\\textcompwordmark{}")
201                 kind_ = LIGATURE_BREAK;
202         else if (command == "\\@.")
203                 kind_ = END_OF_SENTENCE;
204         else if (command == "\\ldots{}")
205                 kind_ = LDOTS;
206         else if (command == "\\menuseparator")
207                 kind_ = MENU_SEPARATOR;
208         else if (command == "~")
209                 kind_ = PROTECTED_SEPARATOR;
210         else
211                 lex.printError("InsetSpecialChar: Unknown kind: `$$Token'");
212 }
213
214
215 int InsetSpecialChar::latex(Buffer const *, ostream & os, bool /*fragile*/,
216                             bool free_space) const
217 {
218         switch (kind_) {
219         case HYPHENATION:
220                 os << "\\-";
221                 break;
222         case LIGATURE_BREAK:
223                 os << "\\textcompwordmark{}";
224                 break;
225         case END_OF_SENTENCE:
226                 os << "\\@.";
227                 break;
228         case LDOTS:
229                 os << "\\ldots{}";
230                 break;
231         case MENU_SEPARATOR:
232                 os << "\\lyxarrow{}";
233                 break;
234         case PROTECTED_SEPARATOR:
235                 os << (free_space ? ' ' : '~');
236                 break;
237         }
238         return 0;
239 }
240
241
242 int InsetSpecialChar::ascii(Buffer const *, ostream & os, int) const
243 {
244         switch (kind_) {
245         case HYPHENATION:
246         case LIGATURE_BREAK:
247                 break;
248         case END_OF_SENTENCE:
249                 os << '.';
250                 break;
251         case LDOTS:
252                 os << "...";
253                 break;
254         case MENU_SEPARATOR:
255                 os << "->";
256                 break;
257         case PROTECTED_SEPARATOR:
258                 os << ' ';
259                 break;
260         }
261         return 0;
262 }
263
264
265 int InsetSpecialChar::linuxdoc(Buffer const *, ostream & os) const
266 {
267         switch (kind_) {
268         case HYPHENATION:
269         case LIGATURE_BREAK:
270                 break;
271         case END_OF_SENTENCE:
272                 os << '.';
273                 break;
274         case LDOTS:
275                 os << "...";
276                 break;
277         case MENU_SEPARATOR:
278                 os << "&lyxarrow;";
279                 break;
280         case PROTECTED_SEPARATOR:
281                 os << "&nbsp;";
282                 break;
283         }
284         return 0;
285 }
286
287
288 int InsetSpecialChar::docbook(Buffer const *, ostream & os, bool) const
289 {
290         switch (kind_) {
291         case HYPHENATION:
292         case LIGATURE_BREAK:
293                 break;
294         case END_OF_SENTENCE:
295                 os << '.';
296                 break;
297         case LDOTS:
298                 os << "...";
299                 break;
300         case MENU_SEPARATOR:
301                 os << "&lyxarrow;";
302                 break;
303         case PROTECTED_SEPARATOR:
304                 os << "&nbsp;";
305                 break;
306         }
307         return 0;
308 }
309
310
311 Inset * InsetSpecialChar::clone(Buffer const &, bool) const
312 {
313         return new InsetSpecialChar(kind_);
314 }
315
316
317 void InsetSpecialChar::validate(LaTeXFeatures & features) const
318 {
319         if (kind_ == MENU_SEPARATOR) {
320                 features.require("lyxarrow");
321         }
322 }
323
324
325 bool InsetSpecialChar::isChar() const
326 {
327         return true;
328 }
329
330
331 bool InsetSpecialChar::isLetter() const
332 {
333         return kind_ == HYPHENATION || kind_ == LIGATURE_BREAK;
334 }
335
336
337 bool InsetSpecialChar::isSpace() const
338 {
339         return kind_ == PROTECTED_SEPARATOR;
340 }
341
342
343 bool InsetSpecialChar::isLineSeparator() const
344 {
345 #if 0
346         // this would be nice, but it does not work, since
347         // Paragraph::stripLeadingSpaces nukes the characters which
348         // have this property. I leave the code here, since it should
349         // eventually be made to work. (JMarc 20020327)
350         return kind_ == HYPHENATION || kind_ == MENU_SEPARATOR;
351 #else
352         return false;
353 #endif
354 }