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