]> git.lyx.org Git - lyx.git/blob - src/insets/insetert.C
Various update/redraw fixes. Cleaned up InsetERT and added a dialog for
[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         LyXFont font(LyXFont::ALL_INHERIT);
71         font.setFamily(LyXFont::TYPEWRITER_FAMILY);
72         font.setColor(LColor::latex);
73         string::const_iterator cit = contents.begin();
74         string::const_iterator end = contents.end();
75         Paragraph::size_type pos = 0;
76         for (; cit != end; ++cit) {
77                 inset.paragraph()->insertChar(pos++, *cit, font);
78         }
79         // the init has to be after the initialization of the paragraph
80         // because of the label settings (draw_label for ert insets).
81         init();
82 }
83
84
85 InsetERT::~InsetERT()
86 {
87         hideDialog();
88 }
89
90
91 void InsetERT::read(Buffer const * buf, LyXLex & lex)
92 {
93         bool token_found = false;
94         if (lex.IsOK()) {
95                 lex.next();
96                 string const token = lex.GetString();
97                 if (token == "status") {
98                         lex.next();
99                         string st;
100                         if (lex.GetString() == "Inlined")
101                                 status_ = Inlined;
102                         else if (lex.GetString() == "Collapsed")
103                                 status_ = Collapsed;
104                         else // leave this as default!
105                                 status_ = Open;
106                         token_found = true;
107                 } else {
108                         lyxerr << "InsetERT::Read: Missing 'status'-tag!"
109                                    << endl;
110                         // take countermeasures
111                         lex.pushToken(token);
112                 }
113         }
114         InsetCollapsable::read(buf, lex);
115         if (!token_found) {
116                 if (collapsed_)
117                         status_ = Collapsed;
118                 else
119                         status_ = Open;
120         }
121         setButtonLabel();
122 }
123
124
125 void InsetERT::write(Buffer const * buf, ostream & os) const 
126 {
127         string st;
128
129         switch(status_) {
130         case Open: 
131                 st = "Open";
132                 break;
133         case Collapsed:
134                 st = "Collapsed";
135                 break;
136         case Inlined:
137                 st = "Inlined";
138                 break;
139         }
140
141         os << getInsetName() << "\n"
142            << "status "<< st << "\n";
143         InsetCollapsable::write(buf, os);
144 }
145
146
147 string const InsetERT::editMessage() const 
148 {
149         return _("Opened ERT Inset");
150 }
151
152
153 bool InsetERT::insertInset(BufferView *, Inset *)
154 {
155         return false;
156 }
157
158
159 void InsetERT::setFont(BufferView *, LyXFont const &, bool, bool selectall)
160 {
161         // if selectall is activated then the fontchange was an outside general
162         // fontchange and this messages is not needed
163         if (!selectall)
164                 WriteAlert(_("Impossible Operation!"),
165                            _("Not permitted to change font-types inside ERT-insets!"),
166                            _("Sorry."));
167 }
168
169
170 void InsetERT::edit(BufferView * bv, int x, int y, unsigned int button)
171 {
172         InsetCollapsable::edit(bv, x, y, button);
173         set_latex_font(bv);
174 }
175
176
177 Inset::EDITABLE InsetERT::editable() const
178 {
179         if (status_ == Collapsed)
180                 return IS_EDITABLE;
181         return HIGHLY_EDITABLE;
182 }
183
184
185 void InsetERT::edit(BufferView * bv, bool front)
186 {
187         InsetCollapsable::edit(bv, front);
188         set_latex_font(bv);
189 }
190
191
192 void InsetERT::insetButtonRelease(BufferView * bv, int x, int y, int button)
193 {
194         if (button == 3) {
195                 showInsetDialog(bv);
196                 return;
197         }
198         if ((x >= 0)  && (x < button_length) &&
199             (y >= button_top_y) &&  (y <= button_bottom_y))
200         {
201 //              if (collapsed_) {
202 //                      setLabel(_("ERT"));
203 //              } else {
204 //                      setLabel(get_new_label());
205 //              }
206                 if (collapsed_) {
207                         status(bv, Open);
208 //                      collapsed_ = false;
209 //                      inset.insetButtonRelease(bv, 0, 0, button);
210 //                      inset.setUpdateStatus(bv, InsetText::FULL);
211 //                      bv->updateInset(this, true);
212                 } else {
213                         status(bv, Collapsed);
214 //                      collapsed_ = true;
215 //                      bv->unlockInset(this);
216 //                      bv->updateInset(this, true);
217                 }
218         } else if (!collapsed_ && (y > button_bottom_y)) {
219                 LyXFont font(LyXFont::ALL_SANE);
220                 int yy = ascent(bv, font) + y -
221                     (ascent_collapsed() +
222                      descent_collapsed() +
223                      inset.ascent(bv, font));
224                 inset.insetButtonRelease(bv, x, yy, button);
225         }
226 }
227
228
229 int InsetERT::latex(Buffer const *, std::ostream & os, bool /*fragile*/,
230                     bool /*free_spc*/) const
231 {
232         Paragraph * par = inset.paragraph();
233         while (par) {
234                 Paragraph::size_type siz = inset.paragraph()->size();
235                 for (Paragraph::size_type i = 0; i != siz; ++i) {
236                         char c = inset.paragraph()->getChar(i);
237                         switch (c) {
238                         case Paragraph::META_NEWLINE:
239                                 os << '\n';
240                                 break;
241                         default:
242                                 os << c;
243                                 break;
244                         }
245                 }
246                 par = par->next();
247         }
248         
249         return 1;
250 }
251
252
253 int InsetERT::ascii(Buffer const *,
254                     std::ostream &, int /*linelen*/) const 
255 {
256         return 0;
257 }
258
259
260 int InsetERT::linuxdoc(Buffer const *, std::ostream &) const
261 {
262         return 0;
263 }
264
265
266 int InsetERT::docBook(Buffer const *, std::ostream &) const
267 {
268         return 0;
269 }
270
271
272 UpdatableInset::RESULT
273 InsetERT::localDispatch(BufferView * bv, kb_action action, string const & arg)
274 {
275         UpdatableInset::RESULT result = DISPATCHED_NOUPDATE;
276
277         if (!inset.paragraph()->size()) {
278                 set_latex_font(bv);
279         }
280
281         switch(action) {
282         case LFUN_LAYOUT:
283                 bv->owner()->setLayout(inset.paragraph()->getLayout());
284                 break;
285         default:
286                 result = InsetCollapsable::localDispatch(bv, action, arg);
287         }
288         switch(action) {
289         case LFUN_BREAKPARAGRAPH:
290         case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
291                 set_latex_font(bv);
292                 break;
293         
294         default:
295                 break;
296         }
297         return result;
298 }
299
300
301 string const InsetERT::get_new_label() const
302 {
303         string la;
304         Paragraph::size_type const max_length = 15;
305
306         Paragraph::size_type const p_siz = inset.paragraph()->size();
307         Paragraph::size_type const n = std::min(max_length, p_siz);
308         int i = 0;
309         int j = 0;
310         for(; i < n && j < p_siz; ++j) {
311                 if (inset.paragraph()->isInset(j))
312                         continue;
313                 la += inset.paragraph()->getChar(j);
314                 ++i;
315         }
316         if (i > 0 && j < p_siz) {
317                 la += "...";
318         }
319         if (la.empty()) {
320                 la = _("ERT");
321         }
322         return la;
323 }
324
325
326 void InsetERT::setButtonLabel() 
327 {
328         if (status_ == Collapsed) {
329                 setLabel(get_new_label());
330         } else {
331                 setLabel(_("ERT"));
332         }
333 }
334
335
336 bool InsetERT::checkInsertChar(LyXFont & font)
337 {
338         LyXFont f(LyXFont::ALL_INHERIT);
339         font = f;
340         font.setFamily(LyXFont::TYPEWRITER_FAMILY);
341         font.setColor(LColor::latex);
342         return true;
343 }
344
345
346 int InsetERT::ascent(BufferView * bv, LyXFont const & font) const
347 {
348         if (!inlined())
349                 return InsetCollapsable::ascent(bv, font);
350
351         return inset.ascent(bv, font);
352 }
353
354
355 int InsetERT::descent(BufferView * bv, LyXFont const & font) const
356 {
357         if (!inlined())
358                 return InsetCollapsable::descent(bv, font);
359
360         return inset.descent(bv, font);
361 }
362
363
364 int InsetERT::width(BufferView * bv, LyXFont const & font) const
365 {
366         if (!inlined())
367                 return InsetCollapsable::width(bv, font);
368
369         return inset.width(bv, font);
370 }
371
372
373 void InsetERT::draw(BufferView * bv, LyXFont const & f, 
374                     int baseline, float & x, bool cleared) const
375 {
376         Painter & pain = bv->painter();
377
378         button_length = width_collapsed();
379         button_top_y = -ascent(bv, f);
380         button_bottom_y = -ascent(bv, f) + ascent_collapsed() +
381                 descent_collapsed();
382
383         if (!isOpen()) {
384                 draw_collapsed(pain, baseline, x);
385                 x += TEXT_TO_INSET_OFFSET;
386                 return;
387         }
388
389         float old_x = x;
390
391         if (!owner())
392                 x += static_cast<float>(scroll());
393
394         if (!cleared && (inset.need_update == InsetText::FULL ||
395                          inset.need_update == InsetText::INIT ||
396                          top_x != int(x) ||
397                          top_baseline != baseline))
398         {
399                 // we don't need anymore to clear here we just have to tell
400                 // the underlying LyXText that it should do the RowClear!
401                 inset.setUpdateStatus(bv, InsetText::FULL);
402                 bv->text->status(bv, LyXText::CHANGED_IN_DRAW);
403                 return;
404         }
405
406         top_x = int(x);
407         top_baseline = baseline;
408
409         int const bl = baseline - ascent(bv, f) + ascent_collapsed();
410
411         if (inlined()) {
412                 inset.draw(bv, f, baseline, x, cleared);
413         } else {
414                 draw_collapsed(pain, bl, old_x);
415                 inset.draw(bv, f, 
416                                    bl + descent_collapsed() + inset.ascent(bv, f),
417                                    x, cleared);
418         }
419         need_update = NONE;
420 }
421
422
423 void InsetERT::set_latex_font(BufferView * bv)
424 {
425         LyXFont font(LyXFont::ALL_INHERIT);
426
427         font.setFamily(LyXFont::TYPEWRITER_FAMILY);
428         font.setColor(LColor::latex);
429         inset.getLyXText(bv)->setFont(bv, font, false);
430 }
431
432
433 void InsetERT::status(BufferView * bv, ERTStatus const st)
434 {
435         if (st != status_) {
436                 status_ = st;
437                 switch(st) {
438                 case Inlined:
439                         inset.setAutoBreakRows(false);
440                         break;
441                 case Open:
442                         inset.setAutoBreakRows(true);
443                         collapsed_ = false;
444                         need_update = FULL;
445                         setButtonLabel();
446                         break;
447                 case Collapsed:
448                         inset.setAutoBreakRows(true);
449                         collapsed_ = true;
450                         need_update = FULL;
451                         setButtonLabel();
452                         bv->unlockInset(this);
453                         break;
454                 }
455                 bv->updateInset(this, true);
456         }
457 }
458
459
460 bool InsetERT::showInsetDialog(BufferView * bv) const
461 {
462         bv->owner()->getDialogs()->showERT(const_cast<InsetERT *>(this));
463         return true;
464 }
465
466
467 void InsetERT::open(BufferView * bv)
468 {
469         if (!collapsed_)
470                 return;
471         status(bv, Open);
472 }
473
474
475 void InsetERT::close(BufferView * bv)
476 {
477         if (collapsed_)
478                 return;
479         status(bv, Collapsed);
480 }