]> git.lyx.org Git - lyx.git/blob - src/insets/InsetCommand.cpp
9d8d10d935921a2d03d0943eced8bc3064c84d1e
[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(InsetCommandParams const & p,
55                            string const & mailer_name)
56         : 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 &) const
110 {
111         os << getCommand();
112         return 0;
113 }
114
115
116 int InsetCommand::plaintext(odocstream & os, OutputParams const &) const
117 {
118         docstring const str = "[" + buffer().B_("LaTeX Command: ")
119                 + from_utf8(getCmdName()) + "]";
120         os << str;
121         return str.size();
122 }
123
124
125 int InsetCommand::docbook(odocstream &, OutputParams const &) const
126 {
127         return 0;
128 }
129
130
131 void InsetCommand::doDispatch(Cursor & cur, FuncRequest & cmd)
132 {
133         switch (cmd.action) {
134         case LFUN_INSET_MODIFY: {
135                 if (cmd.getArg(0) == "changetype") {
136                         p_.setCmdName(cmd.getArg(1));
137                         initView();
138                         break;
139                 }
140                 InsetCommandParams p(p_.code());
141                 InsetCommand::string2params(mailer_name_, to_utf8(cmd.argument()), p);
142                 if (p.getCmdName().empty())
143                         cur.noUpdate();
144                 else
145                         setParams(p);
146                 break;
147         }
148
149         case LFUN_INSET_DIALOG_UPDATE: {
150                 string const name = to_utf8(cmd.argument());
151                 cur.bv().updateDialog(name, params2string(name, params()));
152                 break;
153         }
154
155         default:
156                 Inset::doDispatch(cur, cmd);
157                 break;
158         }
159
160 }
161
162
163 bool InsetCommand::getStatus(Cursor & cur, FuncRequest const & cmd,
164         FuncStatus & status) const
165 {
166         switch (cmd.action) {
167         // suppress these
168         case LFUN_ERT_INSERT:
169                 status.setEnabled(false);
170                 return true;
171         
172         // we handle these
173         case LFUN_INSET_MODIFY:
174                 if (cmd.getArg(0) == "changetype") {
175                         string const newtype = cmd.getArg(1);
176                         status.setEnabled(p_.isCompatibleCommand(p_.code(), newtype));
177                         status.setOnOff(newtype == p_.getCmdName());
178                 } 
179                 status.setEnabled(true);
180                 return true;
181         
182         case LFUN_INSET_DIALOG_UPDATE:
183                 status.setEnabled(true);
184                 return true;
185         
186         default:
187                 return Inset::getStatus(cur, cmd, status);
188         }
189 }
190
191
192 docstring InsetCommand::contextMenu(BufferView const &, int, int) const
193 {
194         return from_ascii("context-") + from_ascii(mailer_name_);
195 }
196
197
198 bool InsetCommand::showInsetDialog(BufferView * bv) const
199 {
200         if (!mailer_name_.empty())
201                 bv->showDialog(mailer_name_, params2string(mailer_name_, p_),
202                         const_cast<InsetCommand *>(this));
203         return true;
204 }
205
206
207 // FIXME This could take an InsetCode instead of a string
208 bool InsetCommand::string2params(string const & name, string const & in,
209         InsetCommandParams & params)
210 {
211         params.clear();
212         if (in.empty())
213                 return false;
214         istringstream data(in);
215         Lexer lex;
216         lex.setStream(data);
217         lex.setContext("InsetCommand::string2params");
218         lex >> name.c_str(); // check for name
219         lex >> "CommandInset";
220         params.read(lex);
221         return true;
222 }
223
224
225 // FIXME This could take an InsetCode instead of a string
226 string InsetCommand::params2string(string const & name,
227                                   InsetCommandParams const & params)
228 {
229         ostringstream data;
230         data << name << ' ';
231         params.write(data);
232         data << "\\end_inset\n";
233         return data.str();
234 }
235
236
237 bool decodeInsetParam(string const & name, string & data,
238         Buffer const & buffer)
239 {
240         InsetCode const code = insetCode(name);
241         switch (code) {
242         case BIBITEM_CODE:
243         case BIBTEX_CODE:
244         case INDEX_CODE:
245         case LABEL_CODE:
246         case NOMENCL_CODE:
247         case NOMENCL_PRINT_CODE:
248         case REF_CODE:
249         case TOC_CODE:
250         case HYPERLINK_CODE: {
251                 InsetCommandParams p(code);
252                 data = InsetCommand::params2string(name, p);
253                 break;
254         }
255         case INCLUDE_CODE: {
256                 // data is the include type: one of "include",
257                 // "input", "verbatiminput" or "verbatiminput*"
258                 if (data.empty())
259                         // default type is requested
260                         data = "include";
261                 InsetCommandParams p(INCLUDE_CODE, data);
262                 data = InsetCommand::params2string("include", p);
263                 break;
264         }
265         case BOX_CODE: {
266                 // \c data == "Boxed" || "Frameless" etc
267                 InsetBoxParams p(data);
268                 data = InsetBox::params2string(p);
269                 break;
270         }
271         case BRANCH_CODE: {
272                 InsetBranchParams p;
273                 data = InsetBranch::params2string(p);
274                 break;
275         }
276         case CITE_CODE: {
277                 InsetCommandParams p(CITE_CODE);
278                 data = InsetCommand::params2string(name, p);
279                 break;
280         }
281         case ERT_CODE: {
282                 data = InsetERT::params2string(InsetCollapsable::Open);
283                 break;
284         }
285         case EXTERNAL_CODE: {
286                 InsetExternalParams p;
287                 data = InsetExternal::params2string(p, buffer);
288                 break;
289         }
290         case FLOAT_CODE:  {
291                 InsetFloatParams p;
292                 data = InsetFloat::params2string(p);
293                 break;
294         }
295         case LISTINGS_CODE: {
296                 InsetListingsParams p;
297                 data = InsetListings::params2string(p);
298                 break;
299         }
300         case GRAPHICS_CODE: {
301                 InsetGraphicsParams p;
302                 data = InsetGraphics::params2string(p, buffer);
303                 break;
304         }
305         case NOTE_CODE: {
306                 InsetNoteParams p;
307                 data = InsetNote::params2string(p);
308                 break;
309         }
310         case PHANTOM_CODE: {
311                 InsetPhantomParams p;
312                 data = InsetPhantom::params2string(p);
313                 break;
314         }
315         case SPACE_CODE: {
316                 InsetSpaceParams p;
317                 data = InsetSpace::params2string(p);
318                 break;
319         }
320         case VSPACE_CODE: {
321                 VSpace space;
322                 data = InsetVSpace::params2string(space);
323                 break;
324         }
325         case WRAP_CODE: {
326                 InsetWrapParams p;
327                 data = InsetWrap::params2string(p);
328                 break;
329         }
330         default:
331                 return false;
332         } // end switch(code)
333         return true;
334 }
335
336 } // namespace lyx