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