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