]> git.lyx.org Git - lyx.git/blob - src/insets/insetert.C
next step...
[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         int lines = 0;
319         while (par) {
320                 Paragraph::size_type siz = par->size();
321                 for (Paragraph::size_type i = 0; i < siz; ++i) {
322                         Paragraph::value_type c = par->getChar(i);
323                         switch (c) {
324                         case Paragraph::META_NEWLINE:
325                                 os << '\n';
326                                 ++lines;
327                                 break;
328                         default:
329                                 os << c;
330                                 break;
331                         }
332                 }
333                 par = par->next();
334                 if (par) {
335                         os << "\n\n";
336                         lines += 2;
337                 }
338         }
339         
340         return lines;
341 }
342
343
344 int InsetERT::ascii(Buffer const *,
345                     std::ostream &, int /*linelen*/) const 
346 {
347         return 0;
348 }
349
350
351 int InsetERT::linuxdoc(Buffer const *, std::ostream & os) const
352 {
353         Paragraph * par = inset.paragraph();
354         int lines = 0;
355         while (par) {
356                 Paragraph::size_type siz = par->size();
357                 for (Paragraph::size_type i = 0; i < siz; ++i) {
358                         Paragraph::value_type c = par->getChar(i);
359                         switch (c) {
360                         case Paragraph::META_NEWLINE:
361                                 os << '\n';
362                                 ++lines;
363                                 break;
364                         default:
365                                 os << c;
366                                 break;
367                         }
368                 }
369                 par = par->next();
370                 if (par) {
371                         os << "\n";
372                         lines ++;
373                 }
374         }
375         
376         return lines;
377 }
378
379
380 int InsetERT::docbook(Buffer const *, std::ostream & os) const
381 {
382         Paragraph * par = inset.paragraph();
383         int lines = 0;
384         while (par) {
385                 Paragraph::size_type siz = par->size();
386                 for (Paragraph::size_type i = 0; i < siz; ++i) {
387                         Paragraph::value_type c = par->getChar(i);
388                         switch (c) {
389                         case Paragraph::META_NEWLINE:
390                                 os << '\n';
391                                 ++lines;
392                                 break;
393                         default:
394                                 os << c;
395                                 break;
396                         }
397                 }
398                 par = par->next();
399                 if (par) {
400                         os << "\n";
401                         lines ++;
402                 }
403         }
404         
405         return lines;
406 }
407
408
409 UpdatableInset::RESULT
410 InsetERT::localDispatch(BufferView * bv, kb_action action, string const & arg)
411 {
412         UpdatableInset::RESULT result = DISPATCHED_NOUPDATE;
413
414         if (!inset.paragraph()->size()) {
415                 set_latex_font(bv);
416         }
417
418         switch(action) {
419         case LFUN_LAYOUT:
420                 bv->owner()->setLayout(inset.paragraph()->getLayout());
421                 break;
422         default:
423                 result = InsetCollapsable::localDispatch(bv, action, arg);
424         }
425         switch(action) {
426         case LFUN_BREAKPARAGRAPH:
427         case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
428         case LFUN_BACKSPACE:
429         case LFUN_BACKSPACE_SKIP:
430         case LFUN_DELETE:
431         case LFUN_DELETE_SKIP:
432         case LFUN_DELETE_LINE_FORWARD:
433         case LFUN_CUT:
434                 set_latex_font(bv);
435                 break;
436         
437         default:
438                 break;
439         }
440         return result;
441 }
442
443
444 string const InsetERT::get_new_label() const
445 {
446         string la;
447         Paragraph::size_type const max_length = 15;
448
449         Paragraph::size_type const p_siz = inset.paragraph()->size();
450         Paragraph::size_type const n = std::min(max_length, p_siz);
451         int i = 0;
452         int j = 0;
453         for(; i < n && j < p_siz; ++j) {
454                 if (inset.paragraph()->isInset(j))
455                         continue;
456                 la += inset.paragraph()->getChar(j);
457                 ++i;
458         }
459         if (i > 0 && j < p_siz) {
460                 la += "...";
461         }
462         if (la.empty()) {
463                 la = _("ERT");
464         }
465         return la;
466 }
467
468
469 void InsetERT::setButtonLabel() const
470 {
471         if (status_ == Collapsed) {
472                 setLabel(get_new_label());
473         } else {
474                 setLabel(_("ERT"));
475         }
476 }
477
478
479 bool InsetERT::checkInsertChar(LyXFont & font)
480 {
481 #ifndef INHERIT_LANG
482         LyXFont f(LyXFont::ALL_INHERIT, latex_language);
483 #else 
484         LyXFont f(LyXFont::ALL_INHERIT);
485 #endif
486         font = f;
487         font.setFamily(LyXFont::TYPEWRITER_FAMILY);
488         font.setColor(LColor::latex);
489         return true;
490 }
491
492
493 int InsetERT::ascent(BufferView * bv, LyXFont const & font) const
494 {
495         if (!inlined())
496                 return InsetCollapsable::ascent(bv, font);
497
498         return inset.ascent(bv, font);
499 }
500
501
502 int InsetERT::descent(BufferView * bv, LyXFont const & font) const
503 {
504         if (!inlined())
505                 return InsetCollapsable::descent(bv, font);
506
507         return inset.descent(bv, font);
508 }
509
510
511 int InsetERT::width(BufferView * bv, LyXFont const & font) const
512 {
513         if (!inlined())
514                 return InsetCollapsable::width(bv, font);
515
516         return inset.width(bv, font);
517 }
518
519
520 void InsetERT::draw(BufferView * bv, LyXFont const & f, 
521                     int baseline, float & x, bool cleared) const
522 {
523         Painter & pain = bv->painter();
524
525         button_length = width_collapsed();
526         button_top_y = -ascent(bv, f);
527         button_bottom_y = -ascent(bv, f) + ascent_collapsed() +
528                 descent_collapsed();
529
530         if (!isOpen()) {
531                 draw_collapsed(pain, baseline, x);
532                 x += TEXT_TO_INSET_OFFSET;
533                 return;
534         }
535
536         float old_x = x;
537
538         if (!owner())
539                 x += static_cast<float>(scroll());
540
541         if (!cleared && (inset.need_update == InsetText::FULL ||
542                          inset.need_update == InsetText::INIT ||
543                          top_x != int(x) ||
544                          top_baseline != baseline))
545         {
546                 // we don't need anymore to clear here we just have to tell
547                 // the underlying LyXText that it should do the RowClear!
548                 inset.setUpdateStatus(bv, InsetText::FULL);
549                 bv->text->status(bv, LyXText::CHANGED_IN_DRAW);
550                 return;
551         }
552
553         top_x = int(x);
554         topx_set = true;
555         top_baseline = baseline;
556
557         int const bl = baseline - ascent(bv, f) + ascent_collapsed();
558
559         if (inlined()) {
560                 inset.draw(bv, f, baseline, x, cleared);
561         } else {
562                 draw_collapsed(pain, bl, old_x);
563                 inset.draw(bv, f, 
564                                    bl + descent_collapsed() + inset.ascent(bv, f),
565                                    x, cleared);
566         }
567         need_update = NONE;
568 }
569
570
571 void InsetERT::set_latex_font(BufferView * bv)
572 {
573 #ifndef INHERIT_LANG
574         LyXFont font(LyXFont::ALL_INHERIT, latex_language);
575 #else 
576         LyXFont font(LyXFont::ALL_INHERIT);
577 #endif
578
579         font.setFamily(LyXFont::TYPEWRITER_FAMILY);
580         font.setColor(LColor::latex);
581         inset.getLyXText(bv)->setFont(bv, font, false);
582 }
583
584
585 void InsetERT::status(BufferView * bv, ERTStatus const st) const
586 {
587         if (st != status_) {
588                 status_ = st;
589                 switch(st) {
590                 case Inlined:
591                         inset.setAutoBreakRows(false);
592                         break;
593                 case Open:
594                         inset.setAutoBreakRows(true);
595                         collapsed_ = false;
596                         need_update = FULL;
597                         setButtonLabel();
598                         break;
599                 case Collapsed:
600                         inset.setAutoBreakRows(true);
601                         collapsed_ = true;
602                         need_update = FULL;
603                         setButtonLabel();
604                         if (bv)
605                                 bv->unlockInset(const_cast<InsetERT *>(this));
606                         break;
607                 }
608                 if (bv)
609                         bv->updateInset(const_cast<InsetERT *>(this), false);
610         }
611 }
612
613
614 bool InsetERT::showInsetDialog(BufferView * bv) const
615 {
616         bv->owner()->getDialogs()->showERT(const_cast<InsetERT *>(this));
617         return true;
618 }
619
620
621 void InsetERT::open(BufferView * bv)
622 {
623         if (!collapsed_)
624                 return;
625         status(bv, Open);
626 }
627
628
629 void InsetERT::close(BufferView * bv) const
630 {
631         if (collapsed_)
632                 return;
633         status(bv, Collapsed);
634 }
635
636
637 string const InsetERT::selectNextWordToSpellcheck(BufferView * bv,float &) const
638 {
639         bv->unlockInset(const_cast<InsetERT *>(this));
640         return string();
641 }