]> git.lyx.org Git - lyx.git/blob - src/insets/InsetCommand.cpp
e68df838a52de70bdcc4321d1340f7b1569b6b06
[lyx.git] / src / insets / InsetCommand.cpp
1 /**
2  * \file InsetCommand.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Angus Leeming
7  * \author Lars Gullik Bjønnes
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "InsetCommand.h"
15
16 #include "Buffer.h"
17 #include "BufferView.h"
18 #include "DispatchResult.h"
19 #include "FuncRequest.h"
20 #include "FuncStatus.h"
21 #include "Lexer.h"
22 #include "MetricsInfo.h"
23
24 #include "insets/InsetBox.h"
25 #include "insets/InsetBranch.h"
26 #include "insets/InsetCommand.h"
27 #include "insets/InsetERT.h"
28 #include "insets/InsetExternal.h"
29 #include "insets/InsetFloat.h"
30 #include "insets/InsetGraphics.h"
31 #include "insets/InsetInclude.h"
32 #include "insets/InsetListings.h"
33 #include "insets/InsetNote.h"
34 #include "insets/InsetPhantom.h"
35 #include "insets/InsetSpace.h"
36 #include "insets/InsetTabular.h"
37 #include "insets/InsetVSpace.h"
38 #include "insets/InsetWrap.h"
39
40 #include "support/debug.h"
41 #include "support/gettext.h"
42
43 #include "frontends/Application.h"
44
45 #include <sstream>
46
47 using namespace std;
48
49
50 namespace lyx {
51
52 // FIXME Would it now be possible to use the InsetCode in 
53 // place of the mailer name and recover that information?
54 InsetCommand::InsetCommand(Buffer * buf, InsetCommandParams const & p,
55                            string const & mailer_name)
56         : Inset(buf), p_(p),
57           mailer_name_(mailer_name),
58           mouse_hover_(false)
59 {}
60
61
62 InsetCommand::~InsetCommand()
63 {
64         if (!mailer_name_.empty())
65                 hideDialogs(mailer_name_, this);
66 }
67
68
69 void InsetCommand::metrics(MetricsInfo & mi, Dimension & dim) const
70 {
71         button_.update(screenLabel(), editable() || hasSettings());
72         button_.metrics(mi, dim);
73 }
74
75
76 bool InsetCommand::setMouseHover(bool mouse_hover)
77 {
78         mouse_hover_ = mouse_hover;
79         return true;
80 }
81
82
83 void InsetCommand::draw(PainterInfo & pi, int x, int y) const
84 {
85         button_.setRenderState(mouse_hover_);
86         button_.draw(pi, x, y);
87 }
88
89
90 void InsetCommand::setParam(std::string const & name, docstring const & value)
91 {
92         p_[name] = value;
93 }
94
95
96 docstring const & InsetCommand::getParam(std::string const & name) const
97 {
98         return p_[name];
99 }
100
101
102 void InsetCommand::setParams(InsetCommandParams const & p)
103 {
104         p_ = p;
105         initView();
106 }
107
108
109 int InsetCommand::latex(odocstream & os, OutputParams const & runparams_in) const
110 {
111         OutputParams runparams = runparams_in;
112         os << getCommand(runparams);
113         return 0;
114 }
115
116
117 int InsetCommand::plaintext(odocstream & os, OutputParams const &) const
118 {
119         docstring const str = "[" + buffer().B_("LaTeX Command: ")
120                 + from_utf8(getCmdName()) + "]";
121         os << str;
122         return str.size();
123 }
124
125
126 int InsetCommand::docbook(odocstream &, OutputParams const &) const
127 {
128         return 0;
129 }
130
131
132 void InsetCommand::doDispatch(Cursor & cur, FuncRequest & cmd)
133 {
134         switch (cmd.action) {
135         case LFUN_INSET_MODIFY: {
136                 if (cmd.getArg(0) == "changetype") {
137                         p_.setCmdName(cmd.getArg(1));
138                         initView();
139                         break;
140                 }
141                 InsetCommandParams p(p_.code());
142                 InsetCommand::string2params(mailer_name_, to_utf8(cmd.argument()), p);
143                 if (p.getCmdName().empty())
144                         cur.noUpdate();
145                 else
146                         setParams(p);
147                 break;
148         }
149
150         case LFUN_INSET_DIALOG_UPDATE: {
151                 string const name = to_utf8(cmd.argument());
152                 cur.bv().updateDialog(name, params2string(name, params()));
153                 break;
154         }
155
156         default:
157                 Inset::doDispatch(cur, cmd);
158                 break;
159         }
160
161 }
162
163
164 bool InsetCommand::getStatus(Cursor & cur, FuncRequest const & cmd,
165         FuncStatus & status) const
166 {
167         switch (cmd.action) {
168         // suppress these
169         case LFUN_ERT_INSERT:
170                 status.setEnabled(false);
171                 return true;
172         
173         // we handle these
174         case LFUN_INSET_MODIFY:
175                 if (cmd.getArg(0) == "changetype") {
176                         string const newtype = cmd.getArg(1);
177                         status.setEnabled(p_.isCompatibleCommand(p_.code(), newtype));
178                         status.setOnOff(newtype == p_.getCmdName());
179                 } 
180                 status.setEnabled(true);
181                 return true;
182         
183         case LFUN_INSET_DIALOG_UPDATE:
184                 status.setEnabled(true);
185                 return true;
186         
187         default:
188                 return Inset::getStatus(cur, cmd, status);
189         }
190 }
191
192
193 docstring InsetCommand::contextMenu(BufferView const &, int, int) const
194 {
195         return from_ascii("context-") + from_ascii(mailer_name_);
196 }
197
198
199 bool InsetCommand::showInsetDialog(BufferView * bv) const
200 {
201         if (!mailer_name_.empty())
202                 bv->showDialog(mailer_name_, params2string(mailer_name_, p_),
203                         const_cast<InsetCommand *>(this));
204         return true;
205 }
206
207
208 // FIXME This could take an InsetCode instead of a string
209 bool InsetCommand::string2params(string const & name, string const & in,
210         InsetCommandParams & params)
211 {
212         params.clear();
213         if (in.empty())
214                 return false;
215         istringstream data(in);
216         Lexer lex;
217         lex.setStream(data);
218         lex.setContext("InsetCommand::string2params");
219         lex >> name.c_str(); // check for name
220         lex >> "CommandInset";
221         params.read(lex);
222         return true;
223 }
224
225
226 // FIXME This could take an InsetCode instead of a string
227 string InsetCommand::params2string(string const & name,
228                                   InsetCommandParams const & params)
229 {
230         ostringstream data;
231         data << name << ' ';
232         params.write(data);
233         data << "\\end_inset\n";
234         return data.str();
235 }
236
237
238 bool decodeInsetParam(string const & name, string & data,
239         Buffer const & buffer)
240 {
241         InsetCode const code = insetCode(name);
242         switch (code) {
243         case BIBITEM_CODE:
244         case BIBTEX_CODE:
245         case INDEX_CODE:
246         case LABEL_CODE:
247         case NOMENCL_CODE:
248         case NOMENCL_PRINT_CODE:
249         case REF_CODE:
250         case TOC_CODE:
251         case HYPERLINK_CODE: {
252                 InsetCommandParams p(code);
253                 data = InsetCommand::params2string(name, p);
254                 break;
255         }
256         case INCLUDE_CODE: {
257                 // data is the include type: one of "include",
258                 // "input", "verbatiminput" or "verbatiminput*"
259                 if (data.empty())
260                         // default type is requested
261                         data = "include";
262                 InsetCommandParams p(INCLUDE_CODE, data);
263                 data = InsetCommand::params2string("include", p);
264                 break;
265         }
266         case BOX_CODE: {
267                 // \c data == "Boxed" || "Frameless" etc
268                 InsetBoxParams p(data);
269                 data = InsetBox::params2string(p);
270                 break;
271         }
272         case BRANCH_CODE: {
273                 InsetBranchParams p;
274                 data = InsetBranch::params2string(p);
275                 break;
276         }
277         case CITE_CODE: {
278                 InsetCommandParams p(CITE_CODE);
279                 data = InsetCommand::params2string(name, p);
280                 break;
281         }
282         case ERT_CODE: {
283                 data = InsetERT::params2string(InsetCollapsable::Open);
284                 break;
285         }
286         case EXTERNAL_CODE: {
287                 InsetExternalParams p;
288                 data = InsetExternal::params2string(p, buffer);
289                 break;
290         }
291         case FLOAT_CODE:  {
292                 InsetFloatParams p;
293                 data = InsetFloat::params2string(p);
294                 break;
295         }
296         case LISTINGS_CODE: {
297                 InsetListingsParams p;
298                 data = InsetListings::params2string(p);
299                 break;
300         }
301         case GRAPHICS_CODE: {
302                 InsetGraphicsParams p;
303                 data = InsetGraphics::params2string(p, buffer);
304                 break;
305         }
306         case NOTE_CODE: {
307                 InsetNoteParams p;
308                 data = InsetNote::params2string(p);
309                 break;
310         }
311         case PHANTOM_CODE: {
312                 InsetPhantomParams p;
313                 data = InsetPhantom::params2string(p);
314                 break;
315         }
316         case SPACE_CODE: {
317                 InsetSpaceParams p;
318                 data = InsetSpace::params2string(p);
319                 break;
320         }
321         case VSPACE_CODE: {
322                 VSpace space;
323                 data = InsetVSpace::params2string(space);
324                 break;
325         }
326         case WRAP_CODE: {
327                 InsetWrapParams p;
328                 data = InsetWrap::params2string(p);
329                 break;
330         }
331         default:
332                 return false;
333         } // end switch(code)
334         return true;
335 }
336
337 } // namespace lyx