]> git.lyx.org Git - lyx.git/blob - src/insets/insettext.C
Various fixes and some "missing features" from Dekels Mail in insettext/
[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 "LColor.h"
42 #include "support/textutils.h"
43 #include "support/LAssert.h"
44 #include "lyxrow.h"
45 #include "lyxrc.h"
46 #include "intl.h"
47 #include "trans_mgr.h"
48 #include "lyxscreen.h"
49 #include "WorkArea.h"
50
51 using std::ostream;
52 using std::ifstream;
53 using std::endl;
54 using std::min;
55 using std::max;
56
57 extern unsigned char getCurrentTextClass(Buffer *);
58
59 InsetText::InsetText()
60 {
61     par = new LyXParagraph();
62     init();
63 }
64
65
66 InsetText::InsetText(InsetText const & ins)
67         : UpdatableInset()
68 {
69     par = 0;
70     init(&ins);
71     autoBreakRows = ins.autoBreakRows;
72 }
73
74
75 InsetText & InsetText::operator=(InsetText const & it)
76 {
77     init(&it);
78     autoBreakRows = it.autoBreakRows;
79     return * this;
80 }
81
82
83 void InsetText::init(InsetText const * ins)
84 {
85     top_y = last_width = last_height = 0;
86     insetAscent = insetDescent = insetWidth = 0;
87     the_locking_inset = 0;
88     cursor_visible = false;
89     interline_space = 1;
90     no_selection = false;
91     need_update = INIT;
92     drawTextXOffset = drawTextYOffset = 0;
93     autoBreakRows = false;
94     drawFrame = NEVER;
95     xpos = 0.0;
96     if (ins) {
97         SetParagraphData(ins->par);
98         autoBreakRows = ins->autoBreakRows;
99         drawFrame = ins->drawFrame;
100     }
101     par->SetInsetOwner(this);
102     frame_color = LColor::insetframe;
103     locked = false;
104     old_par = 0;
105 }
106
107
108 InsetText::~InsetText()
109 {
110     for(Cache::const_iterator cit=cache.begin(); cit != cache.end(); ++cit)
111         delete (*cit).second;
112 //      deleteLyXText((*cit).first);
113     LyXParagraph * p = par->next;
114     delete par;
115     while(p) {
116         par = p;
117         p = p->next;
118         delete par;
119     }
120 }
121
122
123 void InsetText::clear()
124 {
125     LyXParagraph * p = par->next;
126     delete par;
127     while(p) {
128         par = p;
129         p = p->next;
130         delete par;
131     }
132     par = new LyXParagraph();
133 }
134
135
136 Inset * InsetText::Clone() const
137 {
138     InsetText * t = new InsetText(*this);
139     return t;
140 }
141
142
143 void InsetText::Write(Buffer const * buf, ostream & os) const
144 {
145     os << "Text\n";
146     WriteParagraphData(buf, os);
147 }
148
149
150 void InsetText::WriteParagraphData(Buffer const * buf, ostream & os) const
151 {
152     par->writeFile(buf, os, buf->params, 0, 0);
153 }
154
155
156 void InsetText::Read(Buffer const * buf, LyXLex & lex)
157 {
158     string token;
159     int pos = 0;
160     LyXParagraph * return_par = 0;
161     char depth = 0; // signed or unsigned?
162 #ifndef NEW_INSETS
163     LyXParagraph::footnote_flag footnoteflag = LyXParagraph::NO_FOOTNOTE;
164     LyXParagraph::footnote_kind footnotekind = LyXParagraph::FOOTNOTE;
165 #endif
166     LyXFont font(LyXFont::ALL_INHERIT);
167
168     LyXParagraph * p = par->next;
169     delete par;
170     while(p) {
171         par = p;
172         p = p->next;
173         delete par;
174     }
175     par = new LyXParagraph;
176     while (lex.IsOK()) {
177         lex.nextToken();
178         token = lex.GetString();
179         if (token.empty())
180             continue;
181         if (token == "\\end_inset")
182             break;
183         if (const_cast<Buffer*>(buf)->
184             parseSingleLyXformat2Token(lex, par, return_par,token, pos, depth,
185                                        font
186 #ifndef NEW_INSETS
187                                        , footnoteflag, footnotekind
188 #endif
189                                        ))
190         {
191             // the_end read this should NEVER happen
192             lex.printError("\\the_end read in inset! Error in document!");
193             return;
194         }
195     }
196     if (!return_par)
197             return_par = par;
198     par = return_par;
199     while(return_par) {
200         return_par->SetInsetOwner(this);
201         return_par = return_par->next;
202     }
203     
204     if (token != "\\end_inset") {
205         lex.printError("Missing \\end_inset at this point. "
206                        "Read: `$$Token'");
207     }
208     need_update = INIT;
209 }
210
211
212 int InsetText::ascent(BufferView * bv, LyXFont const &) const
213 {
214     long int y_temp = 0;
215     Row * row = TEXT(bv)->GetRowNearY(y_temp);
216     insetAscent = row->ascent_of_text() + TEXT_TO_INSET_OFFSET;
217     return insetAscent;
218 }
219
220
221 int InsetText::descent(BufferView * bv, LyXFont const &) const
222 {
223     long int y_temp = 0;
224     Row * row = TEXT(bv)->GetRowNearY(y_temp);
225     insetDescent = TEXT(bv)->height - row->ascent_of_text() +
226         TEXT_TO_INSET_OFFSET;
227     return insetDescent;
228 }
229
230
231 int InsetText::width(BufferView * bv, LyXFont const &) const
232 {
233     insetWidth = TEXT(bv)->width + (2 * TEXT_TO_INSET_OFFSET);
234     return insetWidth;
235 }
236
237
238 int InsetText::textWidth(Painter & pain) const
239 {
240     int w = getMaxWidth(pain, this);
241     return w;
242 }
243
244
245 void InsetText::draw(BufferView * bv, LyXFont const & f,
246                      int baseline, float & x, bool cleared) const
247 {
248     Painter & pain = bv->painter();
249
250     // no draw is necessary !!!
251     if ((drawFrame == LOCKED) && !locked && !par->size()) {
252         if (!cleared && (need_update == CLEAR_FRAME)) {
253             pain.rectangle(top_x + 1, baseline - insetAscent + 1,
254                            width(bv, f) - 1,
255                            insetAscent + insetDescent - 1,
256                            LColor::background);
257         }
258         top_x = int(x);
259         top_baseline = baseline;
260         x += width(bv, f);
261         need_update = NONE;
262         return;
263     }
264
265     xpos = x;
266     UpdatableInset::draw(bv, f, baseline, x, cleared);
267
268     if (!cleared && ((need_update==FULL) || (top_x!=int(x)) ||
269                      (top_baseline!=baseline))) {
270         int w =  insetWidth;
271         int h = insetAscent + insetDescent;
272         int ty = baseline - insetAscent;
273         
274         if (ty < 0) {
275             h += ty;
276             ty = 0;
277         }
278         if ((ty + h) > pain.paperHeight())
279             h = pain.paperHeight();
280         if ((top_x + drawTextXOffset + w) > pain.paperWidth())
281             w = pain.paperWidth();
282         pain.fillRectangle(top_x+drawTextXOffset, ty, w, h);
283         cleared = true;
284         need_update = FULL;
285     }
286     if (!cleared && (need_update == NONE))
287         return;
288
289     if (top_x != int(x)) {
290         need_update = INIT;
291         top_x = int(x);
292         bv->text->status = LyXText::CHANGED_IN_DRAW;
293         return;
294     }
295
296     top_baseline = baseline;
297     top_y = baseline - ascent(bv, f);
298     last_width = width(bv, f);
299     last_height = ascent(bv, f) + descent(bv, f);
300
301     if (the_locking_inset && (cpar(bv) == inset_par) && (cpos(bv) == inset_pos)) {
302         inset_x = cx(bv) - top_x + drawTextXOffset;
303         inset_y = cy(bv) + drawTextYOffset;
304     }
305     if (!cleared && (need_update == CURSOR) && !TEXT(bv)->selection) {
306         x += width(bv, f);
307         need_update = NONE;
308         return;
309     }
310     x += TEXT_TO_INSET_OFFSET;
311     long int y = 0;
312     Row * row = TEXT(bv)->GetRowNearY(y);
313     y += baseline - row->ascent_of_text();
314     if (cleared || !locked || (need_update == FULL)) {
315         while (row != 0) {
316             TEXT(bv)->GetVisibleRow(bv, int(y), int(x), row, y, cleared);
317             y += row->height();
318             row = row->next();
319         }
320     } else if (need_update == SELECTION) {
321         bv->screen()->ToggleToggle(TEXT(bv), int(y), int(x));
322     } else {
323         locked = false;
324         if (need_update == CURSOR) {
325             bv->screen()->ToggleSelection(TEXT(bv), true, int(y), int(x));
326             TEXT(bv)->ClearSelection();
327             TEXT(bv)->sel_cursor = TEXT(bv)->cursor;
328         }
329         bv->screen()->Update(TEXT(bv), int(y), int(x));
330         locked = true;
331     }
332     TEXT(bv)->refresh_y = 0;
333     TEXT(bv)->status = LyXText::UNCHANGED;
334     if ((drawFrame == ALWAYS) || ((drawFrame == LOCKED) && locked)) {
335             pain.rectangle(top_x + 1, baseline - insetAscent + 1,
336                            width(bv, f) - 1, insetAscent + insetDescent - 1,
337                            frame_color);
338     } else if (need_update == CLEAR_FRAME) {
339             pain.rectangle(top_x + 1, baseline - insetAscent + 1,
340                            width(bv, f) - 1, insetAscent + insetDescent - 1,
341                            LColor::background);
342     }
343     x += width(bv, f) - TEXT_TO_INSET_OFFSET;
344     if (bv->text->status==LyXText::CHANGED_IN_DRAW)
345         need_update = INIT;
346     else if (need_update != INIT)
347         need_update = NONE;
348 }
349
350
351 void InsetText::update(BufferView * bv, LyXFont const & font, bool reinit)
352 {
353     if (reinit) {  // && (need_update != CURSOR)) {
354         need_update = INIT;
355         resizeLyXText(bv);
356         if (owner())
357             owner()->update(bv, font, true);
358         return;
359     }
360     if (the_locking_inset) {
361         inset_x = cx(bv) - top_x + drawTextXOffset;
362         inset_y = cy(bv) + drawTextYOffset;
363         the_locking_inset->update(bv, font, reinit);
364     }
365     if (need_update == INIT) {
366         resizeLyXText(bv);
367         need_update = FULL;
368 //      if (!owner() && bv->text)
369 //          bv->text->UpdateInset(bv, this);
370     }
371     int oldw = insetWidth;
372 #if 1
373     insetWidth = TEXT(bv)->width + (2 * TEXT_TO_INSET_OFFSET);
374     // max(textWidth(bv->painter()),
375     // static_cast<int>(TEXT(bv)->width) + drawTextXOffset) +
376     // (2 * TEXT_TO_INSET_OFFSET);
377 #else
378     insetWidth = textWidth(bv->painter());
379     if (insetWidth < 0)
380             insetWidth = static_cast<int>(TEXT(bv)->width);
381 #endif
382     if (oldw != insetWidth) {
383 //          printf("TW(%p): %d-%d-%d-%d\n",this,insetWidth, oldw,
384 //                 textWidth(bv->painter()),static_cast<int>(TEXT(bv)->width));
385         resizeLyXText(bv);
386         need_update = FULL;
387 #if 0
388         if (owner()) {
389             owner()->update(bv, font, reinit);
390             return;
391         } else {
392             update(bv, font, reinit);
393         }
394 #else
395 #if 1
396         update(bv, font, reinit);
397 #else
398         UpdateLocal(bv, INIT, false);
399 #endif
400 #endif
401         return;
402     }
403     if ((need_update==CURSOR_PAR) && (TEXT(bv)->status==LyXText::UNCHANGED) &&
404         the_locking_inset)
405     {
406         TEXT(bv)->UpdateInset(bv, the_locking_inset);
407     }
408
409     if (TEXT(bv)->status == LyXText::NEED_MORE_REFRESH)
410         need_update = FULL;
411
412     long int y_temp = 0;
413     Row * row = TEXT(bv)->GetRowNearY(y_temp);
414     insetAscent = row->ascent_of_text() + TEXT_TO_INSET_OFFSET;
415     insetDescent = TEXT(bv)->height - row->ascent_of_text() +
416         TEXT_TO_INSET_OFFSET;
417 }
418
419
420 void InsetText::UpdateLocal(BufferView * bv, UpdateCodes what, bool mark_dirty)
421 {
422     TEXT(bv)->FullRebreak(bv);
423     if (need_update != INIT) {
424         if (TEXT(bv)->status == LyXText::NEED_MORE_REFRESH)
425             need_update = FULL;
426         else if (!the_locking_inset || (what != CURSOR))
427             need_update = what;
428     }
429     if ((need_update != CURSOR) || (TEXT(bv)->status != LyXText::UNCHANGED) ||
430         TEXT(bv)->selection)
431             bv->updateInset(this, mark_dirty);
432     bv->owner()->showState();
433     if (old_par != cpar(bv)) {
434             bv->owner()->setLayout(cpar(bv)->GetLayout());
435             old_par = cpar(bv);
436     }
437 }
438
439
440 string const InsetText::EditMessage() const
441 {
442     return _("Opened Text Inset");
443 }
444
445
446 void InsetText::Edit(BufferView * bv, int x, int y, unsigned int button)
447 {
448 //    par->SetInsetOwner(this);
449     UpdatableInset::Edit(bv, x, y, button);
450
451     if (!bv->lockInset(this)) {
452         lyxerr[Debug::INSETS] << "Cannot lock inset" << endl;
453         return;
454     }
455     locked = true;
456     the_locking_inset = 0;
457     inset_pos = inset_x = inset_y = 0;
458     inset_par = 0;
459     old_par = 0;
460     if (!checkAndActivateInset(bv, x, y, button))
461         TEXT(bv)->SetCursorFromCoordinates(bv, x-drawTextXOffset,
462                                            y+TEXT(bv)->first+insetAscent);
463     TEXT(bv)->sel_cursor = TEXT(bv)->cursor;
464     bv->text->FinishUndo();
465     UpdateLocal(bv, FULL, false);
466 }
467
468
469 void InsetText::InsetUnlock(BufferView * bv)
470 {
471     if (the_locking_inset) {
472         the_locking_inset->InsetUnlock(bv);
473         the_locking_inset = 0;
474     }
475     HideInsetCursor(bv);
476     no_selection = false;
477     locked = false;
478     TEXT(bv)->selection = 0;
479     UpdateLocal(bv, CLEAR_FRAME, false);
480     if (owner())
481             bv->owner()->setLayout(owner()->getLyXText(bv)
482                                     ->cursor.par()->GetLayout());
483     else
484             bv->owner()->setLayout(bv->text->cursor.par()->GetLayout());
485 }
486
487
488 bool InsetText::LockInsetInInset(BufferView * bv, UpdatableInset * inset)
489 {
490     lyxerr[Debug::INSETS] << "InsetText::LockInsetInInset(" << inset << "): ";
491     if (!inset)
492         return false;
493     if (inset == cpar(bv)->GetInset(cpos(bv))) {
494         lyxerr[Debug::INSETS] << "OK" << endl;
495         the_locking_inset = inset;
496         inset_x = cx(bv) - top_x + drawTextXOffset;
497         inset_y = cy(bv) + drawTextYOffset;
498         inset_pos = cpos(bv);
499         inset_par = cpar(bv);
500         TEXT(bv)->UpdateInset(bv, the_locking_inset);
501         return true;
502     } else if (the_locking_inset && (the_locking_inset == inset)) {
503         if (cpar(bv) == inset_par && cpos(bv) == inset_pos) {
504             lyxerr[Debug::INSETS] << "OK" << endl;
505             inset_x = cx(bv) - top_x + drawTextXOffset;
506             inset_y = cy(bv) + drawTextYOffset;
507         } else {
508             lyxerr[Debug::INSETS] << "cursor.pos != inset_pos" << endl;
509         }
510     } else if (the_locking_inset) {
511         lyxerr[Debug::INSETS] << "MAYBE" << endl;
512         return the_locking_inset->LockInsetInInset(bv, inset);
513     }
514     lyxerr[Debug::INSETS] << "NOT OK" << endl;
515     return false;
516 }
517
518
519 bool InsetText::UnlockInsetInInset(BufferView * bv, UpdatableInset * inset,
520                                    bool lr)
521 {
522     if (!the_locking_inset)
523         return false;
524     if (the_locking_inset == inset) {
525         the_locking_inset->InsetUnlock(bv);
526         TEXT(bv)->UpdateInset(bv, inset);
527         the_locking_inset = 0;
528         if (lr)
529             moveRight(bv, false);
530         old_par = 0; // force layout setting
531         UpdateLocal(bv, CURSOR_PAR, false);
532         return true;
533     }
534     return the_locking_inset->UnlockInsetInInset(bv, inset, lr);
535 }
536
537
538 bool InsetText::UpdateInsetInInset(BufferView * bv, Inset * inset)
539 {
540     if (!the_locking_inset)
541         return false;
542     if (the_locking_inset != inset) {
543         TEXT(bv)->UpdateInset(bv, the_locking_inset);
544         need_update = CURSOR_PAR;
545         return the_locking_inset->UpdateInsetInInset(bv, inset);
546     }
547 //    UpdateLocal(bv, FULL, false);
548     if (TEXT(bv)->UpdateInset(bv, inset))
549         UpdateLocal(bv, CURSOR_PAR, false);
550     if (cpar(bv) == inset_par && cpos(bv) == inset_pos) {
551         inset_x = cx(bv) - top_x + drawTextXOffset;
552         inset_y = cy(bv) + drawTextYOffset;
553     }
554     return true;
555 }
556
557
558 void InsetText::InsetButtonPress(BufferView * bv, int x, int y, int button)
559 {
560     no_selection = false;
561
562     int tmp_x = x - drawTextXOffset;
563     int tmp_y = y + insetAscent;
564     Inset * inset = bv->checkInsetHit(TEXT(bv), tmp_x, tmp_y, button);
565
566     HideInsetCursor(bv);
567     if (the_locking_inset) {
568         if (the_locking_inset == inset) {
569             the_locking_inset->InsetButtonPress(bv,x-inset_x,y-inset_y,button);
570             return;
571         } else if (inset) {
572             // otherwise unlock the_locking_inset and lock the new inset
573             the_locking_inset->InsetUnlock(bv);
574             inset_x = cx(bv) - top_x + drawTextXOffset;
575             inset_y = cy(bv) + drawTextYOffset;
576             inset->InsetButtonPress(bv, x - inset_x, y - inset_y, button);
577             inset->Edit(bv, x - inset_x, y - inset_y, button);
578             if (the_locking_inset) {
579                 UpdateLocal(bv, CURSOR_PAR, false);
580             }
581             return;
582         }
583         // otherwise only unlock the_locking_inset
584         the_locking_inset->InsetUnlock(bv);
585         the_locking_inset = 0;
586     }
587     if (bv->the_locking_inset) {
588         if (inset && inset->Editable() == Inset::HIGHLY_EDITABLE) {
589             UpdatableInset * uinset = static_cast<UpdatableInset*>(inset);
590             inset_x = cx(bv) - top_x + drawTextXOffset;
591             inset_y = cy(bv) + drawTextYOffset;
592             inset_pos = cpos(bv);
593             inset_par = cpar(bv);
594             uinset->InsetButtonPress(bv, x - inset_x, y - inset_y, button);
595             uinset->Edit(bv, x - inset_x, y - inset_y, 0);
596             if (the_locking_inset) {
597                 UpdateLocal(bv, CURSOR_PAR, false);
598             }
599             return;
600         }
601     }
602     if (!inset) {
603         bool paste_internally = false;
604         if ((button == 2) && TEXT(bv)->selection) {
605             LocalDispatch(bv, LFUN_COPY, "");
606             paste_internally = true;
607         }
608         TEXT(bv)->SetCursorFromCoordinates(bv, x-drawTextXOffset,
609                                            y+TEXT(bv)->first+insetAscent);
610         TEXT(bv)->sel_cursor = TEXT(bv)->cursor;
611         UpdateLocal(bv, CURSOR, false);
612         bv->owner()->setLayout(cpar(bv)->GetLayout());
613         old_par = cpar(bv);
614         // Insert primary selection with middle mouse
615         // if there is a local selection in the current buffer,
616         // insert this
617         if (button == 2) {
618             if (paste_internally)
619                 LocalDispatch(bv, LFUN_PASTE, "");
620             else
621                 LocalDispatch(bv, LFUN_PASTESELECTION, "paragraph");
622         }
623     }
624     ShowInsetCursor(bv);
625 }
626
627
628 void InsetText::InsetButtonRelease(BufferView * bv, int x, int y, int button)
629 {
630     UpdatableInset * inset = 0;
631
632     if (the_locking_inset) {
633             the_locking_inset->InsetButtonRelease(bv,
634                                                   x - inset_x, y - inset_y,
635                                                   button);
636     } else {
637         if (cpar(bv)->GetChar(cpos(bv)) == LyXParagraph::META_INSET) {
638             inset = static_cast<UpdatableInset*>(cpar(bv)->GetInset(cpos(bv)));
639             if (inset->Editable() == Inset::HIGHLY_EDITABLE) {
640                 inset->InsetButtonRelease(bv, x - inset_x, y - inset_y,button);
641             } else {
642                 inset_x = cx(bv) - top_x + drawTextXOffset;
643                 inset_y = cy(bv) + drawTextYOffset;
644                 inset->InsetButtonRelease(bv, x - inset_x, y - inset_y,button);
645                 inset->Edit(bv, x - inset_x, y - inset_y, button);
646             }
647             UpdateLocal(bv, CURSOR_PAR, false);
648         }
649     }
650     no_selection = false;
651 }
652
653
654 void InsetText::InsetMotionNotify(BufferView * bv, int x, int y, int state)
655 {
656     if (the_locking_inset) {
657         the_locking_inset->InsetMotionNotify(bv, x - inset_x,
658                                              y - inset_y,state);
659         return;
660     }
661     if (!no_selection) {
662         HideInsetCursor(bv);
663         TEXT(bv)->SetCursorFromCoordinates(bv, x-drawTextXOffset,
664                                            y+TEXT(bv)->first+insetAscent);
665         TEXT(bv)->SetSelection();
666         if (TEXT(bv)->toggle_cursor.par()!=TEXT(bv)->toggle_end_cursor.par() ||
667             TEXT(bv)->toggle_cursor.pos()!=TEXT(bv)->toggle_end_cursor.pos())
668             UpdateLocal(bv, SELECTION, false);
669         ShowInsetCursor(bv);
670     }
671     no_selection = false;
672 }
673
674
675 void InsetText::InsetKeyPress(XKeyEvent * xke)
676 {
677     if (the_locking_inset) {
678         the_locking_inset->InsetKeyPress(xke);
679         return;
680     }
681 }
682
683
684 UpdatableInset::RESULT
685 InsetText::LocalDispatch(BufferView * bv,
686                          int action, string const & arg)
687 {
688     no_selection = false;
689     UpdatableInset::RESULT
690         result= UpdatableInset::LocalDispatch(bv, action, arg);
691     if (result != UNDISPATCHED) {
692         return DISPATCHED;
693     }
694
695     result=DISPATCHED;
696     if ((action < 0) && arg.empty())
697         return FINISHED;
698
699     if (the_locking_inset) {
700         result = the_locking_inset->LocalDispatch(bv, action, arg);
701         if (result == DISPATCHED_NOUPDATE)
702             return result;
703         else if (result == DISPATCHED) {
704             UpdateLocal(bv, CURSOR_PAR, false);
705             return result;
706         } else if (result == FINISHED) {
707             switch(action) {
708             case -1:
709             case LFUN_RIGHT:
710                 moveRight(bv, false);
711                 break;
712             case LFUN_DOWN:
713                 moveDown(bv);
714                 break;
715             }
716             the_locking_inset = 0;
717             return DISPATCHED;
718         }
719     }
720     HideInsetCursor(bv);
721     switch (action) {
722         // Normal chars
723     case -1:
724         if (bv->buffer()->isReadonly()) {
725             LyXBell();
726 //          setErrorMessage(N_("Document is read only"));
727             break;
728         }
729         if (!arg.empty()) {
730             /* Automatically delete the currently selected
731              * text and replace it with what is being
732              * typed in now. Depends on lyxrc settings
733              * "auto_region_delete", which defaults to
734              * true (on). */
735
736             bv->text->SetUndo(bv->buffer(), Undo::INSERT,
737 #ifndef NEW_INSETS
738                               bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
739                               bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
740 #else
741                               bv->text->cursor.par()->previous,
742                               bv->text->cursor.par()->next
743 #endif
744                     );
745             if (lyxrc.auto_region_delete) {
746                 if (TEXT(bv)->selection){
747                     TEXT(bv)->CutSelection(bv, false);
748                 }
749             }
750             TEXT(bv)->ClearSelection();
751             for (string::size_type i = 0; i < arg.length(); ++i) {
752                 bv->owner()->getIntl()->getTrans()->TranslateAndInsert(arg[i], TEXT(bv));
753             }
754         }
755         UpdateLocal(bv, CURSOR_PAR, true);
756         break;
757         // --- Cursor Movements ---------------------------------------------
758     case LFUN_RIGHTSEL:
759         bv->text->FinishUndo();
760         moveRight(bv, false, true);
761         TEXT(bv)->SetSelection();
762         UpdateLocal(bv, SELECTION, false);
763         break;
764     case LFUN_RIGHT:
765         result = moveRight(bv);
766         bv->text->FinishUndo();
767         UpdateLocal(bv, CURSOR, false);
768         break;
769     case LFUN_LEFTSEL:
770         bv->text->FinishUndo();
771         moveLeft(bv, false, true);
772         TEXT(bv)->SetSelection();
773         UpdateLocal(bv, SELECTION, false);
774         break;
775     case LFUN_LEFT:
776         bv->text->FinishUndo();
777         result= moveLeft(bv);
778         UpdateLocal(bv, CURSOR, false);
779         break;
780     case LFUN_DOWNSEL:
781         bv->text->FinishUndo();
782         moveDown(bv);
783         TEXT(bv)->SetSelection();
784         UpdateLocal(bv, SELECTION, false);
785         break;
786     case LFUN_DOWN:
787         bv->text->FinishUndo();
788         result = moveDown(bv);
789         UpdateLocal(bv, CURSOR, false);
790         break;
791     case LFUN_UPSEL:
792         bv->text->FinishUndo();
793         moveUp(bv);
794         TEXT(bv)->SetSelection();
795         UpdateLocal(bv, SELECTION, false);
796         break;
797     case LFUN_UP:
798         bv->text->FinishUndo();
799         result = moveUp(bv);
800         UpdateLocal(bv, CURSOR, false);
801         break;
802     case LFUN_HOME:
803         bv->text->FinishUndo();
804         TEXT(bv)->CursorHome(bv);
805         UpdateLocal(bv, CURSOR, false);
806         break;
807     case LFUN_END:
808         TEXT(bv)->CursorEnd(bv);
809         UpdateLocal(bv, CURSOR, false);
810         break;
811     case LFUN_BACKSPACE:
812         bv->text->SetUndo(bv->buffer(), Undo::DELETE,
813 #ifndef NEW_INSETS
814           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
815           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
816 #else
817           bv->text->cursor.par()->previous,
818           bv->text->cursor.par()->next
819 #endif
820                 );
821         if (TEXT(bv)->selection)
822             TEXT(bv)->CutSelection(bv);
823         else
824             TEXT(bv)->Backspace(bv);
825         UpdateLocal(bv, CURSOR_PAR, true);
826         break;
827     case LFUN_DELETE:
828         bv->text->SetUndo(bv->buffer(), Undo::DELETE,
829 #ifndef NEW_INSETS
830           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
831           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
832 #else
833           bv->text->cursor.par()->previous,
834           bv->text->cursor.par()->next
835 #endif
836                 );
837         if (TEXT(bv)->selection)
838             TEXT(bv)->CutSelection(bv);
839         else
840             TEXT(bv)->Delete(bv);
841         UpdateLocal(bv, CURSOR_PAR, true);
842         break;
843     case LFUN_CUT:
844         bv->text->SetUndo(bv->buffer(), Undo::DELETE,
845 #ifndef NEW_INSETS
846           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
847           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
848 #else
849           bv->text->cursor.par()->previous,
850           bv->text->cursor.par()->next
851 #endif
852                 );
853         TEXT(bv)->CutSelection(bv);
854         UpdateLocal(bv, CURSOR_PAR, true);
855         break;
856     case LFUN_COPY:
857         bv->text->FinishUndo();
858         TEXT(bv)->CopySelection(bv);
859         UpdateLocal(bv, CURSOR_PAR, false);
860         break;
861     case LFUN_PASTESELECTION:
862     {
863         string clip(bv->workarea()->getClipboard());
864         
865         if (clip.empty())
866             break;
867         if (arg == "paragraph") {
868                 TEXT(bv)->InsertStringB(bv, clip);
869         } else {
870                 TEXT(bv)->InsertStringA(bv, clip);
871         }
872         UpdateLocal(bv, CURSOR_PAR, true);
873         break;
874     }
875     case LFUN_PASTE:
876         if (!autoBreakRows) {
877             CutAndPaste cap;
878
879             if (cap.nrOfParagraphs() > 1) {
880                 WriteAlert(_("Impossible operation"),
881                            _("Cannot include more than one paragraph!"),
882                            _("Sorry."));
883                 break;
884             }
885         }
886         bv->text->SetUndo(bv->buffer(), Undo::INSERT,
887 #ifndef NEW_INSETS
888           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
889           bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
890 #else
891           bv->text->cursor.par()->previous,
892           bv->text->cursor.par()->next
893 #endif
894                 );
895         TEXT(bv)->PasteSelection(bv);
896         UpdateLocal(bv, CURSOR_PAR, true);
897         break;
898     case LFUN_BREAKPARAGRAPH:
899         if (!autoBreakRows)
900             return DISPATCHED;
901         TEXT(bv)->BreakParagraph(bv, 0);
902         UpdateLocal(bv, FULL, true);
903         break;
904     case LFUN_BREAKLINE:
905         if (!autoBreakRows)
906             return DISPATCHED;
907         bv->text->SetUndo(bv->buffer(), Undo::INSERT,
908 #ifndef NEW_INSETS
909             bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
910             bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
911 #else
912             bv->text->cursor.par()->previous,
913             bv->text->cursor.par()->next
914 #endif
915                 );
916         TEXT(bv)->InsertChar(bv, LyXParagraph::META_NEWLINE);
917         UpdateLocal(bv, CURSOR_PAR, true);
918         break;
919     case LFUN_LAYOUT:
920         // do not set layouts on non breakable textinsets
921         if (autoBreakRows) {
922             LyXTextClass::size_type cur_layout = cpar(bv)->layout;
923       
924             // Derive layout number from given argument (string)
925             // and current buffer's textclass (number). */    
926             LyXTextClassList::ClassList::size_type tclass =
927                 bv->buffer()->params.textclass;
928             std::pair <bool, LyXTextClass::size_type> layout = 
929                 textclasslist.NumberOfLayout(tclass, arg);
930
931             // If the entry is obsolete, use the new one instead.
932             if (layout.first) {
933                 string obs = textclasslist.Style(tclass,layout.second).
934                     obsoleted_by();
935                 if (!obs.empty()) 
936                     layout = textclasslist.NumberOfLayout(tclass, obs);
937             }
938
939             // see if we found the layout number:
940             if (!layout.first) {
941                 string msg = string(N_("Layout ")) + arg + N_(" not known");
942
943                 bv->owner()->getMiniBuffer()->Set(msg);
944                 break;
945             }
946
947             if (cur_layout != layout.second) {
948                 cur_layout = layout.second;
949                 TEXT(bv)->SetLayout(bv, layout.second);
950                 bv->owner()->setLayout(cpar(bv)->GetLayout());
951                 UpdateLocal(bv, CURSOR_PAR, true);
952             }
953         } else {
954             // reset the layout box
955             bv->owner()->setLayout(cpar(bv)->GetLayout());
956         }
957         break;
958     case LFUN_PARAGRAPH_SPACING:
959             // This one is absolutely not working. When fiddling with this
960             // it also seems to me that the paragraphs inside the insettext
961             // inherit bufferparams/paragraphparams in a strange way. (Lgb)
962     {
963             LyXParagraph * par = TEXT(bv)->cursor.par();
964             Spacing::Space cur_spacing = par->spacing.getSpace();
965             float cur_value = 1.0;
966             if (cur_spacing == Spacing::Other) {
967                     cur_value = par->spacing.getValue();
968             }
969                         
970             std::istringstream istr(arg.c_str());
971             string tmp;
972             istr >> tmp;
973             Spacing::Space new_spacing = cur_spacing;
974             float new_value = cur_value;
975             if (tmp.empty()) {
976                     lyxerr << "Missing argument to `paragraph-spacing'"
977                            << endl;
978             } else if (tmp == "single") {
979                     new_spacing = Spacing::Single;
980             } else if (tmp == "onehalf") {
981                     new_spacing = Spacing::Onehalf;
982             } else if (tmp == "double") {
983                     new_spacing = Spacing::Double;
984             } else if (tmp == "other") {
985                     new_spacing = Spacing::Other;
986                     float tmpval = 0.0;
987                     istr >> tmpval;
988                     lyxerr << "new_value = " << tmpval << endl;
989                     if (tmpval != 0.0)
990                             new_value = tmpval;
991             } else if (tmp == "default") {
992                     new_spacing = Spacing::Default;
993             } else {
994                     lyxerr << _("Unknown spacing argument: ")
995                            << arg << endl;
996             }
997             if (cur_spacing != new_spacing || cur_value != new_value) {
998                     par->spacing.set(new_spacing, new_value);
999                     //TEXT(bv)->RedoParagraph(owner->view());
1000                     UpdateLocal(bv, CURSOR_PAR, true);
1001                     //bv->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1002             }
1003     }
1004     break;
1005         
1006     default:
1007         result = UNDISPATCHED;
1008         break;
1009     }
1010     if (result != FINISHED) {
1011         ShowInsetCursor(bv);
1012     } else
1013         bv->unlockInset(this);
1014     return result;
1015 }
1016
1017
1018 int InsetText::Latex(Buffer const * buf, ostream & os, bool, bool) const
1019 {
1020     TexRow texrow;
1021     buf->latexParagraphs(os, par, 0, texrow);
1022     return texrow.rows();
1023 }
1024
1025
1026 int InsetText::Ascii(Buffer const * buf, ostream & os, int linelen) const
1027 {
1028     LyXParagraph * p = par;
1029     unsigned int lines = 0;
1030     
1031     while (p) {
1032         string const tmp = buf->asciiParagraph(p, linelen);
1033         lines += countChar(tmp, '\n');
1034         os << tmp;
1035         p = p->next;
1036     }
1037     os << "\n";
1038     ++lines;
1039     return lines;
1040 }
1041
1042
1043 void InsetText::Validate(LaTeXFeatures & features) const
1044 {
1045     LyXParagraph * p = par;
1046     while(p) {
1047         p->validate(features);
1048         p = p->next;
1049     }
1050 }
1051
1052
1053 int InsetText::BeginningOfMainBody(Buffer const * buf, LyXParagraph * p) const
1054 {
1055     if (textclasslist.Style(buf->params.textclass,
1056                             p->GetLayout()).labeltype != LABEL_MANUAL)
1057         return 0;
1058     else
1059         return p->BeginningOfMainBody();
1060 }
1061
1062
1063 void InsetText::GetCursorPos(BufferView * bv, int & x, int & y) const
1064 {
1065     x = cx(bv);
1066     y = cy(bv);
1067 }
1068
1069
1070 int InsetText::InsetInInsetY()
1071 {
1072     if (!the_locking_inset)
1073         return 0;
1074
1075     return (inset_y + the_locking_inset->InsetInInsetY());
1076 }
1077
1078
1079 void InsetText::ToggleInsetCursor(BufferView * bv)
1080 {
1081     if (the_locking_inset) {
1082         the_locking_inset->ToggleInsetCursor(bv);
1083         return;
1084     }
1085
1086     LyXFont font = TEXT(bv)->GetFont(bv->buffer(), cpar(bv), cpos(bv));
1087
1088     int asc = lyxfont::maxAscent(font);
1089     int desc = lyxfont::maxDescent(font);
1090   
1091     if (cursor_visible)
1092         bv->hideLockedInsetCursor();
1093     else
1094         bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1095     cursor_visible = !cursor_visible;
1096 }
1097
1098
1099 void InsetText::ShowInsetCursor(BufferView * bv)
1100 {
1101     if (the_locking_inset) {
1102         the_locking_inset->ShowInsetCursor(bv);
1103         return;
1104     }
1105     if (!cursor_visible) {
1106         LyXFont font = TEXT(bv)->GetFont(bv->buffer(), cpar(bv), cpos(bv));
1107         
1108         int asc = lyxfont::maxAscent(font);
1109         int desc = lyxfont::maxDescent(font);
1110
1111         bv->fitLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1112         bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1113         cursor_visible = true;
1114     }
1115 }
1116
1117
1118 void InsetText::HideInsetCursor(BufferView * bv)
1119 {
1120     if (cursor_visible) {
1121         bv->hideLockedInsetCursor();
1122         cursor_visible = false;
1123     }
1124     if (the_locking_inset)
1125         the_locking_inset->HideInsetCursor(bv);
1126 }
1127
1128
1129 UpdatableInset::RESULT
1130 InsetText::moveRight(BufferView * bv, bool activate_inset, bool selecting)
1131 {
1132     if (!cpar(bv)->next && (cpos(bv) >= cpar(bv)->Last()))
1133         return FINISHED;
1134     if (activate_inset && checkAndActivateInset(bv, false))
1135         return DISPATCHED;
1136     TEXT(bv)->CursorRight(bv, selecting);
1137     return DISPATCHED_NOUPDATE;
1138 }
1139
1140
1141 UpdatableInset::RESULT
1142 InsetText::moveLeft(BufferView * bv, bool activate_inset, bool selecting)
1143 {
1144     if (!cpar(bv)->previous && (cpos(bv) <= 0))
1145         return FINISHED;
1146     TEXT(bv)->CursorLeft(bv, selecting);
1147     if (activate_inset && checkAndActivateInset(bv, true))
1148         return DISPATCHED;
1149     return DISPATCHED_NOUPDATE;
1150 }
1151
1152
1153 UpdatableInset::RESULT
1154 InsetText::moveUp(BufferView * bv)
1155 {
1156     if (!crow(bv)->previous())
1157         return FINISHED;
1158     TEXT(bv)->CursorUp(bv);
1159     return DISPATCHED_NOUPDATE;
1160 }
1161
1162
1163 UpdatableInset::RESULT
1164 InsetText::moveDown(BufferView * bv)
1165 {
1166     if (!crow(bv)->next())
1167         return FINISHED;
1168     TEXT(bv)->CursorDown(bv);
1169     return DISPATCHED_NOUPDATE;
1170 }
1171
1172
1173 bool InsetText::InsertInset(BufferView * bv, Inset * inset)
1174 {
1175     if (the_locking_inset) {
1176         if (the_locking_inset->InsertInsetAllowed(inset))
1177             return the_locking_inset->InsertInset(bv, inset);
1178         return false;
1179     }
1180     bv->text->SetUndo(bv->buffer(), Undo::INSERT,
1181 #ifndef NEW_INSETS
1182               bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
1183               bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
1184 #else
1185               bv->text->cursor.par()->previous,
1186               bv->text->cursor.par()->next
1187 #endif
1188             );
1189     if (inset->Editable() == Inset::IS_EDITABLE) {
1190         UpdatableInset * i = static_cast<UpdatableInset *>(inset);
1191         i->setOwner(static_cast<UpdatableInset *>(this));
1192     }
1193     HideInsetCursor(bv);
1194     TEXT(bv)->InsertInset(bv, inset);
1195     TEXT(bv)->selection = 0;
1196     bv->fitCursor(TEXT(bv));
1197     UpdateLocal(bv, CURSOR_PAR, true);
1198     static_cast<UpdatableInset*>(inset)->Edit(bv, 0, 0, 0);
1199     ShowInsetCursor(bv);
1200     return true;
1201 }
1202
1203
1204 UpdatableInset * InsetText::GetLockingInset()
1205 {
1206     return the_locking_inset ? the_locking_inset->GetLockingInset() : this;
1207 }
1208
1209
1210 UpdatableInset * InsetText::GetFirstLockingInsetOfType(Inset::Code c)
1211 {
1212     if (c == LyxCode())
1213         return this;
1214     if (the_locking_inset)
1215         return the_locking_inset->GetFirstLockingInsetOfType(c);
1216     return 0;
1217 }
1218
1219
1220 void InsetText::SetFont(BufferView * bv, LyXFont const & font, bool toggleall)
1221 {
1222     TEXT(bv)->SetFont(bv, font, toggleall);
1223 }
1224
1225
1226 bool InsetText::checkAndActivateInset(BufferView * bv, bool behind)
1227 {
1228     if (cpar(bv)->GetChar(cpos(bv)) == LyXParagraph::META_INSET) {
1229         int x, y;
1230         Inset * inset =
1231             static_cast<UpdatableInset*>(cpar(bv)->GetInset(cpos(bv)));
1232         if (!inset || inset->Editable() != Inset::HIGHLY_EDITABLE)
1233             return false;
1234         LyXFont font = TEXT(bv)->GetFont(bv->buffer(), cpar(bv), cpos(bv));
1235         if (behind) {
1236             x = inset->width(bv, font);
1237             y = inset->descent(bv, font);
1238         } else {
1239             x = y = 0;
1240         }
1241         inset_x = cx(bv) - top_x + drawTextXOffset;
1242         inset_y = cy(bv) + drawTextYOffset;
1243         inset->Edit(bv, x-inset_x, y-inset_y, 0);
1244         if (!the_locking_inset)
1245             return false;
1246         UpdateLocal(bv, CURSOR_PAR, false);
1247         return true;
1248     }
1249     return false;
1250 }
1251
1252
1253 bool InsetText::checkAndActivateInset(BufferView * bv, int x, int y,
1254                                       int button)
1255 {
1256     int tmp_x = x - drawTextXOffset;
1257     int tmp_y = y + insetAscent;
1258     Inset * inset = bv->checkInsetHit(TEXT(bv), tmp_x, tmp_y, button);
1259
1260     if (inset) {
1261         if (x < 0)
1262             x = insetWidth;
1263         if (y < 0)
1264             y = insetDescent;
1265         inset_x = cx(bv) - top_x + drawTextXOffset;
1266         inset_y = cy(bv) + drawTextYOffset;
1267         inset->Edit(bv, x - inset_x, y - inset_y, button);
1268         if (!the_locking_inset)
1269             return false;
1270         UpdateLocal(bv, CURSOR_PAR, false);
1271         return true;
1272     }
1273     return false;
1274 }
1275
1276
1277 int InsetText::getMaxWidth(Painter & pain, UpdatableInset const * inset) const
1278 {
1279     int w = UpdatableInset::getMaxWidth(pain, inset);
1280     if (w < 0) {
1281         return w;
1282     }
1283     if (owner()) {
1284         w = w - top_x + owner()->x();
1285         return w;
1286     }
1287     w -= (2 * TEXT_TO_INSET_OFFSET);
1288     return w - top_x;
1289 //    return  w - (2*TEXT_TO_INSET_OFFSET);
1290 }
1291
1292
1293 void InsetText::SetParagraphData(LyXParagraph *p)
1294 {
1295     LyXParagraph * np;
1296
1297     if (par) {
1298         np = par->next;
1299         delete par;
1300         while(np) {
1301             par = np;
1302             np = np->next;
1303             delete par;
1304         }
1305     }
1306     par = p->Clone();
1307     par->SetInsetOwner(this);
1308     np = par;
1309     while(p->next) {
1310         p = p->next;
1311         np->next = p->Clone();
1312         np->next->previous = np;
1313         np = np->next;
1314         np->SetInsetOwner(this);
1315     }
1316     need_update = INIT;
1317 }
1318
1319
1320 void InsetText::SetAutoBreakRows(bool flag)
1321 {
1322     if (flag != autoBreakRows) {
1323         autoBreakRows = flag;
1324         need_update = FULL;
1325         if (!flag)
1326             removeNewlines();
1327     }
1328 }
1329
1330
1331 void InsetText::SetDrawFrame(BufferView * bv, DrawFrame how)
1332 {
1333     if (how != drawFrame) {
1334         drawFrame = how;
1335         if (bv)
1336             UpdateLocal(bv, DRAW_FRAME, false);
1337     }
1338 }
1339
1340
1341 void InsetText::SetFrameColor(BufferView * bv, LColor::color col)
1342 {
1343     if (frame_color != col) {
1344         frame_color = col;
1345         if (bv)
1346             UpdateLocal(bv, DRAW_FRAME, false);
1347     }
1348 }
1349
1350 #if 0
1351 LyXFont InsetText::GetDrawFont(BufferView * bv, LyXParagraph * p, int pos) const
1352 {
1353     return TEXT(bv)->GetFont(bv->buffer(), p, pos);
1354 }
1355 #endif
1356
1357
1358 long InsetText::cx(BufferView * bv) const
1359 {
1360     return TEXT(bv)->cursor.x() + top_x + TEXT_TO_INSET_OFFSET;
1361 }
1362
1363
1364 long InsetText::cy(BufferView * bv) const
1365 {
1366     LyXFont font;
1367     return TEXT(bv)->cursor.y() - ascent(bv, font) + TEXT_TO_INSET_OFFSET;
1368 }
1369
1370
1371 int InsetText::cpos(BufferView * bv) const
1372 {
1373     return TEXT(bv)->cursor.pos();
1374 }
1375
1376
1377 LyXParagraph * InsetText::cpar(BufferView * bv) const
1378 {
1379     return TEXT(bv)->cursor.par();
1380 }
1381
1382
1383 Row * InsetText::crow(BufferView * bv) const
1384 {
1385     return TEXT(bv)->cursor.row();
1386 }
1387
1388
1389 LyXText * InsetText::getLyXText(BufferView * bv) const
1390 {
1391     if (cache.find(bv) != cache.end())
1392         return cache[bv];
1393     LyXText * lt = new LyXText(const_cast<InsetText *>(this));
1394     lt->init(bv);
1395     cache[bv] = lt;
1396     if (the_locking_inset) {
1397         lt->SetCursor(bv, inset_par, inset_pos);
1398     }
1399     return lt;
1400 }
1401
1402
1403 void InsetText::deleteLyXText(BufferView * bv, bool recursive) const
1404 {
1405     if (cache.find(bv) == cache.end())
1406         return;
1407     delete cache[bv];
1408     cache.erase(bv);
1409     if (recursive) {
1410         /// then remove all LyXText in text-insets
1411         LyXParagraph * p = par;
1412         for(;p;p = p->next) {
1413             p->deleteInsetsLyXText(bv);
1414         }
1415     }
1416 }
1417
1418
1419 void InsetText::resizeLyXText(BufferView * bv) const
1420 {
1421     if (!par->next && !par->size()) // resize not neccessary!
1422         return;
1423     if (cache.find(bv) == cache.end())
1424         return;
1425
1426     LyXParagraph * lpar = 0;
1427     LyXParagraph * selstartpar = 0;
1428     LyXParagraph * selendpar = 0;
1429     int pos = 0;
1430     int selstartpos = 0;
1431     int selendpos = 0;
1432     int selection = 0;
1433     int mark_set = 0;
1434
1435 //    ProhibitInput(bv);
1436
1437     if (locked) {
1438         lpar = TEXT(bv)->cursor.par();
1439         pos = TEXT(bv)->cursor.pos();
1440         selstartpar = TEXT(bv)->sel_start_cursor.par();
1441         selstartpos = TEXT(bv)->sel_start_cursor.pos();
1442         selendpar = TEXT(bv)->sel_end_cursor.par();
1443         selendpos = TEXT(bv)->sel_end_cursor.pos();
1444         selection = TEXT(bv)->selection;
1445         mark_set = TEXT(bv)->mark_set;
1446     }
1447     deleteLyXText(bv, (the_locking_inset == 0));
1448
1449     if (lpar) {
1450         TEXT(bv)->selection = true;
1451         /* at this point just to avoid the Delete-Empty-Paragraph
1452          * Mechanism when setting the cursor */
1453         TEXT(bv)->mark_set = mark_set;
1454         if (selection) {
1455             TEXT(bv)->SetCursor(bv, selstartpar, selstartpos);
1456             TEXT(bv)->sel_cursor = TEXT(bv)->cursor;
1457             TEXT(bv)->SetCursor(bv, selendpar, selendpos);
1458             TEXT(bv)->SetSelection();
1459             TEXT(bv)->SetCursor(bv, lpar, pos);
1460         } else {
1461             TEXT(bv)->SetCursor(bv, lpar, pos);
1462             TEXT(bv)->sel_cursor = TEXT(bv)->cursor;
1463             TEXT(bv)->selection = false;
1464         }
1465     }
1466     if (bv->screen())
1467             TEXT(bv)->first = bv->screen()->TopCursorVisible(TEXT(bv));
1468     // this will scroll the screen such that the cursor becomes visible 
1469     bv->updateScrollbar();
1470 //    AllowInput(bv);
1471     if (the_locking_inset) {
1472         /// then resize all LyXText in text-insets
1473         inset_x = cx(bv) - top_x + drawTextXOffset;
1474         inset_y = cy(bv) + drawTextYOffset;
1475         for(LyXParagraph * p = par; p; p = p->next) {
1476             p->resizeInsetsLyXText(bv);
1477         }
1478     }
1479     need_update = FULL;
1480 }
1481
1482
1483 void InsetText::removeNewlines()
1484 {
1485     for(LyXParagraph * p = par; p; p = p->next) {
1486         for(int i = 0; i < p->Last(); ++i) {
1487             if (p->GetChar(i) == LyXParagraph::META_NEWLINE)
1488                 p->Erase(i);
1489         }
1490     }
1491 }