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