]> git.lyx.org Git - lyx.git/blob - src/insets/insettext.C
Changes to make text-inset work better (f.ex. cursor), and now we have
[lyx.git] / src / insets / insettext.C
1 // -*- C++ -*-
2 /* This file is part of
3  * ======================================================
4  * 
5  *           LyX, The Document Processor
6  *
7  *           Copyright 1998-2000 The LyX Team.
8  *
9  * ======================================================
10  */
11
12 #include <config.h>
13
14 #include <fstream>
15 #include <algorithm>
16
17 #include <cstdlib>
18
19 #ifdef __GNUG__
20 #pragma implementation
21 #endif
22
23 #include "insettext.h"
24 #include "lyxparagraph.h"
25 #include "lyxlex.h"
26 #include "debug.h"
27 #include "lyxfont.h"
28 #include "commandtags.h"
29 #include "buffer.h"
30 #include "LyXView.h"
31 #include "BufferView.h"
32 #include "layout.h"
33 #include "LaTeXFeatures.h"
34 #include "Painter.h"
35 #include "lyx_gui_misc.h"
36 #include "lyxtext.h"
37 #include "lyxcursor.h"
38 #include "CutAndPaste.h"
39 #include "font.h"
40 #include "minibuffer.h"
41 #include "toolbar.h"
42 #include "LColor.h"
43 #include "support/textutils.h"
44 #include "support/LAssert.h"
45 #include "lyxrow.h"
46 #include "lyxrc.h"
47 #include "intl.h"
48 #include "trans_mgr.h"
49
50 using std::ostream;
51 using std::ifstream;
52 using std::endl;
53 using std::min;
54 using std::max;
55
56 extern unsigned char getCurrentTextClass(Buffer *);
57 #warning BAAAAAAAADDDDDDD current_view (but Lars wanted it :) !!!
58 extern BufferView * current_view;
59
60
61 InsetText::InsetText()
62 {
63     par = new LyXParagraph();
64     init();
65     text = new LyXText(this);
66 }
67
68
69 InsetText::InsetText(InsetText const & ins) : UpdatableInset()
70 {
71     par = 0;
72     init(&ins);
73     text = new LyXText(this);
74     autoBreakRows = ins.autoBreakRows;
75 }
76
77
78 InsetText & InsetText::operator=(InsetText const & it)
79 {
80     init(&it);
81     text = new LyXText(this);
82     autoBreakRows = it.autoBreakRows;
83     return * this;
84 }
85
86 void InsetText::init(InsetText const * ins)
87 {
88     the_locking_inset = 0;
89     cursor_visible = false;
90     cursor.x_fix(-1);
91     interline_space = 1;
92     no_selection = false;
93     init_inset = true;
94     maxAscent = maxDescent = insetWidth = 0;
95     drawTextXOffset = drawTextYOffset = 0;
96     autoBreakRows = drawLockedFrame = false;
97     xpos = 0.0;
98     if (ins) {
99         SetParagraphData(ins->par);
100         autoBreakRows = ins->autoBreakRows;
101         drawLockedFrame = ins->drawLockedFrame;
102     }
103     par->SetInsetOwner(this);
104     cursor.par(par);
105     cursor.pos(0);
106     selection_start_cursor = selection_end_cursor = cursor;
107     frame_color = LColor::insetframe;
108     locked = false;
109     old_par = 0;
110 }
111
112
113 InsetText::~InsetText()
114 {
115     delete par;
116 }
117
118
119 Inset * InsetText::Clone() const
120 {
121     InsetText * t = new InsetText(*this);
122     return t;
123 }
124
125
126 void InsetText::Write(Buffer const * buf, ostream & os) const
127 {
128     os << "Text\n";
129     WriteParagraphData(buf, os);
130 }
131
132
133 void InsetText::WriteParagraphData(Buffer const * buf, ostream & os) const
134 {
135     par->writeFile(buf, os, buf->params, 0, 0);
136 }
137
138
139 void InsetText::Read(Buffer const * buf, LyXLex & lex)
140 {
141     string token, tmptok;
142     int pos = 0;
143     LyXParagraph * return_par = 0;
144     char depth = 0; // signed or unsigned?
145     LyXParagraph::footnote_flag footnoteflag = LyXParagraph::NO_FOOTNOTE;
146     LyXParagraph::footnote_kind footnotekind = LyXParagraph::FOOTNOTE;
147     LyXFont font(LyXFont::ALL_INHERIT);
148
149     delete par;
150     par = new LyXParagraph;
151     par->SetInsetOwner(this);
152     
153     while (lex.IsOK()) {
154         lex.nextToken();
155         token = lex.GetString();
156         if (token.empty())
157             continue;
158         if (token == "\\end_inset")
159             break;
160         if (const_cast<Buffer*>(buf)->parseSingleLyXformat2Token(lex, par, return_par,
161                                             token, pos, depth,
162                                             font, footnoteflag,
163                                             footnotekind)) {
164             // the_end read this should NEVER happen
165             lex.printError("\\the_end read in inset! Error in document!");
166             return;
167         }
168     }
169     if (!return_par)
170             return_par = par;
171     par = return_par;
172     if (token != "\\end_inset") {
173         lex.printError("Missing \\end_inset at this point. "
174                        "Read: `$$Token'");
175     }
176     init_inset = true;
177 }
178
179
180 int InsetText::ascent(Painter &, LyXFont const &) const
181 {
182     long int y_temp = 0;
183     Row * row = text->GetRowNearY(y_temp);
184     return row->ascent_of_text() + 2;
185 }
186
187
188 int InsetText::descent(Painter &, LyXFont const &) const
189 {
190     long int y = 0;
191     Row * row = text->GetRowNearY(y);
192     return text->height - row->ascent_of_text() + 2;
193 }
194
195
196 int InsetText::width(Painter & pain, LyXFont const &) const
197 {
198     return std::max(static_cast<long int>(getMaxTextWidth(pain, this)),
199                     text->width);
200 }
201
202
203 void InsetText::draw(Painter & pain, LyXFont const & f,
204                      int baseline, float & x) const
205 {
206     xpos = x;
207     UpdatableInset::draw(pain, f, baseline, x);
208  
209 #if 0   
210     if (init_inset) {
211         text->init(current_view);
212         computeTextRows(pain);
213         init_inset = false;
214     }
215 #endif
216     if ((baseline != top_baseline) || (top_x != int(x))) {
217         top_baseline = baseline;
218         top_x = int(x);
219         computeBaselines(baseline);
220     }
221     if (the_locking_inset && (text->cursor.pos() == inset_pos)) {
222         resetPos(pain);
223         inset_x = cx() - top_x + drawTextXOffset;
224         inset_y = cy() + drawTextYOffset;
225     }
226     if (drawLockedFrame && locked) {
227         pain.rectangle(int(x), baseline - ascent(pain, f), width(pain, f),
228                        ascent(pain,f) + descent(pain, f), frame_color);
229     }
230     x += TEXT_TO_INSET_OFFSET; // place for border
231 #if 1
232     long int y = 0;
233     Row * row = text->GetRowNearY(y);
234     y += baseline - row->ascent_of_text() + 1;
235     while (row != 0) {
236         text->GetVisibleRow(current_view, y, x, row, y);
237         y += row->height();
238         row = row->next();
239     }
240 #else
241     for(RowList::size_type r = 0; r < rows.size() - 1; ++r) {
242         drawRowSelection(pain, rows[r].pos, rows[r + 1].pos, r, 
243                          rows[r].baseline, x);
244         drawRowText(pain, rows[r].pos, rows[r + 1].pos, rows[r].baseline, x);
245     }
246 #endif
247     x += insetWidth - TEXT_TO_INSET_OFFSET;
248 }
249
250
251 void InsetText::update(BufferView * bv, LyXFont const &) const
252 {
253     if (init_inset) {
254         text->init(bv);
255         init_inset = false;
256 #if 0
257         // Dump all rowinformation:
258         long y_dummy = 0;
259         Row * tmprow = text->GetRowNearY(y_dummy);
260         lyxerr << "Width = " << text->width << endl;
261         lyxerr << "Baseline Paragraph Pos Height Ascent Fill\n";
262         while (tmprow) {
263                 lyxerr << tmprow->baseline() << '\t'
264                        << tmprow->par() << '\t'
265                        << tmprow->pos() << '\t'
266                        << tmprow->height() << '\t'
267                        << tmprow->ascent_of_text() << '\t'
268                        << tmprow->fill() << '\n';
269                 tmprow = tmprow->next();
270         }
271         lyxerr.flush();
272 #endif
273     }
274 }
275
276
277 void InsetText::drawRowSelection(Painter & pain, int startpos, int endpos,
278                                  int row, int baseline, float x) const
279 {
280     if (!hasSelection())
281         return;
282
283     int s_start, s_end;
284     if (selection_start_cursor.pos() > selection_end_cursor.pos()) {
285         s_start = selection_end_cursor.pos();
286         s_end = selection_start_cursor.pos();
287     } else {
288         s_start = selection_start_cursor.pos();
289         s_end = selection_end_cursor.pos();
290     }
291     if ((s_start > endpos) || (s_end < startpos))
292         return;
293     
294     int esel_x;
295     int ssel_x = esel_x = int(x);
296     LyXFont font;
297     int p = startpos;
298     for(; p < endpos; ++p) {
299         if (p == s_start)
300             ssel_x = int(x);
301         if ((p >= s_start) && (p <= s_end))
302             esel_x = int(x);
303         char ch = par->GetChar(p);
304         font = GetDrawFont(current_view->buffer(), par, p);
305         if (IsFloatChar(ch)) {
306             // skip for now
307         } else if (ch == LyXParagraph::META_INSET) {
308             Inset const * tmpinset = par->GetInset(p);
309             x += tmpinset->width(pain, font);
310         } else {
311             x += lyxfont::width(ch, font);
312         }
313     }
314     if (p == s_start)
315         ssel_x = int(x);
316     if ((p >= s_start) && (p <= s_end))
317         esel_x = int(x);
318     if (ssel_x < esel_x) {
319         pain.fillRectangle(int(ssel_x), baseline-rows[row].asc,
320                            int(esel_x - ssel_x),
321                            rows[row].asc + rows[row].desc,
322                            LColor::selection);
323     }
324 }
325
326
327 void InsetText::drawRowText(Painter & pain, int startpos, int endpos,
328                             int baseline, float x) const
329 {
330     Assert(endpos <= par->Last());
331
332     for(int p = startpos; p < endpos; ++p) {
333         char ch = par->GetChar(p);
334         LyXFont font = GetDrawFont(current_view->buffer(), par, p);
335         if (IsFloatChar(ch)) {
336             // skip for now
337         } else if (par->IsNewline(p)) {
338                 // Draw end-of-line marker
339                 int wid = lyxfont::width('n', font);
340                 int asc = lyxfont::maxAscent(font);
341                 int y = baseline;
342                 int xp[3], yp[3];
343                 
344                 xp[0] = int(x + wid * 0.375);
345                 yp[0] = int(y - 0.875 * asc * 0.75);
346                 
347                 xp[1] = int(x);
348                 yp[1] = int(y - 0.500 * asc * 0.75);
349                 
350                 xp[2] = int(x + wid * 0.375);
351                 yp[2] = int(y - 0.125 * asc * 0.75);
352                 
353                 pain.lines(xp, yp, 3, LColor::eolmarker);
354                 
355                 xp[0] = int(x);
356                 yp[0] = int(y - 0.500 * asc * 0.75);
357                 
358                 xp[1] = int(x + wid);
359                 yp[1] = int(y - 0.500 * asc * 0.75);
360                 
361                 xp[2] = int(x + wid);
362                 yp[2] = int(y - asc * 0.75);
363                         
364                 pain.lines(xp, yp, 3, LColor::eolmarker);
365                 x += wid;
366         } else if (ch == LyXParagraph::META_INSET) {
367             Inset * tmpinset = par->GetInset(p);
368             if (tmpinset) 
369                 tmpinset->draw(pain, font, baseline, x);
370         } else {
371             pain.text(int(x), baseline, ch, font);
372             x += lyxfont::width(ch, font);
373         }
374     }
375 }
376
377
378 char const * InsetText::EditMessage() const
379 {
380     return _("Opened Text Inset");
381 }
382
383
384 void InsetText::Edit(BufferView * bv, int x, int y, unsigned int button)
385 {
386     par->SetInsetOwner(this);
387     UpdatableInset::Edit(bv, x, y, button);
388
389     if (!bv->lockInset(this)) {
390         lyxerr[Debug::INSETS] << "Cannot lock inset" << endl;
391         return;
392     }
393     locked = true;
394     the_locking_inset = 0;
395     inset_pos = inset_x = inset_y = 0;
396     setPos(bv->painter(), x, y);
397     checkAndActivateInset(bv, x, y, button);
398     selection_start_cursor = selection_end_cursor = cursor;
399     text->sel_cursor = text->cursor;
400     bv->text->FinishUndo();
401     UpdateLocal(bv, true, false);
402 }
403
404
405 void InsetText::InsetUnlock(BufferView * bv)
406 {
407     if (the_locking_inset) {
408         the_locking_inset->InsetUnlock(bv);
409         the_locking_inset = 0;
410     }
411     HideInsetCursor(bv);
412     lyxerr[Debug::INSETS] << "InsetText::InsetUnlock(" << this <<
413             ")" << endl;
414     selection_start_cursor = selection_end_cursor = cursor;
415     no_selection = false;
416     locked = false;
417     UpdateLocal(bv, true, false);
418 }
419
420
421 bool InsetText::LockInsetInInset(BufferView * bv, UpdatableInset * inset)
422 {
423     lyxerr[Debug::INSETS] << "InsetText::LockInsetInInset(" << inset << "): ";
424     if (!inset)
425         return false;
426     if (inset == par->GetInset(text->cursor.pos())) {
427         lyxerr[Debug::INSETS] << "OK" << endl;
428         the_locking_inset = inset;
429         resetPos(bv->painter());
430         inset_x = cx() - top_x + drawTextXOffset;
431         inset_y = cy() + drawTextYOffset;
432         inset_pos = text->cursor.pos();
433         return true;
434     } else if (the_locking_inset && (the_locking_inset == inset)) {
435         if (text->cursor.pos() == inset_pos) {
436             lyxerr[Debug::INSETS] << "OK" << endl;
437             resetPos(bv->painter());
438             inset_x = cx() - top_x + drawTextXOffset;
439             inset_y = cy() + drawTextYOffset;
440         } else {
441             lyxerr[Debug::INSETS] << "cursor.pos != inset_pos" << endl;
442         }
443     } else if (the_locking_inset) {
444         lyxerr[Debug::INSETS] << "MAYBE" << endl;
445         return the_locking_inset->LockInsetInInset(bv, inset);
446     }
447     lyxerr[Debug::INSETS] << "NOT OK" << endl;
448     return false;
449 }
450
451
452 bool InsetText::UnlockInsetInInset(BufferView * bv, UpdatableInset * inset,
453                                    bool lr)
454 {
455     if (!the_locking_inset)
456         return false;
457     if (the_locking_inset == inset) {
458         the_locking_inset->InsetUnlock(bv);
459         the_locking_inset = 0;
460         if (lr)
461             moveRight(bv, false);
462         return true;
463     }
464     return the_locking_inset->UnlockInsetInInset(bv, inset, lr);
465 }
466
467
468 bool InsetText::UpdateInsetInInset(BufferView * bv, Inset * inset)
469 {
470     if (!the_locking_inset)
471         return false;
472     if (the_locking_inset != inset)
473         return the_locking_inset->UpdateInsetInInset(bv, inset);
474     lyxerr[Debug::INSETS] << "InsetText::UpdateInsetInInset(" << inset <<
475             ")" << endl;
476     UpdateLocal(bv, true, false);
477     if (text->cursor.pos() == inset_pos) {
478         inset_x = cx() - top_x + drawTextXOffset;
479         inset_y = cy() + drawTextYOffset;
480     }
481     return true;
482 }
483
484
485 void InsetText::InsetButtonPress(BufferView * bv, int x, int y, int button)
486 {
487     if (hasSelection()) {
488         selection_start_cursor = selection_end_cursor = cursor;
489         UpdateLocal(bv, false, false);
490     }
491     no_selection = false;
492     setPos(bv->painter(), x, y);
493     cursor.x_fix(-1);
494     if (the_locking_inset) {
495         UpdatableInset * inset = 0;
496         if (par->GetChar(cursor.pos()) == LyXParagraph::META_INSET)
497             inset = static_cast<UpdatableInset*>(par->GetInset(cursor.pos()));
498         if (the_locking_inset == inset) {
499             the_locking_inset->InsetButtonPress(bv,x-inset_x,y-inset_y,button);
500             return;
501         } else if (inset) {
502             // otherwise unlock the_locking_inset and lock the new inset
503             the_locking_inset->InsetUnlock(bv);
504             inset_x = cursor.x() - top_x + drawTextXOffset;
505             inset_y = cursor.y() + drawTextYOffset;
506             inset->InsetButtonPress(bv, x - inset_x, y - inset_y, button);
507             inset->Edit(bv, x - inset_x, y - inset_y, button);
508             UpdateLocal(bv, true, false);
509             return;
510         }
511         // otherwise only unlock the_locking_inset
512         the_locking_inset->InsetUnlock(bv);
513         the_locking_inset = 0;
514     }
515     if (bv->the_locking_inset) {
516         if ((par->GetChar(cursor.pos()) == LyXParagraph::META_INSET) &&
517             par->GetInset(cursor.pos()) &&
518             (par->GetInset(cursor.pos())->Editable() == Inset::HIGHLY_EDITABLE)) {
519             UpdatableInset * inset =
520                 static_cast<UpdatableInset*>(par->GetInset(cursor.pos()));
521             inset_x = cursor.x() - top_x + drawTextXOffset;
522             inset_y = cursor.y() + drawTextYOffset;
523             inset->InsetButtonPress(bv, x - inset_x, y - inset_y, button);
524             inset->Edit(bv, x - inset_x, y - inset_y, 0);
525             UpdateLocal(bv, true, false);
526         }
527     }
528     selection_start_cursor = selection_end_cursor = cursor;
529 }
530
531
532 void InsetText::InsetButtonRelease(BufferView * bv, int x, int y, int button)
533 {
534     UpdatableInset * inset = 0;
535
536     if (the_locking_inset) {
537             the_locking_inset->InsetButtonRelease(bv, x-inset_x, y-inset_y,button);
538     } else {
539         if (par->GetChar(cursor.pos()) == LyXParagraph::META_INSET) {
540             inset = static_cast<UpdatableInset*>(par->GetInset(cursor.pos()));
541             if (inset->Editable() == Inset::HIGHLY_EDITABLE) {
542                 inset->InsetButtonRelease(bv, x - inset_x, y - inset_y,button);
543             } else {
544                 inset_x = cursor.x() - top_x + drawTextXOffset;
545                 inset_y = cursor.y() + drawTextYOffset;
546                 inset->InsetButtonRelease(bv, x - inset_x, y - inset_y,button);
547                 inset->Edit(bv, x - inset_x, y - inset_y, button);
548             }
549         }
550     }
551     no_selection = false;
552 }
553
554
555 void InsetText::InsetMotionNotify(BufferView * bv, int x, int y, int state)
556 {
557     if (the_locking_inset) {
558         the_locking_inset->InsetMotionNotify(bv, x - inset_x,
559                                              y - inset_y,state);
560         return;
561     }
562     if (!no_selection) {
563         LyXCursor old = selection_end_cursor;
564         HideInsetCursor(bv);
565         setPos(bv->painter(), x, y);
566         selection_end_cursor = cursor;
567         if (old != selection_end_cursor)
568             UpdateLocal(bv, false, false);
569         ShowInsetCursor(bv);
570     }
571     no_selection = false;
572 }
573
574
575 void InsetText::InsetKeyPress(XKeyEvent * xke)
576 {
577     if (the_locking_inset) {
578         the_locking_inset->InsetKeyPress(xke);
579         return;
580     }
581 }
582
583
584 UpdatableInset::RESULT
585 InsetText::LocalDispatch(BufferView * bv,
586                          int action, string const & arg)
587 {
588     no_selection = false;
589     UpdatableInset::RESULT
590         result= UpdatableInset::LocalDispatch(bv, action, arg);
591     if (result != UNDISPATCHED) {
592         resetPos(bv->painter());
593         return DISPATCHED;
594     }
595
596     result=DISPATCHED;
597     if ((action < 0) && arg.empty())
598         return FINISHED;
599
600     if ((action != LFUN_DOWN) && (action != LFUN_UP) &&
601         (action != LFUN_DOWNSEL) && (action != LFUN_UPSEL))
602         cursor.x_fix(-1);
603     if (the_locking_inset) {
604         result = the_locking_inset->LocalDispatch(bv, action, arg);
605         if (result == DISPATCHED_NOUPDATE)
606             return result;
607         else if (result == DISPATCHED) {
608             the_locking_inset->ToggleInsetCursor(bv);
609             UpdateLocal(bv, false, false);
610             the_locking_inset->ToggleInsetCursor(bv);
611             return result;
612         } else if (result == FINISHED) {
613             switch(action) {
614             case -1:
615             case LFUN_RIGHT:
616                 cursor.pos(inset_pos + 1);
617                 resetPos(bv->painter());
618                 break;
619             case LFUN_DOWN:
620                 moveDown(bv);
621                 break;
622             }
623             the_locking_inset = 0;
624             return DISPATCHED;
625         }
626     }
627     HideInsetCursor(bv);
628     switch (action) {
629         // Normal chars
630     case -1:
631         if (bv->buffer()->isReadonly()) {
632             LyXBell();
633 //          setErrorMessage(N_("Document is read only"));
634             break;
635         }
636         if (!arg.empty()) {
637             /* Automatically delete the currently selected
638              * text and replace it with what is being
639              * typed in now. Depends on lyxrc settings
640              * "auto_region_delete", which defaults to
641              * true (on). */
642
643             bv->text->SetUndo(bv->buffer(), Undo::INSERT, 
644                               bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
645                               bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next);
646             if (lyxrc.auto_region_delete) {
647                 if (text->selection){
648                     text->CutSelection(bv, false);
649                 }
650             }
651             text->ClearSelection();
652             for (string::size_type i = 0; i < arg.length(); ++i) {
653                 bv->owner()->getIntl()->getTrans()->TranslateAndInsert(arg[i], text);
654             }
655         }
656         UpdateLocal(bv, true, true);
657         break;
658         // --- Cursor Movements ---------------------------------------------
659     case LFUN_RIGHTSEL:
660         bv->text->FinishUndo();
661         moveRight(bv, false);
662         text->SetSelection();
663         UpdateLocal(bv, false, false);
664         break;
665     case LFUN_RIGHT:
666         bv->text->FinishUndo();
667         result = moveRight(bv);
668         text->sel_cursor = text->cursor;
669         UpdateLocal(bv, false, false);
670         break;
671     case LFUN_LEFTSEL:
672         bv->text->FinishUndo();
673         moveLeft(bv, false);
674         text->SetSelection();
675         UpdateLocal(bv, false, false);
676         break;
677     case LFUN_LEFT:
678         bv->text->FinishUndo();
679         result= moveLeft(bv);
680         text->sel_cursor = text->cursor;
681         UpdateLocal(bv, false, false);
682         break;
683     case LFUN_DOWNSEL:
684         bv->text->FinishUndo();
685         moveDown(bv);
686         selection_end_cursor = cursor;
687         UpdateLocal(bv, false, false);
688         break;
689     case LFUN_DOWN:
690         bv->text->FinishUndo();
691         result = moveDown(bv);
692         text->sel_cursor = text->cursor;
693         UpdateLocal(bv, false, false);
694         break;
695     case LFUN_UPSEL:
696         bv->text->FinishUndo();
697         moveUp(bv);
698         selection_end_cursor = cursor;
699         UpdateLocal(bv, false, false);
700         break;
701     case LFUN_UP:
702         bv->text->FinishUndo();
703         result = moveUp(bv);
704         text->sel_cursor = text->cursor;
705         UpdateLocal(bv, false, false);
706         break;
707     case LFUN_HOME:
708         bv->text->FinishUndo();
709         text->CursorHome(bv);
710         text->sel_cursor = text->cursor;
711         UpdateLocal(bv, false, false);
712         break;
713     case LFUN_END:
714         text->CursorEnd(bv);
715         text->sel_cursor = text->cursor;
716         UpdateLocal(bv, false, false);
717         break;
718     case LFUN_BACKSPACE:
719         bv->text->SetUndo(bv->buffer(), Undo::DELETE, 
720           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
721           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next);
722         text->Backspace(bv);
723         UpdateLocal(bv, true, true);
724         break;
725     case LFUN_DELETE:
726         bv->text->SetUndo(bv->buffer(), Undo::DELETE, 
727           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
728           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next);
729         text->Delete(bv);
730         UpdateLocal(bv, true, true);
731         break;
732     case LFUN_CUT:
733         bv->text->SetUndo(bv->buffer(), Undo::DELETE, 
734           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
735           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next);
736         text->CutSelection(bv);
737         UpdateLocal(bv, true, true);
738         break;
739     case LFUN_COPY:
740         bv->text->FinishUndo();
741         text->CopySelection(bv);
742         UpdateLocal(bv, true, false);
743         break;
744     case LFUN_PASTE:
745         bv->text->SetUndo(bv->buffer(), Undo::INSERT, 
746           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
747           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next);
748         text->PasteSelection(bv);
749         UpdateLocal(bv, true, true);
750         break;
751     case LFUN_BREAKPARAGRAPH:
752         if (!autoBreakRows)
753             return DISPATCHED;
754         text->BreakParagraph(bv, 0);
755         UpdateLocal(bv, true, true);
756         break;
757     case LFUN_BREAKLINE:
758         if (!autoBreakRows)
759             return DISPATCHED;
760         bv->text->SetUndo(bv->buffer(), Undo::INSERT, 
761             bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
762             bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next);
763         text->InsertChar(bv, LyXParagraph::META_NEWLINE);
764         UpdateLocal(bv, true, true);
765         break;
766     case LFUN_LAYOUT:
767     {
768       static LyXTextClass::size_type cur_layout = par->layout;
769       
770         // Derive layout number from given argument (string)
771         // and current buffer's textclass (number). */    
772         LyXTextClassList::ClassList::size_type tclass =
773             bv->buffer()->params.textclass;
774         std::pair <bool, LyXTextClass::size_type> layout = 
775             textclasslist.NumberOfLayout(tclass, arg);
776
777         // If the entry is obsolete, use the new one instead.
778         if (layout.first) {
779             string obs = textclasslist.Style(tclass,layout.second).
780                 obsoleted_by();
781             if (!obs.empty()) 
782                 layout = textclasslist.NumberOfLayout(tclass, obs);
783         }
784
785         // see if we found the layout number:
786         if (!layout.first) {
787             string msg = string(N_("Layout ")) + arg + N_(" not known");
788
789             bv->owner()->getMiniBuffer()->Set(msg);
790             break;
791         }
792
793         if (cur_layout != layout.second) {
794             cur_layout = layout.second;
795             text->SetLayout(bv, layout.second);
796             bv->owner()->getToolbar()->combox->select(cursor.par()->GetLayout()+1);
797             UpdateLocal(bv, true, true);
798         }
799     }
800     break;
801     default:
802         result = UNDISPATCHED;
803         break;
804     }
805     if (result != FINISHED) {
806         ShowInsetCursor(bv);
807     } else
808         bv->unlockInset(this);
809     return result;
810 }
811
812
813 int InsetText::Latex(Buffer const * buf, ostream & os, bool, bool) const
814 {
815     TexRow texrow;
816     buf->latexParagraphs(os, par, 0, texrow);
817     return texrow.rows();
818 }
819
820
821 void InsetText::Validate(LaTeXFeatures & features) const
822 {
823     par->validate(features);
824 }
825
826
827 // Returns the width of a character at a certain spot
828 int InsetText::SingleWidth(Painter & pain, LyXParagraph * p, int pos) const
829 {
830     LyXFont font = GetDrawFont(current_view->buffer(), p, pos);
831     char c = p->GetChar(pos);
832
833     if (IsPrintable(c)) {
834         return lyxfont::width(c, font);
835     } else if (c == LyXParagraph::META_INSET) {
836         Inset const * tmpinset = p->GetInset(pos);
837         if (tmpinset)
838             return tmpinset->width(pain, font);
839         else
840             return 0;
841     } else if (IsSeparatorChar(c))
842         c = ' ';
843     else if (IsNewlineChar(c))
844         c = 'n';
845     return lyxfont::width(c, font);
846 }
847
848
849 // Returns the width of a character at a certain spot
850 void InsetText::SingleHeight(Painter & pain, LyXParagraph * p,int pos,
851                              int & asc, int & desc) const
852 {
853     LyXFont font = GetDrawFont(current_view->buffer(), p, pos);
854     char c = p->GetChar(pos);
855
856     asc = desc = 0;
857     if (c == LyXParagraph::META_INSET) {
858         Inset const * tmpinset=p->GetInset(pos);
859         if (tmpinset) {
860             asc = tmpinset->ascent(pain, font);
861             desc = tmpinset->descent(pain, font);
862         }
863     } else {
864         asc = lyxfont::maxAscent(font);
865         desc = lyxfont::maxDescent(font);
866     }
867     return;
868 }
869
870
871 // Gets the fully instantiated font at a given position in a paragraph
872 // Basically the same routine as LyXParagraph::getFont() in paragraph.C.
873 // The difference is that this one is used for displaying, and thus we
874 // are allowed to make cosmetic improvements. For instance make footnotes
875 // smaller. (Asger)
876 // If position is -1, we get the layout font of the paragraph.
877 // If position is -2, we get the font of the manual label of the paragraph.
878 LyXFont InsetText::GetFont(Buffer const * buf, LyXParagraph * p, int pos) const
879 {
880     char par_depth = p->GetDepth();
881
882     LyXLayout const & layout =
883             textclasslist.Style(buf->params.textclass, p->GetLayout());
884
885     // We specialize the 95% common case:
886     if (p->footnoteflag == LyXParagraph::NO_FOOTNOTE && !par_depth) {
887         if (pos >= 0) {
888             // 95% goes here
889             if (layout.labeltype == LABEL_MANUAL
890                 && pos < BeginningOfMainBody(buf, p)) {
891                 // 1% goes here
892                 return p->GetFontSettings(buf->params,
893                                           pos).realize(layout.reslabelfont);
894             } else
895                 return p->GetFontSettings(buf->params,
896                                           pos).realize(layout.resfont);
897         } else {
898             // 5% goes here.
899             // process layoutfont for pos == -1 and labelfont for pos < -1
900             if (pos == -1)
901                 return layout.resfont;
902             else
903                 return layout.reslabelfont;
904         }
905     }
906     // The uncommon case need not be optimized as much
907
908     LyXFont layoutfont, tmpfont;
909
910     if (pos >= 0){
911         // 95% goes here
912         if (pos < BeginningOfMainBody(buf, p)) {
913             // 1% goes here
914             layoutfont = layout.labelfont;
915         } else {
916             // 99% goes here
917             layoutfont = layout.font;
918         }
919         tmpfont = p->GetFontSettings(buf->params, pos);
920         tmpfont.realize(layoutfont);
921     } else{
922         // 5% goes here.
923         // process layoutfont for pos == -1 and labelfont for pos < -1
924         if (pos == -1)
925             tmpfont = layout.font;
926         else
927             tmpfont = layout.labelfont;
928     }
929     
930     // Resolve against environment font information
931     //if (par->GetDepth()){ // already in while condition
932     while (p && par_depth && !tmpfont.resolved()) {
933         p = p->DepthHook(par_depth - 1);
934         if (p) {
935             tmpfont.realize(textclasslist.Style(buf->params.textclass,
936                                                 p->GetLayout()).font);
937             par_depth = p->GetDepth();
938         }
939     }
940     tmpfont.realize((textclasslist.TextClass(buf->params.textclass).
941                     defaultfont()));
942     return tmpfont;
943 }
944
945
946 // the font for drawing may be different from the real font
947 LyXFont InsetText::GetDrawFont(Buffer const * buf, LyXParagraph * p, int pos) const
948 {
949     return text->GetFont(buf, p, pos);
950 }
951
952
953 int InsetText::BeginningOfMainBody(Buffer const * buf, LyXParagraph * p) const
954 {
955     if (textclasslist.Style(buf->params.textclass,
956                             p->GetLayout()).labeltype != LABEL_MANUAL)
957         return 0;
958     else
959         return p->BeginningOfMainBody();
960 }
961
962
963 void InsetText::GetCursorPos(int & x, int & y) const
964 {
965     x = cursor.x();
966     y = cursor.y();
967 }
968
969
970 int InsetText::InsetInInsetY()
971 {
972     if (!the_locking_inset)
973         return 0;
974
975     return (inset_y + the_locking_inset->InsetInInsetY());
976 }
977
978
979 void InsetText::ToggleInsetCursor(BufferView * bv)
980 {
981     if (the_locking_inset) {
982         the_locking_inset->ToggleInsetCursor(bv);
983         return;
984     }
985
986     LyXFont font = GetDrawFont(bv->buffer(), cpar(), cpos());
987
988     int asc = lyxfont::maxAscent(font);
989     int desc = lyxfont::maxDescent(font);
990   
991     if (cursor_visible)
992         bv->hideLockedInsetCursor();
993     else
994         bv->showLockedInsetCursor(cx(), cy(),
995                                   asc, desc);
996     cursor_visible = !cursor_visible;
997 }
998
999
1000 void InsetText::ShowInsetCursor(BufferView * bv)
1001 {
1002     if (the_locking_inset) {
1003         the_locking_inset->ShowInsetCursor(bv);
1004         return;
1005     }
1006     if (!cursor_visible) {
1007         LyXFont font = GetDrawFont(bv->buffer(), cpar(), cpos());
1008         
1009         int asc = lyxfont::maxAscent(font);
1010         int desc = lyxfont::maxDescent(font);
1011
1012         bv->fitLockedInsetCursor(cx(), cy(), asc, desc);
1013         bv->showLockedInsetCursor(cx(), cy(), asc, desc);
1014         cursor_visible = true;
1015     }
1016 }
1017
1018
1019 void InsetText::HideInsetCursor(BufferView * bv)
1020 {
1021     if (cursor_visible) {
1022         bv->hideLockedInsetCursor();
1023         cursor_visible = false;
1024     }
1025     if (the_locking_inset)
1026         the_locking_inset->HideInsetCursor(bv);
1027 }
1028
1029
1030 void InsetText::setPos(Painter & pain, int x, int y) const
1031 {
1032     x -= drawTextXOffset;
1033     y -= drawTextYOffset;
1034     // search right X-pos x==0 -> top_x
1035     cursor.pos(0);
1036     actrow = 0;
1037     cursor.y(top_baseline);
1038     y += cursor.y();
1039     for(unsigned int i = 1;
1040         (long(cursor.y() + rows[i - 1].desc) < y)
1041                 && (i < rows.size() - 1); ++i) {
1042         cursor.y(rows[i].baseline);
1043         cursor.pos(rows[i].pos);
1044         actrow = i;
1045     }
1046     cursor.y(cursor.y() - top_baseline);
1047     cursor.x(top_x + 2); // 2 = frame width
1048     x += cursor.x();
1049
1050     int swh;
1051     int sw = swh = SingleWidth(pain, par, cursor.pos());
1052     if (par->GetChar(cursor.pos()) != LyXParagraph::META_INSET)
1053         swh /= 2;
1054     int checkpos = rows[actrow + 1].pos;
1055     if ((actrow + 2) < (int)rows.size())
1056         --checkpos;
1057     while ((cursor.pos() < checkpos) && ((cursor.x() + swh) < x)) {
1058         cursor.x(cursor.x() + sw);
1059         cursor.pos(cursor.pos() + 1);
1060         sw = swh = SingleWidth(pain, par, cursor.pos());
1061         if (par->GetChar(cursor.pos())!=LyXParagraph::META_INSET)
1062             swh /= 2;
1063     }
1064 }
1065
1066
1067 void InsetText::resetPos(Painter & pain) const
1068 {
1069     cursor.par(par);
1070
1071     if (!rows.size())
1072         return;
1073
1074     int old_pos = cursor.pos();
1075
1076     cursor.y(top_baseline);
1077     actrow = 0;
1078     for(unsigned int i = 0;
1079         i < (rows.size() - 1) && rows[i].pos <= cursor.pos();
1080         ++i) {
1081         cursor.y(rows[i].baseline);
1082         actrow = i;
1083     }
1084     cursor.y(cursor.y() - top_baseline);
1085     setPos(pain, 0, cursor.y());
1086     cursor.x(top_x + 2); // 2 = frame width
1087     while(cursor.pos() < old_pos) {
1088         cursor.x(cursor.x() + SingleWidth(pain, par,cursor.pos()));
1089         cursor.pos(cursor.pos() + 1);
1090     }
1091 }
1092
1093
1094 UpdatableInset::RESULT
1095 InsetText::moveRight(BufferView * bv, bool activate_inset)
1096 {
1097     if (!cpar()->next && (cpos() >= cpar()->Last()))
1098         return FINISHED;
1099     if (activate_inset && checkAndActivateInset(bv)) {
1100         return DISPATCHED;
1101     }
1102     text->CursorRight(bv);
1103 //    real_current_font = current_font = GetFont(bv->buffer(), cpar(), cpos());
1104     return DISPATCHED_NOUPDATE;
1105 }
1106
1107
1108 UpdatableInset::RESULT
1109 InsetText::moveLeft(BufferView * bv, bool activate_inset)
1110 {
1111     if (!cpar()->previous && (cpos() <= 0))
1112         return FINISHED;
1113     text->CursorLeft(bv);
1114     if (activate_inset)
1115         if (checkAndActivateInset(bv, -1, -1))
1116             return DISPATCHED;
1117     return DISPATCHED_NOUPDATE;
1118 }
1119
1120
1121 UpdatableInset::RESULT
1122 InsetText::moveUp(BufferView * bv)
1123 {
1124     if (!crow()->previous())
1125         return FINISHED;
1126     text->CursorUp(bv);
1127     return DISPATCHED_NOUPDATE;
1128 }
1129
1130
1131 UpdatableInset::RESULT
1132 InsetText::moveDown(BufferView * bv)
1133 {
1134     if (!crow()->next())
1135         return FINISHED;
1136     text->CursorDown(bv);
1137     return DISPATCHED_NOUPDATE;
1138 }
1139
1140
1141 bool InsetText::Delete()
1142 {
1143     if ((par->GetChar(cursor.pos())==LyXParagraph::META_INSET) &&
1144         !par->GetInset(cursor.pos())->Deletable()) {
1145         return false;
1146     }
1147     par->Erase(cursor.pos());
1148     return true;
1149 }
1150
1151
1152 bool InsetText::InsertInset(BufferView * bv, Inset * inset)
1153 {
1154     if (the_locking_inset) {
1155         if (the_locking_inset->InsertInsetAllowed(inset))
1156             return the_locking_inset->InsertInset(bv, inset);
1157         return false;
1158     }
1159     bv->text->SetUndo(bv->buffer(), Undo::INSERT, 
1160               bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
1161               bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next);
1162     if (inset->Editable() == Inset::IS_EDITABLE) {
1163         UpdatableInset * i = static_cast<UpdatableInset *>(inset);
1164         i->setOwner(static_cast<UpdatableInset *>(this));
1165     }
1166     par->InsertChar(cursor.pos(), LyXParagraph::META_INSET);
1167     par->InsertInset(cursor.pos(), inset);
1168     if (hasSelection()) {
1169         selection_start_cursor = selection_end_cursor = cursor;
1170     } else {
1171         selection_start_cursor = selection_end_cursor = cursor;
1172     }
1173     UpdateLocal(bv, true, true);
1174     static_cast<UpdatableInset*>(inset)->Edit(bv, 0, 0, 0);
1175     return true;
1176 }
1177
1178
1179 UpdatableInset * InsetText::GetLockingInset()
1180 {
1181     return the_locking_inset ? the_locking_inset->GetLockingInset() : this;
1182 }
1183
1184
1185 UpdatableInset * InsetText::GetFirstLockingInsetOfType(Inset::Code c)
1186 {
1187     if (c == LyxCode())
1188         return this;
1189     if (the_locking_inset)
1190         return the_locking_inset->GetFirstLockingInsetOfType(c);
1191     return 0;
1192 }
1193
1194
1195 void InsetText::SetFont(BufferView * bv, LyXFont const & font, bool toggleall)
1196 {
1197     text->SetFont(bv, font, toggleall);
1198 }
1199
1200
1201 void InsetText::computeTextRows(Painter & pain) const
1202 {
1203     int p,
1204         nwp = 0,
1205         asc = 0,
1206         desc = 0,
1207         oasc = 0,
1208         odesc = 0,
1209         wordAscent,
1210         wordDescent;
1211     row_struct row;
1212
1213     if (rows.size())
1214             rows.clear();
1215     int width = wordAscent = wordDescent = 0;
1216     insetWidth = maxAscent = maxDescent = 0;
1217     row.asc      = 0;
1218     row.desc     = 0;
1219     row.pos      = 0;
1220     row.baseline = 0;
1221     rows.push_back(row);
1222     if (!autoBreakRows || (getMaxTextWidth(pain, this) < 0)) {
1223         for(p = 0; p < par->Last(); ++p) {
1224             insetWidth += SingleWidth(pain, par, p);
1225             SingleHeight(pain, par, p, asc, desc);
1226             maxAscent = max(maxAscent, asc);
1227             maxDescent = max(maxDescent, desc);
1228         }
1229         insetWidth += (2 * TEXT_TO_INSET_OFFSET);
1230         rows[0].asc = maxAscent;
1231         rows[0].desc = maxDescent;
1232         // alocate a dummy row for the endpos
1233         row.pos = par->Last();
1234         rows.push_back(row);
1235         return;
1236     }
1237
1238     bool is_first_word_in_row = true;
1239     int cw, lastWordWidth = 0;
1240     int maxWidth = getMaxTextWidth(pain, this);
1241     // if we auto break rows than the insetwidth should be always the max
1242     // width as the display is stable it may get larger if we have a really
1243     // large word below and we draw it!!!
1244     insetWidth = maxWidth;
1245
1246     for(p = 0; p < par->Last(); ++p) {
1247         if (par->IsNewline(p)) {
1248             rows.back().asc = wordAscent;
1249             rows.back().desc = wordDescent;
1250             row.pos = p+1;
1251             rows.push_back(row);
1252             nwp = p+1;
1253             width = lastWordWidth = 0;
1254             oasc = odesc = wordAscent = wordDescent = 0;
1255             is_first_word_in_row = true;
1256             continue;
1257         }
1258         cw = SingleWidth(pain, par, p);
1259         Inset * inset = 0;
1260         if (par->GetChar(p) == LyXParagraph::META_INSET)
1261             inset = par->GetInset(p);
1262         if (inset && inset->display()) {
1263             inset->setOwner(const_cast<InsetText *>(this));
1264             if (cw > insetWidth)
1265                 insetWidth = cw;
1266             if (!is_first_word_in_row || (p != nwp)) {
1267                 oasc = max(oasc, wordAscent);
1268                 odesc = max(odesc, wordDescent);
1269                 rows.back().asc = oasc;
1270                 rows.back().desc = odesc;
1271                 row.pos = p;
1272                 rows.push_back(row);
1273             }
1274             SingleHeight(pain, par, p, asc, desc);
1275             rows.back().asc = asc;
1276             rows.back().desc = desc;
1277             row.pos = nwp = p + 1;
1278             rows.push_back(row);
1279             width = lastWordWidth = 0;
1280             oasc = odesc = wordAscent = wordDescent = 0;
1281             is_first_word_in_row = true;
1282             continue;
1283         }
1284         SingleHeight(pain, par, p, asc, desc);
1285         width += cw;
1286         lastWordWidth += cw;
1287         if (width > maxWidth) {
1288             if (is_first_word_in_row) {
1289                 if (!(width-cw)) { // only this character in word
1290                     rows.back().asc = asc;
1291                     rows.back().desc = desc;
1292                     row.pos = p+1;
1293                     rows.push_back(row);
1294                     oasc = 0;
1295                     odesc = 0;
1296                     wordAscent = 0;
1297                     wordDescent = 0;
1298                     nwp = p + 1;
1299                     lastWordWidth = width = 0;
1300                 } else {
1301                     rows.back().asc = wordAscent;
1302                     rows.back().desc = wordDescent;
1303                     row.pos = p;
1304                     rows.push_back(row);
1305                     oasc = 0;
1306                     odesc = 0;
1307                     wordAscent = asc;
1308                     wordDescent = desc;
1309                     lastWordWidth = width = cw;
1310                     nwp = p;
1311                 }
1312             } else {
1313                 rows.back().asc = oasc;
1314                 rows.back().desc = odesc;
1315                 row.pos = nwp;
1316                 rows.push_back(row);
1317                 oasc = wordAscent;
1318                 odesc = wordDescent;
1319                 width = lastWordWidth;  
1320                 wordAscent = max(wordAscent, asc);
1321                 wordDescent = max(wordDescent, desc);
1322                 is_first_word_in_row = true;
1323             }
1324         } else {
1325             wordAscent = max(wordAscent, asc);
1326             wordDescent = max(wordDescent, desc);
1327         }
1328         if (par->IsSeparator(p) || inset) {
1329             if (inset) {
1330                 inset->setOwner(const_cast<InsetText *>(this));
1331                 if (cw > maxWidth)
1332                     insetWidth = cw;
1333             }
1334             oasc = max(oasc, wordAscent);
1335             odesc = max(odesc, wordDescent);
1336             wordAscent = wordDescent = lastWordWidth = 0;
1337             nwp = p + 1;
1338             is_first_word_in_row = false;
1339         }
1340     }
1341     // if we have some data in the paragraph we have ascent/descent
1342     if (p) {
1343         // assign last row data
1344         rows.back().asc = max(oasc, wordAscent);
1345         rows.back().desc = max(odesc, wordDescent);
1346     }
1347     insetWidth += (2 * TEXT_TO_INSET_OFFSET);
1348     // alocate a dummy row for the endpos
1349     row.pos = par->Last();
1350     rows.push_back(row);
1351     // calculate maxAscent/Descent
1352     maxAscent = rows[0].asc;
1353     maxDescent = rows[0].desc;
1354     for (RowList::size_type i = 1; i < rows.size() - 1; ++i) {
1355         maxDescent += rows[i].asc + rows[i].desc + interline_space;
1356     }
1357 }
1358
1359
1360 void InsetText::computeBaselines(int baseline) const
1361 {
1362     rows[0].baseline = baseline;
1363     for (unsigned int i = 1; i < rows.size() - 1; i++) {
1364         rows[i].baseline = rows[i - 1].baseline + rows[i - 1].desc + 
1365             rows[i].asc + interline_space;
1366     }
1367 }
1368
1369
1370 void InsetText::UpdateLocal(BufferView * bv, bool what, bool mark_dirty)
1371 {
1372     if (what) {
1373         text->FullRebreak(bv);
1374     }
1375     bv->updateInset(this, mark_dirty);
1376 //    if (flag)
1377 //      resetPos(bv->painter());
1378     if (old_par != cpar()) {
1379             bv->owner()->getToolbar()->combox->select(cpar()->GetLayout()+1);
1380             old_par = cpar();
1381     }
1382 }
1383
1384
1385 bool InsetText::cutSelection(Buffer const * buf)
1386 {
1387     if (!hasSelection())
1388         return false;
1389
1390     CutAndPaste cap;
1391
1392     LyXParagraph * endpar = par;
1393     int start, end;
1394     if (selection_start_cursor.pos() > selection_end_cursor.pos()) {
1395             start = selection_end_cursor.pos();
1396             end = selection_start_cursor.pos();
1397     } else {
1398             start = selection_start_cursor.pos();
1399             end = selection_end_cursor.pos();
1400     }
1401
1402     return cap.cutSelection(par, &endpar, start, end, buf->params.textclass);
1403 }
1404
1405
1406 bool InsetText::copySelection(Buffer const * buf)
1407 {
1408     if (!hasSelection())
1409         return false;
1410
1411     CutAndPaste cap;
1412
1413     int start, end;
1414     if (selection_start_cursor.pos() > selection_end_cursor.pos()) {
1415             start = selection_end_cursor.pos();
1416             end = selection_start_cursor.pos();
1417     } else {
1418             start = selection_start_cursor.pos();
1419             end = selection_end_cursor.pos();
1420     }
1421     return cap.copySelection(par, par, start, end, buf->params.textclass);
1422 }
1423
1424
1425 bool InsetText::pasteSelection(Buffer const * buf)
1426 {
1427     CutAndPaste cap;
1428
1429     if (cap.nrOfParagraphs() > 1) {
1430         WriteAlert(_("Impossible operation"),
1431                    _("Cannot include more than one paragraph!"),
1432                    _("Sorry."));
1433         return false;
1434     }
1435     LyXParagraph * endpar;
1436     LyXParagraph * actpar = par;
1437
1438     int pos = cursor.pos();
1439     bool ret = cap.pasteSelection(&actpar, &endpar, pos,buf->params.textclass);
1440     cursor.pos(pos);
1441     return ret;
1442 }
1443
1444
1445 bool InsetText::checkAndActivateInset(BufferView * bv, int x, int y,
1446                                       int button)
1447 {
1448     if (par->GetChar(cursor.pos()) == LyXParagraph::META_INSET) {
1449         UpdatableInset * inset =
1450             static_cast<UpdatableInset*>(par->GetInset(cursor.pos()));
1451         LyXFont font = text->GetFont(bv->buffer(), cpar(), cpos());
1452         if (x < 0)
1453             x = inset->width(bv->painter(), font);
1454         if (y < 0)
1455             y = inset->descent(bv->painter(), font);
1456         inset_x = cursor.x() - top_x + drawTextXOffset;
1457         inset_y = cursor.y() + drawTextYOffset;
1458         inset->Edit(bv, x - inset_x, y - inset_y, button);
1459         if (!the_locking_inset)
1460             return false;
1461         UpdateLocal(bv, true, false);
1462         return true;
1463     }
1464     return false;
1465 }
1466
1467
1468 int InsetText::getMaxTextWidth(Painter & pain, UpdatableInset const * inset) const
1469 {
1470 //    int w=getMaxWidth(pain, inset);
1471 //    return (w - x);
1472     return getMaxWidth(pain, inset) - 4; // 2+2 width of eventual border
1473 }
1474
1475 void InsetText::SetParagraphData(LyXParagraph *p)
1476 {
1477     if (par)
1478         delete par;
1479     par = p->Clone();
1480     par->SetInsetOwner(this);
1481     init_inset = true;
1482 }
1483
1484 void InsetText::SetAutoBreakRows(bool flag)
1485 {
1486     if (flag != autoBreakRows) {
1487         autoBreakRows = flag;
1488         init_inset = true;
1489     }
1490 }
1491
1492 void InsetText::SetDrawLockedFrame(bool flag)
1493 {
1494     if (flag != drawLockedFrame) {
1495         drawLockedFrame = flag;
1496         init_inset = true;
1497     }
1498 }
1499
1500 void InsetText::SetFrameColor(LColor::color col)
1501 {
1502     if (frame_color != col) {
1503         frame_color = col;
1504         init_inset = true;
1505     }
1506 }
1507
1508 int InsetText::cx() const
1509 {
1510     return text->cursor.x() + top_x + 1;
1511 }
1512
1513 int InsetText::cy() const
1514 {
1515     long int y_dummy = 0;
1516     Row * tmprow = text->GetRowNearY(y_dummy);
1517     return text->cursor.y() - tmprow->baseline();
1518 }
1519
1520 int InsetText::cpos() const
1521 {
1522     return text->cursor.pos();
1523 }
1524
1525 LyXParagraph * InsetText::cpar() const
1526 {
1527     return text->cursor.par();
1528 }
1529
1530 Row * InsetText::crow() const
1531 {
1532     return text->cursor.row();
1533 }