]> git.lyx.org Git - lyx.git/blob - src/insets/insettext.C
c34e618e2ce548f8b28d2af5d95f9278d9748a3f
[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 = INIT;
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         reinitLyXText(true);
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 = INIT;
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 |= INIT;
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                         owner()->update(bv, font, true);
519                 }
520                 return;
521         }
522         in_update = true;
523         if (reinit || need_update == INIT) {
524                 need_update |= FULL;
525 #if 0
526                 resizeLyXText(bv);
527 #else
528                 reinitLyXText();
529 #endif
530                 if (owner())
531                         owner()->update(bv, font, true);
532                 in_update = false;
533                 return;
534         }
535         if (the_locking_inset) {
536                 inset_x = cx(bv) - top_x + drawTextXOffset;
537                 inset_y = cy(bv) + drawTextYOffset;
538                 the_locking_inset->update(bv, font, reinit);
539         }
540
541         bool clear = false;
542         if (!lt) {
543                 lt = getLyXText(bv);
544                 clear = true;
545         }
546         int oldw = insetWidth;
547         insetWidth = lt->width + (2 * TEXT_TO_INSET_OFFSET);
548         if (oldw != insetWidth) {
549                 resizeLyXText(bv);
550                 need_update |= FULL;
551                 if (clear)
552                         lt = 0;
553                 in_update = false;
554                 return;
555         }
556         if ((need_update & CURSOR_PAR) && (lt->status() == LyXText::UNCHANGED) &&
557                 the_locking_inset)
558         {
559                 lt->updateInset(bv, the_locking_inset);
560         }
561         if (lt->status() == LyXText::NEED_MORE_REFRESH)
562                 need_update |= FULL;
563         if (clear)
564                 lt = 0;
565         in_update = false;
566 }
567
568
569 void InsetText::setUpdateStatus(BufferView * bv, int what) const
570 {
571         bool clear = false;
572         if (!lt) {
573                 lt = getLyXText(bv);
574                 clear = true;
575         }
576         need_update |= what;
577         // we have to redraw us full if our LyXText NEEDS_MORE_REFRES or
578         // if we don't break row so that we only have one row to update!
579         if ((lt->status() == LyXText::NEED_MORE_REFRESH) ||
580             (!autoBreakRows &&
581              (lt->status() == LyXText::NEED_VERY_LITTLE_REFRESH)))
582         {
583                 need_update |= FULL;
584         } else if (lt->status() == LyXText::NEED_VERY_LITTLE_REFRESH) {
585                 need_update |= CURSOR_PAR;
586         }
587
588         // this to not draw a selection when we redraw all of it!
589         if (need_update & CURSOR && !(need_update & SELECTION)) {
590                 if (lt->selection.set())
591                         need_update = FULL;
592                 lt->clearSelection();
593         }
594         if (clear)
595                 lt = 0;
596 }
597
598
599 void InsetText::updateLocal(BufferView * bv, int what, bool mark_dirty) const
600 {
601         bool clear = false;
602         if (!lt) {
603                 lt = getLyXText(bv);
604                 clear = true;
605         }
606         lt->fullRebreak(bv);
607         setUpdateStatus(bv, what);
608         if (((need_update != CURSOR) && (need_update != NONE)) ||
609             (lt->status() != LyXText::UNCHANGED) || lt->selection.set())
610         {
611                 bv->updateInset(const_cast<InsetText *>(this), mark_dirty);
612         }
613         if (need_update == CURSOR)
614                 need_update = NONE;
615         bv->owner()->showState();
616         if (old_par != cpar(bv)) {
617                 bv->owner()->setLayout(cpar(bv)->getLayout());
618                 old_par = cpar(bv);
619         }
620         if (clear)
621                 lt = 0;
622 }
623
624
625 string const InsetText::editMessage() const
626 {
627         return _("Opened Text Inset");
628 }
629
630
631 void InsetText::edit(BufferView * bv, int x, int y, unsigned int button)
632 {
633         UpdatableInset::edit(bv, x, y, button);
634         
635         if (!bv->lockInset(this)) {
636                 lyxerr[Debug::INSETS] << "Cannot lock inset" << endl;
637                 return;
638         }
639         locked = true;
640         the_locking_inset = 0;
641         inset_pos = inset_x = inset_y = 0;
642         inset_boundary = false;
643         inset_par = 0;
644         old_par = 0;
645         int tmp_y = (y < 0) ? 0 : y;
646         bool clear = false;
647         if (!lt) {
648                 lt = getLyXText(bv);
649                 clear = true;
650         }
651
652         if (!checkAndActivateInset(bv, x, tmp_y, button))
653                 lt->setCursorFromCoordinates(bv, x - drawTextXOffset,
654                                             y + insetAscent);
655         lt->clearSelection();
656         finishUndo();
657         showInsetCursor(bv);
658         updateLocal(bv, CURSOR, false);
659
660         // If the inset is empty set the language of the current font to the
661         // language to the surronding text (if different).
662         if (par->size() == 0 && !par->next() &&
663                 bv->getParentLanguage(this) != lt->current_font.language()) {
664                 LyXFont font(LyXFont::ALL_IGNORE);
665                 font.setLanguage(bv->getParentLanguage(this));
666                 setFont(bv, font, false);
667         }
668         if (clear)
669                 lt = 0;
670 }
671
672
673 void InsetText::edit(BufferView * bv, bool front)
674 {
675         UpdatableInset::edit(bv, front);
676         
677         if (!bv->lockInset(this)) {
678                 lyxerr[Debug::INSETS] << "Cannot lock inset" << endl;
679                 return;
680         }
681         locked = true;
682         the_locking_inset = 0;
683         inset_pos = inset_x = inset_y = 0;
684         inset_boundary = false;
685         inset_par = 0;
686         old_par = 0;
687         bool clear = false;
688         if (!lt) {
689                 lt = getLyXText(bv);
690                 clear = true;
691         }
692         if (front)
693                 lt->setCursor(bv, par, 0);
694         else {
695                 Paragraph * p = par;
696                 while(p->next())
697                         p = p->next();
698                 int const pos = (p->size() ? p->size()-1 : p->size());
699                 lt->setCursor(bv, p, pos);
700         }
701         lt->clearSelection();
702         finishUndo();
703         showInsetCursor(bv);
704         updateLocal(bv, CURSOR, false);
705
706         // If the inset is empty set the language of the current font to the
707         // language to the surronding text (if different).
708         if (par->size() == 0 && !par->next() &&
709                 bv->getParentLanguage(this) != lt->current_font.language()) {
710                 LyXFont font(LyXFont::ALL_IGNORE);
711                 font.setLanguage(bv->getParentLanguage(this));
712                 setFont(bv, font, false);
713         }
714         if (clear)
715                 lt = 0;
716 }
717
718
719 void InsetText::insetUnlock(BufferView * bv)
720 {
721         if (the_locking_inset) {
722                 the_locking_inset->insetUnlock(bv);
723                 the_locking_inset = 0;
724         }
725         hideInsetCursor(bv);
726         no_selection = false;
727         locked = false;
728         int code;
729         if (drawFrame_ == LOCKED)
730                 code = CURSOR|CLEAR_FRAME;
731         else 
732                 code = CURSOR;
733         bool clear = false;
734         if (!lt) {
735                 lt = getLyXText(bv);
736                 clear = true;
737         }
738         if (lt->selection.set()) {
739                 lt->clearSelection();
740                 code = FULL;
741         } else if (owner()) {
742                 bv->owner()->setLayout(owner()->getLyXText(bv)
743                                        ->cursor.par()->getLayout());
744         } else
745                 bv->owner()->setLayout(bv->text->cursor.par()->getLayout());
746         updateLocal(bv, code, false);
747         if (clear)
748                 lt = 0;
749 }
750
751
752 bool InsetText::lockInsetInInset(BufferView * bv, UpdatableInset * inset)
753 {
754         lyxerr[Debug::INSETS] << "InsetText::LockInsetInInset("
755                               << inset << "): ";
756         if (!inset)
757                 return false;
758         if (inset == cpar(bv)->getInset(cpos(bv))) {
759                 lyxerr[Debug::INSETS] << "OK" << endl;
760                 the_locking_inset = inset;
761                 inset_x = cx(bv) - top_x + drawTextXOffset;
762                 inset_y = cy(bv) + drawTextYOffset;
763                 inset_pos = cpos(bv);
764                 inset_par = cpar(bv);
765                 inset_boundary = cboundary(bv);
766                 updateLocal(bv, CURSOR, false);
767                 return true;
768         } else if (the_locking_inset && (the_locking_inset == inset)) {
769                 if (cpar(bv) == inset_par && cpos(bv) == inset_pos) {
770                         lyxerr[Debug::INSETS] << "OK" << endl;
771                         inset_x = cx(bv) - top_x + drawTextXOffset;
772                         inset_y = cy(bv) + drawTextYOffset;
773                 } else {
774                         lyxerr[Debug::INSETS] << "cursor.pos != inset_pos" << endl;
775                 }
776         } else if (the_locking_inset) {
777                 lyxerr[Debug::INSETS] << "MAYBE" << endl;
778                 return the_locking_inset->lockInsetInInset(bv, inset);
779         }
780         lyxerr[Debug::INSETS] << "NOT OK" << endl;
781         return false;
782 }
783
784
785 bool InsetText::unlockInsetInInset(BufferView * bv, UpdatableInset * inset,
786                                    bool lr)
787 {
788         if (!the_locking_inset)
789                 return false;
790         if (the_locking_inset == inset) {
791                 the_locking_inset->insetUnlock(bv);
792                 getLyXText(bv)->updateInset(bv, inset);
793                 the_locking_inset = 0;
794                 if (lr)
795                         moveRight(bv, false);
796                 old_par = 0; // force layout setting
797                 if (scroll())
798                         scroll(bv, 0.0F);
799                 else
800                         updateLocal(bv, CURSOR, false);
801                 return true;
802         }
803         return the_locking_inset->unlockInsetInInset(bv, inset, lr);
804 }
805
806
807 bool InsetText::updateInsetInInset(BufferView * bv, Inset * inset)
808 {
809         if (!the_locking_inset)
810                 return false;
811         if (the_locking_inset != inset) {
812                 getLyXText(bv)->updateInset(bv, the_locking_inset);
813                 setUpdateStatus(bv, CURSOR_PAR);
814                 return the_locking_inset->updateInsetInInset(bv, inset);
815         }
816         if (getLyXText(bv)->updateInset(bv, inset))
817                 updateLocal(bv, CURSOR_PAR, false);
818         if (cpar(bv) == inset_par && cpos(bv) == inset_pos) {
819                 inset_x = cx(bv) - top_x + drawTextXOffset;
820                 inset_y = cy(bv) + drawTextYOffset;
821         }
822         return true;
823 }
824
825
826 void InsetText::insetButtonPress(BufferView * bv, int x, int y, int button)
827 {
828         no_selection = true;
829
830         int tmp_x = x - drawTextXOffset;
831         int tmp_y = y + insetAscent - getLyXText(bv)->first;
832         Inset * inset = bv->checkInsetHit(getLyXText(bv), tmp_x, tmp_y, button);
833
834         hideInsetCursor(bv);
835         if (the_locking_inset) {
836                 if (the_locking_inset == inset) {
837                         the_locking_inset->insetButtonPress(bv,x-inset_x,y-inset_y,button);
838                         no_selection = false;
839                         return;
840                 } else if (inset) {
841                         // otherwise unlock the_locking_inset and lock the new inset
842                         the_locking_inset->insetUnlock(bv);
843                         inset_x = cx(bv) - top_x + drawTextXOffset;
844                         inset_y = cy(bv) + drawTextYOffset;
845                         the_locking_inset = static_cast<UpdatableInset*>(inset);
846                         inset->insetButtonPress(bv, x - inset_x, y - inset_y, button);
847                         inset->edit(bv, x - inset_x, y - inset_y, button);
848                         if (the_locking_inset)
849                                 updateLocal(bv, CURSOR, false);
850                         no_selection = false;
851                         return;
852                 }
853                 // otherwise only unlock the_locking_inset
854                 the_locking_inset->insetUnlock(bv);
855                 the_locking_inset = 0;
856         }
857         if (bv->theLockingInset()) {
858                 if (inset && inset->editable() == Inset::HIGHLY_EDITABLE) {
859                         UpdatableInset * uinset = static_cast<UpdatableInset*>(inset);
860                         inset_x = cx(bv) - top_x + drawTextXOffset;
861                         inset_y = cy(bv) + drawTextYOffset;
862                         inset_pos = cpos(bv);
863                         inset_par = cpar(bv);
864                         inset_boundary = cboundary(bv);
865                         the_locking_inset = uinset;
866                         uinset->insetButtonPress(bv, x - inset_x, y - inset_y,
867                                                  button);
868                         uinset->edit(bv, x - inset_x, y - inset_y, 0);
869                         if (the_locking_inset)
870                                 updateLocal(bv, CURSOR, false);
871                         no_selection = false;
872                         return;
873                 }
874         }
875         if (!inset) { // && (button == 2)) {
876                 bool paste_internally = false;
877                 if ((button == 2) && getLyXText(bv)->selection.set()) {
878                         localDispatch(bv, LFUN_COPY, "");
879                         paste_internally = true;
880                 }
881                 bool clear = false;
882                 if (!lt) {
883                         lt = getLyXText(bv);
884                         clear = true;
885                 }
886                 lt->setCursorFromCoordinates(bv, x-drawTextXOffset, y + insetAscent);
887                 if (lt->selection.set()) {
888                         lt->clearSelection();
889                         updateLocal(bv, FULL, false);
890                 } else {
891                         lt->clearSelection();
892                 }
893                 bv->owner()->setLayout(cpar(bv)->getLayout());
894                 old_par = cpar(bv);
895                 // Insert primary selection with middle mouse
896                 // if there is a local selection in the current buffer,
897                 // insert this
898                 if (button == 2) {
899                         if (paste_internally)
900                                 localDispatch(bv, LFUN_PASTE, "");
901                         else
902                                 localDispatch(bv, LFUN_PASTESELECTION,
903                                               "paragraph");
904                 }
905                 if (clear)
906                         lt = 0;
907         }
908         showInsetCursor(bv);
909         no_selection = false;
910 }
911
912
913 void InsetText::insetButtonRelease(BufferView * bv, int x, int y, int button)
914 {
915         UpdatableInset * inset = 0;
916
917         if (the_locking_inset) {
918                 the_locking_inset->insetButtonRelease(bv,
919                                                       x - inset_x, y - inset_y,
920                                                       button);
921         } else {
922                 if (cpar(bv)->getChar(cpos(bv)) == Paragraph::META_INSET) {
923                         inset = static_cast<UpdatableInset*>(cpar(bv)->getInset(cpos(bv)));
924                         if (inset->editable() == Inset::HIGHLY_EDITABLE) {
925                                 inset->insetButtonRelease(bv,
926                                                           x - inset_x,
927                                                           y - inset_y, button);
928                         } else {
929                                 inset_x = cx(bv) - top_x + drawTextXOffset;
930                                 inset_y = cy(bv) + drawTextYOffset;
931                                 inset->insetButtonRelease(bv,
932                                                           x - inset_x,
933                                                           y - inset_y, button);
934                                 inset->edit(bv,
935                                             x - inset_x, y - inset_y, button);
936                         }
937                         updateLocal(bv, CURSOR_PAR, false);
938                 }
939         }
940         no_selection = false;
941 }
942
943
944 void InsetText::insetMotionNotify(BufferView * bv, int x, int y, int state)
945 {
946         if (no_selection)
947                 return;
948         if (the_locking_inset) {
949                 the_locking_inset->insetMotionNotify(bv, x - inset_x,
950                                                      y - inset_y,state);
951                 return;
952         }
953         LyXText * t = getLyXText(bv);
954         hideInsetCursor(bv);
955         t->setCursorFromCoordinates(bv, x - drawTextXOffset, y + insetAscent);
956         t->setSelection(bv);
957         if (t->toggle_cursor.par() != t->toggle_end_cursor.par() ||
958                 t->toggle_cursor.pos() != t->toggle_end_cursor.pos())
959                 updateLocal(bv, SELECTION, false);
960         showInsetCursor(bv);
961 }
962
963
964 void InsetText::insetKeyPress(XKeyEvent * xke)
965 {
966         if (the_locking_inset) {
967                 the_locking_inset->insetKeyPress(xke);
968                 return;
969         }
970 }
971
972
973 UpdatableInset::RESULT
974 InsetText::localDispatch(BufferView * bv,
975                          kb_action action, string const & arg)
976 {
977         no_selection = false;
978         UpdatableInset::RESULT
979                 result= UpdatableInset::localDispatch(bv, action, arg);
980         if (result != UNDISPATCHED) {
981                 return DISPATCHED;
982         }
983
984         result = DISPATCHED;
985         if ((action < 0) && arg.empty())
986                 return FINISHED;
987
988         if (the_locking_inset) {
989                 result = the_locking_inset->localDispatch(bv, action, arg);
990                 if (result == DISPATCHED_NOUPDATE)
991                         return result;
992                 else if (result == DISPATCHED) {
993                         updateLocal(bv, CURSOR_PAR, false);
994                         return result;
995                 } else if (result == FINISHED) {
996                         bool dispatched = false;
997                         switch (action) {
998                         case LFUN_UNKNOWN_ACTION:
999                         case LFUN_BREAKPARAGRAPH:
1000                         case LFUN_BREAKLINE:
1001                                 moveRightIntern(bv, false, false);
1002                                 break;
1003                         case LFUN_RIGHT:
1004                                 if (!getLyXText(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
1005                                         moveRightIntern(bv, false, false);
1006                                 dispatched = true;
1007                                 break;
1008                         case LFUN_LEFT:
1009                                 if (getLyXText(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
1010                                         moveRightIntern(bv, false, false);
1011                                 dispatched = true;
1012                                 break;
1013                         default:
1014                                 break;
1015                         }
1016                         the_locking_inset = 0;
1017                         if (dispatched)
1018                                 return DISPATCHED;
1019                 }
1020         }
1021         hideInsetCursor(bv);
1022         bool clear = false;
1023         if (!lt) {
1024                 lt = getLyXText(bv);
1025                 clear = true;
1026         }
1027         switch (action) {
1028         // Normal chars
1029         case LFUN_SELFINSERT:
1030                 if (bv->buffer()->isReadonly()) {
1031 //          setErrorMessage(N_("Document is read only"));
1032                         break;
1033                 }
1034                 if (!arg.empty()) {
1035                         /* Automatically delete the currently selected
1036                          * text and replace it with what is being
1037                          * typed in now. Depends on lyxrc settings
1038                          * "auto_region_delete", which defaults to
1039                          * true (on). */
1040
1041                         setUndo(bv, Undo::INSERT,
1042                                 lt->cursor.par(), lt->cursor.par()->next());
1043                         bv->setState();
1044                         if (lyxrc.auto_region_delete) {
1045                                 if (lt->selection.set()) {
1046                                         lt->cutSelection(bv, false);
1047                                 }
1048                         }
1049                         lt->clearSelection();
1050                         for (string::size_type i = 0; i < arg.length(); ++i) {
1051                                 bv->owner()->getIntl()->getTrans().TranslateAndInsert(arg[i], lt);
1052                         }
1053                 }
1054                 lt->selection.cursor = lt->cursor;
1055                 updateLocal(bv, CURSOR_PAR, true);
1056                 result = DISPATCHED_NOUPDATE;
1057                 break;
1058                 // --- Cursor Movements -----------------------------------
1059         case LFUN_RIGHTSEL:
1060                 finishUndo();
1061                 moveRight(bv, false, true);
1062                 lt->setSelection(bv);
1063                 updateLocal(bv, SELECTION, false);
1064                 break;
1065         case LFUN_RIGHT:
1066                 result = moveRight(bv);
1067                 finishUndo();
1068                 updateLocal(bv, CURSOR, false);
1069                 break;
1070         case LFUN_LEFTSEL:
1071                 finishUndo();
1072                 moveLeft(bv, false, true);
1073                 lt->setSelection(bv);
1074                 updateLocal(bv, SELECTION, false);
1075                 break;
1076         case LFUN_LEFT:
1077                 finishUndo();
1078                 result = moveLeft(bv);
1079                 updateLocal(bv, CURSOR, false);
1080                 break;
1081         case LFUN_DOWNSEL:
1082                 finishUndo();
1083                 moveDown(bv);
1084                 lt->setSelection(bv);
1085                 updateLocal(bv, SELECTION, false);
1086                 break;
1087         case LFUN_DOWN:
1088                 finishUndo();
1089                 result = moveDown(bv);
1090                 updateLocal(bv, CURSOR, false);
1091                 break;
1092         case LFUN_UPSEL:
1093                 finishUndo();
1094                 moveUp(bv);
1095                 lt->setSelection(bv);
1096                 updateLocal(bv, SELECTION, false);
1097                 break;
1098         case LFUN_UP:
1099                 finishUndo();
1100                 result = moveUp(bv);
1101                 updateLocal(bv, CURSOR, false);
1102                 break;
1103         case LFUN_HOME:
1104                 finishUndo();
1105                 lt->cursorHome(bv);
1106                 updateLocal(bv, CURSOR, false);
1107                 break;
1108         case LFUN_END:
1109                 lt->cursorEnd(bv);
1110                 updateLocal(bv, CURSOR, false);
1111                 break;
1112         case LFUN_BACKSPACE: {
1113                 setUndo(bv, Undo::DELETE,
1114                         lt->cursor.par(), lt->cursor.par()->next());
1115                 if (lt->selection.set())
1116                         lt->cutSelection(bv);
1117                 else
1118                         lt->backspace(bv);
1119                 updateLocal(bv, CURSOR_PAR, true);
1120         }
1121         break;
1122         
1123         case LFUN_DELETE: {
1124                 setUndo(bv, Undo::DELETE,
1125                         lt->cursor.par(), lt->cursor.par()->next());
1126                 if (lt->selection.set()) {
1127                         lt->cutSelection(bv);
1128                 } else {
1129                         lt->Delete(bv);
1130                 }
1131                 updateLocal(bv, CURSOR_PAR, true);
1132         }
1133         break;
1134         
1135         case LFUN_CUT: {
1136                 setUndo(bv, Undo::DELETE,
1137                         lt->cursor.par(), lt->cursor.par()->next());
1138                 lt->cutSelection(bv);
1139                 updateLocal(bv, CURSOR_PAR, true);
1140         }
1141         break;
1142
1143         case LFUN_COPY:
1144                 finishUndo();
1145                 lt->copySelection(bv);
1146                 updateLocal(bv, CURSOR_PAR, false);
1147                 break;
1148         case LFUN_PASTESELECTION:
1149         {
1150                 string const clip(bv->getClipboard());
1151         
1152                 if (clip.empty())
1153                         break;
1154                 if (arg == "paragraph") {
1155                         lt->insertStringAsParagraphs(bv, clip);
1156                 } else {
1157                         lt->insertStringAsLines(bv, clip);
1158                 }
1159                 updateLocal(bv, CURSOR_PAR, true);
1160                 break;
1161         }
1162         case LFUN_PASTE: {
1163                 if (!autoBreakRows) {
1164
1165                         if (CutAndPaste::nrOfParagraphs() > 1) {
1166                                 WriteAlert(_("Impossible operation"),
1167                                                    _("Cannot include more than one paragraph!"),
1168                                                    _("Sorry."));
1169                                 break;
1170                         }
1171                 }
1172                 setUndo(bv, Undo::INSERT,
1173                         lt->cursor.par(), lt->cursor.par()->next());
1174                 lt->pasteSelection(bv);
1175                 updateLocal(bv, CURSOR_PAR, true);
1176         }
1177         break;
1178
1179         case LFUN_BREAKPARAGRAPH:
1180                 if (!autoBreakRows) {
1181                         result = DISPATCHED;
1182                         break;
1183                 }
1184                 lt->breakParagraph(bv, 0);
1185                 updateLocal(bv, FULL, true);
1186                 break;
1187         case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
1188                 if (!autoBreakRows) {
1189                         result = DISPATCHED;
1190                         break;
1191                 }
1192                 lt->breakParagraph(bv, 1);
1193                 updateLocal(bv, FULL, true);
1194                 break;
1195
1196         case LFUN_BREAKLINE: {
1197                 if (!autoBreakRows) {
1198                         result = DISPATCHED;
1199                         break;
1200                 }
1201                 setUndo(bv, Undo::INSERT,
1202                         lt->cursor.par(), lt->cursor.par()->next());
1203                 lt->insertChar(bv, Paragraph::META_NEWLINE);
1204                 updateLocal(bv, CURSOR_PAR, true);
1205         }
1206         break;
1207
1208         case LFUN_LAYOUT:
1209                 // do not set layouts on non breakable textinsets
1210                 if (autoBreakRows) {
1211                         LyXTextClass::size_type cur_layout = cpar(bv)->layout;
1212           
1213                         // Derive layout number from given argument (string)
1214                         // and current buffer's textclass (number). */    
1215                         LyXTextClassList::ClassList::size_type tclass =
1216                                 bv->buffer()->params.textclass;
1217                         std::pair <bool, LyXTextClass::size_type> layout = 
1218                                 textclasslist.NumberOfLayout(tclass, arg);
1219
1220                         // If the entry is obsolete, use the new one instead.
1221                         if (layout.first) {
1222                                 string obs = textclasslist.Style(tclass,layout.second).
1223                                         obsoleted_by();
1224                                 if (!obs.empty()) 
1225                                         layout = textclasslist.NumberOfLayout(tclass, obs);
1226                         }
1227
1228                         // see if we found the layout number:
1229                         if (!layout.first) {
1230                                 string const msg = string(N_("Layout ")) + arg + N_(" not known");
1231                                 bv->owner()->getLyXFunc()->dispatch(LFUN_MESSAGE, msg);
1232                                 break;
1233                         }
1234
1235                         if (cur_layout != layout.second) {
1236                                 cur_layout = layout.second;
1237                                 lt->setLayout(bv, layout.second);
1238                                 bv->owner()->setLayout(cpar(bv)->getLayout());
1239                                 updateLocal(bv, CURSOR_PAR, true);
1240                         }
1241                 } else {
1242                         // reset the layout box
1243                         bv->owner()->setLayout(cpar(bv)->getLayout());
1244                 }
1245                 break;
1246         case LFUN_PARAGRAPH_SPACING:
1247                 // This one is absolutely not working. When fiddling with this
1248                 // it also seems to me that the paragraphs inside the insettext
1249                 // inherit bufferparams/paragraphparams in a strange way. (Lgb)
1250         {
1251                 Paragraph * par = lt->cursor.par();
1252                 Spacing::Space cur_spacing = par->params().spacing().getSpace();
1253                 float cur_value = 1.0;
1254                 if (cur_spacing == Spacing::Other) {
1255                         cur_value = par->params().spacing().getValue();
1256                 }
1257                                 
1258                 istringstream istr(arg.c_str());
1259                 string tmp;
1260                 istr >> tmp;
1261                 Spacing::Space new_spacing = cur_spacing;
1262                 float new_value = cur_value;
1263                 if (tmp.empty()) {
1264                         lyxerr << "Missing argument to `paragraph-spacing'"
1265                                    << endl;
1266                 } else if (tmp == "single") {
1267                         new_spacing = Spacing::Single;
1268                 } else if (tmp == "onehalf") {
1269                         new_spacing = Spacing::Onehalf;
1270                 } else if (tmp == "double") {
1271                         new_spacing = Spacing::Double;
1272                 } else if (tmp == "other") {
1273                         new_spacing = Spacing::Other;
1274                         float tmpval = 0.0;
1275                         istr >> tmpval;
1276                         lyxerr << "new_value = " << tmpval << endl;
1277                         if (tmpval != 0.0)
1278                                 new_value = tmpval;
1279                 } else if (tmp == "default") {
1280                         new_spacing = Spacing::Default;
1281                 } else {
1282                         lyxerr << _("Unknown spacing argument: ")
1283                                    << arg << endl;
1284                 }
1285                 if (cur_spacing != new_spacing || cur_value != new_value) {
1286                         par->params().spacing(Spacing(new_spacing, new_value));
1287                         updateLocal(bv, CURSOR_PAR, true);
1288                 }
1289         }
1290         break;
1291         
1292         default:
1293                 if (!bv->Dispatch(action, arg))
1294                         result = UNDISPATCHED;
1295                 break;
1296         }
1297
1298         /// If the action has deleted all text in the inset, we need to change the
1299         // language to the language of the surronding text.
1300         if (par->size() == 0 && !par->next()) {
1301                 LyXFont font(LyXFont::ALL_IGNORE);
1302                 font.setLanguage(bv->getParentLanguage(this));
1303                 setFont(bv, font, false);
1304         }
1305
1306         if (result != FINISHED) {
1307                 showInsetCursor(bv);
1308         } else
1309                 bv->unlockInset(this);
1310         if (clear)
1311                 lt = 0;
1312         return result;
1313 }
1314
1315
1316 int InsetText::latex(Buffer const * buf, ostream & os, bool, bool) const
1317 {
1318         TexRow texrow;
1319         buf->latexParagraphs(os, par, 0, texrow);
1320         return texrow.rows();
1321 }
1322
1323
1324 int InsetText::ascii(Buffer const * buf, ostream & os, int linelen) const
1325 {
1326         Paragraph * p = par;
1327         unsigned int lines = 0;
1328         
1329         while (p) {
1330                 string const tmp = buf->asciiParagraph(p, linelen);
1331                 lines += countChar(tmp, '\n');
1332                 os << tmp;
1333                 p = p->next();
1334         }
1335         return lines;
1336 }
1337
1338
1339 int InsetText::docBook(Buffer const * buf, ostream & os) const
1340 {
1341         Paragraph * p = par;
1342         unsigned int lines = 0;
1343         int desc = 0;
1344         
1345         string tmp;
1346         while (p) {
1347                 buf->simpleDocBookOnePar(os, tmp, p, desc, 0);
1348                 p = p->next();
1349         }
1350         
1351         return lines;
1352 }
1353
1354
1355 void InsetText::validate(LaTeXFeatures & features) const
1356 {
1357         Paragraph * p = par;
1358         while (p) {
1359                 p->validate(features);
1360                 p = p->next();
1361         }
1362 }
1363
1364
1365 int InsetText::beginningOfMainBody(Buffer const * buf, Paragraph * p) const
1366 {
1367         if (textclasslist.Style(buf->params.textclass,
1368                                 p->getLayout()).labeltype != LABEL_MANUAL)
1369                 return 0;
1370         else
1371                 return p->beginningOfMainBody();
1372 }
1373
1374
1375 void InsetText::getCursorPos(BufferView * bv,
1376                              int & x, int & y) const
1377 {
1378         if (the_locking_inset) {
1379                 the_locking_inset->getCursorPos(bv, x, y);
1380                 return;
1381         }
1382         x = cx(bv);
1383         y = cy(bv);
1384 }
1385
1386
1387 unsigned int InsetText::insetInInsetY()
1388 {
1389         if (!the_locking_inset)
1390                 return 0;
1391
1392         return (inset_y + the_locking_inset->insetInInsetY());
1393 }
1394
1395
1396 void InsetText::toggleInsetCursor(BufferView * bv)
1397 {
1398         if (the_locking_inset) {
1399                 the_locking_inset->toggleInsetCursor(bv);
1400                 return;
1401         }
1402
1403         LyXFont const font(getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv)));
1404
1405         int const asc = lyxfont::maxAscent(font);
1406         int const desc = lyxfont::maxDescent(font);
1407   
1408         if (isCursorVisible())
1409                 bv->hideLockedInsetCursor();
1410         else
1411                 bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1412         toggleCursorVisible();
1413 }
1414
1415
1416 void InsetText::showInsetCursor(BufferView * bv, bool show)
1417 {
1418         if (the_locking_inset) {
1419                 the_locking_inset->showInsetCursor(bv, show);
1420                 return;
1421         }
1422         if (!isCursorVisible()) {
1423                 LyXFont const font =
1424                         getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv));
1425         
1426                 int const asc = lyxfont::maxAscent(font);
1427                 int const desc = lyxfont::maxDescent(font);
1428
1429                 bv->fitLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1430                 if (show)
1431                         bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1432                 setCursorVisible(true);
1433         }
1434 }
1435
1436
1437 void InsetText::hideInsetCursor(BufferView * bv)
1438 {
1439         if (isCursorVisible()) {
1440                 bv->hideLockedInsetCursor();
1441                 setCursorVisible(false);
1442         }
1443         if (the_locking_inset)
1444                 the_locking_inset->hideInsetCursor(bv);
1445 }
1446
1447
1448 void InsetText::fitInsetCursor(BufferView * bv) const
1449 {
1450         if (the_locking_inset) {
1451                 the_locking_inset->fitInsetCursor(bv);
1452                 return;
1453         }
1454         LyXFont const font =
1455                 getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv));
1456         
1457         int const asc = lyxfont::maxAscent(font);
1458         int const desc = lyxfont::maxDescent(font);
1459
1460         bv->fitLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1461 }
1462
1463
1464 UpdatableInset::RESULT
1465 InsetText::moveRight(BufferView * bv, bool activate_inset, bool selecting)
1466 {
1467         if (getLyXText(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
1468                 return moveLeftIntern(bv, false, activate_inset, selecting);
1469         else
1470                 return moveRightIntern(bv, false, activate_inset, selecting);
1471 }
1472
1473
1474 UpdatableInset::RESULT
1475 InsetText::moveLeft(BufferView * bv, bool activate_inset, bool selecting)
1476 {
1477         if (getLyXText(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
1478                 return moveRightIntern(bv, true, activate_inset, selecting);
1479         else
1480                 return moveLeftIntern(bv, true, activate_inset, selecting);
1481 }
1482
1483
1484 UpdatableInset::RESULT
1485 InsetText::moveRightIntern(BufferView * bv, bool behind, 
1486                            bool activate_inset, bool selecting)
1487 {
1488         if (!cpar(bv)->next() && (cpos(bv) >= cpar(bv)->size()))
1489                 return FINISHED;
1490         if (activate_inset && checkAndActivateInset(bv, behind))
1491                 return DISPATCHED;
1492         getLyXText(bv)->cursorRight(bv);
1493         if (!selecting)
1494                 getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor;
1495         return DISPATCHED_NOUPDATE;
1496 }
1497
1498
1499 UpdatableInset::RESULT
1500 InsetText::moveLeftIntern(BufferView * bv, bool behind,
1501                           bool activate_inset, bool selecting)
1502 {
1503         if (!cpar(bv)->previous() && (cpos(bv) <= 0))
1504                 return FINISHED;
1505         getLyXText(bv)->cursorLeft(bv);
1506         if (!selecting)
1507                 getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor;
1508         if (activate_inset && checkAndActivateInset(bv, behind))
1509                 return DISPATCHED;
1510         return DISPATCHED_NOUPDATE;
1511 }
1512
1513
1514 UpdatableInset::RESULT
1515 InsetText::moveUp(BufferView * bv)
1516 {
1517         if (!crow(bv)->previous())
1518                 return FINISHED;
1519         getLyXText(bv)->cursorUp(bv);
1520         return DISPATCHED_NOUPDATE;
1521 }
1522
1523
1524 UpdatableInset::RESULT
1525 InsetText::moveDown(BufferView * bv)
1526 {
1527         if (!crow(bv)->next())
1528                 return FINISHED;
1529         getLyXText(bv)->cursorDown(bv);
1530         return DISPATCHED_NOUPDATE;
1531 }
1532
1533
1534 bool InsetText::insertInset(BufferView * bv, Inset * inset)
1535 {
1536         if (the_locking_inset) {
1537                 if (the_locking_inset->insetAllowed(inset))
1538                         return the_locking_inset->insertInset(bv, inset);
1539                 return false;
1540         }
1541         inset->setOwner(this);
1542         hideInsetCursor(bv);
1543
1544         bool clear = false;
1545         if (!lt) {
1546                 lt = getLyXText(bv);
1547                 clear = true;
1548         }
1549         lt->insertInset(bv, inset);
1550 #if 0
1551         if ((cpar(bv)->getChar(cpos(bv)) != Paragraph::META_INSET) ||
1552                 (cpar(bv)->getInset(cpos(bv)) != inset))
1553                 lt->cursorLeft(bv);
1554 #endif
1555         bv->fitCursor();
1556         updateLocal(bv, CURSOR_PAR|CURSOR, true);
1557         showInsetCursor(bv);
1558         if (clear)
1559                 lt = 0;
1560         return true;
1561 }
1562
1563
1564 bool InsetText::insetAllowed(Inset::Code code) const
1565 {
1566         if (the_locking_inset)
1567                 return the_locking_inset->insetAllowed(code);
1568         return true;
1569 }
1570
1571
1572 UpdatableInset * InsetText::getLockingInset() const
1573 {
1574         return the_locking_inset ? the_locking_inset->getLockingInset() :
1575                 const_cast<InsetText *>(this);
1576 }
1577
1578
1579 UpdatableInset * InsetText::getFirstLockingInsetOfType(Inset::Code c)
1580 {
1581         if (c == lyxCode())
1582                 return this;
1583         if (the_locking_inset)
1584                 return the_locking_inset->getFirstLockingInsetOfType(c);
1585         return 0;
1586 }
1587
1588
1589 bool InsetText::showInsetDialog(BufferView * bv) const
1590 {
1591         if (the_locking_inset)
1592                 return the_locking_inset->showInsetDialog(bv);
1593         return false;
1594 }
1595
1596
1597 std::vector<string> const InsetText::getLabelList() const 
1598 {
1599         std::vector<string> label_list;
1600
1601         Paragraph * tpar = par;
1602         while (tpar) {
1603                 Paragraph::inset_iterator beg = tpar->inset_iterator_begin();
1604                 Paragraph::inset_iterator end = tpar->inset_iterator_end();
1605                 for (; beg != end; ++beg) {
1606                         std::vector<string> const l = (*beg)->getLabelList();
1607                         label_list.insert(label_list.end(), l.begin(), l.end());
1608                 }
1609                 tpar = tpar->next();
1610         }
1611         return label_list;
1612 }
1613
1614
1615 void InsetText::setFont(BufferView * bv, LyXFont const & font, bool toggleall,
1616                         bool selectall)
1617 {
1618         if (the_locking_inset) {
1619                 the_locking_inset->setFont(bv, font, toggleall, selectall);
1620                 return;
1621         }
1622         if ((!par->next() && !par->size()) || !cpar(bv)->size()) {
1623                 getLyXText(bv)->setFont(bv, font, toggleall);
1624                 return;
1625         }
1626         bool clear = false;
1627         if (!lt) {
1628                 lt = getLyXText(bv);
1629                 clear = true;
1630         }
1631         if (lt->selection.set()) {
1632                 setUndo(bv, Undo::EDIT, lt->cursor.par(), lt->cursor.par()->next());
1633         }
1634         if (selectall)
1635                 selectAll(bv);
1636         lt->toggleFree(bv, font, toggleall);
1637         if (selectall)
1638                 lt->clearSelection();
1639         bv->fitCursor();
1640         if (selectall || lt->selection.set())
1641                 updateLocal(bv, FULL, true);
1642         else
1643                 updateLocal(bv, CURSOR_PAR, true);
1644         if (clear)
1645                 lt = 0;
1646 }
1647
1648
1649 bool InsetText::checkAndActivateInset(BufferView * bv, bool behind)
1650 {
1651         if (cpar(bv)->getChar(cpos(bv)) == Paragraph::META_INSET) {
1652                 unsigned int x;
1653                 unsigned int y;
1654                 Inset * inset =
1655                         static_cast<UpdatableInset*>(cpar(bv)->getInset(cpos(bv)));
1656                 if (!inset || inset->editable() != Inset::HIGHLY_EDITABLE)
1657                         return false;
1658                 LyXFont const font =
1659                         getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv));
1660                 if (behind) {
1661                         x = inset->width(bv, font);
1662                         y = font.isRightToLeft() ? 0 : inset->descent(bv, font);
1663                 } else {
1664                         x = 0;
1665                         y = font.isRightToLeft() ? inset->descent(bv, font) : 0;
1666                 }
1667                 //inset_x = cx(bv) - top_x + drawTextXOffset;
1668                 //inset_y = cy(bv) + drawTextYOffset;
1669                 inset->edit(bv, x, y, 0);
1670                 if (!the_locking_inset)
1671                         return false;
1672                 updateLocal(bv, CURSOR, false);
1673                 return true;
1674         }
1675         return false;
1676 }
1677
1678
1679 bool InsetText::checkAndActivateInset(BufferView * bv, int x, int y,
1680                                       int button)
1681 {
1682         x -= drawTextXOffset;
1683         int dummyx = x;
1684         int dummyy = y + insetAscent;
1685         Inset * inset = bv->checkInsetHit(getLyXText(bv), dummyx, dummyy, button);
1686
1687         if (inset) {
1688                 if (x < 0)
1689                         x = insetWidth;
1690                 if (y < 0)
1691                         y = insetDescent;
1692                 inset_x = cx(bv) - top_x + drawTextXOffset;
1693                 inset_y = cy(bv) + drawTextYOffset;
1694                 inset->edit(bv, x - inset_x, y - inset_y, button);
1695                 if (!the_locking_inset)
1696                         return false;
1697                 updateLocal(bv, CURSOR, false);
1698                 return true;
1699         }
1700         return false;
1701 }
1702
1703
1704 int InsetText::getMaxWidth(BufferView * bv, UpdatableInset const * inset) const
1705 {
1706 #if 0
1707         int w = UpdatableInset::getMaxWidth(bv, inset);
1708         if (w < 0) {
1709                 return -1;
1710         }
1711         if (owner()) {
1712                 w = w - top_x + owner()->x();
1713                 return w;
1714         }
1715         w -= (2 * TEXT_TO_INSET_OFFSET);
1716         return w - top_x;
1717 #else
1718         return UpdatableInset::getMaxWidth(bv, inset);
1719 #endif
1720 }
1721
1722
1723 void InsetText::setParagraphData(Paragraph * p)
1724 {
1725         // we have to unlock any locked inset otherwise we're in troubles
1726         the_locking_inset = 0;
1727         while (par) {
1728                 Paragraph * tmp = par->next();
1729                 delete par;
1730                 par = tmp;
1731         }
1732
1733         par = new Paragraph(*p);
1734         par->setInsetOwner(this);
1735         Paragraph * np = par;
1736         while (p->next()) {
1737                 p = p->next();
1738                 np->next(new Paragraph(*p));
1739                 np->next()->previous(np);
1740                 np = np->next();
1741                 np->setInsetOwner(this);
1742         }
1743         reinitLyXText(true);
1744 }
1745
1746
1747 void InsetText::setText(string const & data)
1748 {
1749         clear();
1750         LyXFont font(LyXFont::ALL_SANE);
1751         for (unsigned int i=0; i < data.length(); ++i)
1752                 par->insertChar(i, data[i], font);
1753 }
1754
1755
1756 void InsetText::setAutoBreakRows(bool flag)
1757 {
1758         if (flag != autoBreakRows) {
1759                 autoBreakRows = flag;
1760                 need_update = FULL;
1761                 if (!flag)
1762                         removeNewlines();
1763                 reinitLyXText(true);
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         if (!par->next() && !par->size()) // no data, resize not neccessary!
1908                 return;
1909         // one endless line, resize normally not necessary
1910         if (!force && getMaxWidth(bv, this) < 0)
1911                 return;
1912
1913         Cache::iterator it = cache.find(bv);
1914         if (it == cache.end()) {
1915                 return;
1916         }
1917         lyx::Assert(it->second.text.get());
1918
1919         LyXText * t = it->second.text.get();
1920         saveLyXTextState(t);
1921         for (Paragraph * p = par; p; p = p->next()) {
1922                 p->resizeInsetsLyXText(bv);
1923         }
1924         t->init(bv, true);
1925         restoreLyXTextState(bv, t);
1926         if (the_locking_inset) {
1927                 inset_x = cx(bv) - top_x + drawTextXOffset;
1928                 inset_y = cy(bv) + drawTextYOffset;
1929         }
1930
1931         if (bv->screen()) {
1932                 t->first = bv->screen()->topCursorVisible(t);
1933         }
1934         if (!owner()) {
1935                 updateLocal(bv, FULL, false);
1936                 // this will scroll the screen such that the cursor becomes visible 
1937                 bv->updateScrollbar();
1938         } else {
1939                 need_update |= FULL;
1940         }
1941 }
1942
1943
1944 void InsetText::reinitLyXText(bool wrong_cursor) const
1945 {
1946         for(Cache::iterator it = cache.begin(); it != cache.end(); ++it) {
1947                 lyx::Assert(it->second.text.get());
1948
1949                 LyXText * t = it->second.text.get();
1950                 BufferView * bv = it->first;
1951
1952                 if (wrong_cursor) {
1953                         t->cursor.par(par);
1954                         t->cursor.pos(0);
1955                         t->clearSelection();
1956                 }
1957                 saveLyXTextState(t);
1958                 for (Paragraph * p = par; p; p = p->next()) {
1959                         p->resizeInsetsLyXText(bv);
1960                 }
1961                 t->init(bv, true);
1962                 restoreLyXTextState(bv, t);
1963                 if (the_locking_inset) {
1964                         inset_x = cx(bv) - top_x + drawTextXOffset;
1965                         inset_y = cy(bv) + drawTextYOffset;
1966                 }
1967                 if (bv->screen()) {
1968                         t->first = bv->screen()->topCursorVisible(t);
1969                 }
1970                 if (!owner()) {
1971                         updateLocal(bv, FULL, false);
1972                         // this will scroll the screen such that the cursor becomes visible 
1973                         bv->updateScrollbar();
1974                 } else {
1975                         need_update = FULL;
1976                 }
1977         }
1978 }
1979
1980
1981 void InsetText::removeNewlines()
1982 {
1983         for (Paragraph * p = par; p; p = p->next()) {
1984                 for (int i = 0; i < p->size(); ++i) {
1985                         if (p->getChar(i) == Paragraph::META_NEWLINE)
1986                                 p->erase(i);
1987                 }
1988         }
1989 }
1990
1991
1992 bool InsetText::nodraw() const
1993 {
1994         if (the_locking_inset)
1995                 return the_locking_inset->nodraw();
1996         return UpdatableInset::nodraw();
1997 }
1998
1999
2000 int InsetText::scroll(bool recursive) const
2001 {
2002         int sx = UpdatableInset::scroll(false);
2003
2004         if (recursive && the_locking_inset)
2005                 sx += the_locking_inset->scroll(recursive);
2006
2007         return sx;
2008 }
2009
2010
2011 bool InsetText::doClearArea() const
2012 {
2013         return !locked || (need_update & (FULL|INIT));
2014 }
2015
2016
2017 void InsetText::selectAll(BufferView * bv)
2018 {
2019         getLyXText(bv)->cursorTop(bv);
2020         getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor;
2021         getLyXText(bv)->cursorBottom(bv);
2022         getLyXText(bv)->setSelection(bv);
2023 }
2024
2025
2026 void InsetText::clearSelection(BufferView * bv)
2027 {
2028         getLyXText(bv)->clearSelection();
2029 }
2030
2031
2032 void InsetText::clearInset(Painter & pain, int baseline, bool & cleared) const
2033 {
2034         int w = insetWidth;
2035         int h = insetAscent + insetDescent;
2036         int ty = baseline - insetAscent;
2037         
2038         if (ty < 0) {
2039                 h += ty;
2040                 ty = 0;
2041         }
2042         if ((ty + h) > pain.paperHeight())
2043                 h = pain.paperHeight();
2044         if ((top_x + drawTextXOffset + w) > pain.paperWidth())
2045                 w = pain.paperWidth();
2046 //      w -= TEXT_TO_INSET_OFFSET;
2047         pain.fillRectangle(top_x, ty, w+1, h+1, backgroundColor());
2048         cleared = true;
2049         need_update = FULL;
2050         frame_is_visible = false;
2051 }
2052
2053
2054 Paragraph * InsetText::getParFromID(int id) const
2055 {
2056 #if 0
2057         Paragraph * result = par;
2058         Paragraph * ires = 0;
2059         while (result && result->id() != id) {
2060                 if ((ires = result->getParFromID(id)))
2061                         return ires;
2062                 result = result->next();
2063         }
2064         return result;
2065 #else
2066         Paragraph * tmp = par;
2067         while (tmp) {
2068                 int tmp_id = tmp->id();
2069                 lyxerr << "Looking at paragraph: " << tmp_id << endl;
2070                 if (tmp->id() == id) {
2071                         return tmp;
2072                 }
2073                 Paragraph * tmp2 = tmp->getParFromID(id);
2074                 if (tmp2 != 0) {
2075                         return tmp2;
2076                 }
2077                 tmp = tmp->next();
2078         }
2079         return 0;
2080 #endif
2081 }
2082
2083
2084 Paragraph * InsetText::firstParagraph() const
2085 {
2086         Paragraph * result;
2087         if (the_locking_inset)
2088                 if ((result = the_locking_inset->firstParagraph()))
2089                         return result;
2090         return par;
2091 }
2092
2093
2094 LyXCursor const & InsetText::cursor(BufferView * bv) const
2095 {
2096                 if (the_locking_inset)
2097                                 return the_locking_inset->cursor(bv);
2098                 return getLyXText(bv)->cursor;
2099 }
2100
2101
2102 Paragraph * InsetText::paragraph() const
2103 {
2104         return par;
2105 }
2106
2107
2108 void InsetText::paragraph(Paragraph * p)
2109 {
2110         par = p;
2111 #if 0
2112         // we now have to update/redraw all instances
2113         for (Cache::iterator cit = cache.begin(); cit != cache.end(); ++cit) {
2114                 delete cit->second;
2115                 cit->second = 0;
2116         }
2117 #endif
2118         // redraw myself when asked for
2119         need_update |= INIT;
2120 }
2121
2122
2123 Inset * InsetText::getInsetFromID(int id_arg) const
2124 {
2125         if (id_arg == id())
2126                 return const_cast<InsetText *>(this);
2127
2128         Paragraph * lp = par;
2129
2130         while(lp) {
2131                 for (Paragraph::inset_iterator it = lp->inset_iterator_begin(),
2132                          en = lp->inset_iterator_end();
2133                          it != en; ++it)
2134                 {
2135                         if ((*it)->id() == id_arg)
2136                                 return *it;
2137                         Inset * in = (*it)->getInsetFromID(id_arg);
2138                         if (in)
2139                                 return in;
2140                 }
2141                 lp = lp->next();
2142         }
2143         return 0;
2144 }
2145
2146
2147 string const InsetText::selectNextWord(BufferView * bv, float & value) const
2148 {
2149         bool clear = false;
2150         string str;
2151
2152         if (!lt) {
2153                 lt = getLyXText(bv);
2154                 clear = true;
2155         }
2156         if (the_locking_inset) {
2157                 str = the_locking_inset->selectNextWord(bv, value);
2158                 if (!str.empty()) {
2159                         value += cy(bv);
2160                         if (clear)
2161                                 lt = 0;
2162                         return str;
2163                 }
2164 #warning Dekel please have a look on this one RTL? (Jug)
2165                 // we have to go on checking so move cusor to the right
2166                 lt->cursor.pos(lt->cursor.pos() + 1);
2167         }
2168         str = lt->selectNextWord(bv, value);
2169         if (str.empty())
2170                 bv->unlockInset(const_cast<InsetText *>(this));
2171         else
2172                 value = cy(bv);
2173         if (clear)
2174                 lt = 0;
2175         return str;
2176 }
2177
2178
2179 void InsetText::selectSelectedWord(BufferView * bv)
2180 {
2181         if (the_locking_inset) {
2182                 the_locking_inset->selectSelectedWord(bv);
2183                 return;
2184         }
2185         getLyXText(bv)->selectSelectedWord(bv);
2186         updateLocal(bv, SELECTION, false);
2187 }
2188
2189
2190 void InsetText::toggleSelection(BufferView * bv, bool kill_selection)
2191 {
2192         if (the_locking_inset) {
2193                 the_locking_inset->toggleSelection(bv, kill_selection);
2194         }
2195         bool clear = false;
2196         if (!lt) {
2197                 lt = getLyXText(bv);
2198                 clear = true;
2199         }
2200
2201         int x = top_x + TEXT_TO_INSET_OFFSET;
2202
2203         int y = 0;
2204         Row * row = lt->getRowNearY(y);
2205         int y_offset = top_baseline - row->ascent_of_text();
2206         y = y_offset;
2207         while ((row != 0) && ((y+row->height()) <= 0)) {
2208                 y += row->height();
2209                 row = row->next();
2210         }
2211         if (y_offset < 0)
2212                 y_offset = y;
2213         
2214         if (need_update & SELECTION)
2215                 need_update = NONE;
2216         bv->screen()->toggleSelection(lt, bv, kill_selection, y_offset, x);
2217         if (clear)
2218                 lt = 0;
2219 }
2220
2221
2222 bool InsetText::searchForward(BufferView * bv, string const & str,
2223                               bool const & cs, bool const & mw)
2224 {
2225         if (the_locking_inset) {
2226                 if (the_locking_inset->searchForward(bv, str, cs, mw))
2227                         return true;
2228                 bool clear = false;
2229                 if (!lt) {
2230                         lt = getLyXText(bv);
2231                         clear = true;
2232                 }
2233                 Paragraph * lpar = lt->cursor.par();
2234                 Paragraph::size_type pos = lt->cursor.pos();
2235                 if (pos < lpar->size() - 1)
2236                         ++pos;
2237                 else {
2238                         pos = 0;
2239                         lpar = lpar->next();
2240                 }
2241                 if (!lpar) {
2242                         if (clear)
2243                                 lt = 0;
2244                         return false;
2245                 }
2246                 lt->setCursor(bv, lpar, pos);
2247                 if (clear)
2248                         lt = 0;
2249         }
2250         if (LyXFind(bv, str, true, true, cs , mw)) {
2251                 return true;
2252         }
2253         // we have to unlock ourself in this function by default!
2254         bv->unlockInset(const_cast<InsetText *>(this));
2255         return false;
2256 }
2257
2258 bool InsetText::searchBackward(BufferView * bv, string const & str,
2259                                bool const & cs, bool const & mw)
2260 {
2261         if (the_locking_inset)
2262                 if (the_locking_inset->searchBackward(bv, str, cs, mw))
2263                         return true;
2264         if (LyXFind(bv, str, false, true, cs, mw)) {
2265                 return true;
2266         }
2267         // we have to unlock ourself in this function by default!
2268         bv->unlockInset(const_cast<InsetText *>(this));
2269         return false;
2270 }