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