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