]> git.lyx.org Git - lyx.git/blob - src/insets/insetert.C
skak support, John's ERT fixes, loclae blunder fix
[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::updateStatus(BufferView * bv, bool swap) const
242 {
243         if (status_ != Inlined) {
244                 if (collapsed_) {
245                         status(bv, swap ? Open : Collapsed);
246                 } else {
247                         status(bv, swap ? Collapsed : Open);
248                 }
249         }
250 }
251
252  
253 void InsetERT::edit(BufferView * bv, int x, int y, unsigned int button)
254 {
255         if (button == 3)
256                 return;
257  
258         InsetCollapsable::edit(bv, x, y, button);
259         updateStatus(0);
260         set_latex_font(bv);
261 }
262
263
264 Inset::EDITABLE InsetERT::editable() const
265 {
266         if (status_ == Collapsed)
267                 return IS_EDITABLE;
268         return HIGHLY_EDITABLE;
269 }
270
271
272 void InsetERT::edit(BufferView * bv, bool front)
273 {
274         InsetCollapsable::edit(bv, front);
275         updateStatus(0);
276         set_latex_font(bv);
277 }
278
279
280 void InsetERT::insetButtonRelease(BufferView * bv, int x, int y, int button)
281 {
282         if (button == 3) {
283                 showInsetDialog(bv);
284                 return;
285         }
286  
287         if (status_ != Inlined && (x >= 0)  && (x < button_length) &&
288             (y >= button_top_y) &&  (y <= button_bottom_y)) {
289                 updateStatus(bv, true);
290         } else {
291                 LyXFont font(LyXFont::ALL_SANE);
292                 int yy = ascent(bv, font) + y - inset.ascent(bv, font);
293  
294                 // inlined is special - the text appears above 
295                 // button_bottom_y
296                 if (status_ == Inlined) {
297                         inset.insetButtonRelease(bv, x, yy, button);
298                 } else if (!collapsed_ && (y > button_bottom_y)) {
299                         yy -= (ascent_collapsed() + descent_collapsed());
300                         inset.insetButtonRelease(bv, x, yy, button);
301                 }
302         }
303 }
304
305
306 int InsetERT::latex(Buffer const *, std::ostream & os, bool /*fragile*/,
307                     bool /*free_spc*/) const
308 {
309         Paragraph * par = inset.paragraph();
310         int lines = 0;
311         while (par) {
312                 Paragraph::size_type siz = par->size();
313                 for (Paragraph::size_type i = 0; i < siz; ++i) {
314                         Paragraph::value_type c = par->getChar(i);
315                         switch (c) {
316                         case Paragraph::META_NEWLINE:
317                                 os << '\n';
318                                 ++lines;
319                                 break;
320                         default:
321                                 os << c;
322                                 break;
323                         }
324                 }
325                 par = par->next();
326                 if (par) {
327                         os << "\n\n";
328                         lines += 2;
329                 }
330         }
331         
332         return lines;
333 }
334
335
336 int InsetERT::ascii(Buffer const *,
337                     std::ostream &, int /*linelen*/) const 
338 {
339         return 0;
340 }
341
342
343 int InsetERT::linuxdoc(Buffer const *, std::ostream & os) const
344 {
345         Paragraph * par = inset.paragraph();
346         int lines = 0;
347         while (par) {
348                 Paragraph::size_type siz = par->size();
349                 for (Paragraph::size_type i = 0; i < siz; ++i) {
350                         Paragraph::value_type c = par->getChar(i);
351                         switch (c) {
352                         case Paragraph::META_NEWLINE:
353                                 os << '\n';
354                                 ++lines;
355                                 break;
356                         default:
357                                 os << c;
358                                 break;
359                         }
360                 }
361                 par = par->next();
362                 if (par) {
363                         os << "\n";
364                         lines ++;
365                 }
366         }
367         
368         return lines;
369 }
370
371
372 int InsetERT::docbook(Buffer const *, std::ostream & os) const
373 {
374         Paragraph * par = inset.paragraph();
375         int lines = 0;
376         while (par) {
377                 Paragraph::size_type siz = par->size();
378                 for (Paragraph::size_type i = 0; i < siz; ++i) {
379                         Paragraph::value_type c = par->getChar(i);
380                         switch (c) {
381                         case Paragraph::META_NEWLINE:
382                                 os << '\n';
383                                 ++lines;
384                                 break;
385                         default:
386                                 os << c;
387                                 break;
388                         }
389                 }
390                 par = par->next();
391                 if (par) {
392                         os << "\n";
393                         lines ++;
394                 }
395         }
396         
397         return lines;
398 }
399
400
401 UpdatableInset::RESULT
402 InsetERT::localDispatch(BufferView * bv, kb_action action, string const & arg)
403 {
404         UpdatableInset::RESULT result = DISPATCHED_NOUPDATE;
405
406         if (!inset.paragraph()->size()) {
407                 set_latex_font(bv);
408         }
409
410         switch(action) {
411         case LFUN_LAYOUT:
412                 bv->owner()->setLayout(inset.paragraph()->getLayout());
413                 break;
414         default:
415                 result = InsetCollapsable::localDispatch(bv, action, arg);
416         }
417         switch(action) {
418         case LFUN_BREAKPARAGRAPH:
419         case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
420         case LFUN_BACKSPACE:
421         case LFUN_BACKSPACE_SKIP:
422         case LFUN_DELETE:
423         case LFUN_DELETE_SKIP:
424         case LFUN_DELETE_LINE_FORWARD:
425         case LFUN_CUT:
426                 set_latex_font(bv);
427                 break;
428         
429         default:
430                 break;
431         }
432         return result;
433 }
434
435
436 string const InsetERT::get_new_label() const
437 {
438         string la;
439         Paragraph::size_type const max_length = 15;
440
441         Paragraph::size_type const p_siz = inset.paragraph()->size();
442         Paragraph::size_type const n = std::min(max_length, p_siz);
443         int i = 0;
444         int j = 0;
445         for(; i < n && j < p_siz; ++j) {
446                 if (inset.paragraph()->isInset(j))
447                         continue;
448                 la += inset.paragraph()->getChar(j);
449                 ++i;
450         }
451         if (i > 0 && j < p_siz) {
452                 la += "...";
453         }
454         if (la.empty()) {
455                 la = _("ERT");
456         }
457         return la;
458 }
459
460
461 void InsetERT::setButtonLabel() const
462 {
463         if (status_ == Collapsed) {
464                 setLabel(get_new_label());
465         } else {
466                 setLabel(_("ERT"));
467         }
468 }
469
470
471 bool InsetERT::checkInsertChar(LyXFont & font)
472 {
473 #ifndef INHERIT_LANG
474         LyXFont f(LyXFont::ALL_INHERIT, latex_language);
475 #else 
476         LyXFont f(LyXFont::ALL_INHERIT);
477 #endif
478         font = f;
479         font.setFamily(LyXFont::TYPEWRITER_FAMILY);
480         font.setColor(LColor::latex);
481         return true;
482 }
483
484
485 int InsetERT::ascent(BufferView * bv, LyXFont const & font) const
486 {
487         if (!inlined())
488                 return InsetCollapsable::ascent(bv, font);
489
490         return inset.ascent(bv, font);
491 }
492
493
494 int InsetERT::descent(BufferView * bv, LyXFont const & font) const
495 {
496         if (!inlined())
497                 return InsetCollapsable::descent(bv, font);
498
499         return inset.descent(bv, font);
500 }
501
502
503 int InsetERT::width(BufferView * bv, LyXFont const & font) const
504 {
505         if (!inlined())
506                 return InsetCollapsable::width(bv, font);
507
508         return inset.width(bv, font);
509 }
510
511
512 void InsetERT::draw(BufferView * bv, LyXFont const & f, 
513                     int baseline, float & x, bool cleared) const
514 {
515         Painter & pain = bv->painter();
516
517         button_length = width_collapsed();
518         button_top_y = -ascent(bv, f);
519         button_bottom_y = -ascent(bv, f) + ascent_collapsed() +
520                 descent_collapsed();
521
522         if (!isOpen()) {
523                 draw_collapsed(pain, baseline, x);
524                 x += TEXT_TO_INSET_OFFSET;
525                 return;
526         }
527
528         float old_x = x;
529
530         if (!owner())
531                 x += static_cast<float>(scroll());
532
533         if (!cleared && (inset.need_update == InsetText::FULL ||
534                          inset.need_update == InsetText::INIT ||
535                          top_x != int(x) ||
536                          top_baseline != baseline))
537         {
538                 // we don't need anymore to clear here we just have to tell
539                 // the underlying LyXText that it should do the RowClear!
540                 inset.setUpdateStatus(bv, InsetText::FULL);
541                 bv->text->status(bv, LyXText::CHANGED_IN_DRAW);
542                 return;
543         }
544
545         top_x = int(x);
546         topx_set = true;
547         top_baseline = baseline;
548
549         int const bl = baseline - ascent(bv, f) + ascent_collapsed();
550
551         if (inlined()) {
552                 inset.draw(bv, f, baseline, x, cleared);
553         } else {
554                 draw_collapsed(pain, bl, old_x);
555                 inset.draw(bv, f, 
556                                    bl + descent_collapsed() + inset.ascent(bv, f),
557                                    x, cleared);
558         }
559         need_update = NONE;
560 }
561
562
563 void InsetERT::set_latex_font(BufferView * bv)
564 {
565 #ifndef INHERIT_LANG
566         LyXFont font(LyXFont::ALL_INHERIT, latex_language);
567 #else 
568         LyXFont font(LyXFont::ALL_INHERIT);
569 #endif
570
571         font.setFamily(LyXFont::TYPEWRITER_FAMILY);
572         font.setColor(LColor::latex);
573         inset.getLyXText(bv)->setFont(bv, font, false);
574 }
575
576
577 void InsetERT::status(BufferView * bv, ERTStatus const st) const
578 {
579         if (st != status_) {
580                 status_ = st;
581                 switch(st) {
582                 case Inlined:
583                         inset.setAutoBreakRows(false);
584                         break;
585                 case Open:
586                         inset.setAutoBreakRows(true);
587                         collapsed_ = false;
588                         need_update = FULL;
589                         setButtonLabel();
590                         break;
591                 case Collapsed:
592                         inset.setAutoBreakRows(true);
593                         collapsed_ = true;
594                         need_update = FULL;
595                         setButtonLabel();
596                         if (bv)
597                                 bv->unlockInset(const_cast<InsetERT *>(this));
598                         break;
599                 }
600                 if (bv)
601                         bv->updateInset(const_cast<InsetERT *>(this), false);
602         }
603 }
604
605
606 bool InsetERT::showInsetDialog(BufferView * bv) const
607 {
608         bv->owner()->getDialogs()->showERT(const_cast<InsetERT *>(this));
609         return true;
610 }
611
612
613 void InsetERT::open(BufferView * bv)
614 {
615         if (!collapsed_)
616                 return;
617         status(bv, Open);
618 }
619
620
621 void InsetERT::close(BufferView * bv) const
622 {
623         if (collapsed_)
624                 return;
625         status(bv, Collapsed);
626 }
627
628
629 string const InsetERT::selectNextWordToSpellcheck(BufferView * bv,float &) const
630 {
631         bv->unlockInset(const_cast<InsetERT *>(this));
632         return string();
633 }