]> git.lyx.org Git - features.git/blob - src/insets/InsetERT.cpp
Move Color::color enum to ColorCode.h
[features.git] / src / insets / InsetERT.cpp
1 /**
2  * \file InsetERT.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Jürgen Vigna
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 "InsetERT.h"
15
16 #include "Buffer.h"
17 #include "BufferParams.h"
18 #include "BufferView.h"
19 #include "Cursor.h"
20 #include "debug.h"
21 #include "DispatchResult.h"
22 #include "FuncRequest.h"
23 #include "FuncStatus.h"
24 #include "gettext.h"
25 #include "Language.h"
26 #include "Layout.h"
27 #include "LyXAction.h"
28 #include "Lexer.h"
29 #include "TextClass.h"
30 #include "MetricsInfo.h"
31 #include "ParagraphParameters.h"
32 #include "Paragraph.h"
33
34 #include "frontends/alert.h"
35
36 #include <sstream>
37
38
39 namespace lyx {
40
41 using support::token;
42
43 using std::endl;
44 using std::min;
45
46 using std::istringstream;
47 using std::ostream;
48 using std::ostringstream;
49 using std::string;
50
51
52 void InsetERT::init()
53 {
54         setButtonLabel();
55         setLabelFont(layout_.labelfont);
56         // FIXME: what to do with those?
57         //text_.current_font.setLanguage(latex_language);
58         //text_.real_current_font.setLanguage(latex_language);
59 }
60
61
62 InsetERT::InsetERT(BufferParams const & bp, CollapseStatus status)
63         : InsetCollapsable(bp, status)
64 {
65         setLayout(bp);
66         init();
67 }
68
69
70 InsetERT::InsetERT(InsetERT const & in)
71         : InsetCollapsable(in)
72 {
73         init();
74 }
75
76
77 Inset * InsetERT::clone() const
78 {
79         return new InsetERT(*this);
80 }
81
82
83 #if 0
84 InsetERT::InsetERT(BufferParams const & bp,
85                    Language const *, string const & contents, CollapseStatus status)
86         : InsetCollapsable(bp, status)
87 {
88         Font font(Font::ALL_INHERIT, latex_language);
89         paragraphs().begin()->insert(0, contents, font);
90
91         // the init has to be after the initialization of the paragraph
92         // because of the label settings (draw_label for ert insets).
93         init();
94 }
95 #endif
96
97
98 InsetERT::~InsetERT()
99 {
100         InsetERTMailer(*this).hideDialog();
101 }
102
103
104 void InsetERT::write(Buffer const & buf, ostream & os) const
105 {
106         os << "ERT" << "\n";
107         InsetCollapsable::write(buf, os);
108 }
109
110
111 void InsetERT::read(Buffer const & buf, Lexer & lex)
112 {
113         InsetCollapsable::read(buf, lex);
114
115         // Force default font
116         // This avoids paragraphs in buffer language that would have a
117         // foreign language after a document langauge change, and it ensures
118         // that all new text in ERT gets the "latex" language, since new text
119         // inherits the language from the last position of the existing text.
120         // As a side effect this makes us also robust against bugs in LyX
121         // that might lead to font changes in ERT in .lyx files.
122         Font font(Font::ALL_INHERIT, latex_language);
123         ParagraphList::iterator par = paragraphs().begin();
124         ParagraphList::iterator const end = paragraphs().end();
125         while (par != end) {
126                 pos_type siz = par->size();
127                 for (pos_type i = 0; i <= siz; ++i) {
128                         par->setFont(i, font);
129                 }
130                 ++par;
131         }
132 }
133
134
135 docstring const InsetERT::editMessage() const
136 {
137         return _("Opened ERT Inset");
138 }
139
140
141 int InsetERT::latex(Buffer const & buf, odocstream & os,
142                     OutputParams const & op) const
143 {
144         return InsetCollapsable::latex(buf, os, op);
145 }
146
147
148 int InsetERT::plaintext(Buffer const &, odocstream &,
149                         OutputParams const &) const
150 {
151         return 0; // do not output TeX code
152 }
153
154
155 int InsetERT::docbook(Buffer const &, odocstream & os,
156                       OutputParams const &) const
157 {
158         // FIXME can we do the same thing here as for LaTeX?
159         ParagraphList::const_iterator par = paragraphs().begin();
160         ParagraphList::const_iterator end = paragraphs().end();
161
162         int lines = 0;
163         while (par != end) {
164                 pos_type siz = par->size();
165                 for (pos_type i = 0; i < siz; ++i)
166                         os.put(par->getChar(i));
167                 ++par;
168                 if (par != end) {
169                         os << "\n";
170                         ++lines;
171                 }
172         }
173
174         return lines;
175 }
176
177
178 void InsetERT::doDispatch(Cursor & cur, FuncRequest & cmd)
179 {
180         BufferParams const & bp = cur.buffer().params();
181         LayoutPtr const layout =
182                         bp.getTextClass().defaultLayout();
183         //lyxerr << "\nInsetERT::doDispatch (begin): cmd: " << cmd << endl;
184         switch (cmd.action) {
185
186         case LFUN_MOUSE_PRESS:
187                 if (cmd.button() != mouse_button::button3)
188                         InsetCollapsable::doDispatch(cur, cmd);
189                 else
190                         // This makes the cursor leave the
191                         // inset when it collapses on mouse-3
192                         cur.undispatched();
193                 break;
194
195         case LFUN_QUOTE_INSERT: {
196                 // We need to bypass the fancy quotes in Text
197                 FuncRequest f(LFUN_SELF_INSERT, "\"");
198                 dispatch(cur, f);
199                 break;
200         }
201         case LFUN_INSET_MODIFY: {
202                 InsetCollapsable::CollapseStatus st;
203                 InsetERTMailer::string2params(to_utf8(cmd.argument()), st);
204                 setStatus(cur, st);
205                 break;
206         }
207         case LFUN_PASTE:
208         case LFUN_CLIPBOARD_PASTE:
209         case LFUN_PRIMARY_SELECTION_PASTE: {
210                 InsetCollapsable::doDispatch(cur, cmd);
211
212                 // Since we can only store plain text, we must reset all
213                 // attributes.
214                 // FIXME: Change only the pasted paragraphs
215
216                 Font font = layout->font;
217                 // ERT contents has always latex_language
218                 font.setLanguage(latex_language);
219                 ParagraphList::iterator const end = paragraphs().end();
220                 for (ParagraphList::iterator par = paragraphs().begin();
221                      par != end; ++par) {
222                         // in case par had a manual label
223                         par->setBeginOfBody();
224                         pos_type const siz = par->size();
225                         for (pos_type i = 0; i < siz; ++i) {
226                                 par->setFont(i, font);
227                         }
228                         par->params().clear();
229                 }
230                 break;
231         }
232         default:
233                 // Force any new text to latex_language
234                 // FIXME: This should only be necessary in init(), but
235                 // new paragraphs that are created by pressing enter at the
236                 // start of an existing paragraph get the buffer language
237                 // and not latex_language, so we take this brute force
238                 // approach.
239                 cur.current_font = layout->font;
240                 cur.real_current_font = layout->font;
241                 cur.current_font.setLanguage(latex_language);
242                 cur.real_current_font.setLanguage(latex_language);
243                 InsetCollapsable::doDispatch(cur, cmd);
244                 break;
245         }
246 }
247
248
249 bool InsetERT::getStatus(Cursor & cur, FuncRequest const & cmd,
250         FuncStatus & status) const
251 {
252         switch (cmd.action) {
253                 case LFUN_CLIPBOARD_PASTE:
254                 case LFUN_INSET_MODIFY:
255                 case LFUN_PASTE:
256                 case LFUN_PRIMARY_SELECTION_PASTE:
257                 case LFUN_QUOTE_INSERT:
258                         status.enabled(true);
259                         return true;
260
261                 // this one is difficult to get right. As a half-baked
262                 // solution, we consider only the first action of the sequence
263                 case LFUN_COMMAND_SEQUENCE: {
264                         // argument contains ';'-terminated commands
265                         string const firstcmd = token(to_utf8(cmd.argument()), ';', 0);
266                         FuncRequest func(lyxaction.lookupFunc(firstcmd));
267                         func.origin = cmd.origin;
268                         return getStatus(cur, func, status);
269                 }
270
271                 default:
272                         return InsetCollapsable::getStatus(cur, cmd, status);
273         }
274 }
275
276
277 void InsetERT::setButtonLabel()
278 {
279         // FIXME UNICODE
280         if (decoration() == Classic)
281                 setLabel(isOpen() ? _("ERT") : getNewLabel(_("ERT")));
282         else
283                 setLabel(getNewLabel(_("ERT")));
284 }
285
286
287 bool InsetERT::insetAllowed(InsetCode /* code */) const
288 {
289         return false;
290 }
291
292
293 void InsetERT::metrics(MetricsInfo & mi, Dimension & dim) const
294 {
295         Font tmpfont = mi.base.font;
296         getDrawFont(mi.base.font);
297         mi.base.font.realize(tmpfont);
298         InsetCollapsable::metrics(mi, dim);
299         mi.base.font = tmpfont;
300 }
301
302
303 void InsetERT::draw(PainterInfo & pi, int x, int y) const
304 {
305         Font tmpfont = pi.base.font;
306         getDrawFont(pi.base.font);
307         pi.base.font.realize(tmpfont);
308         const_cast<InsetERT &>(*this).setButtonLabel();
309         InsetCollapsable::draw(pi, x, y);
310         pi.base.font = tmpfont;
311 }
312
313
314 bool InsetERT::showInsetDialog(BufferView * bv) const
315 {
316         InsetERTMailer(const_cast<InsetERT &>(*this)).showDialog(bv);
317         return true;
318 }
319
320
321 void InsetERT::getDrawFont(Font & font) const
322 {
323         font = Font(Font::ALL_INHERIT, latex_language);
324         font.realize(layout_.font);
325 }
326
327
328 string const InsetERTMailer::name_("ert");
329
330 InsetERTMailer::InsetERTMailer(InsetERT & inset)
331         : inset_(inset)
332 {}
333
334
335 string const InsetERTMailer::inset2string(Buffer const &) const
336 {
337         return params2string(inset_.status());
338 }
339
340
341 void InsetERTMailer::string2params(string const & in,
342                                    InsetCollapsable::CollapseStatus & status)
343 {
344         status = InsetCollapsable::Collapsed;
345         if (in.empty())
346                 return;
347
348         istringstream data(in);
349         Lexer lex(0,0);
350         lex.setStream(data);
351
352         string name;
353         lex >> name;
354         if (name != name_)
355                 return print_mailer_error("InsetERTMailer", in, 1, name_);
356
357         int s;
358         lex >> s;
359         if (lex)
360                 status = static_cast<InsetCollapsable::CollapseStatus>(s);
361 }
362
363
364 string const
365 InsetERTMailer::params2string(InsetCollapsable::CollapseStatus status)
366 {
367         ostringstream data;
368         data << name_ << ' ' << status;
369         return data.str();
370 }
371
372
373 } // namespace lyx