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