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