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