]> git.lyx.org Git - lyx.git/blob - src/insets/insetert.C
4780c868ee1a31dab918bc52f9f124756e093d9f
[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         if (!token_found) {
141                 if (collapsed_) {
142                         status(0, Collapsed);
143                 } else {
144                         status(0, Open);
145                 }
146         }
147         setButtonLabel();
148 }
149
150
151 void InsetERT::write(Buffer const * buf, ostream & os) const 
152 {
153         string st;
154
155         switch(status_) {
156         case Open: 
157                 st = "Open";
158                 break;
159         case Collapsed:
160                 st = "Collapsed";
161                 break;
162         case Inlined:
163                 st = "Inlined";
164                 break;
165         }
166
167         os << getInsetName() << "\n"
168            << "status "<< st << "\n";
169
170         inset.writeParagraphData(buf, os);
171 }
172
173
174 string const InsetERT::editMessage() const 
175 {
176         return _("Opened ERT Inset");
177 }
178
179
180 bool InsetERT::insertInset(BufferView *, Inset *)
181 {
182         return false;
183 }
184
185
186 void InsetERT::setFont(BufferView *, LyXFont const &, bool, bool selectall)
187 {
188         // if selectall is activated then the fontchange was an outside general
189         // fontchange and this messages is not needed
190         if (!selectall)
191                 WriteAlert(_("Impossible Operation!"),
192                            _("Not permitted to change font-types inside ERT-insets!"),
193                            _("Sorry."));
194 }
195
196
197 void InsetERT::edit(BufferView * bv, int x, int y, unsigned int button)
198 {
199         InsetCollapsable::edit(bv, x, y, button);
200         if (status_ != Inlined) {
201                 if (collapsed_) {
202                         status(0, Collapsed);
203                 } else {
204                         status(0, Open);
205                 }
206         }
207         set_latex_font(bv);
208 }
209
210
211 Inset::EDITABLE InsetERT::editable() const
212 {
213         if (status_ == Collapsed)
214                 return IS_EDITABLE;
215         return HIGHLY_EDITABLE;
216 }
217
218
219 void InsetERT::edit(BufferView * bv, bool front)
220 {
221         InsetCollapsable::edit(bv, front);
222         if (status_ != Inlined) {
223                 if (collapsed_) {
224                         status(0, Collapsed);
225                 } else {
226                         status(0, Open);
227                 }
228         }
229         set_latex_font(bv);
230 }
231
232
233 void InsetERT::insetButtonRelease(BufferView * bv, int x, int y, int button)
234 {
235         if (button == 3) {
236                 showInsetDialog(bv);
237                 return;
238         }
239         if ((x >= 0)  && (x < button_length) &&
240             (y >= button_top_y) &&  (y <= button_bottom_y))
241         {
242 //              if (collapsed_) {
243 //                      setLabel(_("ERT"));
244 //              } else {
245 //                      setLabel(get_new_label());
246 //              }
247                 if (collapsed_) {
248                         status(bv, Open);
249 //                      collapsed_ = false;
250 //                      inset.insetButtonRelease(bv, 0, 0, button);
251 //                      inset.setUpdateStatus(bv, InsetText::FULL);
252 //                      bv->updateInset(this, true);
253                 } else {
254                         status(bv, Collapsed);
255 //                      collapsed_ = true;
256 //                      bv->unlockInset(this);
257 //                      bv->updateInset(this, true);
258                 }
259         } else if (!collapsed_ && (y > button_bottom_y)) {
260                 LyXFont font(LyXFont::ALL_SANE);
261                 int yy = ascent(bv, font) + y -
262                     (ascent_collapsed() +
263                      descent_collapsed() +
264                      inset.ascent(bv, font));
265                 inset.insetButtonRelease(bv, x, yy, button);
266         }
267 }
268
269
270 int InsetERT::latex(Buffer const *, std::ostream & os, bool /*fragile*/,
271                     bool /*free_spc*/) const
272 {
273         Paragraph * par = inset.paragraph();
274         while (par) {
275                 Paragraph::size_type siz = inset.paragraph()->size();
276                 for (Paragraph::size_type i = 0; i != siz; ++i) {
277                         char c = inset.paragraph()->getChar(i);
278                         switch (c) {
279                         case Paragraph::META_NEWLINE:
280                                 os << '\n';
281                                 break;
282                         default:
283                                 os << c;
284                                 break;
285                         }
286                 }
287                 par = par->next();
288         }
289         
290         return 1;
291 }
292
293
294 int InsetERT::ascii(Buffer const *,
295                     std::ostream &, int /*linelen*/) const 
296 {
297         return 0;
298 }
299
300
301 int InsetERT::linuxdoc(Buffer const *, std::ostream &) const
302 {
303         return 0;
304 }
305
306
307 int InsetERT::docBook(Buffer const *, std::ostream &) const
308 {
309         return 0;
310 }
311
312
313 UpdatableInset::RESULT
314 InsetERT::localDispatch(BufferView * bv, kb_action action, string const & arg)
315 {
316         UpdatableInset::RESULT result = DISPATCHED_NOUPDATE;
317
318         if (!inset.paragraph()->size()) {
319                 set_latex_font(bv);
320         }
321
322         switch(action) {
323         case LFUN_LAYOUT:
324                 bv->owner()->setLayout(inset.paragraph()->getLayout());
325                 break;
326         default:
327                 result = InsetCollapsable::localDispatch(bv, action, arg);
328         }
329         switch(action) {
330         case LFUN_BREAKPARAGRAPH:
331         case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
332                 set_latex_font(bv);
333                 break;
334         
335         default:
336                 break;
337         }
338         return result;
339 }
340
341
342 string const InsetERT::get_new_label() const
343 {
344         string la;
345         Paragraph::size_type const max_length = 15;
346
347         Paragraph::size_type const p_siz = inset.paragraph()->size();
348         Paragraph::size_type const n = std::min(max_length, p_siz);
349         int i = 0;
350         int j = 0;
351         for(; i < n && j < p_siz; ++j) {
352                 if (inset.paragraph()->isInset(j))
353                         continue;
354                 la += inset.paragraph()->getChar(j);
355                 ++i;
356         }
357         if (i > 0 && j < p_siz) {
358                 la += "...";
359         }
360         if (la.empty()) {
361                 la = _("ERT");
362         }
363         return la;
364 }
365
366
367 void InsetERT::setButtonLabel() const
368 {
369         if (status_ == Collapsed) {
370                 setLabel(get_new_label());
371         } else {
372                 setLabel(_("ERT"));
373         }
374 }
375
376
377 bool InsetERT::checkInsertChar(LyXFont & font)
378 {
379 #ifndef INHERIT_LANG
380         LyXFont f(LyXFont::ALL_INHERIT, latex_language);
381 #else 
382         LyXFont f(LyXFont::ALL_INHERIT);
383 #endif
384         font = f;
385         font.setFamily(LyXFont::TYPEWRITER_FAMILY);
386         font.setColor(LColor::latex);
387         return true;
388 }
389
390
391 int InsetERT::ascent(BufferView * bv, LyXFont const & font) const
392 {
393         if (!inlined())
394                 return InsetCollapsable::ascent(bv, font);
395
396         return inset.ascent(bv, font);
397 }
398
399
400 int InsetERT::descent(BufferView * bv, LyXFont const & font) const
401 {
402         if (!inlined())
403                 return InsetCollapsable::descent(bv, font);
404
405         return inset.descent(bv, font);
406 }
407
408
409 int InsetERT::width(BufferView * bv, LyXFont const & font) const
410 {
411         if (!inlined())
412                 return InsetCollapsable::width(bv, font);
413
414         return inset.width(bv, font);
415 }
416
417
418 void InsetERT::draw(BufferView * bv, LyXFont const & f, 
419                     int baseline, float & x, bool cleared) const
420 {
421         Painter & pain = bv->painter();
422
423         button_length = width_collapsed();
424         button_top_y = -ascent(bv, f);
425         button_bottom_y = -ascent(bv, f) + ascent_collapsed() +
426                 descent_collapsed();
427
428         if (!isOpen()) {
429                 draw_collapsed(pain, baseline, x);
430                 x += TEXT_TO_INSET_OFFSET;
431                 return;
432         }
433
434         float old_x = x;
435
436         if (!owner())
437                 x += static_cast<float>(scroll());
438
439         if (!cleared && (inset.need_update == InsetText::FULL ||
440                          inset.need_update == InsetText::INIT ||
441                          top_x != int(x) ||
442                          top_baseline != baseline))
443         {
444                 // we don't need anymore to clear here we just have to tell
445                 // the underlying LyXText that it should do the RowClear!
446                 inset.setUpdateStatus(bv, InsetText::FULL);
447                 bv->text->status(bv, LyXText::CHANGED_IN_DRAW);
448                 return;
449         }
450
451         top_x = int(x);
452         topx_set = true;
453         top_baseline = baseline;
454
455         int const bl = baseline - ascent(bv, f) + ascent_collapsed();
456
457         if (inlined()) {
458                 inset.draw(bv, f, baseline, x, cleared);
459         } else {
460                 draw_collapsed(pain, bl, old_x);
461                 inset.draw(bv, f, 
462                                    bl + descent_collapsed() + inset.ascent(bv, f),
463                                    x, cleared);
464         }
465         need_update = NONE;
466 }
467
468
469 void InsetERT::set_latex_font(BufferView * bv)
470 {
471 #ifndef INHERIT_LANG
472         LyXFont font(LyXFont::ALL_INHERIT, latex_language);
473 #else 
474         LyXFont font(LyXFont::ALL_INHERIT);
475 #endif
476
477         font.setFamily(LyXFont::TYPEWRITER_FAMILY);
478         font.setColor(LColor::latex);
479         inset.getLyXText(bv)->setFont(bv, font, false);
480 }
481
482
483 void InsetERT::status(BufferView * bv, ERTStatus const st) const
484 {
485         if (st != status_) {
486                 status_ = st;
487                 switch(st) {
488                 case Inlined:
489                         inset.setAutoBreakRows(false);
490                         break;
491                 case Open:
492                         inset.setAutoBreakRows(true);
493                         collapsed_ = false;
494                         need_update = FULL;
495                         setButtonLabel();
496                         break;
497                 case Collapsed:
498                         inset.setAutoBreakRows(true);
499                         collapsed_ = true;
500                         need_update = FULL;
501                         setButtonLabel();
502                         if (bv)
503                                 bv->unlockInset(const_cast<InsetERT *>(this));
504                         break;
505                 }
506                 if (bv)
507                         bv->updateInset(const_cast<InsetERT *>(this), true);
508         }
509 }
510
511
512 bool InsetERT::showInsetDialog(BufferView * bv) const
513 {
514         bv->owner()->getDialogs()->showERT(const_cast<InsetERT *>(this));
515         return true;
516 }
517
518
519 void InsetERT::open(BufferView * bv)
520 {
521         if (!collapsed_)
522                 return;
523         status(bv, Open);
524 }
525
526
527 void InsetERT::close(BufferView * bv) const
528 {
529         if (collapsed_)
530                 return;
531         status(bv, Collapsed);
532 }