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