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