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