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