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