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