]> git.lyx.org Git - features.git/blob - src/insets/insettext.C
Add latex_language and remove inherit_language
[features.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         bool was_empty = par->size() == 0 && !par->next();
991         no_selection = false;
992         UpdatableInset::RESULT
993                 result= UpdatableInset::localDispatch(bv, action, arg);
994         if (result != UNDISPATCHED) {
995                 return DISPATCHED;
996         }
997
998         result = DISPATCHED;
999         if ((action < 0) && arg.empty())
1000                 return FINISHED;
1001
1002         if (the_locking_inset) {
1003                 result = the_locking_inset->localDispatch(bv, action, arg);
1004                 if (result == DISPATCHED_NOUPDATE)
1005                         return result;
1006                 else if (result == DISPATCHED) {
1007                         updateLocal(bv, CURSOR_PAR, false);
1008                         return result;
1009                 } else if (result == FINISHED) {
1010                         bool dispatched = false;
1011                         switch (action) {
1012                         case LFUN_UNKNOWN_ACTION:
1013                         case LFUN_BREAKPARAGRAPH:
1014                         case LFUN_BREAKLINE:
1015                                 moveRightIntern(bv, false, false);
1016                                 break;
1017                         case LFUN_RIGHT:
1018                                 if (!getLyXText(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
1019                                         moveRightIntern(bv, false, false);
1020                                 dispatched = true;
1021                                 break;
1022                         case LFUN_LEFT:
1023                                 if (getLyXText(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
1024                                         moveRightIntern(bv, false, false);
1025                                 dispatched = true;
1026                                 break;
1027                         default:
1028                                 break;
1029                         }
1030                         the_locking_inset = 0;
1031                         if (dispatched)
1032                                 return DISPATCHED;
1033                 }
1034         }
1035         hideInsetCursor(bv);
1036         bool clear = false;
1037         if (!lt) {
1038                 lt = getLyXText(bv);
1039                 clear = true;
1040         }
1041         switch (action) {
1042         // Normal chars
1043         case LFUN_SELFINSERT:
1044                 if (bv->buffer()->isReadonly()) {
1045 //          setErrorMessage(N_("Document is read only"));
1046                         break;
1047                 }
1048                 if (!arg.empty()) {
1049                         /* Automatically delete the currently selected
1050                          * text and replace it with what is being
1051                          * typed in now. Depends on lyxrc settings
1052                          * "auto_region_delete", which defaults to
1053                          * true (on). */
1054
1055                         setUndo(bv, Undo::INSERT,
1056                                 lt->cursor.par(), lt->cursor.par()->next());
1057                         bv->setState();
1058                         if (lyxrc.auto_region_delete) {
1059                                 if (lt->selection.set()) {
1060                                         lt->cutSelection(bv, false);
1061                                 }
1062                         }
1063                         lt->clearSelection();
1064                         for (string::size_type i = 0; i < arg.length(); ++i) {
1065                                 bv->owner()->getIntl()->getTrans().TranslateAndInsert(arg[i], lt);
1066                         }
1067                 }
1068                 lt->selection.cursor = lt->cursor;
1069                 updateLocal(bv, CURSOR_PAR, true);
1070                 result = DISPATCHED_NOUPDATE;
1071                 break;
1072                 // --- Cursor Movements -----------------------------------
1073         case LFUN_RIGHTSEL:
1074                 finishUndo();
1075                 moveRight(bv, false, true);
1076                 lt->setSelection(bv);
1077                 updateLocal(bv, SELECTION, false);
1078                 break;
1079         case LFUN_RIGHT:
1080                 result = moveRight(bv);
1081                 finishUndo();
1082                 updateLocal(bv, CURSOR, false);
1083                 break;
1084         case LFUN_LEFTSEL:
1085                 finishUndo();
1086                 moveLeft(bv, false, true);
1087                 lt->setSelection(bv);
1088                 updateLocal(bv, SELECTION, false);
1089                 break;
1090         case LFUN_LEFT:
1091                 finishUndo();
1092                 result = moveLeft(bv);
1093                 updateLocal(bv, CURSOR, false);
1094                 break;
1095         case LFUN_DOWNSEL:
1096                 finishUndo();
1097                 moveDown(bv);
1098                 lt->setSelection(bv);
1099                 updateLocal(bv, SELECTION, false);
1100                 break;
1101         case LFUN_DOWN:
1102                 finishUndo();
1103                 result = moveDown(bv);
1104                 updateLocal(bv, CURSOR, false);
1105                 break;
1106         case LFUN_UPSEL:
1107                 finishUndo();
1108                 moveUp(bv);
1109                 lt->setSelection(bv);
1110                 updateLocal(bv, SELECTION, false);
1111                 break;
1112         case LFUN_UP:
1113                 finishUndo();
1114                 result = moveUp(bv);
1115                 updateLocal(bv, CURSOR, false);
1116                 break;
1117         case LFUN_HOME:
1118                 finishUndo();
1119                 lt->cursorHome(bv);
1120                 updateLocal(bv, CURSOR, false);
1121                 break;
1122         case LFUN_END:
1123                 lt->cursorEnd(bv);
1124                 updateLocal(bv, CURSOR, false);
1125                 break;
1126         case LFUN_BACKSPACE: {
1127                 setUndo(bv, Undo::DELETE,
1128                         lt->cursor.par(), lt->cursor.par()->next());
1129                 if (lt->selection.set())
1130                         lt->cutSelection(bv);
1131                 else
1132                         lt->backspace(bv);
1133                 updateLocal(bv, CURSOR_PAR, true);
1134         }
1135         break;
1136         
1137         case LFUN_DELETE: {
1138                 setUndo(bv, Undo::DELETE,
1139                         lt->cursor.par(), lt->cursor.par()->next());
1140                 if (lt->selection.set()) {
1141                         lt->cutSelection(bv);
1142                 } else {
1143                         lt->Delete(bv);
1144                 }
1145                 updateLocal(bv, CURSOR_PAR, true);
1146         }
1147         break;
1148         
1149         case LFUN_CUT: {
1150                 setUndo(bv, Undo::DELETE,
1151                         lt->cursor.par(), lt->cursor.par()->next());
1152                 lt->cutSelection(bv);
1153                 updateLocal(bv, CURSOR_PAR, true);
1154         }
1155         break;
1156
1157         case LFUN_COPY:
1158                 finishUndo();
1159                 lt->copySelection(bv);
1160                 updateLocal(bv, CURSOR_PAR, false);
1161                 break;
1162         case LFUN_PASTESELECTION:
1163         {
1164                 string const clip(bv->getClipboard());
1165         
1166                 if (clip.empty())
1167                         break;
1168                 if (arg == "paragraph") {
1169                         lt->insertStringAsParagraphs(bv, clip);
1170                 } else {
1171                         lt->insertStringAsLines(bv, clip);
1172                 }
1173                 updateLocal(bv, CURSOR_PAR, true);
1174                 break;
1175         }
1176         case LFUN_PASTE: {
1177                 if (!autoBreakRows) {
1178
1179                         if (CutAndPaste::nrOfParagraphs() > 1) {
1180                                 WriteAlert(_("Impossible operation"),
1181                                                    _("Cannot include more than one paragraph!"),
1182                                                    _("Sorry."));
1183                                 break;
1184                         }
1185                 }
1186                 setUndo(bv, Undo::INSERT,
1187                         lt->cursor.par(), lt->cursor.par()->next());
1188                 lt->pasteSelection(bv);
1189                 updateLocal(bv, CURSOR_PAR, true);
1190         }
1191         break;
1192
1193         case LFUN_BREAKPARAGRAPH:
1194                 if (!autoBreakRows) {
1195                         result = DISPATCHED;
1196                         break;
1197                 }
1198                 lt->breakParagraph(bv, 0);
1199                 updateLocal(bv, FULL, true);
1200                 break;
1201         case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
1202                 if (!autoBreakRows) {
1203                         result = DISPATCHED;
1204                         break;
1205                 }
1206                 lt->breakParagraph(bv, 1);
1207                 updateLocal(bv, FULL, true);
1208                 break;
1209
1210         case LFUN_BREAKLINE: {
1211                 if (!autoBreakRows) {
1212                         result = DISPATCHED;
1213                         break;
1214                 }
1215                 setUndo(bv, Undo::INSERT,
1216                         lt->cursor.par(), lt->cursor.par()->next());
1217                 lt->insertChar(bv, Paragraph::META_NEWLINE);
1218                 updateLocal(bv, CURSOR_PAR, true);
1219         }
1220         break;
1221
1222         case LFUN_LAYOUT:
1223                 // do not set layouts on non breakable textinsets
1224                 if (autoBreakRows) {
1225                         LyXTextClass::size_type cur_layout = cpar(bv)->layout;
1226           
1227                         // Derive layout number from given argument (string)
1228                         // and current buffer's textclass (number). */    
1229                         LyXTextClassList::ClassList::size_type tclass =
1230                                 bv->buffer()->params.textclass;
1231                         std::pair <bool, LyXTextClass::size_type> layout = 
1232                                 textclasslist.NumberOfLayout(tclass, arg);
1233
1234                         // If the entry is obsolete, use the new one instead.
1235                         if (layout.first) {
1236                                 string obs = textclasslist.Style(tclass,layout.second).
1237                                         obsoleted_by();
1238                                 if (!obs.empty()) 
1239                                         layout = textclasslist.NumberOfLayout(tclass, obs);
1240                         }
1241
1242                         // see if we found the layout number:
1243                         if (!layout.first) {
1244                                 string const msg = string(N_("Layout ")) + arg + N_(" not known");
1245                                 bv->owner()->getLyXFunc()->dispatch(LFUN_MESSAGE, msg);
1246                                 break;
1247                         }
1248
1249                         if (cur_layout != layout.second) {
1250                                 cur_layout = layout.second;
1251                                 lt->setLayout(bv, layout.second);
1252                                 bv->owner()->setLayout(cpar(bv)->getLayout());
1253                                 updateLocal(bv, CURSOR_PAR, true);
1254                         }
1255                 } else {
1256                         // reset the layout box
1257                         bv->owner()->setLayout(cpar(bv)->getLayout());
1258                 }
1259                 break;
1260         case LFUN_PARAGRAPH_SPACING:
1261                 // This one is absolutely not working. When fiddling with this
1262                 // it also seems to me that the paragraphs inside the insettext
1263                 // inherit bufferparams/paragraphparams in a strange way. (Lgb)
1264         {
1265                 Paragraph * par = lt->cursor.par();
1266                 Spacing::Space cur_spacing = par->params().spacing().getSpace();
1267                 float cur_value = 1.0;
1268                 if (cur_spacing == Spacing::Other) {
1269                         cur_value = par->params().spacing().getValue();
1270                 }
1271                                 
1272                 istringstream istr(arg.c_str());
1273                 string tmp;
1274                 istr >> tmp;
1275                 Spacing::Space new_spacing = cur_spacing;
1276                 float new_value = cur_value;
1277                 if (tmp.empty()) {
1278                         lyxerr << "Missing argument to `paragraph-spacing'"
1279                                    << endl;
1280                 } else if (tmp == "single") {
1281                         new_spacing = Spacing::Single;
1282                 } else if (tmp == "onehalf") {
1283                         new_spacing = Spacing::Onehalf;
1284                 } else if (tmp == "double") {
1285                         new_spacing = Spacing::Double;
1286                 } else if (tmp == "other") {
1287                         new_spacing = Spacing::Other;
1288                         float tmpval = 0.0;
1289                         istr >> tmpval;
1290                         lyxerr << "new_value = " << tmpval << endl;
1291                         if (tmpval != 0.0)
1292                                 new_value = tmpval;
1293                 } else if (tmp == "default") {
1294                         new_spacing = Spacing::Default;
1295                 } else {
1296                         lyxerr << _("Unknown spacing argument: ")
1297                                    << arg << endl;
1298                 }
1299                 if (cur_spacing != new_spacing || cur_value != new_value) {
1300                         par->params().spacing(Spacing(new_spacing, new_value));
1301                         updateLocal(bv, CURSOR_PAR, true);
1302                 }
1303         }
1304         break;
1305         
1306         default:
1307                 if (!bv->Dispatch(action, arg))
1308                         result = UNDISPATCHED;
1309                 break;
1310         }
1311
1312         /// If the action has deleted all text in the inset, we need to change the
1313         // language to the language of the surronding text.
1314         if (!was_empty && par->size() == 0 && !par->next()) {
1315                 LyXFont font(LyXFont::ALL_IGNORE);
1316                 font.setLanguage(bv->getParentLanguage(this));
1317                 setFont(bv, font, false);
1318         }
1319
1320         if (result != FINISHED) {
1321                 showInsetCursor(bv);
1322         } else
1323                 bv->unlockInset(this);
1324         if (clear)
1325                 lt = 0;
1326         return result;
1327 }
1328
1329
1330 int InsetText::latex(Buffer const * buf, ostream & os, bool, bool) const
1331 {
1332         TexRow texrow;
1333         buf->latexParagraphs(os, par, 0, texrow);
1334         return texrow.rows();
1335 }
1336
1337
1338 int InsetText::ascii(Buffer const * buf, ostream & os, int linelen) const
1339 {
1340         Paragraph * p = par;
1341         unsigned int lines = 0;
1342         
1343         while (p) {
1344                 string const tmp = buf->asciiParagraph(p, linelen);
1345                 lines += countChar(tmp, '\n');
1346                 os << tmp;
1347                 p = p->next();
1348         }
1349         return lines;
1350 }
1351
1352
1353 int InsetText::docBook(Buffer const * buf, ostream & os) const
1354 {
1355         Paragraph * p = par;
1356         unsigned int lines = 0;
1357         int desc = 0;
1358         
1359         string tmp;
1360         while (p) {
1361                 buf->simpleDocBookOnePar(os, tmp, p, desc, 0);
1362                 p = p->next();
1363         }
1364         
1365         return lines;
1366 }
1367
1368
1369 void InsetText::validate(LaTeXFeatures & features) const
1370 {
1371         Paragraph * p = par;
1372         while (p) {
1373                 p->validate(features);
1374                 p = p->next();
1375         }
1376 }
1377
1378
1379 int InsetText::beginningOfMainBody(Buffer const * buf, Paragraph * p) const
1380 {
1381         if (textclasslist.Style(buf->params.textclass,
1382                                 p->getLayout()).labeltype != LABEL_MANUAL)
1383                 return 0;
1384         else
1385                 return p->beginningOfMainBody();
1386 }
1387
1388
1389 void InsetText::getCursorPos(BufferView * bv,
1390                              int & x, int & y) const
1391 {
1392         if (the_locking_inset) {
1393                 the_locking_inset->getCursorPos(bv, x, y);
1394                 return;
1395         }
1396         x = cx(bv);
1397         y = cy(bv);
1398 }
1399
1400
1401 unsigned int InsetText::insetInInsetY()
1402 {
1403         if (!the_locking_inset)
1404                 return 0;
1405
1406         return (inset_y + the_locking_inset->insetInInsetY());
1407 }
1408
1409
1410 void InsetText::toggleInsetCursor(BufferView * bv)
1411 {
1412         if (the_locking_inset) {
1413                 the_locking_inset->toggleInsetCursor(bv);
1414                 return;
1415         }
1416
1417         LyXFont const font(getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv)));
1418
1419         int const asc = lyxfont::maxAscent(font);
1420         int const desc = lyxfont::maxDescent(font);
1421   
1422         if (isCursorVisible())
1423                 bv->hideLockedInsetCursor();
1424         else
1425                 bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1426         toggleCursorVisible();
1427 }
1428
1429
1430 void InsetText::showInsetCursor(BufferView * bv, bool show)
1431 {
1432         if (the_locking_inset) {
1433                 the_locking_inset->showInsetCursor(bv, show);
1434                 return;
1435         }
1436         if (!isCursorVisible()) {
1437                 LyXFont const font =
1438                         getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv));
1439         
1440                 int const asc = lyxfont::maxAscent(font);
1441                 int const desc = lyxfont::maxDescent(font);
1442
1443                 bv->fitLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1444                 if (show)
1445                         bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1446                 setCursorVisible(true);
1447         }
1448 }
1449
1450
1451 void InsetText::hideInsetCursor(BufferView * bv)
1452 {
1453         if (isCursorVisible()) {
1454                 bv->hideLockedInsetCursor();
1455                 setCursorVisible(false);
1456         }
1457         if (the_locking_inset)
1458                 the_locking_inset->hideInsetCursor(bv);
1459 }
1460
1461
1462 void InsetText::fitInsetCursor(BufferView * bv) const
1463 {
1464         if (the_locking_inset) {
1465                 the_locking_inset->fitInsetCursor(bv);
1466                 return;
1467         }
1468         LyXFont const font =
1469                 getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv));
1470         
1471         int const asc = lyxfont::maxAscent(font);
1472         int const desc = lyxfont::maxDescent(font);
1473
1474         bv->fitLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1475 }
1476
1477
1478 UpdatableInset::RESULT
1479 InsetText::moveRight(BufferView * bv, bool activate_inset, bool selecting)
1480 {
1481         if (getLyXText(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
1482                 return moveLeftIntern(bv, false, activate_inset, selecting);
1483         else
1484                 return moveRightIntern(bv, false, activate_inset, selecting);
1485 }
1486
1487
1488 UpdatableInset::RESULT
1489 InsetText::moveLeft(BufferView * bv, bool activate_inset, bool selecting)
1490 {
1491         if (getLyXText(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
1492                 return moveRightIntern(bv, true, activate_inset, selecting);
1493         else
1494                 return moveLeftIntern(bv, true, activate_inset, selecting);
1495 }
1496
1497
1498 UpdatableInset::RESULT
1499 InsetText::moveRightIntern(BufferView * bv, bool behind, 
1500                            bool activate_inset, bool selecting)
1501 {
1502         if (!cpar(bv)->next() && (cpos(bv) >= cpar(bv)->size()))
1503                 return FINISHED;
1504         if (activate_inset && checkAndActivateInset(bv, behind))
1505                 return DISPATCHED;
1506         getLyXText(bv)->cursorRight(bv);
1507         if (!selecting)
1508                 getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor;
1509         return DISPATCHED_NOUPDATE;
1510 }
1511
1512
1513 UpdatableInset::RESULT
1514 InsetText::moveLeftIntern(BufferView * bv, bool behind,
1515                           bool activate_inset, bool selecting)
1516 {
1517         if (!cpar(bv)->previous() && (cpos(bv) <= 0))
1518                 return FINISHED;
1519         getLyXText(bv)->cursorLeft(bv);
1520         if (!selecting)
1521                 getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor;
1522         if (activate_inset && checkAndActivateInset(bv, behind))
1523                 return DISPATCHED;
1524         return DISPATCHED_NOUPDATE;
1525 }
1526
1527
1528 UpdatableInset::RESULT
1529 InsetText::moveUp(BufferView * bv)
1530 {
1531         if (!crow(bv)->previous())
1532                 return FINISHED;
1533         getLyXText(bv)->cursorUp(bv);
1534         return DISPATCHED_NOUPDATE;
1535 }
1536
1537
1538 UpdatableInset::RESULT
1539 InsetText::moveDown(BufferView * bv)
1540 {
1541         if (!crow(bv)->next())
1542                 return FINISHED;
1543         getLyXText(bv)->cursorDown(bv);
1544         return DISPATCHED_NOUPDATE;
1545 }
1546
1547
1548 bool InsetText::insertInset(BufferView * bv, Inset * inset)
1549 {
1550         if (the_locking_inset) {
1551                 if (the_locking_inset->insetAllowed(inset))
1552                         return the_locking_inset->insertInset(bv, inset);
1553                 return false;
1554         }
1555         inset->setOwner(this);
1556         hideInsetCursor(bv);
1557
1558         bool clear = false;
1559         if (!lt) {
1560                 lt = getLyXText(bv);
1561                 clear = true;
1562         }
1563         lt->insertInset(bv, inset);
1564 #if 0
1565         if ((cpar(bv)->getChar(cpos(bv)) != Paragraph::META_INSET) ||
1566                 (cpar(bv)->getInset(cpos(bv)) != inset))
1567                 lt->cursorLeft(bv);
1568 #endif
1569         bv->fitCursor();
1570         updateLocal(bv, CURSOR_PAR|CURSOR, true);
1571         showInsetCursor(bv);
1572         if (clear)
1573                 lt = 0;
1574         return true;
1575 }
1576
1577
1578 bool InsetText::insetAllowed(Inset::Code code) const
1579 {
1580         if (the_locking_inset)
1581                 return the_locking_inset->insetAllowed(code);
1582         return true;
1583 }
1584
1585
1586 UpdatableInset * InsetText::getLockingInset() const
1587 {
1588         return the_locking_inset ? the_locking_inset->getLockingInset() :
1589                 const_cast<InsetText *>(this);
1590 }
1591
1592
1593 UpdatableInset * InsetText::getFirstLockingInsetOfType(Inset::Code c)
1594 {
1595         if (c == lyxCode())
1596                 return this;
1597         if (the_locking_inset)
1598                 return the_locking_inset->getFirstLockingInsetOfType(c);
1599         return 0;
1600 }
1601
1602
1603 bool InsetText::showInsetDialog(BufferView * bv) const
1604 {
1605         if (the_locking_inset)
1606                 return the_locking_inset->showInsetDialog(bv);
1607         return false;
1608 }
1609
1610
1611 std::vector<string> const InsetText::getLabelList() const 
1612 {
1613         std::vector<string> label_list;
1614
1615         Paragraph * tpar = par;
1616         while (tpar) {
1617                 Paragraph::inset_iterator beg = tpar->inset_iterator_begin();
1618                 Paragraph::inset_iterator end = tpar->inset_iterator_end();
1619                 for (; beg != end; ++beg) {
1620                         std::vector<string> const l = (*beg)->getLabelList();
1621                         label_list.insert(label_list.end(), l.begin(), l.end());
1622                 }
1623                 tpar = tpar->next();
1624         }
1625         return label_list;
1626 }
1627
1628
1629 void InsetText::setFont(BufferView * bv, LyXFont const & font, bool toggleall,
1630                         bool selectall)
1631 {
1632         if (the_locking_inset) {
1633                 the_locking_inset->setFont(bv, font, toggleall, selectall);
1634                 return;
1635         }
1636         if ((!par->next() && !par->size()) || !cpar(bv)->size()) {
1637                 getLyXText(bv)->setFont(bv, font, toggleall);
1638                 return;
1639         }
1640         bool clear = false;
1641         if (!lt) {
1642                 lt = getLyXText(bv);
1643                 clear = true;
1644         }
1645         if (lt->selection.set()) {
1646                 setUndo(bv, Undo::EDIT, lt->cursor.par(), lt->cursor.par()->next());
1647         }
1648         if (selectall)
1649                 selectAll(bv);
1650         lt->toggleFree(bv, font, toggleall);
1651         if (selectall)
1652                 lt->clearSelection();
1653         bv->fitCursor();
1654         if (selectall || lt->selection.set())
1655                 updateLocal(bv, FULL, true);
1656         else
1657                 updateLocal(bv, CURSOR_PAR, true);
1658         if (clear)
1659                 lt = 0;
1660 }
1661
1662
1663 bool InsetText::checkAndActivateInset(BufferView * bv, bool behind)
1664 {
1665         if (cpar(bv)->getChar(cpos(bv)) == Paragraph::META_INSET) {
1666                 unsigned int x;
1667                 unsigned int y;
1668                 Inset * inset =
1669                         static_cast<UpdatableInset*>(cpar(bv)->getInset(cpos(bv)));
1670                 if (!inset || inset->editable() != Inset::HIGHLY_EDITABLE)
1671                         return false;
1672                 LyXFont const font =
1673                         getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv));
1674                 if (behind) {
1675                         x = inset->width(bv, font);
1676                         y = font.isRightToLeft() ? 0 : inset->descent(bv, font);
1677                 } else {
1678                         x = 0;
1679                         y = font.isRightToLeft() ? inset->descent(bv, font) : 0;
1680                 }
1681                 //inset_x = cx(bv) - top_x + drawTextXOffset;
1682                 //inset_y = cy(bv) + drawTextYOffset;
1683                 inset->edit(bv, x, y, 0);
1684                 if (!the_locking_inset)
1685                         return false;
1686                 updateLocal(bv, CURSOR, false);
1687                 return true;
1688         }
1689         return false;
1690 }
1691
1692
1693 bool InsetText::checkAndActivateInset(BufferView * bv, int x, int y,
1694                                       int button)
1695 {
1696         x -= drawTextXOffset;
1697         int dummyx = x;
1698         int dummyy = y + insetAscent;
1699         Inset * inset = bv->checkInsetHit(getLyXText(bv), dummyx, dummyy, button);
1700
1701         if (inset) {
1702                 if (x < 0)
1703                         x = insetWidth;
1704                 if (y < 0)
1705                         y = insetDescent;
1706                 inset_x = cx(bv) - top_x + drawTextXOffset;
1707                 inset_y = cy(bv) + drawTextYOffset;
1708                 inset->edit(bv, x - inset_x, y - inset_y, button);
1709                 if (!the_locking_inset)
1710                         return false;
1711                 updateLocal(bv, CURSOR, false);
1712                 return true;
1713         }
1714         return false;
1715 }
1716
1717
1718 int InsetText::getMaxWidth(BufferView * bv, UpdatableInset const * inset) const
1719 {
1720 #if 0
1721         int w = UpdatableInset::getMaxWidth(bv, inset);
1722         if (w < 0) {
1723                 return -1;
1724         }
1725         if (owner()) {
1726                 w = w - top_x + owner()->x();
1727                 return w;
1728         }
1729         w -= (2 * TEXT_TO_INSET_OFFSET);
1730         return w - top_x;
1731 #else
1732         return UpdatableInset::getMaxWidth(bv, inset);
1733 #endif
1734 }
1735
1736
1737 void InsetText::setParagraphData(Paragraph * p)
1738 {
1739         // we have to unlock any locked inset otherwise we're in troubles
1740         the_locking_inset = 0;
1741         while (par) {
1742                 Paragraph * tmp = par->next();
1743                 delete par;
1744                 par = tmp;
1745         }
1746
1747         par = new Paragraph(*p);
1748         par->setInsetOwner(this);
1749         Paragraph * np = par;
1750         while (p->next()) {
1751                 p = p->next();
1752                 np->next(new Paragraph(*p));
1753                 np->next()->previous(np);
1754                 np = np->next();
1755                 np->setInsetOwner(this);
1756         }
1757         need_update = INIT;
1758 }
1759
1760
1761 void InsetText::setText(string const & data)
1762 {
1763         clear();
1764         LyXFont font(LyXFont::ALL_SANE);
1765         for (unsigned int i=0; i < data.length(); ++i)
1766                 par->insertChar(i, data[i], font);
1767 }
1768
1769
1770 void InsetText::setAutoBreakRows(bool flag)
1771 {
1772         if (flag != autoBreakRows) {
1773                 autoBreakRows = flag;
1774                 if (!flag)
1775                         removeNewlines();
1776                 need_update = INIT;
1777         }
1778 }
1779
1780
1781 void InsetText::setDrawFrame(BufferView * bv, DrawFrame how)
1782 {
1783         if (how != drawFrame_) {
1784                 drawFrame_ = how;
1785                 if (bv)
1786                         updateLocal(bv, DRAW_FRAME, false);
1787         }
1788 }
1789
1790
1791 void InsetText::setFrameColor(BufferView * bv, LColor::color col)
1792 {
1793         if (frame_color != col) {
1794                 frame_color = col;
1795                 if (bv)
1796                         updateLocal(bv, DRAW_FRAME, false);
1797         }
1798 }
1799
1800
1801 int InsetText::cx(BufferView * bv) const
1802 {
1803         bool clear = false;
1804         if (!lt) {
1805                 lt = getLyXText(bv);
1806                 clear = true;
1807         }
1808         int x = lt->cursor.x() + top_x + TEXT_TO_INSET_OFFSET;
1809         if (the_locking_inset) {
1810                 LyXFont font = lt->getFont(bv->buffer(),
1811                                              lt->cursor.par(),
1812                                              lt->cursor.pos());
1813                 if (font.isVisibleRightToLeft())
1814                         x -= the_locking_inset->width(bv, font);
1815         }
1816         if (clear)
1817                 lt = 0;
1818         return x;
1819 }
1820
1821
1822 int InsetText::cy(BufferView * bv) const
1823 {
1824         LyXFont font;
1825         return getLyXText(bv)->cursor.y() - ascent(bv, font) + TEXT_TO_INSET_OFFSET;
1826 }
1827
1828
1829 Paragraph::size_type InsetText::cpos(BufferView * bv) const
1830 {
1831         return getLyXText(bv)->cursor.pos();
1832 }
1833
1834
1835 Paragraph * InsetText::cpar(BufferView * bv) const
1836 {
1837         return getLyXText(bv)->cursor.par();
1838 }
1839
1840
1841 bool InsetText::cboundary(BufferView * bv) const
1842 {
1843         return getLyXText(bv)->cursor.boundary();
1844 }
1845
1846
1847 Row * InsetText::crow(BufferView * bv) const
1848 {
1849         return getLyXText(bv)->cursor.row();
1850 }
1851
1852
1853 LyXText * InsetText::getLyXText(BufferView const * lbv,
1854                                           bool const recursive) const
1855 {
1856         if (!recursive && (cached_bview == lbv))
1857                 return cached_text.get();
1858         
1859         // Super UGLY! (Lgb)
1860         BufferView * bv = const_cast<BufferView *>(lbv);
1861         
1862         cached_bview = bv;
1863         Cache::iterator it = cache.find(bv);
1864
1865         if (it != cache.end()) {
1866                 if (lt || !it->second.remove) {
1867                         lyx::Assert(it->second.text.get());
1868                         cached_text = it->second.text;
1869                         if (recursive && the_locking_inset) {
1870                                 return the_locking_inset->getLyXText(bv, true);
1871                         }
1872                         return cached_text.get();
1873                 } else if (it->second.remove) {
1874                         if (locked) {
1875                                 saveLyXTextState(it->second.text.get());
1876                         } else {
1877                                 sstate.lpar = 0;
1878                         }
1879                 }
1880         }
1881         
1882         cached_text.reset(new LyXText(const_cast<InsetText *>(this)));
1883         cached_text->init(bv);
1884         restoreLyXTextState(bv, cached_text.get());
1885
1886         cache.insert(make_pair(bv, cached_text));
1887         
1888         if (the_locking_inset && recursive) {
1889                 return the_locking_inset->getLyXText(bv);
1890         }
1891         return cached_text.get();
1892 }
1893
1894
1895 void InsetText::deleteLyXText(BufferView * bv, bool recursive) const
1896 {
1897         cached_bview = 0;
1898
1899         Cache::iterator it = cache.find(bv);
1900         
1901         if (it == cache.end()) {
1902                 return;
1903         }
1904
1905         lyx::Assert(it->second.text.get());
1906
1907         it->second.remove = true;
1908         if (recursive) {
1909                 /// then remove all LyXText in text-insets
1910                 Paragraph * p = par;
1911                 for (; p; p = p->next()) {
1912                         p->deleteInsetsLyXText(bv);
1913                 }
1914         }
1915 }
1916
1917
1918 void InsetText::resizeLyXText(BufferView * bv, bool force) const
1919 {
1920 //      lyxerr << "InsetText::resizeLyXText\n";
1921         if (!par->next() && !par->size()) // no data, resize not neccessary!
1922                 return;
1923         // one endless line, resize normally not necessary
1924         if (!force && getMaxWidth(bv, this) < 0)
1925                 return;
1926
1927         Cache::iterator it = cache.find(bv);
1928         if (it == cache.end()) {
1929                 return;
1930         }
1931         lyx::Assert(it->second.text.get());
1932
1933         LyXText * t = it->second.text.get();
1934         saveLyXTextState(t);
1935         for (Paragraph * p = par; p; p = p->next()) {
1936                 p->resizeInsetsLyXText(bv);
1937         }
1938         t->init(bv, true);
1939         restoreLyXTextState(bv, t);
1940         if (the_locking_inset) {
1941                 inset_x = cx(bv) - top_x + drawTextXOffset;
1942                 inset_y = cy(bv) + drawTextYOffset;
1943         }
1944
1945         if (bv->screen()) {
1946                 t->first = bv->screen()->topCursorVisible(t);
1947         }
1948         if (!owner()) {
1949                 updateLocal(bv, FULL, false);
1950                 // this will scroll the screen such that the cursor becomes visible 
1951                 bv->updateScrollbar();
1952         } else {
1953                 need_update |= FULL;
1954         }
1955 }
1956
1957
1958 void InsetText::reinitLyXText() const
1959 {
1960 //      lyxerr << "InsetText::reinitLyXText\n";
1961         for(Cache::iterator it = cache.begin(); it != cache.end(); ++it) {
1962                 lyx::Assert(it->second.text.get());
1963
1964                 LyXText * t = it->second.text.get();
1965                 BufferView * bv = it->first;
1966
1967                 saveLyXTextState(t);
1968                 for (Paragraph * p = par; p; p = p->next()) {
1969                         p->resizeInsetsLyXText(bv);
1970                 }
1971                 t->init(bv, true);
1972                 restoreLyXTextState(bv, t);
1973                 if (the_locking_inset) {
1974                         inset_x = cx(bv) - top_x + drawTextXOffset;
1975                         inset_y = cy(bv) + drawTextYOffset;
1976                 }
1977                 if (bv->screen()) {
1978                         t->first = bv->screen()->topCursorVisible(t);
1979                 }
1980                 if (!owner()) {
1981                         updateLocal(bv, FULL, false);
1982                         // this will scroll the screen such that the cursor becomes visible 
1983                         bv->updateScrollbar();
1984                 } else {
1985                         need_update = FULL;
1986                 }
1987         }
1988 }
1989
1990
1991 void InsetText::removeNewlines()
1992 {
1993         for (Paragraph * p = par; p; p = p->next()) {
1994                 for (int i = 0; i < p->size(); ++i) {
1995                         if (p->getChar(i) == Paragraph::META_NEWLINE)
1996                                 p->erase(i);
1997                 }
1998         }
1999 }
2000
2001
2002 bool InsetText::nodraw() const
2003 {
2004         if (the_locking_inset)
2005                 return the_locking_inset->nodraw();
2006         return UpdatableInset::nodraw();
2007 }
2008
2009
2010 int InsetText::scroll(bool recursive) const
2011 {
2012         int sx = UpdatableInset::scroll(false);
2013
2014         if (recursive && the_locking_inset)
2015                 sx += the_locking_inset->scroll(recursive);
2016
2017         return sx;
2018 }
2019
2020
2021 bool InsetText::doClearArea() const
2022 {
2023         return !locked || (need_update & (FULL|INIT));
2024 }
2025
2026
2027 void InsetText::selectAll(BufferView * bv)
2028 {
2029         getLyXText(bv)->cursorTop(bv);
2030         getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor;
2031         getLyXText(bv)->cursorBottom(bv);
2032         getLyXText(bv)->setSelection(bv);
2033 }
2034
2035
2036 void InsetText::clearSelection(BufferView * bv)
2037 {
2038         getLyXText(bv)->clearSelection();
2039 }
2040
2041
2042 void InsetText::clearInset(Painter & pain, int baseline, bool & cleared) const
2043 {
2044         int w = insetWidth;
2045         int h = insetAscent + insetDescent;
2046         int ty = baseline - insetAscent;
2047         
2048         if (ty < 0) {
2049                 h += ty;
2050                 ty = 0;
2051         }
2052         if ((ty + h) > pain.paperHeight())
2053                 h = pain.paperHeight();
2054         if ((top_x + drawTextXOffset + w) > pain.paperWidth())
2055                 w = pain.paperWidth();
2056 //      w -= TEXT_TO_INSET_OFFSET;
2057         pain.fillRectangle(top_x, ty, w+1, h+1, backgroundColor());
2058         cleared = true;
2059         need_update = FULL;
2060         frame_is_visible = false;
2061 }
2062
2063
2064 Paragraph * InsetText::getParFromID(int id) const
2065 {
2066 #if 0
2067         Paragraph * result = par;
2068         Paragraph * ires = 0;
2069         while (result && result->id() != id) {
2070                 if ((ires = result->getParFromID(id)))
2071                         return ires;
2072                 result = result->next();
2073         }
2074         return result;
2075 #else
2076         Paragraph * tmp = par;
2077         while (tmp) {
2078                 int tmp_id = tmp->id();
2079                 lyxerr << "Looking at paragraph: " << tmp_id << endl;
2080                 if (tmp->id() == id) {
2081                         return tmp;
2082                 }
2083                 Paragraph * tmp2 = tmp->getParFromID(id);
2084                 if (tmp2 != 0) {
2085                         return tmp2;
2086                 }
2087                 tmp = tmp->next();
2088         }
2089         return 0;
2090 #endif
2091 }
2092
2093
2094 Paragraph * InsetText::firstParagraph() const
2095 {
2096         Paragraph * result;
2097         if (the_locking_inset)
2098                 if ((result = the_locking_inset->firstParagraph()))
2099                         return result;
2100         return par;
2101 }
2102
2103
2104 LyXCursor const & InsetText::cursor(BufferView * bv) const
2105 {
2106                 if (the_locking_inset)
2107                                 return the_locking_inset->cursor(bv);
2108                 return getLyXText(bv)->cursor;
2109 }
2110
2111
2112 Paragraph * InsetText::paragraph() const
2113 {
2114         return par;
2115 }
2116
2117
2118 void InsetText::paragraph(Paragraph * p)
2119 {
2120         par = p;
2121 #if 0
2122         // we now have to update/redraw all instances
2123         for (Cache::iterator cit = cache.begin(); cit != cache.end(); ++cit) {
2124                 delete cit->second;
2125                 cit->second = 0;
2126         }
2127 #endif
2128         // redraw myself when asked for
2129         need_update = INIT;
2130 }
2131
2132
2133 Inset * InsetText::getInsetFromID(int id_arg) const
2134 {
2135         if (id_arg == id())
2136                 return const_cast<InsetText *>(this);
2137
2138         Paragraph * lp = par;
2139
2140         while(lp) {
2141                 for (Paragraph::inset_iterator it = lp->inset_iterator_begin(),
2142                          en = lp->inset_iterator_end();
2143                          it != en; ++it)
2144                 {
2145                         if ((*it)->id() == id_arg)
2146                                 return *it;
2147                         Inset * in = (*it)->getInsetFromID(id_arg);
2148                         if (in)
2149                                 return in;
2150                 }
2151                 lp = lp->next();
2152         }
2153         return 0;
2154 }
2155
2156
2157 string const InsetText::selectNextWord(BufferView * bv, float & value) const
2158 {
2159         bool clear = false;
2160         string str;
2161
2162         if (!lt) {
2163                 lt = getLyXText(bv);
2164                 clear = true;
2165         }
2166         if (the_locking_inset) {
2167                 str = the_locking_inset->selectNextWord(bv, value);
2168                 if (!str.empty()) {
2169                         value += cy(bv);
2170                         if (clear)
2171                                 lt = 0;
2172                         return str;
2173                 }
2174 #warning Dekel please have a look on this one RTL? (Jug)
2175                 // we have to go on checking so move cusor to the right
2176                 lt->cursor.pos(lt->cursor.pos() + 1);
2177         }
2178         str = lt->selectNextWord(bv, value);
2179         if (str.empty())
2180                 bv->unlockInset(const_cast<InsetText *>(this));
2181         else
2182                 value = cy(bv);
2183         if (clear)
2184                 lt = 0;
2185         return str;
2186 }
2187
2188
2189 void InsetText::selectSelectedWord(BufferView * bv)
2190 {
2191         if (the_locking_inset) {
2192                 the_locking_inset->selectSelectedWord(bv);
2193                 return;
2194         }
2195         getLyXText(bv)->selectSelectedWord(bv);
2196         updateLocal(bv, SELECTION, false);
2197 }
2198
2199
2200 void InsetText::toggleSelection(BufferView * bv, bool kill_selection)
2201 {
2202         if (the_locking_inset) {
2203                 the_locking_inset->toggleSelection(bv, kill_selection);
2204         }
2205         bool clear = false;
2206         if (!lt) {
2207                 lt = getLyXText(bv);
2208                 clear = true;
2209         }
2210
2211         int x = top_x + TEXT_TO_INSET_OFFSET;
2212
2213         int y = 0;
2214         Row * row = lt->getRowNearY(y);
2215         int y_offset = top_baseline - row->ascent_of_text();
2216         y = y_offset;
2217         while ((row != 0) && ((y+row->height()) <= 0)) {
2218                 y += row->height();
2219                 row = row->next();
2220         }
2221         if (y_offset < 0)
2222                 y_offset = y;
2223         
2224         if (need_update & SELECTION)
2225                 need_update = NONE;
2226         bv->screen()->toggleSelection(lt, bv, kill_selection, y_offset, x);
2227         if (clear)
2228                 lt = 0;
2229 }
2230
2231
2232 bool InsetText::searchForward(BufferView * bv, string const & str,
2233                               bool const & cs, bool const & mw)
2234 {
2235         if (the_locking_inset) {
2236                 if (the_locking_inset->searchForward(bv, str, cs, mw))
2237                         return true;
2238                 bool clear = false;
2239                 if (!lt) {
2240                         lt = getLyXText(bv);
2241                         clear = true;
2242                 }
2243                 Paragraph * lpar = lt->cursor.par();
2244                 Paragraph::size_type pos = lt->cursor.pos();
2245                 if (pos < lpar->size() - 1)
2246                         ++pos;
2247                 else {
2248                         pos = 0;
2249                         lpar = lpar->next();
2250                 }
2251                 if (!lpar) {
2252                         if (clear)
2253                                 lt = 0;
2254                         return false;
2255                 }
2256                 lt->setCursor(bv, lpar, pos);
2257                 if (clear)
2258                         lt = 0;
2259         }
2260         if (LyXFind(bv, str, true, true, cs , mw)) {
2261                 return true;
2262         }
2263         // we have to unlock ourself in this function by default!
2264         bv->unlockInset(const_cast<InsetText *>(this));
2265         return false;
2266 }
2267
2268 bool InsetText::searchBackward(BufferView * bv, string const & str,
2269                                bool const & cs, bool const & mw)
2270 {
2271         if (the_locking_inset)
2272                 if (the_locking_inset->searchBackward(bv, str, cs, mw))
2273                         return true;
2274         if (LyXFind(bv, str, false, true, cs, mw)) {
2275                 return true;
2276         }
2277         // we have to unlock ourself in this function by default!
2278         bv->unlockInset(const_cast<InsetText *>(this));
2279         return false;
2280 }