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