]> git.lyx.org Git - lyx.git/blob - src/insets/insettext.C
cleanups by john and andre
[lyx.git] / src / insets / insettext.C
1 /* This file is part of
2  * ======================================================
3  * 
4  *           LyX, The Document Processor
5  *
6  *           Copyright 1998-2001 The LyX Team.
7  *
8  * ======================================================
9  */
10
11 #include <config.h>
12
13 #include <fstream>
14 #include <algorithm>
15
16 #include <cstdlib>
17 //#include <signal.h>
18
19 #ifdef __GNUG__
20 #pragma implementation
21 #endif
22
23 #include "insettext.h"
24 #include "paragraph.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 "frontends/Alert.h"
36 #include "lyxtext.h"
37 #include "lyxcursor.h"
38 #include "CutAndPaste.h"
39 #include "font.h"
40 #include "LColor.h"
41 #include "support/textutils.h"
42 #include "support/LAssert.h"
43 #include "support/lstrings.h"
44 #include "lyxrow.h"
45 #include "lyxrc.h"
46 #include "intl.h"
47 #include "trans_mgr.h"
48 #include "lyxscreen.h"
49 #include "WorkArea.h"
50 #include "gettext.h"
51 #include "lyxfunc.h"
52 #include "ParagraphParameters.h"
53 #include "undo_funcs.h"
54 #include "lyxfind.h"
55
56 using std::ostream;
57 using std::ifstream;
58 using std::endl;
59 using std::min;
60 using std::max;
61 using std::make_pair;
62 using std::vector;
63
64 using lyx::pos_type;
65
66 extern unsigned char getCurrentTextClass(Buffer *);
67 extern bool math_insert_greek(BufferView *, char);
68 extern int greek_kb_flag;
69
70
71 // These functions should probably go into bufferview_funcs somehow (Jug)
72
73 void InsetText::saveLyXTextState(LyXText * t) const
74 {
75         // check if my paragraphs are still valid
76         Paragraph * p = par;
77         while(p) {
78                 if (p == t->cursor.par())
79                         break;
80                 p = p->next();
81         }
82         
83         if (p && t->cursor.pos() <= p->size()) {
84                 sstate.lpar = t->cursor.par();
85                 sstate.pos = t->cursor.pos();
86                 sstate.boundary = t->cursor.boundary();
87                 sstate.selstartpar = t->selection.start.par();
88                 sstate.selstartpos = t->selection.start.pos();
89                 sstate.selstartboundary = t->selection.start.boundary();
90                 sstate.selendpar = t->selection.end.par();
91                 sstate.selendpos = t->selection.end.pos();
92                 sstate.selendboundary = t->selection.end.boundary();
93                 sstate.selection = t->selection.set();
94                 sstate.mark_set = t->selection.mark();
95                 sstate.refresh = t->refresh_row != 0;
96         } else {
97                 sstate.lpar = 0;
98         }
99 }
100
101 void InsetText::restoreLyXTextState(BufferView * bv, LyXText * t) const
102 {
103         if (sstate.lpar) {
104                 t->selection.set(true);
105                 /* at this point just to avoid the Delete-Empty-Paragraph
106                  * Mechanism when setting the cursor */
107                 t->selection.mark(sstate.mark_set);
108                 if (sstate.selection) {
109                         t->setCursor(bv, sstate.selstartpar, sstate.selstartpos,
110                                      true, sstate.selstartboundary);
111                         t->selection.cursor = t->cursor;
112                         t->setCursor(bv, sstate.selendpar, sstate.selendpos,
113                                      true, sstate.selendboundary);
114                         t->setSelection(bv);
115                         t->setCursor(bv, sstate.lpar, sstate.pos);
116                 } else {
117                         t->setCursor(bv, sstate.lpar, sstate.pos, true, sstate.boundary);
118                         t->selection.cursor = t->cursor;
119                         t->selection.set(false);
120                 }
121                 if (sstate.refresh) {
122                 }
123         }
124 }
125
126
127 InsetText::InnerCache::InnerCache(boost::shared_ptr<LyXText> t)
128 {
129         text = t;
130         remove = false;
131 }
132
133
134 InsetText::InsetText()
135         : UpdatableInset(), lt(0), in_update(false), do_resize(0),
136           do_reinit(false)
137 {
138         par = new Paragraph;
139         init();
140 }
141
142
143 InsetText::InsetText(InsetText const & in, bool same_id)
144         : UpdatableInset(in, same_id), lt(0), in_update(false), do_resize(0),
145           do_reinit(false)
146 {
147         par = 0;
148         init(&in, same_id);
149 }
150
151
152 InsetText & InsetText::operator=(InsetText const & it)
153 {
154         init(&it);
155         return * this;
156 }
157
158
159 void InsetText::init(InsetText const * ins, bool same_id)
160 {
161         if (ins) {
162                 setParagraphData(ins->par);
163                 autoBreakRows = ins->autoBreakRows;
164                 drawFrame_ = ins->drawFrame_;
165                 frame_color = ins->frame_color;
166                 if (same_id)
167                         id_ = ins->id_;
168         } else {
169                 Paragraph * p = par;
170                 while(p) {
171                         p->setInsetOwner(this);
172                         p = p->next();
173                 }
174                 the_locking_inset = 0;
175                 drawFrame_ = NEVER;
176                 frame_color = LColor::insetframe;
177                 autoBreakRows = false;
178         }
179         top_y = 0;
180         last_width = 0;
181         last_height = 0;
182         insetAscent = 0;
183         insetDescent = 0;
184         insetWidth = 0;
185         old_max_width = 0;
186         no_selection = false;
187         need_update = FULL;
188         drawTextXOffset = 0;
189         drawTextYOffset = 0;
190         xpos = 0.0;
191         locked = false;
192         old_par = 0;
193         last_drawn_width = -1;
194         frame_is_visible = false;
195         cached_bview = 0;
196         sstate.lpar = 0;
197 }
198
199
200 InsetText::~InsetText()
201 {
202         cached_bview = 0;
203
204         // NOTE
205         
206         while (par) {
207                 Paragraph * tmp = par->next();
208                 delete par;
209                 par = tmp;
210         }
211 }
212
213
214 void InsetText::clear()
215 {
216         while (par) {
217                 Paragraph * tmp = par->next();
218                 delete par;
219                 par = tmp;
220         }
221         par = new Paragraph;
222         need_update = INIT;
223 }
224
225
226 Inset * InsetText::clone(Buffer const &, bool same_id) const
227 {
228         return  new InsetText(*this, same_id);
229 }
230
231
232 void InsetText::write(Buffer const * buf, ostream & os) const
233 {
234         os << "Text\n";
235         writeParagraphData(buf, os);
236 }
237
238
239 void InsetText::writeParagraphData(Buffer const * buf, ostream & os) const
240 {
241         par->writeFile(buf, os, buf->params, 0);
242 }
243
244
245 void InsetText::read(Buffer const * buf, LyXLex & lex)
246 {
247         string token;
248         int pos = 0;
249         Paragraph * return_par = 0;
250         Paragraph::depth_type depth = 0; 
251         LyXFont font(LyXFont::ALL_INHERIT);
252
253         clear();
254         
255         while (lex.isOK()) {
256                 lex.nextToken();
257                 token = lex.getString();
258                 if (token.empty())
259                         continue;
260                 if (token == "\\end_inset") {
261 #ifndef NO_COMPABILITY
262                         const_cast<Buffer*>(buf)->insertErtContents(par, pos, font, false);
263 #endif
264                         break;
265                 }
266                 
267                 if (const_cast<Buffer*>(buf)->
268                         parseSingleLyXformat2Token(lex, par, return_par,
269                                                    token, pos, depth, font)) {
270                         // the_end read this should NEVER happen
271                         lex.printError("\\the_end read in inset! Error in document!");
272                         return;
273                 }
274         }
275         if (!return_par)
276                 return_par = par;
277         par = return_par;
278         while(return_par) {
279                 return_par->setInsetOwner(this);
280                 return_par = return_par->next();
281         }
282         
283         if (token != "\\end_inset") {
284                 lex.printError("Missing \\end_inset at this point. "
285                                            "Read: `$$Token'");
286         }
287         need_update = FULL;
288 }
289
290
291 int InsetText::ascent(BufferView * bv, LyXFont const &) const
292 {
293         int y_temp = 0;
294         Row * row = getLyXText(bv)->getRowNearY(y_temp);
295         insetAscent = row->ascent_of_text() + TEXT_TO_INSET_OFFSET;
296         return insetAscent;
297 }
298
299
300 int InsetText::descent(BufferView * bv, LyXFont const &) const
301 {
302         bool clear = false;
303         if (!lt) {
304                 lt = getLyXText(bv);
305                 clear = true;
306         }
307         int y_temp = 0;
308         Row * row = lt->getRowNearY(y_temp);
309         insetDescent = lt->height - row->ascent_of_text() +
310         TEXT_TO_INSET_OFFSET;
311         if (clear)
312                 lt = 0;
313         return insetDescent;
314 }
315
316
317 int InsetText::width(BufferView * bv, LyXFont const &) const
318 {
319         insetWidth = max(textWidth(bv), (int)getLyXText(bv)->width) +
320                 (2 * TEXT_TO_INSET_OFFSET);
321         insetWidth = max(insetWidth, 10);
322         return insetWidth;
323 }
324
325
326 int InsetText::textWidth(BufferView * bv, bool fordraw) const
327 {
328         int w;
329         if (!autoBreakRows) {
330                 w = -1;
331         } else {
332                 w = getMaxWidth(bv, this);
333         }
334         if (fordraw) {
335                 return max(w - (2 * TEXT_TO_INSET_OFFSET),
336                            (int)getLyXText(bv)->width);
337         } else if (w < 0) {
338             return -1;
339         }
340         return w - (2 * TEXT_TO_INSET_OFFSET);
341 }
342
343
344 void InsetText::draw(BufferView * bv, LyXFont const & f,
345                      int baseline, float & x, bool cleared) const
346 {
347         if (nodraw())
348                 return;
349
350         Painter & pain = bv->painter();
351         
352         // this is the first thing we have to ask because if the x pos
353         // changed we have to do a complete rebreak of the text as we
354         // may have few space to draw in. Well we should check on this too
355         int old_x = top_x;
356         if (top_x != int(x)) {
357                 top_x = int(x);
358                 int nw = getMaxWidth(bv, this);
359                 if (nw > 0 && old_max_width != nw) {
360                         need_update = INIT;
361                         old_max_width = nw;
362                         bv->text->status(bv, LyXText::CHANGED_IN_DRAW);
363                         topx_set = true;
364                         return;
365                 } else {
366                         top_x = old_x;
367                 }
368         }
369
370         // repaint the background if needed
371         if (cleared && backgroundColor() != LColor::background) {
372                 top_x = int(x);
373                 clearInset(pain, baseline, cleared);
374                 top_x = old_x;
375         }
376
377         // no draw is necessary !!!
378         if ((drawFrame_ == LOCKED) && !locked && !par->size()) {
379                 top_x = int(x);
380                 topx_set = true;
381                 top_baseline = baseline;
382                 x += width(bv, f);
383                 if (need_update & CLEAR_FRAME)
384                         clearFrame(pain, cleared);
385                 need_update = NONE;
386                 return;
387         }
388
389         xpos = x;
390         if (!owner())
391                 x += static_cast<float>(scroll());
392
393         // if top_x differs we did it already
394         if (!cleared && (top_x == int(x)) &&
395                 ((need_update&(INIT|FULL)) || (top_baseline!=baseline) ||
396                  (last_drawn_width!=insetWidth))) {
397                 clearInset(pain, baseline, cleared);
398         }
399
400         top_x = int(x);
401         topx_set = true;
402         if (cleared)
403                 frame_is_visible = false;
404
405         if (!cleared && (need_update == NONE)) {
406                 if (locked)
407                         drawFrame(pain, cleared);
408                 return;
409         }
410
411         top_baseline = baseline;
412         top_y = baseline - ascent(bv, f);
413         last_width = width(bv, f);
414         last_height = ascent(bv, f) + descent(bv, f);
415
416         if (cleared || (last_drawn_width != insetWidth)) {
417                 if (!cleared) 
418                         clearInset(pain, baseline, cleared);
419                 need_update |= FULL;
420                 last_drawn_width = insetWidth;
421         }
422
423         if (the_locking_inset && (cpar(bv) == inset_par)
424                 && (cpos(bv) == inset_pos)) {
425                 inset_x = cx(bv) - top_x + drawTextXOffset;
426                 inset_y = cy(bv) + drawTextYOffset;
427         }
428         if (!cleared && (need_update == CURSOR)
429             && !getLyXText(bv)->selection.set()) {
430                 drawFrame(pain, cleared);
431                 x += last_width; // was width(bv, f);
432                 need_update = NONE;
433                 return;
434         }
435         bool clear = false;
436         if (!lt) {
437                 lt = getLyXText(bv);
438                 clear = true;
439         }
440         x += TEXT_TO_INSET_OFFSET;
441
442         int y = 0;
443         Row * row = lt->getRowNearY(y);
444         int y_offset = baseline - row->ascent_of_text();
445         int ph = pain.paperHeight();
446         int first = 0;
447         y = y_offset;
448         while ((row != 0) && ((y+row->height()) <= 0)) {
449                 y += row->height();
450                 first += row->height();
451                 row = row->next();
452         }
453         if (y_offset < 0)
454                 y_offset = y;
455         lt->first = first;
456         if (cleared || (need_update&(INIT|FULL))) {
457                 int yf = y_offset;
458                 y = 0;
459                 while ((row != 0) && (yf < ph)) {
460                         lt->getVisibleRow(bv, y+y_offset, int(x), row,
461                                                 y+first, cleared);
462                         y += row->height();
463                         yf += row->height();
464                         row = row->next();
465                 }
466         } else if (!locked) {
467                 if (need_update & CURSOR) {
468                         bv->screen()->toggleSelection(lt, bv, true, y_offset,int(x));
469                         lt->clearSelection();
470                         lt->selection.cursor = lt->cursor;
471                 }
472                 bv->screen()->update(lt, bv, y_offset, int(x));
473         } else {
474                 locked = false;
475                 if (need_update & SELECTION) {
476                         bv->screen()->toggleToggle(lt, bv, y_offset, int(x));
477                 } else if (need_update & CURSOR) {
478                         bv->screen()->toggleSelection(lt, bv, true, y_offset,int(x));
479                         lt->clearSelection();
480                         lt->selection.cursor = lt->cursor;
481                 }
482                 bv->screen()->update(lt, bv, y_offset, int(x));
483                 locked = true;
484         }
485
486         lt->refresh_y = 0;
487         lt->status(bv, LyXText::UNCHANGED);
488         if ((need_update != CURSOR_PAR) &&
489             ((drawFrame_ == ALWAYS) || ((drawFrame_ == LOCKED) && locked))) {
490                 drawFrame(pain, cleared);
491         } else if (need_update & CLEAR_FRAME) {
492                 clearFrame(pain, cleared);
493         }
494         
495         x += last_width /* was width(bv, f) */ - TEXT_TO_INSET_OFFSET;
496         
497         if (bv->text->status() == LyXText::CHANGED_IN_DRAW) {
498                 need_update |= FULL;
499         } else if (need_update != INIT) {
500                 need_update = NONE;
501         }
502         
503         if (clear)
504                 lt = 0;
505 }
506
507
508 void InsetText::drawFrame(Painter & pain, bool cleared) const
509 {
510         static int const ttoD2 = TEXT_TO_INSET_OFFSET / 2;
511         if (!frame_is_visible || cleared) {
512                 frame_x = top_x + ttoD2;
513                 frame_y = top_baseline - insetAscent + ttoD2;
514                 frame_w = last_width - TEXT_TO_INSET_OFFSET;
515                 frame_h = insetAscent + insetDescent - TEXT_TO_INSET_OFFSET;
516                 pain.rectangle(frame_x, frame_y,
517                                frame_w, frame_h,
518                                frame_color);
519                 frame_is_visible = true;
520         }
521 }
522
523
524 void InsetText::clearFrame(Painter & pain, bool cleared) const
525 {
526         if (frame_is_visible) {
527                 if (!cleared) {
528                         pain.rectangle(frame_x, frame_y, frame_w, frame_h,
529                                        backgroundColor());
530                 }
531                 frame_is_visible = false;
532         }
533 }
534
535
536 void InsetText::update(BufferView * bv, LyXFont const & font, bool reinit)
537 {
538         if (in_update) {
539                 if (reinit && owner()) {
540                         reinitLyXText();
541                         owner()->update(bv, font, true);
542                 }
543                 return;
544         }
545         in_update = true;
546         if (reinit || need_update == INIT) {
547                 need_update = FULL;
548                 reinitLyXText();
549                 if (owner())
550                         owner()->update(bv, font, true);
551                 in_update = false;
552                 return;
553         }
554         if (the_locking_inset) {
555                 inset_x = cx(bv) - top_x + drawTextXOffset;
556                 inset_y = cy(bv) + drawTextYOffset;
557                 the_locking_inset->update(bv, font, reinit);
558         }
559
560         bool clear = false;
561         if (!lt) {
562                 lt = getLyXText(bv);
563                 clear = true;
564         }
565 #if 0
566         int oldw = insetWidth;
567         insetWidth = lt->width + (2 * TEXT_TO_INSET_OFFSET);
568         if (oldw != insetWidth) {
569                 resizeLyXText(bv);
570                 need_update |= FULL;
571                 if (clear)
572                         lt = 0;
573                 in_update = false;
574                 return;
575         }
576 #endif
577         if ((need_update & CURSOR_PAR) && (lt->status() == LyXText::UNCHANGED) &&
578                 the_locking_inset)
579         {
580                 lt->updateInset(bv, the_locking_inset);
581         }
582         if (lt->status() == LyXText::NEED_MORE_REFRESH)
583                 need_update |= FULL;
584         if (clear)
585                 lt = 0;
586         in_update = false;
587 }
588
589
590 void InsetText::setUpdateStatus(BufferView * bv, int what) const
591 {
592         bool clear = false;
593         if (!lt) {
594                 lt = getLyXText(bv);
595                 clear = true;
596         }
597         need_update |= what;
598         // we have to redraw us full if our LyXText NEEDS_MORE_REFRES or
599         // if we don't break row so that we only have one row to update!
600         if ((lt->status() == LyXText::NEED_MORE_REFRESH) ||
601             (!autoBreakRows &&
602              (lt->status() == LyXText::NEED_VERY_LITTLE_REFRESH)))
603         {
604                 need_update |= FULL;
605         } else if (lt->status() == LyXText::NEED_VERY_LITTLE_REFRESH) {
606                 need_update |= CURSOR_PAR;
607         }
608
609         // this to not draw a selection when we redraw all of it!
610         if (need_update & CURSOR && !(need_update & SELECTION)) {
611                 if (lt->selection.set())
612                         need_update = FULL;
613                 lt->clearSelection();
614         }
615         if (clear)
616                 lt = 0;
617 }
618
619
620 void InsetText::updateLocal(BufferView * bv, int what, bool mark_dirty) const
621 {
622         bool clear = false;
623         if (!lt) {
624                 lt = getLyXText(bv);
625                 clear = true;
626         }
627         lt->fullRebreak(bv);
628         setUpdateStatus(bv, what);
629         if (((need_update != CURSOR) && (need_update != NONE)) ||
630             (lt->status() != LyXText::UNCHANGED) || lt->selection.set())
631         {
632                 bv->updateInset(const_cast<InsetText *>(this), mark_dirty);
633         }
634         if (need_update == CURSOR)
635                 need_update = NONE;
636         bv->owner()->showState();
637         if (old_par != cpar(bv)) {
638                 bv->owner()->setLayout(cpar(bv)->getLayout());
639                 old_par = cpar(bv);
640         }
641         if (clear)
642                 lt = 0;
643 }
644
645
646 string const InsetText::editMessage() const
647 {
648         return _("Opened Text Inset");
649 }
650
651
652 void InsetText::edit(BufferView * bv, int x, int y, unsigned int button)
653 {
654         UpdatableInset::edit(bv, x, y, button);
655         
656         if (!bv->lockInset(this)) {
657                 lyxerr[Debug::INSETS] << "Cannot lock inset" << endl;
658                 return;
659         }
660         locked = true;
661         the_locking_inset = 0;
662         inset_pos = inset_x = inset_y = 0;
663         inset_boundary = false;
664         inset_par = 0;
665         old_par = 0;
666         int tmp_y = (y < 0) ? 0 : y;
667         bool clear = false;
668         if (!lt) {
669                 lt = getLyXText(bv);
670                 clear = true;
671         }
672
673         if (!checkAndActivateInset(bv, x, tmp_y, button))
674                 lt->setCursorFromCoordinates(bv, x - drawTextXOffset,
675                                             y + insetAscent);
676         lt->clearSelection();
677         finishUndo();
678         showInsetCursor(bv);
679         updateLocal(bv, CURSOR, false);
680
681         // If the inset is empty set the language of the current font to the
682         // language to the surronding text (if different).
683         if (par->size() == 0 && !par->next() &&
684                 bv->getParentLanguage(this) != lt->current_font.language()) {
685                 LyXFont font(LyXFont::ALL_IGNORE);
686                 font.setLanguage(bv->getParentLanguage(this));
687                 setFont(bv, font, false);
688         }
689         if (clear)
690                 lt = 0;
691 }
692
693
694 void InsetText::edit(BufferView * bv, bool front)
695 {
696         UpdatableInset::edit(bv, front);
697         
698         if (!bv->lockInset(this)) {
699                 lyxerr[Debug::INSETS] << "Cannot lock inset" << endl;
700                 return;
701         }
702         locked = true;
703         the_locking_inset = 0;
704         inset_pos = inset_x = inset_y = 0;
705         inset_boundary = false;
706         inset_par = 0;
707         old_par = 0;
708         bool clear = false;
709         if (!lt) {
710                 lt = getLyXText(bv);
711                 clear = true;
712         }
713         if (front)
714                 lt->setCursor(bv, par, 0);
715         else {
716                 Paragraph * p = par;
717                 while(p->next())
718                         p = p->next();
719 //              int const pos = (p->size() ? p->size()-1 : p->size());
720                 lt->setCursor(bv, p, p->size());
721         }
722         lt->clearSelection();
723         finishUndo();
724         showInsetCursor(bv);
725         updateLocal(bv, CURSOR, false);
726
727         // If the inset is empty set the language of the current font to the
728         // language to the surronding text (if different).
729         if (par->size() == 0 && !par->next() &&
730                 bv->getParentLanguage(this) != lt->current_font.language()) {
731                 LyXFont font(LyXFont::ALL_IGNORE);
732                 font.setLanguage(bv->getParentLanguage(this));
733                 setFont(bv, font, false);
734         }
735         if (clear)
736                 lt = 0;
737 }
738
739
740 void InsetText::insetUnlock(BufferView * bv)
741 {
742         if (the_locking_inset) {
743                 the_locking_inset->insetUnlock(bv);
744                 the_locking_inset = 0;
745         }
746         hideInsetCursor(bv);
747         no_selection = false;
748         locked = false;
749         int code;
750         if (drawFrame_ == LOCKED)
751                 code = CURSOR|CLEAR_FRAME;
752         else 
753                 code = CURSOR;
754         bool clear = false;
755         if (!lt) {
756                 lt = getLyXText(bv);
757                 clear = true;
758         }
759         if (lt->selection.set()) {
760                 lt->clearSelection();
761                 code = FULL;
762         } else if (owner()) {
763                 bv->owner()->setLayout(owner()->getLyXText(bv)
764                                        ->cursor.par()->getLayout());
765         } else
766                 bv->owner()->setLayout(bv->text->cursor.par()->getLayout());
767         // hack for deleteEmptyParMech
768         lt->setCursor(bv, par, 0);
769         updateLocal(bv, code, false);
770         if (clear)
771                 lt = 0;
772 }
773
774
775 bool InsetText::lockInsetInInset(BufferView * bv, UpdatableInset * inset)
776 {
777         lyxerr[Debug::INSETS] << "InsetText::LockInsetInInset("
778                               << inset << "): ";
779         if (!inset)
780                 return false;
781         if (inset == cpar(bv)->getInset(cpos(bv))) {
782                 lyxerr[Debug::INSETS] << "OK" << endl;
783                 the_locking_inset = inset;
784                 inset_x = cx(bv) - top_x + drawTextXOffset;
785                 inset_y = cy(bv) + drawTextYOffset;
786                 inset_pos = cpos(bv);
787                 inset_par = cpar(bv);
788                 inset_boundary = cboundary(bv);
789                 updateLocal(bv, CURSOR, false);
790                 return true;
791         } else if (the_locking_inset && (the_locking_inset == inset)) {
792                 if (cpar(bv) == inset_par && cpos(bv) == inset_pos) {
793                         lyxerr[Debug::INSETS] << "OK" << endl;
794                         inset_x = cx(bv) - top_x + drawTextXOffset;
795                         inset_y = cy(bv) + drawTextYOffset;
796                 } else {
797                         lyxerr[Debug::INSETS] << "cursor.pos != inset_pos" << endl;
798                 }
799         } else if (the_locking_inset) {
800                 lyxerr[Debug::INSETS] << "MAYBE" << endl;
801                 return the_locking_inset->lockInsetInInset(bv, inset);
802         }
803         lyxerr[Debug::INSETS] << "NOT OK" << endl;
804         return false;
805 }
806
807
808 bool InsetText::unlockInsetInInset(BufferView * bv, UpdatableInset * inset,
809                                    bool lr)
810 {
811         if (!the_locking_inset)
812                 return false;
813         if (the_locking_inset == inset) {
814                 the_locking_inset->insetUnlock(bv);
815                 getLyXText(bv)->updateInset(bv, inset);
816                 the_locking_inset = 0;
817                 if (lr)
818                         moveRight(bv, false);
819                 old_par = 0; // force layout setting
820                 if (scroll())
821                         scroll(bv, 0.0F);
822                 else
823                         updateLocal(bv, CURSOR, false);
824                 return true;
825         }
826         return the_locking_inset->unlockInsetInInset(bv, inset, lr);
827 }
828
829
830 bool InsetText::updateInsetInInset(BufferView * bv, Inset * inset)
831 {
832         if (!the_locking_inset)
833                 return false;
834         if (the_locking_inset != inset) {
835                 getLyXText(bv)->updateInset(bv, the_locking_inset);
836                 setUpdateStatus(bv, CURSOR_PAR);
837                 return the_locking_inset->updateInsetInInset(bv, inset);
838         }
839         if (getLyXText(bv)->updateInset(bv, inset))
840                 updateLocal(bv, CURSOR_PAR, false);
841         if (cpar(bv) == inset_par && cpos(bv) == inset_pos) {
842                 inset_x = cx(bv) - top_x + drawTextXOffset;
843                 inset_y = cy(bv) + drawTextYOffset;
844         }
845         return true;
846 }
847
848
849 void InsetText::insetButtonPress(BufferView * bv, int x, int y, int button)
850 {
851         no_selection = true;
852
853         int tmp_x = x - drawTextXOffset;
854         int tmp_y = y + insetAscent - getLyXText(bv)->first;
855         Inset * inset = bv->checkInsetHit(getLyXText(bv), tmp_x, tmp_y, button);
856
857         hideInsetCursor(bv);
858         if (the_locking_inset) {
859                 if (the_locking_inset == inset) {
860                         the_locking_inset->insetButtonPress(bv,x-inset_x,y-inset_y,button);
861                         no_selection = false;
862                         return;
863                 } else if (inset) {
864                         // otherwise unlock the_locking_inset and lock the new inset
865                         the_locking_inset->insetUnlock(bv);
866                         inset_x = cx(bv) - top_x + drawTextXOffset;
867                         inset_y = cy(bv) + drawTextYOffset;
868                         the_locking_inset = static_cast<UpdatableInset*>(inset);
869                         inset->insetButtonPress(bv, x - inset_x, y - inset_y, button);
870                         inset->edit(bv, x - inset_x, y - inset_y, button);
871                         if (the_locking_inset)
872                                 updateLocal(bv, CURSOR, false);
873                         no_selection = false;
874                         return;
875                 }
876                 // otherwise only unlock the_locking_inset
877                 the_locking_inset->insetUnlock(bv);
878                 the_locking_inset = 0;
879         }
880         if (bv->theLockingInset()) {
881                 if (isHighlyEditableInset(inset)) {
882                         UpdatableInset * uinset = static_cast<UpdatableInset*>(inset);
883                         inset_x = cx(bv) - top_x + drawTextXOffset;
884                         inset_y = cy(bv) + drawTextYOffset;
885                         inset_pos = cpos(bv);
886                         inset_par = cpar(bv);
887                         inset_boundary = cboundary(bv);
888                         the_locking_inset = uinset;
889                         uinset->insetButtonPress(bv, x - inset_x, y - inset_y,
890                                                  button);
891                         uinset->edit(bv, x - inset_x, y - inset_y, 0);
892                         if (the_locking_inset)
893                                 updateLocal(bv, CURSOR, false);
894                         no_selection = false;
895                         return;
896                 }
897         }
898         if (!inset) { // && (button == 2)) {
899                 bool paste_internally = false;
900                 if ((button == 2) && getLyXText(bv)->selection.set()) {
901                         localDispatch(bv, LFUN_COPY, "");
902                         paste_internally = true;
903                 }
904                 bool clear = false;
905                 if (!lt) {
906                         lt = getLyXText(bv);
907                         clear = true;
908                 }
909                 lt->setCursorFromCoordinates(bv, x-drawTextXOffset, y + insetAscent);
910                 if (lt->selection.set()) {
911                         lt->clearSelection();
912                         updateLocal(bv, FULL, false);
913                 } else {
914                         lt->clearSelection();
915                 }
916                 bv->owner()->setLayout(cpar(bv)->getLayout());
917                 old_par = cpar(bv);
918                 // Insert primary selection with middle mouse
919                 // if there is a local selection in the current buffer,
920                 // insert this
921                 if (button == 2) {
922                         if (paste_internally)
923                                 localDispatch(bv, LFUN_PASTE, "");
924                         else
925                                 localDispatch(bv, LFUN_PASTESELECTION,
926                                               "paragraph");
927                 }
928                 if (clear)
929                         lt = 0;
930         }
931         showInsetCursor(bv);
932         no_selection = false;
933 }
934
935
936 void InsetText::insetButtonRelease(BufferView * bv, int x, int y, int button)
937 {
938         UpdatableInset * inset = 0;
939
940         if (the_locking_inset) {
941                 the_locking_inset->insetButtonRelease(bv,
942                                                       x - inset_x, y - inset_y,
943                                                       button);
944         } else {
945                 if (cpar(bv)->isInset(cpos(bv))) {
946                         inset = static_cast<UpdatableInset*>(cpar(bv)->getInset(cpos(bv)));
947                         if (isHighlyEditableInset(inset)) {
948                                 inset->insetButtonRelease(bv,
949                                                           x - inset_x,
950                                                           y - inset_y, button);
951                         } else {
952                                 inset_x = cx(bv) - top_x + drawTextXOffset;
953                                 inset_y = cy(bv) + drawTextYOffset;
954                                 inset->insetButtonRelease(bv,
955                                                           x - inset_x,
956                                                           y - inset_y, button);
957                                 inset->edit(bv,
958                                             x - inset_x, y - inset_y, button);
959                         }
960                         updateLocal(bv, CURSOR_PAR, false);
961                 }
962         }
963         no_selection = false;
964 }
965
966
967 void InsetText::insetMotionNotify(BufferView * bv, int x, int y, int state)
968 {
969         if (no_selection)
970                 return;
971         if (the_locking_inset) {
972                 the_locking_inset->insetMotionNotify(bv, x - inset_x,
973                                                      y - inset_y,state);
974                 return;
975         }
976         LyXText * t = getLyXText(bv);
977         hideInsetCursor(bv);
978         t->setCursorFromCoordinates(bv, x - drawTextXOffset, y + insetAscent);
979         t->setSelection(bv);
980         if (t->toggle_cursor.par() != t->toggle_end_cursor.par() ||
981                 t->toggle_cursor.pos() != t->toggle_end_cursor.pos())
982                 updateLocal(bv, SELECTION, false);
983         showInsetCursor(bv);
984 }
985
986
987 void InsetText::insetKeyPress(XKeyEvent * xke)
988 {
989         if (the_locking_inset) {
990                 the_locking_inset->insetKeyPress(xke);
991                 return;
992         }
993 }
994
995
996 UpdatableInset::RESULT
997 InsetText::localDispatch(BufferView * bv,
998                          kb_action action, string const & arg)
999 {
1000         bool was_empty = par->size() == 0 && !par->next();
1001         no_selection = false;
1002         UpdatableInset::RESULT
1003                 result= UpdatableInset::localDispatch(bv, action, arg);
1004         if (result != UNDISPATCHED) {
1005                 return DISPATCHED;
1006         }
1007
1008         result = DISPATCHED;
1009         if ((action < 0) && arg.empty())
1010                 return FINISHED;
1011
1012         if (the_locking_inset) {
1013                 result = the_locking_inset->localDispatch(bv, action, arg);
1014                 if (result == DISPATCHED_NOUPDATE)
1015                         return result;
1016                 else if (result == DISPATCHED) {
1017                         updateLocal(bv, CURSOR_PAR, false);
1018                         return result;
1019                 } else if (result >= FINISHED) {
1020                         switch(result) {
1021                         case FINISHED_RIGHT:
1022                                 moveRightIntern(bv, false, false);
1023                                 result = DISPATCHED;
1024                                 break;
1025                         case FINISHED_UP:
1026                                 if ((result = moveUp(bv)) >= FINISHED) {
1027                                         updateLocal(bv, CURSOR, false);
1028                                         bv->unlockInset(this);
1029                                 }
1030                                 break;
1031                         case FINISHED_DOWN:
1032                                 if ((result = moveDown(bv)) >= FINISHED) {
1033                                         updateLocal(bv, CURSOR, false);
1034                                         bv->unlockInset(this);
1035                                 }
1036                                 break;
1037                         default:
1038                                 result = DISPATCHED;
1039                                 break;
1040                         }
1041                         the_locking_inset = 0;
1042 #ifdef WITH_WARNINGS
1043 #warning I changed this to always return Dispatched maybe it is wrong (20011001 Jug)
1044 #endif
1045                         return result;
1046                 }
1047         }
1048         hideInsetCursor(bv);
1049         bool clear = false;
1050         if (!lt) {
1051                 lt = getLyXText(bv);
1052                 clear = true;
1053         }
1054         switch (action) {
1055         // Normal chars
1056         case LFUN_SELFINSERT:
1057                 if (bv->buffer()->isReadonly()) {
1058 //          setErrorMessage(N_("Document is read only"));
1059                         break;
1060                 }
1061                 if (!arg.empty()) {
1062                         /* Automatically delete the currently selected
1063                          * text and replace it with what is being
1064                          * typed in now. Depends on lyxrc settings
1065                          * "auto_region_delete", which defaults to
1066                          * true (on). */
1067
1068                         setUndo(bv, Undo::INSERT,
1069                                 lt->cursor.par(), lt->cursor.par()->next());
1070                         bv->setState();
1071                         if (lyxrc.auto_region_delete) {
1072                                 if (lt->selection.set()) {
1073                                         lt->cutSelection(bv, false);
1074                                 }
1075                         }
1076                         lt->clearSelection();
1077                         for (string::size_type i = 0; i < arg.length(); ++i) {
1078                                 bv->owner()->getIntl()->getTrans().TranslateAndInsert(arg[i], lt);
1079                         }
1080                 }
1081                 lt->selection.cursor = lt->cursor;
1082                 updateLocal(bv, CURSOR_PAR, true);
1083                 result = DISPATCHED_NOUPDATE;
1084                 break;
1085                 // --- Cursor Movements -----------------------------------
1086         case LFUN_RIGHTSEL:
1087                 finishUndo();
1088                 moveRight(bv, false, true);
1089                 lt->setSelection(bv);
1090                 updateLocal(bv, SELECTION, false);
1091                 break;
1092         case LFUN_RIGHT:
1093                 result = moveRight(bv);
1094                 finishUndo();
1095                 updateLocal(bv, CURSOR, false);
1096                 break;
1097         case LFUN_LEFTSEL:
1098                 finishUndo();
1099                 moveLeft(bv, false, true);
1100                 lt->setSelection(bv);
1101                 updateLocal(bv, SELECTION, false);
1102                 break;
1103         case LFUN_LEFT:
1104                 finishUndo();
1105                 result = moveLeft(bv);
1106                 updateLocal(bv, CURSOR, false);
1107                 break;
1108         case LFUN_DOWNSEL:
1109                 finishUndo();
1110                 moveDown(bv);
1111                 lt->setSelection(bv);
1112                 updateLocal(bv, SELECTION, false);
1113                 break;
1114         case LFUN_DOWN:
1115                 finishUndo();
1116                 result = moveDown(bv);
1117                 updateLocal(bv, CURSOR, false);
1118                 break;
1119         case LFUN_UPSEL:
1120                 finishUndo();
1121                 moveUp(bv);
1122                 lt->setSelection(bv);
1123                 updateLocal(bv, SELECTION, false);
1124                 break;
1125         case LFUN_UP:
1126                 finishUndo();
1127                 result = moveUp(bv);
1128                 updateLocal(bv, CURSOR, false);
1129                 break;
1130         case LFUN_HOME:
1131                 finishUndo();
1132                 lt->cursorHome(bv);
1133                 updateLocal(bv, CURSOR, false);
1134                 break;
1135         case LFUN_END:
1136                 lt->cursorEnd(bv);
1137                 updateLocal(bv, CURSOR, false);
1138                 break;
1139         case LFUN_BACKSPACE: {
1140                 setUndo(bv, Undo::DELETE,
1141                         lt->cursor.par(), lt->cursor.par()->next());
1142                 if (lt->selection.set())
1143                         lt->cutSelection(bv);
1144                 else
1145                         lt->backspace(bv);
1146                 updateLocal(bv, CURSOR_PAR, true);
1147         }
1148         break;
1149         
1150         case LFUN_DELETE: {
1151                 setUndo(bv, Undo::DELETE,
1152                         lt->cursor.par(), lt->cursor.par()->next());
1153                 if (lt->selection.set()) {
1154                         lt->cutSelection(bv);
1155                 } else {
1156                         lt->Delete(bv);
1157                 }
1158                 updateLocal(bv, CURSOR_PAR, true);
1159         }
1160         break;
1161         
1162         case LFUN_CUT: {
1163                 setUndo(bv, Undo::DELETE,
1164                         lt->cursor.par(), lt->cursor.par()->next());
1165                 lt->cutSelection(bv);
1166                 updateLocal(bv, CURSOR_PAR, true);
1167         }
1168         break;
1169
1170         case LFUN_COPY:
1171                 finishUndo();
1172                 lt->copySelection(bv);
1173                 updateLocal(bv, CURSOR_PAR, false);
1174                 break;
1175         case LFUN_PASTESELECTION:
1176         {
1177                 string const clip(bv->getClipboard());
1178         
1179                 if (clip.empty())
1180                         break;
1181                 if (arg == "paragraph") {
1182                         lt->insertStringAsParagraphs(bv, clip);
1183                 } else {
1184                         lt->insertStringAsLines(bv, clip);
1185                 }
1186                 updateLocal(bv, CURSOR_PAR, true);
1187                 break;
1188         }
1189         case LFUN_PASTE: {
1190                 if (!autoBreakRows) {
1191
1192                         if (CutAndPaste::nrOfParagraphs() > 1) {
1193                                 Alert::alert(_("Impossible operation"),
1194                                                    _("Cannot include more than one paragraph!"),
1195                                                    _("Sorry."));
1196                                 break;
1197                         }
1198                 }
1199                 setUndo(bv, Undo::INSERT,
1200                         lt->cursor.par(), lt->cursor.par()->next());
1201                 lt->pasteSelection(bv);
1202                 updateLocal(bv, CURSOR_PAR, true);
1203         }
1204         break;
1205
1206         case LFUN_BREAKPARAGRAPH:
1207                 if (!autoBreakRows) {
1208                         result = DISPATCHED;
1209                         break;
1210                 }
1211                 lt->breakParagraph(bv, 0);
1212                 updateLocal(bv, FULL, true);
1213                 break;
1214         case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
1215                 if (!autoBreakRows) {
1216                         result = DISPATCHED;
1217                         break;
1218                 }
1219                 lt->breakParagraph(bv, 1);
1220                 updateLocal(bv, FULL, true);
1221                 break;
1222
1223         case LFUN_BREAKLINE: {
1224                 if (!autoBreakRows) {
1225                         result = DISPATCHED;
1226                         break;
1227                 }
1228                 setUndo(bv, Undo::INSERT,
1229                         lt->cursor.par(), lt->cursor.par()->next());
1230                 lt->insertChar(bv, Paragraph::META_NEWLINE);
1231                 updateLocal(bv, CURSOR_PAR, true);
1232         }
1233         break;
1234
1235         case LFUN_LAYOUT:
1236                 // do not set layouts on non breakable textinsets
1237                 if (autoBreakRows) {
1238                         LyXTextClass::size_type cur_layout = cpar(bv)->layout;
1239           
1240                         // Derive layout number from given argument (string)
1241                         // and current buffer's textclass (number). */    
1242                         LyXTextClassList::ClassList::size_type tclass =
1243                                 bv->buffer()->params.textclass;
1244                         std::pair <bool, LyXTextClass::size_type> layout = 
1245                                 textclasslist.NumberOfLayout(tclass, arg);
1246
1247                         // If the entry is obsolete, use the new one instead.
1248                         if (layout.first) {
1249                                 string obs = textclasslist.Style(tclass,layout.second).
1250                                         obsoleted_by();
1251                                 if (!obs.empty()) 
1252                                         layout = textclasslist.NumberOfLayout(tclass, obs);
1253                         }
1254
1255                         // see if we found the layout number:
1256                         if (!layout.first) {
1257                                 string const msg = string(N_("Layout ")) + arg + N_(" not known");
1258                                 bv->owner()->getLyXFunc()->dispatch(LFUN_MESSAGE, msg);
1259                                 break;
1260                         }
1261
1262                         if (cur_layout != layout.second) {
1263                                 cur_layout = layout.second;
1264                                 lt->setLayout(bv, layout.second);
1265                                 bv->owner()->setLayout(cpar(bv)->getLayout());
1266                                 updateLocal(bv, CURSOR_PAR, true);
1267                         }
1268                 } else {
1269                         // reset the layout box
1270                         bv->owner()->setLayout(cpar(bv)->getLayout());
1271                 }
1272                 break;
1273         case LFUN_PARAGRAPH_SPACING:
1274                 // This one is absolutely not working. When fiddling with this
1275                 // it also seems to me that the paragraphs inside the insettext
1276                 // inherit bufferparams/paragraphparams in a strange way. (Lgb)
1277         {
1278                 Paragraph * par = lt->cursor.par();
1279                 Spacing::Space cur_spacing = par->params().spacing().getSpace();
1280                 float cur_value = 1.0;
1281                 if (cur_spacing == Spacing::Other) {
1282                         cur_value = par->params().spacing().getValue();
1283                 }
1284                                 
1285                 istringstream istr(arg.c_str());
1286                 string tmp;
1287                 istr >> tmp;
1288                 Spacing::Space new_spacing = cur_spacing;
1289                 float new_value = cur_value;
1290                 if (tmp.empty()) {
1291                         lyxerr << "Missing argument to `paragraph-spacing'"
1292                                    << endl;
1293                 } else if (tmp == "single") {
1294                         new_spacing = Spacing::Single;
1295                 } else if (tmp == "onehalf") {
1296                         new_spacing = Spacing::Onehalf;
1297                 } else if (tmp == "double") {
1298                         new_spacing = Spacing::Double;
1299                 } else if (tmp == "other") {
1300                         new_spacing = Spacing::Other;
1301                         float tmpval = 0.0;
1302                         istr >> tmpval;
1303                         lyxerr << "new_value = " << tmpval << endl;
1304                         if (tmpval != 0.0)
1305                                 new_value = tmpval;
1306                 } else if (tmp == "default") {
1307                         new_spacing = Spacing::Default;
1308                 } else {
1309                         lyxerr << _("Unknown spacing argument: ")
1310                                    << arg << endl;
1311                 }
1312                 if (cur_spacing != new_spacing || cur_value != new_value) {
1313                         par->params().spacing(Spacing(new_spacing, new_value));
1314                         updateLocal(bv, CURSOR_PAR, true);
1315                 }
1316         }
1317         break;
1318         
1319         default:
1320                 if (!bv->Dispatch(action, arg))
1321                         result = UNDISPATCHED;
1322                 break;
1323         }
1324
1325         /// If the action has deleted all text in the inset, we need to change the
1326         // language to the language of the surronding text.
1327         if (!was_empty && par->size() == 0 && !par->next()) {
1328                 LyXFont font(LyXFont::ALL_IGNORE);
1329                 font.setLanguage(bv->getParentLanguage(this));
1330                 setFont(bv, font, false);
1331         }
1332
1333         if (result < FINISHED) {
1334                 showInsetCursor(bv);
1335         } else
1336                 bv->unlockInset(this);
1337         if (clear)
1338                 lt = 0;
1339         return result;
1340 }
1341
1342
1343 int InsetText::latex(Buffer const * buf, ostream & os, bool, bool) const
1344 {
1345         TexRow texrow;
1346         buf->latexParagraphs(os, par, 0, texrow);
1347         return texrow.rows();
1348 }
1349
1350
1351 int InsetText::ascii(Buffer const * buf, ostream & os, int linelen) const
1352 {
1353         Paragraph * p = par;
1354         unsigned int lines = 0;
1355         
1356         while (p) {
1357                 string const tmp = buf->asciiParagraph(p, linelen);
1358                 lines += countChar(tmp, '\n');
1359                 os << tmp;
1360                 p = p->next();
1361         }
1362         return lines;
1363 }
1364
1365
1366 int InsetText::docbook(Buffer const * buf, ostream & os) const
1367 {
1368         Paragraph * p = par;
1369         unsigned int lines = 0;
1370
1371         vector<string> environment_stack(10);
1372         vector<string> environment_inner(10);
1373         
1374         int const command_depth = 0;
1375         string item_name;
1376         
1377         Paragraph::depth_type depth = 0; // paragraph depth
1378
1379         while (p) {
1380                 string sgmlparam;
1381                 int desc_on = 0; // description mode
1382
1383                 LyXLayout const & style =
1384                         textclasslist.Style(buf->params.textclass,
1385                                             p->layout);
1386
1387                 // environment tag closing
1388                 for (; depth > p->params().depth(); --depth) {
1389                         if (environment_inner[depth] != "!-- --") {
1390                                 item_name = "listitem";
1391                                 buf->sgmlCloseTag(os, command_depth + depth,
1392                                              item_name);
1393                                 if (environment_inner[depth] == "varlistentry")
1394                                         buf->sgmlCloseTag(os, depth+command_depth,
1395                                                      environment_inner[depth]);
1396                         }
1397                         buf->sgmlCloseTag(os, depth + command_depth,
1398                                      environment_stack[depth]);
1399                         environment_stack[depth].erase();
1400                         environment_inner[depth].erase();
1401                 }
1402
1403                 if (depth == p->params().depth()
1404                    && environment_stack[depth] != style.latexname()
1405                    && !environment_stack[depth].empty()) {
1406                         if (environment_inner[depth] != "!-- --") {
1407                                 item_name= "listitem";
1408                                 buf->sgmlCloseTag(os, command_depth+depth,
1409                                                   item_name);
1410                                 if (environment_inner[depth] == "varlistentry")
1411                                         buf->sgmlCloseTag(os,
1412                                                           depth + command_depth,
1413                                                           environment_inner[depth]);
1414                         }
1415                         
1416                         buf->sgmlCloseTag(os, depth + command_depth,
1417                                           environment_stack[depth]);
1418                         
1419                         environment_stack[depth].erase();
1420                         environment_inner[depth].erase();
1421                 }
1422
1423                 // Write opening SGML tags.
1424                 switch (style.latextype) {
1425                 case LATEX_PARAGRAPH:
1426                         buf->sgmlOpenTag(os, depth + command_depth,
1427                                          style.latexname());
1428                         break;
1429
1430                 case LATEX_COMMAND:
1431                         buf->sgmlError(p, 0,
1432                                        _("Error : LatexType Command not allowed here.\n"));
1433                         return -1;
1434                         break;
1435
1436                 case LATEX_ENVIRONMENT:
1437                 case LATEX_ITEM_ENVIRONMENT:
1438                         if (depth < p->params().depth()) {
1439                                 depth = p->params().depth();
1440                                 environment_stack[depth].erase();
1441                         }
1442
1443                         if (environment_stack[depth] != style.latexname()) {
1444                                 if(environment_stack.size() == depth + 1) {
1445                                         environment_stack.push_back("!-- --");
1446                                         environment_inner.push_back("!-- --");
1447                                 }
1448                                 environment_stack[depth] = style.latexname();
1449                                 environment_inner[depth] = "!-- --";
1450                                 buf->sgmlOpenTag(os, depth + command_depth,
1451                                                  environment_stack[depth]);
1452                         } else {
1453                                 if (environment_inner[depth] != "!-- --") {
1454                                         item_name= "listitem";
1455                                         buf->sgmlCloseTag(os,
1456                                                           command_depth + depth,
1457                                                           item_name);
1458                                         if (environment_inner[depth] == "varlistentry")
1459                                                 buf->sgmlCloseTag(os,
1460                                                                   depth + command_depth,
1461                                                                   environment_inner[depth]);
1462                                 }
1463                         }
1464                         
1465                         if (style.latextype == LATEX_ENVIRONMENT) {
1466                                 if (!style.latexparam().empty()) {
1467                                         if(style.latexparam() == "CDATA")
1468                                                 os << "<![CDATA[";
1469                                         else
1470                                                 buf->sgmlOpenTag(os, depth + command_depth,
1471                                                                  style.latexparam());
1472                                 }
1473                                 break;
1474                         }
1475
1476                         desc_on = (style.labeltype == LABEL_MANUAL);
1477
1478                         if (desc_on)
1479                                 environment_inner[depth]= "varlistentry";
1480                         else
1481                                 environment_inner[depth]= "listitem";
1482
1483                         buf->sgmlOpenTag(os, depth + 1 + command_depth,
1484                                          environment_inner[depth]);
1485
1486                         if (desc_on) {
1487                                 item_name= "term";
1488                                 buf->sgmlOpenTag(os, depth + 1 + command_depth,
1489                                                  item_name);
1490                         } else {
1491                                 item_name= "para";
1492                                 buf->sgmlOpenTag(os, depth + 1 + command_depth,
1493                                                  item_name);
1494                         }
1495                         break;
1496                 default:
1497                         buf->sgmlOpenTag(os, depth + command_depth,
1498                                          style.latexname());
1499                         break;
1500                 }
1501
1502                 buf->simpleDocBookOnePar(os, p, desc_on,
1503                                          depth + 1 + command_depth);
1504                 p = p->next();
1505
1506                 string end_tag;
1507                 // write closing SGML tags
1508                 switch (style.latextype) {
1509                 case LATEX_ENVIRONMENT:
1510                         if (!style.latexparam().empty()) {
1511                                 if(style.latexparam() == "CDATA")
1512                                         os << "]]>";
1513                                 else
1514                                         buf->sgmlCloseTag(os, depth + command_depth,
1515                                                           style.latexparam());
1516                         }
1517                         break;
1518                 case LATEX_ITEM_ENVIRONMENT:
1519                         if (desc_on == 1) break;
1520                         end_tag= "para";
1521                         buf->sgmlCloseTag(os, depth + 1 + command_depth, end_tag);
1522                         break;
1523                 case LATEX_PARAGRAPH:
1524                         buf->sgmlCloseTag(os, depth + command_depth, style.latexname());
1525                         break;
1526                 default:
1527                         buf->sgmlCloseTag(os, depth + command_depth, style.latexname());
1528                         break;
1529                 }
1530         }
1531
1532         // Close open tags
1533         for (int d = depth; d >= 0; --d) {
1534                 if (!environment_stack[depth].empty()) {
1535                         if (environment_inner[depth] != "!-- --") {
1536                                 item_name = "listitem";
1537                                 buf->sgmlCloseTag(os, command_depth + depth,
1538                                                   item_name);
1539                                if (environment_inner[depth] == "varlistentry")
1540                                        buf->sgmlCloseTag(os, depth + command_depth,
1541                                                          environment_inner[depth]);
1542                         }
1543                         
1544                         buf->sgmlCloseTag(os, depth + command_depth,
1545                                           environment_stack[depth]);
1546                 }
1547         }
1548         
1549         return lines;
1550 }
1551
1552
1553 void InsetText::validate(LaTeXFeatures & features) const
1554 {
1555         Paragraph * p = par;
1556         while (p) {
1557                 p->validate(features);
1558                 p = p->next();
1559         }
1560 }
1561
1562
1563 int InsetText::beginningOfMainBody(Buffer const * buf, Paragraph * p) const
1564 {
1565         if (textclasslist.Style(buf->params.textclass,
1566                                 p->getLayout()).labeltype != LABEL_MANUAL)
1567                 return 0;
1568         else
1569                 return p->beginningOfMainBody();
1570 }
1571
1572
1573 void InsetText::getCursorPos(BufferView * bv,
1574                              int & x, int & y) const
1575 {
1576         if (the_locking_inset) {
1577                 the_locking_inset->getCursorPos(bv, x, y);
1578                 return;
1579         }
1580         x = cx(bv);
1581         y = cy(bv);
1582 }
1583
1584
1585 unsigned int InsetText::insetInInsetY()
1586 {
1587         if (!the_locking_inset)
1588                 return 0;
1589
1590         return (inset_y + the_locking_inset->insetInInsetY());
1591 }
1592
1593
1594 void InsetText::toggleInsetCursor(BufferView * bv)
1595 {
1596         if (the_locking_inset) {
1597                 the_locking_inset->toggleInsetCursor(bv);
1598                 return;
1599         }
1600
1601         LyXFont const font(getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv)));
1602
1603         int const asc = lyxfont::maxAscent(font);
1604         int const desc = lyxfont::maxDescent(font);
1605   
1606         if (isCursorVisible())
1607                 bv->hideLockedInsetCursor();
1608         else
1609                 bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1610         toggleCursorVisible();
1611 }
1612
1613
1614 void InsetText::showInsetCursor(BufferView * bv, bool show)
1615 {
1616         if (the_locking_inset) {
1617                 the_locking_inset->showInsetCursor(bv, show);
1618                 return;
1619         }
1620         if (!isCursorVisible()) {
1621                 LyXFont const font =
1622                         getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv));
1623         
1624                 int const asc = lyxfont::maxAscent(font);
1625                 int const desc = lyxfont::maxDescent(font);
1626
1627                 bv->fitLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1628                 if (show)
1629                         bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1630                 setCursorVisible(true);
1631         }
1632 }
1633
1634
1635 void InsetText::hideInsetCursor(BufferView * bv)
1636 {
1637         if (isCursorVisible()) {
1638                 bv->hideLockedInsetCursor();
1639                 setCursorVisible(false);
1640         }
1641         if (the_locking_inset)
1642                 the_locking_inset->hideInsetCursor(bv);
1643 }
1644
1645
1646 void InsetText::fitInsetCursor(BufferView * bv) const
1647 {
1648         if (the_locking_inset) {
1649                 the_locking_inset->fitInsetCursor(bv);
1650                 return;
1651         }
1652         LyXFont const font =
1653                 getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv));
1654         
1655         int const asc = lyxfont::maxAscent(font);
1656         int const desc = lyxfont::maxDescent(font);
1657
1658         bv->fitLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1659 }
1660
1661
1662 UpdatableInset::RESULT
1663 InsetText::moveRight(BufferView * bv, bool activate_inset, bool selecting)
1664 {
1665         if (getLyXText(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
1666                 return moveLeftIntern(bv, false, activate_inset, selecting);
1667         else
1668                 return moveRightIntern(bv, false, activate_inset, selecting);
1669 }
1670
1671
1672 UpdatableInset::RESULT
1673 InsetText::moveLeft(BufferView * bv, bool activate_inset, bool selecting)
1674 {
1675         if (getLyXText(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
1676                 return moveRightIntern(bv, true, activate_inset, selecting);
1677         else
1678                 return moveLeftIntern(bv, true, activate_inset, selecting);
1679 }
1680
1681
1682 UpdatableInset::RESULT
1683 InsetText::moveRightIntern(BufferView * bv, bool behind, 
1684                            bool activate_inset, bool selecting)
1685 {
1686         if (!cpar(bv)->next() && (cpos(bv) >= cpar(bv)->size()))
1687                 return FINISHED_RIGHT;
1688         if (activate_inset && checkAndActivateInset(bv, behind))
1689                 return DISPATCHED;
1690         getLyXText(bv)->cursorRight(bv);
1691         if (!selecting)
1692                 getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor;
1693         return DISPATCHED_NOUPDATE;
1694 }
1695
1696
1697 UpdatableInset::RESULT
1698 InsetText::moveLeftIntern(BufferView * bv, bool behind,
1699                           bool activate_inset, bool selecting)
1700 {
1701         if (!cpar(bv)->previous() && (cpos(bv) <= 0))
1702                 return FINISHED;
1703         getLyXText(bv)->cursorLeft(bv);
1704         if (!selecting)
1705                 getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor;
1706         if (activate_inset && checkAndActivateInset(bv, behind))
1707                 return DISPATCHED;
1708         return DISPATCHED_NOUPDATE;
1709 }
1710
1711
1712 UpdatableInset::RESULT
1713 InsetText::moveUp(BufferView * bv)
1714 {
1715         if (!crow(bv)->previous())
1716                 return FINISHED_UP;
1717         getLyXText(bv)->cursorUp(bv);
1718         return DISPATCHED_NOUPDATE;
1719 }
1720
1721
1722 UpdatableInset::RESULT
1723 InsetText::moveDown(BufferView * bv)
1724 {
1725         if (!crow(bv)->next())
1726                 return FINISHED_DOWN;
1727         getLyXText(bv)->cursorDown(bv);
1728         return DISPATCHED_NOUPDATE;
1729 }
1730
1731
1732 bool InsetText::insertInset(BufferView * bv, Inset * inset)
1733 {
1734         if (the_locking_inset) {
1735                 if (the_locking_inset->insetAllowed(inset))
1736                         return the_locking_inset->insertInset(bv, inset);
1737                 return false;
1738         }
1739         inset->setOwner(this);
1740         hideInsetCursor(bv);
1741
1742         bool clear = false;
1743         if (!lt) {
1744                 lt = getLyXText(bv);
1745                 clear = true;
1746         }
1747         lt->insertInset(bv, inset);
1748 #if 0
1749         if ((!cpar(bv)->isInset(cpos(bv))) ||
1750                 (cpar(bv)->getInset(cpos(bv)) != inset))
1751                 lt->cursorLeft(bv);
1752 #endif
1753         bv->fitCursor();
1754         updateLocal(bv, CURSOR_PAR|CURSOR, true);
1755         showInsetCursor(bv);
1756         if (clear)
1757                 lt = 0;
1758         return true;
1759 }
1760
1761
1762 bool InsetText::insetAllowed(Inset::Code code) const
1763 {
1764         if (the_locking_inset)
1765                 return the_locking_inset->insetAllowed(code);
1766         return true;
1767 }
1768
1769
1770 UpdatableInset * InsetText::getLockingInset() const
1771 {
1772         return the_locking_inset ? the_locking_inset->getLockingInset() :
1773                 const_cast<InsetText *>(this);
1774 }
1775
1776
1777 UpdatableInset * InsetText::getFirstLockingInsetOfType(Inset::Code c)
1778 {
1779         if (c == lyxCode())
1780                 return this;
1781         if (the_locking_inset)
1782                 return the_locking_inset->getFirstLockingInsetOfType(c);
1783         return 0;
1784 }
1785
1786
1787 bool InsetText::showInsetDialog(BufferView * bv) const
1788 {
1789         if (the_locking_inset)
1790                 return the_locking_inset->showInsetDialog(bv);
1791         return false;
1792 }
1793
1794
1795 std::vector<string> const InsetText::getLabelList() const 
1796 {
1797         std::vector<string> label_list;
1798
1799         Paragraph * tpar = par;
1800         while (tpar) {
1801                 Paragraph::inset_iterator beg = tpar->inset_iterator_begin();
1802                 Paragraph::inset_iterator end = tpar->inset_iterator_end();
1803                 for (; beg != end; ++beg) {
1804                         std::vector<string> const l = (*beg)->getLabelList();
1805                         label_list.insert(label_list.end(), l.begin(), l.end());
1806                 }
1807                 tpar = tpar->next();
1808         }
1809         return label_list;
1810 }
1811
1812
1813 void InsetText::setFont(BufferView * bv, LyXFont const & font, bool toggleall,
1814                         bool selectall)
1815 {
1816         if (the_locking_inset) {
1817                 the_locking_inset->setFont(bv, font, toggleall, selectall);
1818                 return;
1819         }
1820         if ((!par->next() && !par->size()) || !cpar(bv)->size()) {
1821                 getLyXText(bv)->setFont(bv, font, toggleall);
1822                 return;
1823         }
1824         bool clear = false;
1825         if (!lt) {
1826                 lt = getLyXText(bv);
1827                 clear = true;
1828         }
1829         if (lt->selection.set()) {
1830                 setUndo(bv, Undo::EDIT, lt->cursor.par(), lt->cursor.par()->next());
1831         }
1832         if (selectall)
1833                 selectAll(bv);
1834         lt->toggleFree(bv, font, toggleall);
1835         if (selectall)
1836                 lt->clearSelection();
1837         bv->fitCursor();
1838         if (selectall || lt->selection.set())
1839                 updateLocal(bv, FULL, true);
1840         else
1841                 updateLocal(bv, CURSOR_PAR, true);
1842         if (clear)
1843                 lt = 0;
1844 }
1845
1846
1847 bool InsetText::checkAndActivateInset(BufferView * bv, bool behind)
1848 {
1849         if (cpar(bv)->isInset(cpos(bv))) {
1850                 unsigned int x;
1851                 unsigned int y;
1852                 Inset * inset =
1853                         static_cast<UpdatableInset*>(cpar(bv)->getInset(cpos(bv)));
1854                 if (!isHighlyEditableInset(inset))
1855                         return false;
1856                 LyXFont const font =
1857                         getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv));
1858                 if (behind) {
1859                         x = inset->width(bv, font);
1860                         y = font.isRightToLeft() ? 0 : inset->descent(bv, font);
1861                 } else {
1862                         x = 0;
1863                         y = font.isRightToLeft() ? inset->descent(bv, font) : 0;
1864                 }
1865                 //inset_x = cx(bv) - top_x + drawTextXOffset;
1866                 //inset_y = cy(bv) + drawTextYOffset;
1867                 inset->edit(bv, x, y, 0);
1868                 if (!the_locking_inset)
1869                         return false;
1870                 updateLocal(bv, CURSOR, false);
1871                 return true;
1872         }
1873         return false;
1874 }
1875
1876
1877 bool InsetText::checkAndActivateInset(BufferView * bv, int x, int y,
1878                                       int button)
1879 {
1880         x -= drawTextXOffset;
1881         int dummyx = x;
1882         int dummyy = y + insetAscent;
1883         Inset * inset = bv->checkInsetHit(getLyXText(bv), dummyx, dummyy, button);
1884
1885         if (inset) {
1886                 if (x < 0)
1887                         x = insetWidth;
1888                 if (y < 0)
1889                         y = insetDescent;
1890                 inset_x = cx(bv) - top_x + drawTextXOffset;
1891                 inset_y = cy(bv) + drawTextYOffset;
1892                 inset->edit(bv, x - inset_x, y - inset_y, button);
1893                 if (!the_locking_inset)
1894                         return false;
1895                 updateLocal(bv, CURSOR, false);
1896                 return true;
1897         }
1898         return false;
1899 }
1900
1901
1902 int InsetText::getMaxWidth(BufferView * bv, UpdatableInset const * inset) const
1903 {
1904 #if 0
1905         int w = UpdatableInset::getMaxWidth(bv, inset);
1906         if (w < 0) {
1907                 return -1;
1908         }
1909         if (owner()) {
1910                 w = w - top_x + owner()->x();
1911                 return w;
1912         }
1913         w -= (2 * TEXT_TO_INSET_OFFSET);
1914         return w - top_x;
1915 #else
1916         return UpdatableInset::getMaxWidth(bv, inset);
1917 #endif
1918 }
1919
1920
1921 void InsetText::setParagraphData(Paragraph * p)
1922 {
1923         // we have to unlock any locked inset otherwise we're in troubles
1924         the_locking_inset = 0;
1925         while (par) {
1926                 Paragraph * tmp = par->next();
1927                 delete par;
1928                 par = tmp;
1929         }
1930
1931         par = new Paragraph(*p, false);
1932         par->setInsetOwner(this);
1933         Paragraph * np = par;
1934         while (p->next()) {
1935                 p = p->next();
1936                 np->next(new Paragraph(*p, false));
1937                 np->next()->previous(np);
1938                 np = np->next();
1939                 np->setInsetOwner(this);
1940         }
1941         need_update = INIT;
1942 }
1943
1944
1945 void InsetText::setText(string const & data)
1946 {
1947         clear();
1948         LyXFont font(LyXFont::ALL_SANE);
1949         for (unsigned int i=0; i < data.length(); ++i)
1950                 par->insertChar(i, data[i], font);
1951 }
1952
1953
1954 void InsetText::setAutoBreakRows(bool flag)
1955 {
1956         if (flag != autoBreakRows) {
1957                 autoBreakRows = flag;
1958                 if (!flag)
1959                         removeNewlines();
1960                 need_update = INIT;
1961         }
1962 }
1963
1964
1965 void InsetText::setDrawFrame(BufferView * bv, DrawFrame how)
1966 {
1967         if (how != drawFrame_) {
1968                 drawFrame_ = how;
1969                 if (bv)
1970                         updateLocal(bv, DRAW_FRAME, false);
1971         }
1972 }
1973
1974
1975 void InsetText::setFrameColor(BufferView * bv, LColor::color col)
1976 {
1977         if (frame_color != col) {
1978                 frame_color = col;
1979                 if (bv)
1980                         updateLocal(bv, DRAW_FRAME, false);
1981         }
1982 }
1983
1984
1985 int InsetText::cx(BufferView * bv) const
1986 {
1987         bool clear = false;
1988         if (!lt) {
1989                 lt = getLyXText(bv);
1990                 clear = true;
1991         }
1992         int x = lt->cursor.x() + top_x + TEXT_TO_INSET_OFFSET;
1993         if (the_locking_inset) {
1994                 LyXFont font = lt->getFont(bv->buffer(),
1995                                              lt->cursor.par(),
1996                                              lt->cursor.pos());
1997                 if (font.isVisibleRightToLeft())
1998                         x -= the_locking_inset->width(bv, font);
1999         }
2000         if (clear)
2001                 lt = 0;
2002         return x;
2003 }
2004
2005
2006 int InsetText::cy(BufferView * bv) const
2007 {
2008         LyXFont font;
2009         return getLyXText(bv)->cursor.y() - ascent(bv, font) + TEXT_TO_INSET_OFFSET;
2010 }
2011
2012
2013 pos_type InsetText::cpos(BufferView * bv) const
2014 {
2015         return getLyXText(bv)->cursor.pos();
2016 }
2017
2018
2019 Paragraph * InsetText::cpar(BufferView * bv) const
2020 {
2021         return getLyXText(bv)->cursor.par();
2022 }
2023
2024
2025 bool InsetText::cboundary(BufferView * bv) const
2026 {
2027         return getLyXText(bv)->cursor.boundary();
2028 }
2029
2030
2031 Row * InsetText::crow(BufferView * bv) const
2032 {
2033         return getLyXText(bv)->cursor.row();
2034 }
2035
2036
2037 LyXText * InsetText::getLyXText(BufferView const * lbv,
2038                                 bool const recursive) const
2039 {
2040         if (!recursive && (cached_bview == lbv))
2041                 return cached_text.get();
2042         
2043         // Super UGLY! (Lgb)
2044         BufferView * bv = const_cast<BufferView *>(lbv);
2045         
2046         cached_bview = bv;
2047         Cache::iterator it = cache.find(bv);
2048
2049         if (it != cache.end()) {
2050                 if (do_reinit)
2051                         reinitLyXText();
2052                 else if (do_resize)
2053                         resizeLyXText(do_resize);
2054                 if (lt || !it->second.remove) {
2055                         lyx::Assert(it->second.text.get());
2056                         cached_text = it->second.text;
2057                         if (recursive && the_locking_inset) {
2058                                 return the_locking_inset->getLyXText(bv, true);
2059                         }
2060                         return cached_text.get();
2061                 } else if (it->second.remove) {
2062                         if (locked) {
2063                                 saveLyXTextState(it->second.text.get());
2064                         } else {
2065                                 sstate.lpar = 0;
2066                         }
2067                 }
2068         }
2069         
2070         cached_text.reset(new LyXText(const_cast<InsetText *>(this)));
2071         cached_text->init(bv);
2072         restoreLyXTextState(bv, cached_text.get());
2073
2074         cache.insert(make_pair(bv, cached_text));
2075         
2076         if (the_locking_inset && recursive) {
2077                 return the_locking_inset->getLyXText(bv);
2078         }
2079         return cached_text.get();
2080 }
2081
2082
2083 void InsetText::deleteLyXText(BufferView * bv, bool recursive) const
2084 {
2085         cached_bview = 0;
2086
2087         Cache::iterator it = cache.find(bv);
2088         
2089         if (it == cache.end()) {
2090                 return;
2091         }
2092
2093         lyx::Assert(it->second.text.get());
2094
2095         it->second.remove = true;
2096         if (recursive) {
2097                 /// then remove all LyXText in text-insets
2098                 Paragraph * p = par;
2099                 for (; p; p = p->next()) {
2100                         p->deleteInsetsLyXText(bv);
2101                 }
2102         }
2103 }
2104
2105
2106 void InsetText::resizeLyXText(BufferView * bv, bool force) const
2107 {
2108         if (lt) {
2109                 // we cannot resize this because we are in use!
2110                 // so do this on the next possible getLyXText()
2111                 do_resize = bv;
2112                 return;
2113         }
2114         do_resize = 0;
2115 //      lyxerr << "InsetText::resizeLyXText\n";
2116         if (!par->next() && !par->size()) // no data, resize not neccessary!
2117                 return;
2118         // one endless line, resize normally not necessary
2119         if (!force && getMaxWidth(bv, this) < 0)
2120                 return;
2121
2122         Cache::iterator it = cache.find(bv);
2123         if (it == cache.end()) {
2124                 return;
2125         }
2126         lyx::Assert(it->second.text.get());
2127
2128         LyXText * t = it->second.text.get();
2129         saveLyXTextState(t);
2130         for (Paragraph * p = par; p; p = p->next()) {
2131                 p->resizeInsetsLyXText(bv);
2132         }
2133         t->init(bv, true);
2134         restoreLyXTextState(bv, t);
2135         if (the_locking_inset) {
2136                 inset_x = cx(bv) - top_x + drawTextXOffset;
2137                 inset_y = cy(bv) + drawTextYOffset;
2138         }
2139
2140         if (bv->screen()) {
2141                 t->first = bv->screen()->topCursorVisible(t);
2142         }
2143         if (!owner()) {
2144                 updateLocal(bv, FULL, false);
2145                 // this will scroll the screen such that the cursor becomes visible 
2146                 bv->updateScrollbar();
2147         } else {
2148                 need_update |= FULL;
2149         }
2150 }
2151
2152
2153 void InsetText::reinitLyXText() const
2154 {
2155         if (lt) {
2156                 // we cannot resize this because we are in use!
2157                 // so do this on the next possible getLyXText()
2158                 do_reinit = true;
2159                 return;
2160         }
2161         do_reinit = false;
2162         do_resize = 0;
2163 //      lyxerr << "InsetText::reinitLyXText\n";
2164         for(Cache::iterator it = cache.begin(); it != cache.end(); ++it) {
2165                 lyx::Assert(it->second.text.get());
2166
2167                 LyXText * t = it->second.text.get();
2168                 BufferView * bv = it->first;
2169
2170                 saveLyXTextState(t);
2171                 for (Paragraph * p = par; p; p = p->next()) {
2172                         p->resizeInsetsLyXText(bv);
2173                 }
2174                 t->init(bv, true);
2175                 restoreLyXTextState(bv, t);
2176                 if (the_locking_inset) {
2177                         inset_x = cx(bv) - top_x + drawTextXOffset;
2178                         inset_y = cy(bv) + drawTextYOffset;
2179                 }
2180                 if (bv->screen()) {
2181                         t->first = bv->screen()->topCursorVisible(t);
2182                 }
2183                 if (!owner()) {
2184                         updateLocal(bv, FULL, false);
2185                         // this will scroll the screen such that the cursor becomes visible 
2186                         bv->updateScrollbar();
2187                 } else {
2188                         need_update = FULL;
2189                 }
2190         }
2191 }
2192
2193
2194 void InsetText::removeNewlines()
2195 {
2196         for (Paragraph * p = par; p; p = p->next()) {
2197                 for (int i = 0; i < p->size(); ++i) {
2198                         if (p->getChar(i) == Paragraph::META_NEWLINE)
2199                                 p->erase(i);
2200                 }
2201         }
2202 }
2203
2204
2205 bool InsetText::nodraw() const
2206 {
2207         if (the_locking_inset)
2208                 return the_locking_inset->nodraw();
2209         return UpdatableInset::nodraw();
2210 }
2211
2212
2213 int InsetText::scroll(bool recursive) const
2214 {
2215         int sx = UpdatableInset::scroll(false);
2216
2217         if (recursive && the_locking_inset)
2218                 sx += the_locking_inset->scroll(recursive);
2219
2220         return sx;
2221 }
2222
2223
2224 bool InsetText::doClearArea() const
2225 {
2226         return !locked || (need_update & (FULL|INIT));
2227 }
2228
2229
2230 void InsetText::selectAll(BufferView * bv)
2231 {
2232         getLyXText(bv)->cursorTop(bv);
2233         getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor;
2234         getLyXText(bv)->cursorBottom(bv);
2235         getLyXText(bv)->setSelection(bv);
2236 }
2237
2238
2239 void InsetText::clearSelection(BufferView * bv)
2240 {
2241         getLyXText(bv)->clearSelection();
2242 }
2243
2244
2245 void InsetText::clearInset(Painter & pain, int baseline, bool & cleared) const
2246 {
2247         int w = insetWidth;
2248         int h = insetAscent + insetDescent;
2249         int ty = baseline - insetAscent;
2250         
2251         if (ty < 0) {
2252                 h += ty;
2253                 ty = 0;
2254         }
2255         if ((ty + h) > pain.paperHeight())
2256                 h = pain.paperHeight();
2257         if ((top_x + drawTextXOffset + w) > pain.paperWidth())
2258                 w = pain.paperWidth();
2259 //      w -= TEXT_TO_INSET_OFFSET;
2260         pain.fillRectangle(top_x, ty, w+1, h+1, backgroundColor());
2261         cleared = true;
2262         need_update = FULL;
2263         frame_is_visible = false;
2264 }
2265
2266
2267 Paragraph * InsetText::getParFromID(int id) const
2268 {
2269 #if 0
2270         Paragraph * result = par;
2271         Paragraph * ires = 0;
2272         while (result && result->id() != id) {
2273                 if ((ires = result->getParFromID(id)))
2274                         return ires;
2275                 result = result->next();
2276         }
2277         return result;
2278 #else
2279         Paragraph * tmp = par;
2280         while (tmp) {
2281                 int tmp_id = tmp->id();
2282                 lyxerr << "Looking at paragraph: " << tmp_id << endl;
2283                 if (tmp->id() == id) {
2284                         return tmp;
2285                 }
2286                 Paragraph * tmp2 = tmp->getParFromID(id);
2287                 if (tmp2 != 0) {
2288                         return tmp2;
2289                 }
2290                 tmp = tmp->next();
2291         }
2292         return 0;
2293 #endif
2294 }
2295
2296
2297 Paragraph * InsetText::firstParagraph() const
2298 {
2299         Paragraph * result;
2300         if (the_locking_inset)
2301                 if ((result = the_locking_inset->firstParagraph()))
2302                         return result;
2303         return par;
2304 }
2305
2306
2307 Paragraph * InsetText::getFirstParagraph(int i) const
2308 {
2309         return (i == 0) ? par : 0;
2310 }
2311
2312
2313 LyXCursor const & InsetText::cursor(BufferView * bv) const
2314 {
2315                 if (the_locking_inset)
2316                                 return the_locking_inset->cursor(bv);
2317                 return getLyXText(bv)->cursor;
2318 }
2319
2320
2321 Paragraph * InsetText::paragraph() const
2322 {
2323         return par;
2324 }
2325
2326
2327 void InsetText::paragraph(Paragraph * p)
2328 {
2329         par = p;
2330 #if 0
2331         // we now have to update/redraw all instances
2332         for (Cache::iterator cit = cache.begin(); cit != cache.end(); ++cit) {
2333                 delete cit->second;
2334                 cit->second = 0;
2335         }
2336 #endif
2337         // redraw myself when asked for
2338         need_update = INIT;
2339 }
2340
2341
2342 Inset * InsetText::getInsetFromID(int id_arg) const
2343 {
2344         if (id_arg == id())
2345                 return const_cast<InsetText *>(this);
2346
2347         Paragraph * lp = par;
2348
2349         while(lp) {
2350                 for (Paragraph::inset_iterator it = lp->inset_iterator_begin(),
2351                          en = lp->inset_iterator_end();
2352                          it != en; ++it)
2353                 {
2354                         if ((*it)->id() == id_arg)
2355                                 return *it;
2356                         Inset * in = (*it)->getInsetFromID(id_arg);
2357                         if (in)
2358                                 return in;
2359                 }
2360                 lp = lp->next();
2361         }
2362         return 0;
2363 }
2364
2365
2366 string const InsetText::selectNextWordToSpellcheck(BufferView * bv, float & value) const
2367 {
2368         bool clear = false;
2369         string str;
2370
2371         if (!lt) {
2372                 lt = getLyXText(bv);
2373                 clear = true;
2374         }
2375         if (the_locking_inset) {
2376                 str = the_locking_inset->selectNextWordToSpellcheck(bv, value);
2377                 if (!str.empty()) {
2378                         value += cy(bv);
2379                         if (clear)
2380                                 lt = 0;
2381                         return str;
2382                 }
2383 #warning Dekel please have a look on this one RTL? (Jug)
2384 #warning DEKEL!
2385                 // we have to go on checking so move cusor to the right
2386                 lt->cursor.pos(lt->cursor.pos() + 1);
2387         }
2388         str = lt->selectNextWordToSpellcheck(bv, value);
2389         if (str.empty())
2390                 bv->unlockInset(const_cast<InsetText *>(this));
2391         else
2392                 value = cy(bv);
2393         if (clear)
2394                 lt = 0;
2395         return str;
2396 }
2397
2398
2399 void InsetText::selectSelectedWord(BufferView * bv)
2400 {
2401         if (the_locking_inset) {
2402                 the_locking_inset->selectSelectedWord(bv);
2403                 return;
2404         }
2405         getLyXText(bv)->selectSelectedWord(bv);
2406         updateLocal(bv, SELECTION, false);
2407 }
2408
2409
2410 void InsetText::toggleSelection(BufferView * bv, bool kill_selection)
2411 {
2412         if (the_locking_inset) {
2413                 the_locking_inset->toggleSelection(bv, kill_selection);
2414         }
2415         bool clear = false;
2416         if (!lt) {
2417                 lt = getLyXText(bv);
2418                 clear = true;
2419         }
2420
2421         int x = top_x + TEXT_TO_INSET_OFFSET;
2422
2423         int y = 0;
2424         Row * row = lt->getRowNearY(y);
2425         int y_offset = top_baseline - row->ascent_of_text();
2426         y = y_offset;
2427         while ((row != 0) && ((y+row->height()) <= 0)) {
2428                 y += row->height();
2429                 row = row->next();
2430         }
2431         if (y_offset < 0)
2432                 y_offset = y;
2433         
2434         if (need_update & SELECTION)
2435                 need_update = NONE;
2436         bv->screen()->toggleSelection(lt, bv, kill_selection, y_offset, x);
2437         if (clear)
2438                 lt = 0;
2439 }
2440
2441
2442 bool InsetText::searchForward(BufferView * bv, string const & str,
2443                               bool const & cs, bool const & mw)
2444 {
2445         if (the_locking_inset) {
2446                 if (the_locking_inset->searchForward(bv, str, cs, mw))
2447                         return true;
2448                 bool clear = false;
2449                 if (!lt) {
2450                         lt = getLyXText(bv);
2451                         clear = true;
2452                 }
2453                 Paragraph * lpar = lt->cursor.par();
2454                 pos_type pos = lt->cursor.pos();
2455                 if (pos < lpar->size() - 1)
2456                         ++pos;
2457                 else {
2458                         pos = 0;
2459                         lpar = lpar->next();
2460                 }
2461                 if (!lpar) {
2462                         if (clear)
2463                                 lt = 0;
2464                         // we have to unlock ourself in this function by default!
2465                         bv->unlockInset(const_cast<InsetText *>(this));
2466                         return false;
2467                 }
2468                 lt->setCursor(bv, lpar, pos);
2469                 if (clear)
2470                         lt = 0;
2471         }
2472         if (LyXFind(bv, str, true, true, cs , mw)) {
2473                 return true;
2474         }
2475         // we have to unlock ourself in this function by default!
2476         bv->unlockInset(const_cast<InsetText *>(this));
2477         return false;
2478 }
2479
2480 bool InsetText::searchBackward(BufferView * bv, string const & str,
2481                                bool const & cs, bool const & mw)
2482 {
2483         if (the_locking_inset)
2484                 if (the_locking_inset->searchBackward(bv, str, cs, mw))
2485                         return true;
2486         if (LyXFind(bv, str, false, true, cs, mw)) {
2487                 return true;
2488         }
2489         // we have to unlock ourself in this function by default!
2490         bv->unlockInset(const_cast<InsetText *>(this));
2491         return false;
2492 }
2493
2494
2495 bool InsetText::checkInsertChar(LyXFont & font)
2496 {
2497         if (owner())
2498                 return owner()->checkInsertChar(font);
2499         return true;
2500 }