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