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