]> git.lyx.org Git - lyx.git/blob - src/insets/insetert.C
5113d04c6825e69c44a884ed785d71da2d854b39
[lyx.git] / src / insets / insetert.C
1 /**
2  * \file insetert.C
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 "debug.h"
20 #include "dispatchresult.h"
21 #include "funcrequest.h"
22 #include "gettext.h"
23 #include "language.h"
24 #include "LColor.h"
25 #include "lyxlex.h"
26 #include "metricsinfo.h"
27 #include "paragraph.h"
28
29 #include "frontends/Alert.h"
30 #include "frontends/LyXView.h"
31
32 #include "support/tostr.h"
33
34 using lyx::pos_type;
35
36 using lyx::support::split;
37 using lyx::support::strToInt;
38
39 using std::endl;
40 using std::min;
41 using std::string;
42 using std::auto_ptr;
43 using std::ostream;
44
45
46 void InsetERT::init()
47 {
48         setButtonLabel();
49
50         LyXFont font(LyXFont::ALL_SANE);
51         font.decSize();
52         font.decSize();
53         font.setColor(LColor::latex);
54         setLabelFont(font);
55
56         setInsetName("ERT");
57 }
58
59
60 InsetERT::InsetERT(BufferParams const & bp, bool collapsed)
61         : InsetCollapsable(bp, collapsed)
62 {
63         status_ = collapsed ? Collapsed : Open;
64         init();
65 }
66
67
68 InsetERT::InsetERT(InsetERT const & in)
69         : InsetCollapsable(in)
70 {
71         init();
72 }
73
74
75 auto_ptr<InsetBase> InsetERT::clone() const
76 {
77         return auto_ptr<InsetBase>(new InsetERT(*this));
78 }
79
80
81 InsetERT::InsetERT(BufferParams const & bp,
82                    Language const * l, string const & contents, bool collapsed)
83         : InsetCollapsable(bp, collapsed)
84 {
85         status_ = collapsed ? Collapsed : Open;
86
87         LyXFont font(LyXFont::ALL_INHERIT, l);
88 #ifdef SET_HARD_FONT
89         font.setFamily(LyXFont::TYPEWRITER_FAMILY);
90         font.setColor(LColor::latex);
91 #endif
92
93         string::const_iterator cit = contents.begin();
94         string::const_iterator end = contents.end();
95         pos_type pos = 0;
96         for (; cit != end; ++cit) {
97                 inset.paragraphs().begin()->insertChar(pos++, *cit, font);
98         }
99         // the init has to be after the initialization of the paragraph
100         // because of the label settings (draw_label for ert insets).
101         init();
102 }
103
104
105 InsetERT::~InsetERT()
106 {
107         InsetERTMailer(*this).hideDialog();
108 }
109
110
111 void InsetERT::read(Buffer const & buf, LyXLex & lex)
112 {
113         bool token_found = false;
114         if (lex.isOK()) {
115                 lex.next();
116                 string const token = lex.getString();
117                 if (token == "status") {
118                         lex.next();
119                         string const tmp_token = lex.getString();
120
121                         if (tmp_token == "Inlined") {
122                                 status_ = Inlined;
123                         } else if (tmp_token == "Collapsed") {
124                                 status_ = Collapsed;
125                         } else {
126                                 // leave this as default!
127                                 status_ = Open;
128                         }
129
130                         token_found = true;
131                 } else {
132                         lyxerr << "InsetERT::Read: Missing 'status'-tag!"
133                                    << endl;
134                         // take countermeasures
135                         lex.pushToken(token);
136                 }
137         }
138         inset.read(buf, lex);
139
140 #ifdef SET_HARD_FONT
141         LyXFont font(LyXFont::ALL_INHERIT, latex_language);
142         font.setFamily(LyXFont::TYPEWRITER_FAMILY);
143         font.setColor(LColor::latex);
144
145         ParagraphList::iterator pit = inset.paragraphs().begin();
146         ParagraphList::iterator pend = inset.paragraphs().end();
147         for (; pit != pend; ++pit) {
148                 pos_type siz = pit->size();
149                 for (pos_type i = 0; i < siz; ++i) {
150                         pit->setFont(i, font);
151                 }
152         }
153 #endif
154
155         if (!token_found) {
156                 if (isOpen())
157                         status_ = Open;
158                 else
159                         status_ = Collapsed;
160         }
161         setButtonLabel();
162 }
163
164
165 void InsetERT::write(Buffer const & buf, ostream & os) const
166 {
167         string st;
168
169         switch (status_) {
170         case Open:
171                 st = "Open";
172                 break;
173         case Collapsed:
174                 st = "Collapsed";
175                 break;
176         case Inlined:
177                 st = "Inlined";
178                 break;
179         }
180
181         os << getInsetName() << "\n" << "status "<< st << "\n";
182
183         //inset.writeParagraphData(buf, os);
184         string const layout(buf.params().getLyXTextClass().defaultLayoutName());
185         ParagraphList::iterator par = inset.paragraphs().begin();
186         ParagraphList::iterator end = inset.paragraphs().end();
187         for (; par != end; ++par) {
188                 os << "\n\\begin_layout " << layout << "\n";
189                 pos_type siz = par->size();
190                 for (pos_type i = 0; i < siz; ++i) {
191                         Paragraph::value_type c = par->getChar(i);
192                         switch (c) {
193                         case Paragraph::META_INSET:
194                                 if (par->getInset(i)->lyxCode() != InsetOld::NEWLINE_CODE) {
195                                         lyxerr << "Element is not allowed in insertERT"
196                                                << endl;
197                                 } else {
198                                         par->getInset(i)->write(buf, os);
199                                 }
200                                 break;
201
202                         case '\\':
203                                 os << "\n\\backslash \n";
204                                 break;
205                         default:
206                                 os << c;
207                                 break;
208                         }
209                 }
210                 os << "\n\\end_layout\n";
211         }
212 }
213
214
215 string const InsetERT::editMessage() const
216 {
217         return _("Opened ERT Inset");
218 }
219
220
221 bool InsetERT::insertInset(BufferView *, InsetOld *)
222 {
223         return false;
224 }
225
226
227 void InsetERT::updateStatus(bool swap) const
228 {
229         if (status_ != Inlined) {
230                 if (isOpen())
231                         status_ = swap ? Collapsed : Open;
232                 else
233                         status_ = swap ? Open : Collapsed;
234         }
235 }
236
237
238 void InsetERT::lfunMousePress(FuncRequest const & cmd)
239 {
240         if (status_ == Inlined)
241                 inset.dispatch(cmd);
242         else {
243                 idx_type idx = 0;
244                 pos_type pos = 0;
245                 InsetCollapsable::priv_dispatch(cmd, idx, pos);
246         }
247 }
248
249
250 bool InsetERT::lfunMouseRelease(FuncRequest const & cmd)
251 {
252         BufferView * bv = cmd.view();
253
254         if (cmd.button() == mouse_button::button3) {
255                 showInsetDialog(bv);
256                 return true;
257         }
258
259         if (status_ != Inlined && hitButton(cmd)) {
260                 updateStatus(true);
261         } else {
262                 FuncRequest cmd1 = cmd;
263 #warning metrics?
264                 cmd1.y = ascent() + cmd.y - inset.ascent();
265
266                 // inlined is special - the text appears above
267                 if (status_ == Inlined)
268                         inset.dispatch(cmd1);
269                 else if (isOpen() && cmd.y > buttonDim().y2) {
270                         cmd1.y -= height_collapsed();
271                         inset.dispatch(cmd1);
272                 }
273         }
274         return false;
275 }
276
277
278 void InsetERT::lfunMouseMotion(FuncRequest const & cmd)
279 {
280         if (status_ == Inlined)
281                 inset.dispatch(cmd);
282         else {
283                 idx_type idx = 0;
284                 pos_type pos = 0;
285                 InsetCollapsable::priv_dispatch(cmd, idx, pos);
286         }
287 }
288
289
290 int InsetERT::latex(Buffer const &, ostream & os,
291                     OutputParams const &) const
292 {
293         ParagraphList::iterator par = inset.paragraphs().begin();
294         ParagraphList::iterator end = inset.paragraphs().end();
295
296         int lines = 0;
297         while (par != end) {
298                 pos_type siz = par->size();
299                 for (pos_type i = 0; i < siz; ++i) {
300                         // ignore all struck out text
301                         if (isDeletedText(*par, i))
302                                 continue;
303
304                         if (par->isNewline(i)) {
305                                 os << '\n';
306                                 ++lines;
307                         } else {
308                                 os << par->getChar(i);
309                         }
310                 }
311                 ++par;
312                 if (par != end) {
313                         os << "\n";
314                         ++lines;
315                 }
316         }
317
318         return lines;
319 }
320
321
322 int InsetERT::plaintext(Buffer const &, ostream &,
323                     OutputParams const & /*runparams*/) const
324 {
325         return 0;
326 }
327
328
329 int InsetERT::linuxdoc(Buffer const &, ostream & os,
330                        OutputParams const &)const
331 {
332         ParagraphList::iterator par = inset.paragraphs().begin();
333         ParagraphList::iterator end = inset.paragraphs().end();
334
335         int lines = 0;
336         while (par != end) {
337                 pos_type siz = par->size();
338                 for (pos_type i = 0; i < siz; ++i) {
339                         if (par->isNewline(i)) {
340                                 os << '\n';
341                                 ++lines;
342                         } else {
343                                 os << par->getChar(i);
344                         }
345                 }
346                 ++par;
347                 if (par != end) {
348                         os << "\n";
349                         lines ++;
350                 }
351         }
352
353         return lines;
354 }
355
356
357 int InsetERT::docbook(Buffer const &, ostream & os,
358                       OutputParams const &) const
359 {
360         ParagraphList::iterator par = inset.paragraphs().begin();
361         ParagraphList::iterator end = inset.paragraphs().end();
362
363         int lines = 0;
364         while (par != end) {
365                 pos_type siz = par->size();
366                 for (pos_type i = 0; i < siz; ++i) {
367                         if (par->isNewline(i)) {
368                                 os << '\n';
369                                 ++lines;
370                         } else {
371                                 os << par->getChar(i);
372                         }
373                 }
374                 ++par;
375                 if (par != end) {
376                         os << "\n";
377                         lines ++;
378                 }
379         }
380
381         return lines;
382 }
383
384
385 void InsetERT::edit(BufferView * bv, bool left)
386 {
387         if (status_ == Inlined) {
388                 inset.edit(bv, left);
389         } else {
390                 InsetCollapsable::edit(bv, left);
391         }
392         setLatexFont(bv);
393         updateStatus();
394 }
395
396
397 DispatchResult
398 InsetERT::priv_dispatch(FuncRequest const & cmd, idx_type & idx, pos_type & pos)
399 {
400         BufferView * bv = cmd.view();
401
402         if (inset.paragraphs().begin()->empty())
403                 setLatexFont(bv);
404
405         switch (cmd.action) {
406
407         case LFUN_INSET_MODIFY: {
408                 InsetERTMailer::string2params(cmd.argument, status_);
409                 bv->update();
410                 return DispatchResult(true, true);
411         }
412
413         case LFUN_MOUSE_PRESS:
414                 lfunMousePress(cmd);
415                 return DispatchResult(true, true);
416
417         case LFUN_MOUSE_MOTION:
418                 lfunMouseMotion(cmd);
419                 return DispatchResult(true, true);
420
421         case LFUN_MOUSE_RELEASE:
422                 lfunMouseRelease(cmd);
423                 return DispatchResult(true, true);
424
425         case LFUN_LAYOUT:
426                 bv->owner()->setLayout(inset.paragraphs().begin()->layout()->name());
427                 return DispatchResult(true);
428
429         case LFUN_BREAKPARAGRAPH:
430         case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
431         case LFUN_BACKSPACE:
432         case LFUN_BACKSPACE_SKIP:
433         case LFUN_DELETE:
434         case LFUN_DELETE_SKIP:
435         case LFUN_DELETE_LINE_FORWARD:
436         case LFUN_CUT:
437                 setLatexFont(bv);
438                 return InsetCollapsable::priv_dispatch(cmd, idx, pos);
439
440         default:
441                 return InsetCollapsable::priv_dispatch(cmd, idx, pos);
442         }
443 }
444
445
446 void InsetERT::setButtonLabel() const
447 {
448         setLabel(status_ == Collapsed ? getNewLabel(_("ERT")) : _("ERT"));
449 }
450
451
452 bool InsetERT::insetAllowed(InsetOld::Code code) const
453 {
454         return code == InsetOld::NEWLINE_CODE;
455 }
456
457
458 void InsetERT::metrics(MetricsInfo & mi, Dimension & dim) const
459 {
460         InsetCollapsable::metrics(mi, dim);
461         dim_ = dim;
462 }
463
464
465 void InsetERT::draw(PainterInfo & pi, int x, int y) const
466 {
467         InsetCollapsable::draw(pi, x, y);
468 }
469
470
471 void InsetERT::setLatexFont(BufferView * /*bv*/)
472 {
473 #ifdef SET_HARD_FONT
474         LyXFont font(LyXFont::ALL_INHERIT, latex_language);
475         font.setFamily(LyXFont::TYPEWRITER_FAMILY);
476         font.setColor(LColor::latex);
477         inset.text_.setFont(bv, font, false);
478 #endif
479 }
480
481
482 void InsetERT::setStatus(CollapseStatus st)
483 {
484         status_ = st;
485         setButtonLabel();
486 }
487
488
489 bool InsetERT::showInsetDialog(BufferView * bv) const
490 {
491         InsetERTMailer(const_cast<InsetERT &>(*this)).showDialog(bv);
492         return true;
493 }
494
495
496 void InsetERT::getDrawFont(LyXFont & font) const
497 {
498         font = LyXFont(LyXFont::ALL_INHERIT, latex_language);
499         font.setFamily(LyXFont::TYPEWRITER_FAMILY);
500         font.setColor(LColor::latex);
501 }
502
503
504 string const InsetERTMailer::name_("ert");
505
506 InsetERTMailer::InsetERTMailer(InsetERT & inset)
507         : inset_(inset)
508 {}
509
510
511 string const InsetERTMailer::inset2string(Buffer const &) const
512 {
513         return params2string(inset_.status());
514 }
515
516
517 void InsetERTMailer::string2params(string const & in,
518                                    InsetCollapsable::InsetCollapsable::CollapseStatus & status)
519 {
520         status = InsetCollapsable::Collapsed;
521
522         string name;
523         string body = split(in, name, ' ');
524
525         if (body.empty())
526                 return;
527
528         status = static_cast<InsetCollapsable::CollapseStatus>(strToInt(body));
529 }
530
531
532 string const
533 InsetERTMailer::params2string(InsetCollapsable::CollapseStatus status)
534 {
535         return name_ + ' ' + tostr(status);
536 }