]> git.lyx.org Git - lyx.git/blob - src/insets/insetcommand.C
9c7c8b1bda3dbf215a5e0b492ce437be7ff5f685
[lyx.git] / src / insets / insetcommand.C
1 /* This file is part of
2  * ======================================================
3  * 
4  *           LyX, The Document Processor
5  *       
6  *          Copyright 1995 Matthias Ettrich
7  *          Copyright 1995-1999 The LyX Team.
8  *
9  * ====================================================== */
10
11 #include <config.h>
12
13 #ifdef __GNUG__
14 #pragma implementation
15 #endif
16
17 #include "insetcommand.h"
18 #include "debug.h"
19 #include "Painter.h"
20
21 InsetCommand::InsetCommand()
22 {
23 }
24
25
26 InsetCommand::InsetCommand(string const & cmd, string const & arg, 
27                            string const & opt)
28         : command(cmd), options(opt), contents(arg)
29 {
30 }
31
32
33 int InsetCommand::ascent(Painter & pain, LyXFont const &) const
34 {
35 #if 1
36         LyXFont font(LyXFont::ALL_SANE);
37         font.decSize();
38         
39         int width, ascent, descent;
40         string s = getScreenLabel();
41         
42         if (Editable()) {
43                 pain.buttonText(0, 0, s, font,
44                                 false, width, ascent, descent);
45         } else {
46                 pain.rectText(0, 0, s, font,
47                               LColor::commandbg, LColor::commandframe,
48                               false, width, ascent, descent);
49         }
50         return ascent;
51 #else
52         LyXFont f = font;
53         f.decSize();
54         return f.maxAscent() + 3;
55 #endif
56 }
57
58
59 int InsetCommand::descent(Painter & pain, LyXFont const &) const
60 {
61 #if 1
62         LyXFont font(LyXFont::ALL_SANE);
63         font.decSize();
64         
65         int width, ascent, descent;
66         string s = getScreenLabel();
67         
68         if (Editable()) {
69                 pain.buttonText(0, 0, s, font,
70                                 false, width, ascent, descent);
71         } else {
72                 pain.rectText(0, 0, s, font,
73                               LColor::commandbg, LColor::commandframe,
74                               false, width, ascent, descent);
75         }
76         return descent;
77 #else
78         LyXFont f = font;
79         f.decSize();
80         return f.maxDescent() + 3;
81 #endif
82 }
83
84
85 int InsetCommand::width(Painter & pain, LyXFont const &) const
86 {
87 #if 1
88         LyXFont font(LyXFont::ALL_SANE);
89         font.decSize();
90         
91         int width, ascent, descent;
92         string s = getScreenLabel();
93         
94         if (Editable()) {
95                 pain.buttonText(0, 0, s, font,
96                                 false, width, ascent, descent);
97         } else {
98                 pain.rectText(0, 0, s, font,
99                               LColor::commandbg, LColor::commandframe,
100                               false, width, ascent, descent);
101         }
102         return width;
103 #else
104         LyXFont f = font;
105         f.decSize();
106         string s = getScreenLabel();
107         return 10 + f.stringWidth(s);
108 #endif
109 }
110
111
112 void InsetCommand::draw(Painter & pain, LyXFont const &,
113                         int baseline, float & x) const
114 {
115         // Draw it as a box with the LaTeX text
116 #if 1
117         LyXFont font(LyXFont::ALL_SANE);
118         font.setColor(LColor::command).decSize();
119
120         int width;
121         string s = getScreenLabel();
122
123         if (Editable()) {
124                 pain.buttonText(int(x), baseline, s, font, true, width);
125         } else {
126                 pain.rectText(int(x), baseline, s, font,
127                               LColor::commandbg, LColor::commandframe,
128                               true, width);
129         }
130
131         x += width;
132 #else
133                 
134         x += 3;
135
136         pain.fillRectangle(int(x), baseline - ascent(pain, font) + 1,
137                            width(pain, font) - 6,
138                            ascent(pain, font) + descent(pain, font) - 2,
139                            LColor::insetbg);
140         // Tell whether this slows down the drawing  (ale)
141         // lets draw editable and non-editable insets differently
142         if (Editable()) {
143                 int y = baseline - ascent(pain, font) + 1;
144                 int w = width(pain, font) - 6;
145                 int h = ascent(pain, font) + descent(pain, font) - 2;
146                 pain.rectangle(int(x), y, w, h, LColor::insetframe);
147         } else {
148                 
149                 pain.rectangle(int(x), baseline - ascent(pain, font) + 1,
150                                width(pain, font) - 6,
151                                ascent(pain, font) + descent(pain, font) - 2,
152                                LColor::insetframe); 
153         }
154         string s = getScreenLabel();
155         LyXFont f(font);
156         f.decSize();
157         f.setColor(LColor::none);
158         f.setLatex(LyXFont::OFF);
159         pain.text(int(x + 2), baseline, s, f);
160         
161         x +=  width(pain, font) - 3;
162 #endif
163 }
164
165
166 // In lyxf3 this will be just LaTeX
167 void InsetCommand::Write(ostream & os) const
168 {
169         os << "LatexCommand " << getCommand() << "\n";
170 }
171
172
173 void InsetCommand::scanCommand(string const & cmd)
174 {
175         string tcommand, toptions, tcontents;
176
177         if (cmd.empty()) return;
178
179         enum { WS, Command, Option, Content } state = WS;
180         
181         // Used to handle things like \command[foo[bar]]{foo{bar}}
182         int nestdepth = 0;
183
184         for (string::size_type i = 0; i < cmd.length(); ++i) {
185                 char c = cmd[i];
186                 if ((state == Command && c == ' ') ||
187                     (state == Command && c == '[') ||
188                     (state == Command && c == '{')) {
189                         state = WS;
190                 }
191                 if ((state == Option  && c == ']') ||
192                     (state == Content && c == '}')) {
193                         if (nestdepth == 0) {
194                                 state = WS;
195                         } else {
196                                 --nestdepth;
197                         }
198                 }
199                 if ((state == Option  && c == '[') ||
200                     (state == Content && c == '{')) {
201                         ++nestdepth;
202                 }
203                 switch (state) {
204                 case Command:   tcommand += c; break;
205                 case Option:    toptions += c; break;
206                 case Content:   tcontents += c; break;
207                 case WS:
208                         if (c == '\\') {
209                                 state = Command;
210                         } else if (c == '[') {
211                                 state = Option;
212                                 nestdepth = 0; // Just to be sure
213                         } else if (c == '{') {
214                                 state = Content;
215                                 nestdepth = 0; // Just to be sure
216                         }
217                         break;
218                 }
219         }
220
221         // Don't mess with this.
222         if (!tcommand.empty()) command = tcommand;
223         if (!toptions.empty()) options = toptions;
224         if (!tcontents.empty()) setContents(tcontents); 
225                         // setContents is overloaded in InsetInclude
226
227         if (lyxerr.debugging(Debug::PARSER))
228                 lyxerr << "Command <" <<  cmd
229                        << "> == <" << getCommand()
230                        << "> == <" << getCmdName()
231                        << '|' << getContents()
232                        << '|' << getOptions() << '>' << endl;
233 }
234
235
236 // This function will not be necessary when lyx3
237 void InsetCommand::Read(LyXLex & lex)
238 {    
239         if (lex.EatLine()) {
240                 string t = lex.GetString();
241                 scanCommand(t);
242         } else
243                 lex.printError("InsetCommand: Parse error: `$$Token'");
244 }
245
246
247 int InsetCommand::Latex(ostream & os, signed char /*fragile*/) const
248 {
249         os << getCommand();
250         return 0;
251 }
252
253
254 #ifndef USE_OSTREAM_ONLY
255 int InsetCommand::Latex(string & file, signed char /*fragile*/) const
256 {
257         file += getCommand();
258         return 0;
259 }
260 #endif
261
262
263 int InsetCommand::Linuxdoc(string &/*file*/) const
264 {
265         return 0;
266 }
267
268
269 int InsetCommand::DocBook(string &/*file*/) const
270 {
271         return 0;
272 }
273
274
275 Inset * InsetCommand::Clone() const
276 {
277         return new InsetCommand(command, contents, options);
278 }
279
280
281 string InsetCommand::getCommand() const
282 {       
283         string s;
284         if (!command.empty()) s += "\\"+command;
285         if (!options.empty()) s += "["+options+']';
286         s += "{"+contents+'}';
287         return s;
288 }