]> git.lyx.org Git - lyx.git/blob - src/insets/insetert.C
d8e0873597c42edc0d292324d5050ecb13807f09
[lyx.git] / src / insets / insetert.C
1 /* This file is part of
2  * ======================================================
3  * 
4  *           LyX, The Document Processor
5  *       
6  *          Copyright 1998 The LyX Team.
7  *
8  *======================================================*/
9
10 #include <config.h>
11
12 #ifdef __GNUG__
13 #pragma implementation
14 #endif
15
16 #include "insetert.h"
17 #include "gettext.h"
18 #include "lyxfont.h"
19 #include "buffer.h"
20 #include "insets/insettext.h"
21 #include "support/LOstream.h"
22 #include "lyx_gui_misc.h"
23 #include "BufferView.h"
24 #include "LyXView.h"
25 #include "lyxtext.h"
26 #include "frontends/Dialogs.h"
27 #include "debug.h"
28
29 using std::ostream;
30
31 void InsetERT::init()
32 {
33         setButtonLabel();
34         labelfont = LyXFont(LyXFont::ALL_SANE);
35         labelfont.decSize();
36         labelfont.decSize();
37         labelfont.setColor(LColor::latex);
38         setInsetName("ERT");
39                 
40 }
41
42
43 InsetERT::InsetERT(bool collapsed)
44         : InsetCollapsable(collapsed)
45 {
46         if (collapsed)
47                 status_ = Collapsed;
48         else
49                 status_ = Open;
50         init();
51 }
52
53
54 InsetERT::InsetERT(InsetERT const & in, bool same_id)
55         : InsetCollapsable(in, same_id), status_(in.status_)
56 {
57         init();
58 }
59
60
61 Inset * InsetERT::clone(Buffer const &, bool same_id) const
62 {
63         return new InsetERT(*const_cast<InsetERT *>(this), same_id);
64 }
65
66
67 InsetERT::InsetERT(string const & contents, bool collapsed)
68         : InsetCollapsable(collapsed)
69 {
70         if (collapsed)
71                 status_ = Collapsed;
72         else
73                 status_ = Open;
74 #ifndef INHERIT_LANG
75         LyXFont font(LyXFont::ALL_INHERIT, latex_language);
76 #else 
77         LyXFont font(LyXFont::ALL_INHERIT);
78 #endif
79         font.setFamily(LyXFont::TYPEWRITER_FAMILY);
80         font.setColor(LColor::latex);
81         string::const_iterator cit = contents.begin();
82         string::const_iterator end = contents.end();
83         Paragraph::size_type pos = 0;
84         for (; cit != end; ++cit) {
85                 inset.paragraph()->insertChar(pos++, *cit, font);
86         }
87         // the init has to be after the initialization of the paragraph
88         // because of the label settings (draw_label for ert insets).
89         init();
90 }
91
92
93 InsetERT::~InsetERT()
94 {
95         hideDialog();
96 }
97
98
99 void InsetERT::read(Buffer const * buf, LyXLex & lex)
100 {
101         bool token_found = false;
102         if (lex.isOK()) {
103                 lex.next();
104                 string const token = lex.getString();
105                 if (token == "status") {
106                         lex.next();
107                         string const tmp_token = lex.getString();
108                         
109                         if (tmp_token == "Inlined") {
110                                 status(0, Inlined);
111                         } else if (tmp_token == "Collapsed") {
112                                 status(0, Collapsed);
113                         } else {
114                                 // leave this as default!
115                                 status(0, Open);
116                         }
117                         
118                         token_found = true;
119                 } else {
120                         lyxerr << "InsetERT::Read: Missing 'status'-tag!"
121                                    << std::endl;
122                         // take countermeasures
123                         lex.pushToken(token);
124                 }
125         }
126 #warning this should be really short lived only for compatibility to
127 #warning files written 07/08/2001 so this has to go before 1.2.0! (Jug)
128         if (lex.isOK()) {
129                 lex.next();
130                 string const token = lex.getString();
131                 if (token == "collapsed") {
132                         lex.next();
133                         collapsed_ = lex.getBool();
134                 } else {
135                         // Take countermeasures
136                         lex.pushToken(token);
137                 }
138         }
139         inset.read(buf, lex);
140
141 #ifndef INHERIT_LANG
142         LyXFont font(LyXFont::ALL_INHERIT, latex_language);
143 #else 
144         LyXFont font(LyXFont::ALL_INHERIT);
145 #endif
146
147         font.setFamily(LyXFont::TYPEWRITER_FAMILY);
148         font.setColor(LColor::latex);
149         Paragraph * par = inset.paragraph();
150         while (par) {
151                 Paragraph::size_type siz = par->size();
152                 for (Paragraph::size_type i = 0; i < siz; ++i) {
153                         par->setFont(i, font);
154                 }
155                 par = par->next();
156         }
157
158         if (!token_found) {
159                 if (collapsed_) {
160                         status(0, Collapsed);
161                 } else {
162                         status(0, Open);
163                 }
164         }
165         setButtonLabel();
166 }
167
168
169 void InsetERT::write(Buffer const * buf, ostream & os) const 
170 {
171         string st;
172
173         switch(status_) {
174         case Open: 
175                 st = "Open";
176                 break;
177         case Collapsed:
178                 st = "Collapsed";
179                 break;
180         case Inlined:
181                 st = "Inlined";
182                 break;
183         }
184
185         os << getInsetName() << "\n"
186            << "status "<< st << "\n";
187
188         //inset.writeParagraphData(buf, os);
189         string const layout =
190                 textclasslist.NameOfLayout(buf->params.textclass, 0);
191         Paragraph * par = inset.paragraph();
192         while (par) {
193                 os << "\n\\layout " << layout << "\n";
194                 Paragraph::size_type siz = par->size();
195                 for (Paragraph::size_type i = 0; i < siz; ++i) {
196                         Paragraph::value_type c = par->getChar(i);
197                         switch (c) {
198                         case Paragraph::META_INSET:
199                         case Paragraph::META_HFILL:
200                                 lyxerr << "Element is not allowed in insertERT"
201                                        << std::endl;
202                         case Paragraph::META_NEWLINE:
203                                 os << "\n\\newline \n";
204                                 break;
205                         case '\\':
206                                 os << "\n\\backslash \n";
207                                 break;
208                         default:
209                                 os << c;
210                                 break;
211                         }
212                 }
213                 par = par->next();
214         }
215 }
216
217
218 string const InsetERT::editMessage() const 
219 {
220         return _("Opened ERT Inset");
221 }
222
223
224 bool InsetERT::insertInset(BufferView *, Inset *)
225 {
226         return false;
227 }
228
229
230 void InsetERT::setFont(BufferView *, LyXFont const &, bool, bool selectall)
231 {
232         // if selectall is activated then the fontchange was an outside general
233         // fontchange and this messages is not needed
234         if (!selectall)
235                 WriteAlert(_("Impossible Operation!"),
236                            _("Not permitted to change font-types inside ERT-insets!"),
237                            _("Sorry."));
238 }
239
240
241 void InsetERT::edit(BufferView * bv, int x, int y, unsigned int button)
242 {
243         InsetCollapsable::edit(bv, x, y, button);
244         if (status_ != Inlined) {
245                 if (collapsed_) {
246                         status(0, Collapsed);
247                 } else {
248                         status(0, Open);
249                 }
250         }
251         set_latex_font(bv);
252 }
253
254
255 Inset::EDITABLE InsetERT::editable() const
256 {
257         if (status_ == Collapsed)
258                 return IS_EDITABLE;
259         return HIGHLY_EDITABLE;
260 }
261
262
263 void InsetERT::edit(BufferView * bv, bool front)
264 {
265         InsetCollapsable::edit(bv, front);
266         if (status_ != Inlined) {
267                 if (collapsed_) {
268                         status(0, Collapsed);
269                 } else {
270                         status(0, Open);
271                 }
272         }
273         set_latex_font(bv);
274 }
275
276
277 void InsetERT::insetButtonRelease(BufferView * bv, int x, int y, int button)
278 {
279         if (button == 3) {
280                 showInsetDialog(bv);
281                 return;
282         }
283         if ((x >= 0)  && (x < button_length) &&
284             (y >= button_top_y) &&  (y <= button_bottom_y))
285         {
286 //              if (collapsed_) {
287 //                      setLabel(_("ERT"));
288 //              } else {
289 //                      setLabel(get_new_label());
290 //              }
291                 if (collapsed_) {
292                         status(bv, Open);
293 //                      collapsed_ = false;
294 //                      inset.insetButtonRelease(bv, 0, 0, button);
295 //                      inset.setUpdateStatus(bv, InsetText::FULL);
296 //                      bv->updateInset(this, true);
297                 } else {
298                         status(bv, Collapsed);
299 //                      collapsed_ = true;
300 //                      bv->unlockInset(this);
301 //                      bv->updateInset(this, true);
302                 }
303         } else if (!collapsed_ && (y > button_bottom_y)) {
304                 LyXFont font(LyXFont::ALL_SANE);
305                 int yy = ascent(bv, font) + y -
306                     (ascent_collapsed() +
307                      descent_collapsed() +
308                      inset.ascent(bv, font));
309                 inset.insetButtonRelease(bv, x, yy, button);
310         }
311 }
312
313
314 int InsetERT::latex(Buffer const *, std::ostream & os, bool /*fragile*/,
315                     bool /*free_spc*/) const
316 {
317         Paragraph * par = inset.paragraph();
318         while (par) {
319                 Paragraph::size_type siz = par->size();
320                 for (Paragraph::size_type i = 0; i < siz; ++i) {
321                         Paragraph::value_type c = par->getChar(i);
322                         switch (c) {
323                         case Paragraph::META_NEWLINE:
324                                 os << '\n';
325                                 break;
326                         default:
327                                 os << c;
328                                 break;
329                         }
330                 }
331                 par = par->next();
332                 if (par)
333                         os << "\n\n";
334         }
335         
336         return 1;
337 }
338
339
340 int InsetERT::ascii(Buffer const *,
341                     std::ostream &, int /*linelen*/) const 
342 {
343         return 0;
344 }
345
346
347 int InsetERT::linuxdoc(Buffer const *, std::ostream &) const
348 {
349         return 0;
350 }
351
352
353 int InsetERT::docbook(Buffer const *, std::ostream &) const
354 {
355         return 0;
356 }
357
358
359 UpdatableInset::RESULT
360 InsetERT::localDispatch(BufferView * bv, kb_action action, string const & arg)
361 {
362         UpdatableInset::RESULT result = DISPATCHED_NOUPDATE;
363
364         if (!inset.paragraph()->size()) {
365                 set_latex_font(bv);
366         }
367
368         switch(action) {
369         case LFUN_LAYOUT:
370                 bv->owner()->setLayout(inset.paragraph()->getLayout());
371                 break;
372         default:
373                 result = InsetCollapsable::localDispatch(bv, action, arg);
374         }
375         switch(action) {
376         case LFUN_BREAKPARAGRAPH:
377         case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
378         case LFUN_BACKSPACE:
379         case LFUN_BACKSPACE_SKIP:
380         case LFUN_DELETE:
381         case LFUN_DELETE_SKIP:
382         case LFUN_DELETE_LINE_FORWARD:
383         case LFUN_CUT:
384                 set_latex_font(bv);
385                 break;
386         
387         default:
388                 break;
389         }
390         return result;
391 }
392
393
394 string const InsetERT::get_new_label() const
395 {
396         string la;
397         Paragraph::size_type const max_length = 15;
398
399         Paragraph::size_type const p_siz = inset.paragraph()->size();
400         Paragraph::size_type const n = std::min(max_length, p_siz);
401         int i = 0;
402         int j = 0;
403         for(; i < n && j < p_siz; ++j) {
404                 if (inset.paragraph()->isInset(j))
405                         continue;
406                 la += inset.paragraph()->getChar(j);
407                 ++i;
408         }
409         if (i > 0 && j < p_siz) {
410                 la += "...";
411         }
412         if (la.empty()) {
413                 la = _("ERT");
414         }
415         return la;
416 }
417
418
419 void InsetERT::setButtonLabel() const
420 {
421         if (status_ == Collapsed) {
422                 setLabel(get_new_label());
423         } else {
424                 setLabel(_("ERT"));
425         }
426 }
427
428
429 bool InsetERT::checkInsertChar(LyXFont & font)
430 {
431 #ifndef INHERIT_LANG
432         LyXFont f(LyXFont::ALL_INHERIT, latex_language);
433 #else 
434         LyXFont f(LyXFont::ALL_INHERIT);
435 #endif
436         font = f;
437         font.setFamily(LyXFont::TYPEWRITER_FAMILY);
438         font.setColor(LColor::latex);
439         return true;
440 }
441
442
443 int InsetERT::ascent(BufferView * bv, LyXFont const & font) const
444 {
445         if (!inlined())
446                 return InsetCollapsable::ascent(bv, font);
447
448         return inset.ascent(bv, font);
449 }
450
451
452 int InsetERT::descent(BufferView * bv, LyXFont const & font) const
453 {
454         if (!inlined())
455                 return InsetCollapsable::descent(bv, font);
456
457         return inset.descent(bv, font);
458 }
459
460
461 int InsetERT::width(BufferView * bv, LyXFont const & font) const
462 {
463         if (!inlined())
464                 return InsetCollapsable::width(bv, font);
465
466         return inset.width(bv, font);
467 }
468
469
470 void InsetERT::draw(BufferView * bv, LyXFont const & f, 
471                     int baseline, float & x, bool cleared) const
472 {
473         Painter & pain = bv->painter();
474
475         button_length = width_collapsed();
476         button_top_y = -ascent(bv, f);
477         button_bottom_y = -ascent(bv, f) + ascent_collapsed() +
478                 descent_collapsed();
479
480         if (!isOpen()) {
481                 draw_collapsed(pain, baseline, x);
482                 x += TEXT_TO_INSET_OFFSET;
483                 return;
484         }
485
486         float old_x = x;
487
488         if (!owner())
489                 x += static_cast<float>(scroll());
490
491         if (!cleared && (inset.need_update == InsetText::FULL ||
492                          inset.need_update == InsetText::INIT ||
493                          top_x != int(x) ||
494                          top_baseline != baseline))
495         {
496                 // we don't need anymore to clear here we just have to tell
497                 // the underlying LyXText that it should do the RowClear!
498                 inset.setUpdateStatus(bv, InsetText::FULL);
499                 bv->text->status(bv, LyXText::CHANGED_IN_DRAW);
500                 return;
501         }
502
503         top_x = int(x);
504         topx_set = true;
505         top_baseline = baseline;
506
507         int const bl = baseline - ascent(bv, f) + ascent_collapsed();
508
509         if (inlined()) {
510                 inset.draw(bv, f, baseline, x, cleared);
511         } else {
512                 draw_collapsed(pain, bl, old_x);
513                 inset.draw(bv, f, 
514                                    bl + descent_collapsed() + inset.ascent(bv, f),
515                                    x, cleared);
516         }
517         need_update = NONE;
518 }
519
520
521 void InsetERT::set_latex_font(BufferView * bv)
522 {
523 #ifndef INHERIT_LANG
524         LyXFont font(LyXFont::ALL_INHERIT, latex_language);
525 #else 
526         LyXFont font(LyXFont::ALL_INHERIT);
527 #endif
528
529         font.setFamily(LyXFont::TYPEWRITER_FAMILY);
530         font.setColor(LColor::latex);
531         inset.getLyXText(bv)->setFont(bv, font, false);
532 }
533
534
535 void InsetERT::status(BufferView * bv, ERTStatus const st) const
536 {
537         if (st != status_) {
538                 status_ = st;
539                 switch(st) {
540                 case Inlined:
541                         inset.setAutoBreakRows(false);
542                         break;
543                 case Open:
544                         inset.setAutoBreakRows(true);
545                         collapsed_ = false;
546                         need_update = FULL;
547                         setButtonLabel();
548                         break;
549                 case Collapsed:
550                         inset.setAutoBreakRows(true);
551                         collapsed_ = true;
552                         need_update = FULL;
553                         setButtonLabel();
554                         if (bv)
555                                 bv->unlockInset(const_cast<InsetERT *>(this));
556                         break;
557                 }
558                 if (bv)
559                         bv->updateInset(const_cast<InsetERT *>(this), true);
560         }
561 }
562
563
564 bool InsetERT::showInsetDialog(BufferView * bv) const
565 {
566         bv->owner()->getDialogs()->showERT(const_cast<InsetERT *>(this));
567         return true;
568 }
569
570
571 void InsetERT::open(BufferView * bv)
572 {
573         if (!collapsed_)
574                 return;
575         status(bv, Open);
576 }
577
578
579 void InsetERT::close(BufferView * bv) const
580 {
581         if (collapsed_)
582                 return;
583         status(bv, Collapsed);
584 }