]> git.lyx.org Git - lyx.git/blob - src/insets/insettext.C
some reindentation, revert workarea xpos++, constify, remove all traces of LyXParagra...
[lyx.git] / src / insets / insettext.C
1 // -*- C++ -*-
2 /* This file is part of
3  * ======================================================
4  * 
5  *           LyX, The Document Processor
6  *
7  *           Copyright 1998-2000 The LyX Team.
8  *
9  * ======================================================
10  */
11
12 #include <config.h>
13
14 #include <fstream>
15 #include <algorithm>
16
17 #include <cstdlib>
18
19 #ifdef __GNUG__
20 #pragma implementation
21 #endif
22
23 #include "insettext.h"
24 #include "lyxparagraph.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 "lyxrow.h"
44 #include "lyxrc.h"
45 #include "intl.h"
46 #include "trans_mgr.h"
47 #include "lyxscreen.h"
48 #include "WorkArea.h"
49 #include "gettext.h"
50 #include "lyxfunc.h"
51
52 using std::ostream;
53 using std::ifstream;
54 using std::endl;
55 using std::min;
56 using std::max;
57
58 extern unsigned char getCurrentTextClass(Buffer *);
59 extern bool math_insert_greek(BufferView *, char);
60 extern int greek_kb_flag;
61
62 InsetText::InsetText()
63 {
64         par = new LyXParagraph;
65         init();
66 }
67
68
69 InsetText::InsetText(InsetText const & ins)
70         : UpdatableInset()
71 {
72         par = 0;
73         init(&ins);
74         autoBreakRows = ins.autoBreakRows;
75 }
76
77
78 InsetText & InsetText::operator=(InsetText const & it)
79 {
80         init(&it);
81         autoBreakRows = it.autoBreakRows;
82         return * this;
83 }
84
85
86 void InsetText::init(InsetText const * ins)
87 {
88         top_y = 0;
89         last_width = 0;
90         last_height = 0;
91         insetAscent = 0;
92         insetDescent = 0;
93         insetWidth = 0;
94         the_locking_inset = 0;
95         interline_space = 1;
96         no_selection = false;
97         need_update = INIT;
98         drawTextXOffset = 0;
99         drawTextYOffset = 0;
100         autoBreakRows = false;
101         drawFrame_ = NEVER;
102         xpos = 0.0;
103         if (ins) {
104                 SetParagraphData(ins->par);
105                 autoBreakRows = ins->autoBreakRows;
106                 drawFrame_ = ins->drawFrame_;
107         }
108         par->SetInsetOwner(this);
109         frame_color = LColor::insetframe;
110         locked = false;
111         old_par = 0;
112         last_drawn_width = -1;
113         frame_is_visible = false;
114 }
115
116
117 InsetText::~InsetText()
118 {
119         // delete all instances of LyXText before deleting the paragraps used
120         // by it.
121         for (Cache::iterator cit = cache.begin(); cit != cache.end(); ++cit) {
122                 delete (*cit).second;
123                 (*cit).second = 0;
124         }
125
126         while (par) {
127                 LyXParagraph * tmp = par->next();
128                 delete par;
129                 par = tmp;
130         }
131 }
132
133
134 void InsetText::clear()
135 {
136         // delete all instances of LyXText before deleting the paragraps used
137         // by it.
138         for (Cache::iterator cit = cache.begin(); cit != cache.end(); ++cit) {
139                 delete (*cit).second;
140                 (*cit).second = 0;
141         }
142
143         while (par) {
144                 LyXParagraph * tmp = par->next();
145                 delete par;
146                 par = tmp;
147         }
148         par = new LyXParagraph;
149 }
150
151
152 Inset * InsetText::Clone(Buffer const &) const
153 {
154         InsetText * t = new InsetText(*this);
155         return t;
156 }
157
158
159 void InsetText::Write(Buffer const * buf, ostream & os) const
160 {
161         os << "Text\n";
162         WriteParagraphData(buf, os);
163 }
164
165
166 void InsetText::WriteParagraphData(Buffer const * buf, ostream & os) const
167 {
168         par->writeFile(buf, os, buf->params, 0, 0);
169 }
170
171
172 void InsetText::Read(Buffer const * buf, LyXLex & lex)
173 {
174         string token;
175         int pos = 0;
176         LyXParagraph * return_par = 0;
177         char depth = 0; // signed or unsigned?
178         LyXFont font(LyXFont::ALL_INHERIT);
179
180         clear();
181         
182         while (lex.IsOK()) {
183                 lex.nextToken();
184                 token = lex.GetString();
185                 if (token.empty())
186                         continue;
187                 if (token == "\\end_inset")
188                         break;
189                 if (const_cast<Buffer*>(buf)->
190                         parseSingleLyXformat2Token(lex, par, return_par,
191                                                    token, pos, depth, font)) {
192                         // the_end read this should NEVER happen
193                         lex.printError("\\the_end read in inset! Error in document!");
194                         return;
195                 }
196         }
197         if (!return_par)
198                 return_par = par;
199         par = return_par;
200         while(return_par) {
201                 return_par->SetInsetOwner(this);
202                 return_par = return_par->next();
203         }
204         
205         if (token != "\\end_inset") {
206                 lex.printError("Missing \\end_inset at this point. "
207                                            "Read: `$$Token'");
208         }
209         need_update = INIT;
210 }
211
212
213 int InsetText::ascent(BufferView * bv, LyXFont const &) const
214 {
215         int y_temp = 0;
216         Row * row = TEXT(bv)->GetRowNearY(y_temp);
217         insetAscent = row->ascent_of_text() + TEXT_TO_INSET_OFFSET;
218         return insetAscent;
219 }
220
221
222 int InsetText::descent(BufferView * bv, LyXFont const &) const
223 {
224         int y_temp = 0;
225         Row * row = TEXT(bv)->GetRowNearY(y_temp);
226         insetDescent = TEXT(bv)->height - row->ascent_of_text() +
227         TEXT_TO_INSET_OFFSET;
228         return insetDescent;
229 }
230
231
232 int InsetText::width(BufferView * bv, LyXFont const &) const
233 {
234         insetWidth = max(textWidth(bv),
235                          (int)TEXT(bv)->width + (2 * TEXT_TO_INSET_OFFSET));
236         return insetWidth;
237 }
238
239
240 int InsetText::textWidth(BufferView * bv) const
241 {
242         int const w = getMaxWidth(bv, this);
243         return w;
244 }
245
246
247 void InsetText::draw(BufferView * bv, LyXFont const & f,
248                      int baseline, float & x, bool cleared) const
249 {
250         if (nodraw())
251                 return;
252
253         Painter & pain = bv->painter();
254
255         // no draw is necessary !!!
256         if ((drawFrame_ == LOCKED) && !locked && !par->size()) {
257                 top_x = int(x);
258                 top_baseline = baseline;
259                 x += width(bv, f);
260                 if (!cleared && (need_update & CLEAR_FRAME))
261                         clearFrame(pain, cleared);
262                 need_update = NONE;
263                 return;
264         }
265
266         xpos = x;
267 #if 0
268         UpdatableInset::draw(bv, f, baseline, x, cleared);
269 #else
270         if (!owner())
271                 x += static_cast<float>(scroll());
272 #endif
273         // update insetWidth and insetHeight with dummy calls
274         (void)ascent(bv, f);
275         (void)descent(bv, f);
276         (void)width(bv, f);
277
278         // if top_x differs we have a rule down and we don't have to clear anything
279         if (!cleared && (top_x == int(x)) &&
280                 ((need_update&(INIT|FULL)) || (top_baseline!=baseline) ||
281                  (last_drawn_width!=insetWidth)))
282         {
283                 int w =  insetWidth;
284                 int h = insetAscent + insetDescent;
285                 int ty = baseline - insetAscent;
286         
287                 if (ty < 0) {
288                         h += ty;
289                         ty = 0;
290                 }
291                 if ((ty + h) > pain.paperHeight())
292                         h = pain.paperHeight();
293                 if ((top_x + drawTextXOffset + w) > pain.paperWidth())
294                         w = pain.paperWidth();
295                 pain.fillRectangle(top_x+drawTextXOffset, ty, w, h);
296                 cleared = true;
297                 need_update = FULL;
298         }
299         if (!cleared && (need_update == NONE))
300                 return;
301
302         if (top_x != int(x)) {
303                 need_update |= INIT;
304                 top_x = int(x);
305                 bv->text->status = LyXText::CHANGED_IN_DRAW;
306                 return;
307         }
308
309 //      lyxerr << "InsetText::draw[" << this << "](" << need_update << ":" << int(x) << ":" << top_x << ")\n";
310
311         if (cleared || (last_drawn_width != insetWidth)) {
312                 need_update |= FULL;
313                 last_drawn_width = insetWidth;
314         }
315
316         top_baseline = baseline;
317         top_y = baseline - ascent(bv, f);
318         last_width = width(bv, f);
319         last_height = ascent(bv, f) + descent(bv, f);
320
321         if (the_locking_inset && (cpar(bv) == inset_par) && (cpos(bv) == inset_pos)) {
322                 inset_x = cx(bv) - top_x + drawTextXOffset;
323                 inset_y = cy(bv) + drawTextYOffset;
324         }
325         if (!cleared && (need_update == CURSOR) && !TEXT(bv)->selection) {
326                 drawFrame(pain, cleared);
327                 x += width(bv, f);
328                 need_update = NONE;
329                 return;
330         }
331         x += TEXT_TO_INSET_OFFSET;
332
333 #ifdef WITH_WARNINGS
334 #warning Jürgen, why is this a block of its own? (Lgb)
335 #warning because you told me to define variables only in local context (Jug)!
336 #warning then make it a function/method of its own. (Lgb)
337 #endif
338         {
339         int y = 0;
340         Row * row = TEXT(bv)->GetRowNearY(y);
341         int y_offset = baseline - row->ascent_of_text();
342         int ph = pain.paperHeight();
343         int first = 0;
344         y = y_offset;
345         while ((row != 0) && ((y+row->height()) <= 0)) {
346                 y += row->height();
347                 first += row->height();
348                 row = row->next();
349         }
350         if (y_offset < 0)
351                 y_offset = y;
352         TEXT(bv)->first = first;
353         if (cleared) {
354                 int yf = y_offset;
355                 y = 0;
356                 while ((row != 0) && (yf < ph)) {
357                         TEXT(bv)->GetVisibleRow(bv, y+y_offset, int(x), row,
358                                                 y+first, cleared);
359                 y += row->height();
360                 yf += row->height();
361                 row = row->next();
362                 }
363         } else if (!locked) {
364                 if (need_update & CURSOR) {
365                         bv->screen()->ToggleSelection(TEXT(bv), bv, true, y_offset,int(x));
366                         TEXT(bv)->ClearSelection(bv);
367                         TEXT(bv)->sel_cursor = TEXT(bv)->cursor;
368                 }
369                 bv->screen()->Update(TEXT(bv), bv, y_offset, int(x));
370         } else {
371                 locked = false;
372                 if (need_update & SELECTION)
373                         bv->screen()->ToggleToggle(TEXT(bv), bv, y_offset, int(x));
374                 else if (need_update & CURSOR) {
375                         bv->screen()->ToggleSelection(TEXT(bv), bv, true, y_offset,int(x));
376                         TEXT(bv)->ClearSelection(bv);
377                         TEXT(bv)->sel_cursor = TEXT(bv)->cursor;
378                 }
379                 bv->screen()->Update(TEXT(bv), bv, y_offset, int(x));
380                 locked = true;
381         }
382         }
383         TEXT(bv)->refresh_y = 0;
384         TEXT(bv)->status = LyXText::UNCHANGED;
385         if ((need_update != CURSOR_PAR) &&
386                 ((drawFrame_ == ALWAYS) || ((drawFrame_ == LOCKED) && locked)))
387                 drawFrame(pain, cleared);
388         else if (need_update & CLEAR_FRAME)
389                 clearFrame(pain, cleared);
390         x += width(bv, f) - TEXT_TO_INSET_OFFSET;
391         if (bv->text->status==LyXText::CHANGED_IN_DRAW) {
392                 need_update |= INIT;
393         } else if (need_update != INIT)
394                 need_update = NONE;
395 }
396
397
398 void InsetText::drawFrame(Painter & pain, bool cleared) const
399 {
400         if (!frame_is_visible || cleared) {
401                 pain.rectangle(top_x + 1, top_baseline - insetAscent + 1,
402                                insetWidth - 1, insetAscent + insetDescent - 1,
403                                frame_color);
404                 frame_is_visible = true;
405         }
406 }
407
408
409 void InsetText::clearFrame(Painter & pain, bool cleared) const
410 {
411         if (frame_is_visible) {
412                 if (!cleared) {
413                         pain.rectangle(top_x + 1, top_baseline - insetAscent + 1,
414                                        insetWidth - 1, insetAscent + insetDescent - 1,
415                                        LColor::background);
416                 }
417                 frame_is_visible = false;
418         }
419 }
420
421
422 void InsetText::update(BufferView * bv, LyXFont const & font, bool reinit)
423 {
424         if (reinit) {
425                 need_update |= INIT;
426                 resizeLyXText(bv);
427                 if (owner())
428                         owner()->update(bv, font, true);
429                 return;
430         }
431         if (the_locking_inset) {
432                 inset_x = cx(bv) - top_x + drawTextXOffset;
433                 inset_y = cy(bv) + drawTextYOffset;
434                 the_locking_inset->update(bv, font, reinit);
435         }
436 #if 0
437         if (need_update == INIT) {
438                 resizeLyXText(bv);
439                 need_update |= FULL;
440         }
441 #endif
442         int oldw = insetWidth;
443         insetWidth = TEXT(bv)->width + (2 * TEXT_TO_INSET_OFFSET);
444         if (oldw != insetWidth) {
445                 resizeLyXText(bv);
446                 need_update |= FULL;
447 //              update(bv, font, reinit);
448                 return;
449         }
450         if ((need_update&CURSOR_PAR) && (TEXT(bv)->status==LyXText::UNCHANGED) &&
451                 the_locking_inset)
452         {
453                 TEXT(bv)->UpdateInset(bv, the_locking_inset);
454         }
455         
456         if (TEXT(bv)->status == LyXText::NEED_MORE_REFRESH)
457                 need_update |= FULL;
458 #if 0
459         int y_temp = 0;
460         Row * row = TEXT(bv)->GetRowNearY(y_temp);
461         insetAscent = row->ascent_of_text() + TEXT_TO_INSET_OFFSET;
462         insetDescent = TEXT(bv)->height - row->ascent_of_text() +
463                 TEXT_TO_INSET_OFFSET;
464 #endif
465 }
466
467
468 void InsetText::SetUpdateStatus(BufferView * bv, int what) const
469 {
470         need_update |= what;
471         if (TEXT(bv)->status == LyXText::NEED_MORE_REFRESH)
472                 need_update |= FULL;
473         else if (TEXT(bv)->status == LyXText::NEED_VERY_LITTLE_REFRESH)
474                 need_update |= CURSOR_PAR;
475
476         // this to not draw a selection when we redraw all of it!
477         if ((need_update & (INIT|FULL)) && (need_update & CURSOR))
478                 TEXT(bv)->ClearSelection(bv);
479 }
480
481
482 void InsetText::UpdateLocal(BufferView * bv, int what, bool mark_dirty)
483 {
484         TEXT(bv)->FullRebreak(bv);
485         SetUpdateStatus(bv, what);
486         if ((need_update != CURSOR) || (TEXT(bv)->status != LyXText::UNCHANGED) ||
487                 TEXT(bv)->selection)
488                 bv->updateInset(this, mark_dirty);
489         bv->owner()->showState();
490         if (old_par != cpar(bv)) {
491                 bv->owner()->setLayout(cpar(bv)->GetLayout());
492                 old_par = cpar(bv);
493         }
494 }
495
496
497 string const InsetText::EditMessage() const
498 {
499         return _("Opened Text Inset");
500 }
501
502
503 void InsetText::Edit(BufferView * bv, int x, int y, unsigned int button)
504 {
505 //    par->SetInsetOwner(this);
506         UpdatableInset::Edit(bv, x, y, button);
507
508         if (!bv->lockInset(this)) {
509                 lyxerr[Debug::INSETS] << "Cannot lock inset" << endl;
510                 return;
511         }
512         locked = true;
513         the_locking_inset = 0;
514         inset_pos = inset_x = inset_y = 0;
515         inset_boundary = false;
516         inset_par = 0;
517         old_par = 0;
518         int tmp_y = (y < 0)?0:y;
519         if (!checkAndActivateInset(bv, x, tmp_y, button))
520                 TEXT(bv)->SetCursorFromCoordinates(bv, x - drawTextXOffset,
521                                                    y + insetAscent);
522         TEXT(bv)->sel_cursor = TEXT(bv)->cursor;
523         bv->text->FinishUndo();
524         ShowInsetCursor(bv);
525         UpdateLocal(bv, CURSOR, false);
526
527         // If the inset is empty set the language of the current font to the
528         // language to the surronding text.
529         if (par->size() == 0 && !par->next()) {
530                 LyXFont font(LyXFont::ALL_IGNORE);
531                 font.setLanguage(bv->getParentLanguage(this));
532                 SetFont(bv, font, false);
533         }
534 }
535
536
537 void InsetText::InsetUnlock(BufferView * bv)
538 {
539         if (the_locking_inset) {
540                 the_locking_inset->InsetUnlock(bv);
541                 the_locking_inset = 0;
542         }
543         HideInsetCursor(bv);
544         no_selection = false;
545         locked = false;
546         UpdateLocal(bv, CLEAR_FRAME|CURSOR, false);
547         if (owner())
548                 bv->owner()->setLayout(owner()->getLyXText(bv)
549                                        ->cursor.par()->GetLayout());
550         else
551                 bv->owner()->setLayout(bv->text->cursor.par()->GetLayout());
552 }
553
554
555 bool InsetText::LockInsetInInset(BufferView * bv, UpdatableInset * inset)
556 {
557         lyxerr[Debug::INSETS] << "InsetText::LockInsetInInset("
558                               << inset << "): ";
559         if (!inset)
560                 return false;
561         if (inset == cpar(bv)->GetInset(cpos(bv))) {
562                 lyxerr[Debug::INSETS] << "OK" << endl;
563                 the_locking_inset = inset;
564                 inset_x = cx(bv) - top_x + drawTextXOffset;
565                 inset_y = cy(bv) + drawTextYOffset;
566                 inset_pos = cpos(bv);
567                 inset_par = cpar(bv);
568                 inset_boundary = cboundary(bv);
569 #if 0
570                 TEXT(bv)->ClearSelection(bv);
571                 TEXT(bv)->sel_cursor = TEXT(bv)->cursor;
572                 TEXT(bv)->UpdateInset(bv, the_locking_inset);
573 #else
574                 UpdateLocal(bv, CURSOR, false);
575 #endif
576                 return true;
577         } else if (the_locking_inset && (the_locking_inset == inset)) {
578                 if (cpar(bv) == inset_par && cpos(bv) == inset_pos) {
579                         lyxerr[Debug::INSETS] << "OK" << endl;
580                         inset_x = cx(bv) - top_x + drawTextXOffset;
581                         inset_y = cy(bv) + drawTextYOffset;
582                 } else {
583                         lyxerr[Debug::INSETS] << "cursor.pos != inset_pos" << endl;
584                 }
585         } else if (the_locking_inset) {
586                 lyxerr[Debug::INSETS] << "MAYBE" << endl;
587                 return the_locking_inset->LockInsetInInset(bv, inset);
588         }
589         lyxerr[Debug::INSETS] << "NOT OK" << endl;
590         return false;
591 }
592
593
594 bool InsetText::UnlockInsetInInset(BufferView * bv, UpdatableInset * inset,
595                                    bool lr)
596 {
597         if (!the_locking_inset)
598                 return false;
599         if (the_locking_inset == inset) {
600                 the_locking_inset->InsetUnlock(bv);
601                 TEXT(bv)->UpdateInset(bv, inset);
602                 the_locking_inset = 0;
603                 if (lr)
604                         moveRight(bv, false);
605                 old_par = 0; // force layout setting
606                 if (scroll())
607                         scroll(bv, 0.0F);
608                 else
609                         UpdateLocal(bv, CURSOR, false);
610                 return true;
611         }
612         return the_locking_inset->UnlockInsetInInset(bv, inset, lr);
613 }
614
615
616 bool InsetText::UpdateInsetInInset(BufferView * bv, Inset * inset)
617 {
618         if (!the_locking_inset)
619                 return false;
620         if (the_locking_inset != inset) {
621                 TEXT(bv)->UpdateInset(bv, the_locking_inset);
622                 SetUpdateStatus(bv, CURSOR_PAR);
623                 return the_locking_inset->UpdateInsetInInset(bv, inset);
624         }
625 //    UpdateLocal(bv, FULL, false);
626         if (TEXT(bv)->UpdateInset(bv, inset))
627                 UpdateLocal(bv, CURSOR_PAR, false);
628         if (cpar(bv) == inset_par && cpos(bv) == inset_pos) {
629                 inset_x = cx(bv) - top_x + drawTextXOffset;
630                 inset_y = cy(bv) + drawTextYOffset;
631         }
632         return true;
633 }
634
635
636 void InsetText::InsetButtonPress(BufferView * bv, int x, int y, int button)
637 {
638         no_selection = true;
639
640         int tmp_x = x - drawTextXOffset;
641         int tmp_y = y + insetAscent - TEXT(bv)->first;
642         Inset * inset = bv->checkInsetHit(TEXT(bv), tmp_x, tmp_y, button);
643
644         HideInsetCursor(bv);
645         if (the_locking_inset) {
646                 if (the_locking_inset == inset) {
647                         the_locking_inset->InsetButtonPress(bv,x-inset_x,y-inset_y,button);
648                         no_selection = false;
649                         return;
650                 } else if (inset) {
651                         // otherwise unlock the_locking_inset and lock the new inset
652                         the_locking_inset->InsetUnlock(bv);
653                         inset_x = cx(bv) - top_x + drawTextXOffset;
654                         inset_y = cy(bv) + drawTextYOffset;
655                         the_locking_inset = static_cast<UpdatableInset*>(inset);
656                         inset->InsetButtonPress(bv, x - inset_x, y - inset_y, button);
657                         inset->Edit(bv, x - inset_x, y - inset_y, button);
658                         if (the_locking_inset)
659                                 UpdateLocal(bv, CURSOR, false);
660                         no_selection = false;
661                         return;
662                 }
663                 // otherwise only unlock the_locking_inset
664                 the_locking_inset->InsetUnlock(bv);
665                 the_locking_inset = 0;
666         }
667         if (bv->theLockingInset()) {
668                 if (inset && inset->Editable() == Inset::HIGHLY_EDITABLE) {
669                         UpdatableInset * uinset = static_cast<UpdatableInset*>(inset);
670                         inset_x = cx(bv) - top_x + drawTextXOffset;
671                         inset_y = cy(bv) + drawTextYOffset;
672                         inset_pos = cpos(bv);
673                         inset_par = cpar(bv);
674                         inset_boundary = cboundary(bv);
675                         the_locking_inset = uinset;
676                         uinset->InsetButtonPress(bv, x - inset_x, y - inset_y,
677                                                  button);
678                         uinset->Edit(bv, x - inset_x, y - inset_y, 0);
679                         if (the_locking_inset)
680                                 UpdateLocal(bv, CURSOR, false);
681                         no_selection = false;
682                         return;
683                 }
684         }
685         if (!inset) { // && (button == 2)) {
686                 bool paste_internally = false;
687                 if ((button == 2) && TEXT(bv)->selection) {
688                         LocalDispatch(bv, LFUN_COPY, "");
689                         paste_internally = true;
690                 }
691                 TEXT(bv)->SetCursorFromCoordinates(bv, x-drawTextXOffset,
692                                                    y + insetAscent);
693                 TEXT(bv)->sel_cursor = TEXT(bv)->cursor;
694                 UpdateLocal(bv, CURSOR, false);
695                 bv->owner()->setLayout(cpar(bv)->GetLayout());
696                 old_par = cpar(bv);
697                 // Insert primary selection with middle mouse
698                 // if there is a local selection in the current buffer,
699                 // insert this
700                 if (button == 2) {
701                         if (paste_internally)
702                                 LocalDispatch(bv, LFUN_PASTE, "");
703                         else
704                                 LocalDispatch(bv, LFUN_PASTESELECTION,
705                                               "paragraph");
706                 }
707         }
708         ShowInsetCursor(bv);
709         no_selection = false;
710 }
711
712
713 void InsetText::InsetButtonRelease(BufferView * bv, int x, int y, int button)
714 {
715         UpdatableInset * inset = 0;
716
717         if (the_locking_inset) {
718                 the_locking_inset->InsetButtonRelease(bv,
719                                                       x - inset_x, y - inset_y,
720                                                       button);
721         } else {
722                 if (cpar(bv)->GetChar(cpos(bv)) == LyXParagraph::META_INSET) {
723                         inset = static_cast<UpdatableInset*>(cpar(bv)->GetInset(cpos(bv)));
724                         if (inset->Editable() == Inset::HIGHLY_EDITABLE) {
725                                 inset->InsetButtonRelease(bv,
726                                                           x - inset_x,
727                                                           y - inset_y, button);
728                         } else {
729                                 inset_x = cx(bv) - top_x + drawTextXOffset;
730                                 inset_y = cy(bv) + drawTextYOffset;
731                                 inset->InsetButtonRelease(bv,
732                                                           x - inset_x,
733                                                           y - inset_y, button);
734                                 inset->Edit(bv,
735                                             x - inset_x, y - inset_y, button);
736                         }
737                         UpdateLocal(bv, CURSOR_PAR, false);
738                 }
739         }
740         no_selection = false;
741 }
742
743
744 void InsetText::InsetMotionNotify(BufferView * bv, int x, int y, int state)
745 {
746         if (no_selection)
747                 return;
748         if (the_locking_inset) {
749                 the_locking_inset->InsetMotionNotify(bv, x - inset_x,
750                                                      y - inset_y,state);
751                 return;
752         }
753         HideInsetCursor(bv);
754         TEXT(bv)->SetCursorFromCoordinates(bv, x - drawTextXOffset,
755                                            y + insetAscent);
756         TEXT(bv)->SetSelection(bv);
757         if (TEXT(bv)->toggle_cursor.par()!=TEXT(bv)->toggle_end_cursor.par() ||
758                 TEXT(bv)->toggle_cursor.pos()!=TEXT(bv)->toggle_end_cursor.pos())
759                 UpdateLocal(bv, SELECTION, false);
760         ShowInsetCursor(bv);
761 }
762
763
764 void InsetText::InsetKeyPress(XKeyEvent * xke)
765 {
766         if (the_locking_inset) {
767                 the_locking_inset->InsetKeyPress(xke);
768                 return;
769         }
770 }
771
772
773 UpdatableInset::RESULT
774 InsetText::LocalDispatch(BufferView * bv,
775                          kb_action action, string const & arg)
776 {
777         no_selection = false;
778         UpdatableInset::RESULT
779                 result= UpdatableInset::LocalDispatch(bv, action, arg);
780         if (result != UNDISPATCHED) {
781                 return DISPATCHED;
782         }
783
784         result = DISPATCHED;
785         if ((action < 0) && arg.empty())
786                 return FINISHED;
787
788         if (the_locking_inset) {
789                 result = the_locking_inset->LocalDispatch(bv, action, arg);
790                 if (result == DISPATCHED_NOUPDATE)
791                         return result;
792                 else if (result == DISPATCHED) {
793                         UpdateLocal(bv, CURSOR_PAR, false);
794                         return result;
795                 } else if (result == FINISHED) {
796                         bool dispatched = false;
797                         switch (action) {
798                         case LFUN_UNKNOWN_ACTION:
799                         case LFUN_BREAKPARAGRAPH:
800                         case LFUN_BREAKLINE:
801                                 moveRightIntern(bv, false, false);
802                                 break;
803                         case LFUN_RIGHT:
804                                 if (!TEXT(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
805                                         moveRightIntern(bv, false, false);
806                                 dispatched = true;
807                                 break;
808                         case LFUN_LEFT:
809                                 if (TEXT(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
810                                         moveRightIntern(bv, false, false);
811                                 dispatched = true;
812                                 break;
813                         default:
814                                 break;
815                         }
816                         the_locking_inset = 0;
817                         if (dispatched)
818                                 return DISPATCHED;
819                 }
820         }
821         HideInsetCursor(bv);
822         switch (action) {
823         // Normal chars
824         case LFUN_UNKNOWN_ACTION:
825                 if (bv->buffer()->isReadonly()) {
826 //          setErrorMessage(N_("Document is read only"));
827                         break;
828                 }
829                 if (!arg.empty()) {
830                         /* Automatically delete the currently selected
831                          * text and replace it with what is being
832                          * typed in now. Depends on lyxrc settings
833                          * "auto_region_delete", which defaults to
834                          * true (on). */
835
836                         bv->text->SetUndo(bv->buffer(), Undo::INSERT,
837                                           bv->text->cursor.par()->previous(),
838                                           bv->text->cursor.par()->next());
839                         bv->setState();
840                         if (lyxrc.auto_region_delete) {
841                                 if (TEXT(bv)->selection){
842                                         TEXT(bv)->CutSelection(bv, false);
843                                 }
844                         }
845                         TEXT(bv)->ClearSelection(bv);
846                         for (string::size_type i = 0; i < arg.length(); ++i) {
847                                 if (greek_kb_flag) {
848                                         if (!math_insert_greek(bv, arg[i])) {
849                                                 bv->owner()->getIntl()->getTrans().TranslateAndInsert(arg[i], TEXT(bv));
850                                         } else if (!the_locking_inset) {
851                                                 (void)moveRight(bv, false);
852                                         }
853                                 } else {
854                                         bv->owner()->getIntl()->getTrans().TranslateAndInsert(arg[i], TEXT(bv));
855                                 }
856                         }
857                 }
858                 TEXT(bv)->sel_cursor = TEXT(bv)->cursor;
859                 UpdateLocal(bv, CURSOR_PAR, true);
860                 result=DISPATCHED_NOUPDATE;
861                 break;
862                 // --- Cursor Movements -----------------------------------
863         case LFUN_RIGHTSEL:
864                 bv->text->FinishUndo();
865                 moveRight(bv, false, true);
866                 TEXT(bv)->SetSelection(bv);
867                 UpdateLocal(bv, SELECTION, false);
868                 break;
869         case LFUN_RIGHT:
870                 result = moveRight(bv);
871                 bv->text->FinishUndo();
872                 UpdateLocal(bv, CURSOR, false);
873                 break;
874         case LFUN_LEFTSEL:
875                 bv->text->FinishUndo();
876                 moveLeft(bv, false, true);
877                 TEXT(bv)->SetSelection(bv);
878                 UpdateLocal(bv, SELECTION, false);
879                 break;
880         case LFUN_LEFT:
881                 bv->text->FinishUndo();
882                 result = moveLeft(bv);
883                 UpdateLocal(bv, CURSOR, false);
884                 break;
885         case LFUN_DOWNSEL:
886                 bv->text->FinishUndo();
887                 moveDown(bv);
888                 TEXT(bv)->SetSelection(bv);
889                 UpdateLocal(bv, SELECTION, false);
890                 break;
891         case LFUN_DOWN:
892                 bv->text->FinishUndo();
893                 result = moveDown(bv);
894                 UpdateLocal(bv, CURSOR, false);
895                 break;
896         case LFUN_UPSEL:
897                 bv->text->FinishUndo();
898                 moveUp(bv);
899                 TEXT(bv)->SetSelection(bv);
900                 UpdateLocal(bv, SELECTION, false);
901                 break;
902         case LFUN_UP:
903                 bv->text->FinishUndo();
904                 result = moveUp(bv);
905                 UpdateLocal(bv, CURSOR, false);
906                 break;
907         case LFUN_HOME:
908                 bv->text->FinishUndo();
909                 TEXT(bv)->CursorHome(bv);
910                 UpdateLocal(bv, CURSOR, false);
911                 break;
912         case LFUN_END:
913                 TEXT(bv)->CursorEnd(bv);
914                 UpdateLocal(bv, CURSOR, false);
915                 break;
916         case LFUN_BACKSPACE:
917                 bv->text->SetUndo(bv->buffer(), Undo::DELETE,
918                                   bv->text->cursor.par()->previous(),
919                                   bv->text->cursor.par()->next());
920                 if (TEXT(bv)->selection)
921                         TEXT(bv)->CutSelection(bv);
922                 else
923                         TEXT(bv)->Backspace(bv);
924                 UpdateLocal(bv, CURSOR_PAR, true);
925                 break;
926         case LFUN_DELETE:
927                 bv->text->SetUndo(bv->buffer(), Undo::DELETE,
928                                   bv->text->cursor.par()->previous(),
929                                   bv->text->cursor.par()->next());
930                 if (TEXT(bv)->selection)
931                         TEXT(bv)->CutSelection(bv);
932                 else
933                         TEXT(bv)->Delete(bv);
934                 UpdateLocal(bv, CURSOR_PAR, true);
935                 break;
936         case LFUN_CUT:
937                 bv->text->SetUndo(bv->buffer(), Undo::DELETE,
938                                   bv->text->cursor.par()->previous(),
939                                   bv->text->cursor.par()->next());
940                 TEXT(bv)->CutSelection(bv);
941                 UpdateLocal(bv, CURSOR_PAR, true);
942                 break;
943         case LFUN_COPY:
944                 bv->text->FinishUndo();
945                 TEXT(bv)->CopySelection(bv);
946                 UpdateLocal(bv, CURSOR_PAR, false);
947                 break;
948         case LFUN_PASTESELECTION:
949         {
950                 string clip(bv->getClipboard());
951         
952                 if (clip.empty())
953                         break;
954                 if (arg == "paragraph") {
955                         TEXT(bv)->InsertStringB(bv, clip);
956                 } else {
957                         TEXT(bv)->InsertStringA(bv, clip);
958                 }
959                 UpdateLocal(bv, CURSOR_PAR, true);
960                 break;
961         }
962         case LFUN_PASTE:
963                 if (!autoBreakRows) {
964                         CutAndPaste cap;
965
966                         if (cap.nrOfParagraphs() > 1) {
967                                 WriteAlert(_("Impossible operation"),
968                                                    _("Cannot include more than one paragraph!"),
969                                                    _("Sorry."));
970                                 break;
971                         }
972                 }
973                 bv->text->SetUndo(bv->buffer(), Undo::INSERT,
974                                   bv->text->cursor.par()->previous(),
975                                   bv->text->cursor.par()->next());
976                 TEXT(bv)->PasteSelection(bv);
977                 UpdateLocal(bv, CURSOR_PAR, true);
978                 break;
979         case LFUN_BREAKPARAGRAPH:
980                 if (!autoBreakRows)
981                         return DISPATCHED;
982                 TEXT(bv)->BreakParagraph(bv, 0);
983                 UpdateLocal(bv, FULL, true);
984                 break;
985         case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
986                 if (!autoBreakRows)
987                         return DISPATCHED;
988                 TEXT(bv)->BreakParagraph(bv, 1);
989                 UpdateLocal(bv, FULL, true);
990                 break;
991         case LFUN_BREAKLINE:
992                 if (!autoBreakRows)
993                         return DISPATCHED;
994                 bv->text->SetUndo(bv->buffer(), Undo::INSERT,
995                                   bv->text->cursor.par()->previous(),
996                                   bv->text->cursor.par()->next());
997                 TEXT(bv)->InsertChar(bv, LyXParagraph::META_NEWLINE);
998                 UpdateLocal(bv, CURSOR_PAR, true);
999                 break;
1000         case LFUN_LAYOUT:
1001                 // do not set layouts on non breakable textinsets
1002                 if (autoBreakRows) {
1003                         LyXTextClass::size_type cur_layout = cpar(bv)->layout;
1004           
1005                         // Derive layout number from given argument (string)
1006                         // and current buffer's textclass (number). */    
1007                         LyXTextClassList::ClassList::size_type tclass =
1008                                 bv->buffer()->params.textclass;
1009                         std::pair <bool, LyXTextClass::size_type> layout = 
1010                                 textclasslist.NumberOfLayout(tclass, arg);
1011
1012                         // If the entry is obsolete, use the new one instead.
1013                         if (layout.first) {
1014                                 string obs = textclasslist.Style(tclass,layout.second).
1015                                         obsoleted_by();
1016                                 if (!obs.empty()) 
1017                                         layout = textclasslist.NumberOfLayout(tclass, obs);
1018                         }
1019
1020                         // see if we found the layout number:
1021                         if (!layout.first) {
1022                                 string const msg = string(N_("Layout ")) + arg + N_(" not known");
1023                                 bv->owner()->getLyXFunc()->Dispatch(LFUN_MESSAGE, msg);
1024                                 break;
1025                         }
1026
1027                         if (cur_layout != layout.second) {
1028                                 cur_layout = layout.second;
1029                                 TEXT(bv)->SetLayout(bv, layout.second);
1030                                 bv->owner()->setLayout(cpar(bv)->GetLayout());
1031                                 UpdateLocal(bv, CURSOR_PAR, true);
1032                         }
1033                 } else {
1034                         // reset the layout box
1035                         bv->owner()->setLayout(cpar(bv)->GetLayout());
1036                 }
1037                 break;
1038         case LFUN_PARAGRAPH_SPACING:
1039                 // This one is absolutely not working. When fiddling with this
1040                 // it also seems to me that the paragraphs inside the insettext
1041                 // inherit bufferparams/paragraphparams in a strange way. (Lgb)
1042         {
1043                 LyXParagraph * par = TEXT(bv)->cursor.par();
1044                 Spacing::Space cur_spacing = par->params.spacing().getSpace();
1045                 float cur_value = 1.0;
1046                 if (cur_spacing == Spacing::Other) {
1047                         cur_value = par->params.spacing().getValue();
1048                 }
1049                                 
1050                 std::istringstream istr(arg.c_str());
1051                 string tmp;
1052                 istr >> tmp;
1053                 Spacing::Space new_spacing = cur_spacing;
1054                 float new_value = cur_value;
1055                 if (tmp.empty()) {
1056                         lyxerr << "Missing argument to `paragraph-spacing'"
1057                                    << endl;
1058                 } else if (tmp == "single") {
1059                         new_spacing = Spacing::Single;
1060                 } else if (tmp == "onehalf") {
1061                         new_spacing = Spacing::Onehalf;
1062                 } else if (tmp == "double") {
1063                         new_spacing = Spacing::Double;
1064                 } else if (tmp == "other") {
1065                         new_spacing = Spacing::Other;
1066                         float tmpval = 0.0;
1067                         istr >> tmpval;
1068                         lyxerr << "new_value = " << tmpval << endl;
1069                         if (tmpval != 0.0)
1070                                 new_value = tmpval;
1071                 } else if (tmp == "default") {
1072                         new_spacing = Spacing::Default;
1073                 } else {
1074                         lyxerr << _("Unknown spacing argument: ")
1075                                    << arg << endl;
1076                 }
1077                 if (cur_spacing != new_spacing || cur_value != new_value) {
1078                         par->params.spacing(Spacing(new_spacing, new_value));
1079                         //TEXT(bv)->RedoParagraph(owner->view());
1080                         UpdateLocal(bv, CURSOR_PAR, true);
1081                         //bv->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1082                 }
1083         }
1084         break;
1085         
1086         default:
1087                 if (!bv->Dispatch(action, arg))
1088                         result = UNDISPATCHED;
1089                 break;
1090         }
1091
1092         /// If the action has deleted all text in the inset, we need to change the
1093         // language to the language to the surronding text.
1094         if (par->size() == 0 && !par->next()) {
1095                 LyXFont font(LyXFont::ALL_IGNORE);
1096                 font.setLanguage(bv->getParentLanguage(this));
1097                 SetFont(bv, font, false);
1098         }
1099
1100         if (result != FINISHED) {
1101                 ShowInsetCursor(bv);
1102         } else
1103                 bv->unlockInset(this);
1104         return result;
1105 }
1106
1107
1108 int InsetText::Latex(Buffer const * buf, ostream & os, bool, bool) const
1109 {
1110         TexRow texrow;
1111         buf->latexParagraphs(os, par, 0, texrow);
1112         return texrow.rows();
1113 }
1114
1115
1116 int InsetText::Ascii(Buffer const * buf, ostream & os, int linelen) const
1117 {
1118         LyXParagraph * p = par;
1119         unsigned int lines = 0;
1120         
1121         string tmp;
1122         while (p) {
1123                 tmp = buf->asciiParagraph(p, linelen);
1124                 lines += countChar(tmp, '\n');
1125                 os << tmp;
1126                 p = p->next();
1127         }
1128         return lines;
1129 }
1130
1131
1132 int InsetText::DocBook(Buffer const * buf, ostream & os) const
1133 {
1134         LyXParagraph * p = par;
1135         unsigned int lines = 0;
1136         int desc=0;
1137         
1138         string tmp;
1139         while (p) {
1140                 buf->SimpleDocBookOnePar(os,tmp,p,desc,0);
1141                 p = p->next();
1142         }
1143         
1144         return lines;
1145 }
1146
1147
1148 void InsetText::Validate(LaTeXFeatures & features) const
1149 {
1150         LyXParagraph * p = par;
1151         while(p) {
1152                 p->validate(features);
1153                 p = p->next();
1154         }
1155 }
1156
1157
1158 int InsetText::BeginningOfMainBody(Buffer const * buf, LyXParagraph * p) const
1159 {
1160         if (textclasslist.Style(buf->params.textclass,
1161                                 p->GetLayout()).labeltype != LABEL_MANUAL)
1162                 return 0;
1163         else
1164                 return p->BeginningOfMainBody();
1165 }
1166
1167
1168 void InsetText::GetCursorPos(BufferView * bv,
1169                              int & x, int & y) const
1170 {
1171         x = cx(bv);
1172         y = cy(bv);
1173 }
1174
1175
1176 unsigned int InsetText::InsetInInsetY()
1177 {
1178         if (!the_locking_inset)
1179                 return 0;
1180
1181         return (inset_y + the_locking_inset->InsetInInsetY());
1182 }
1183
1184
1185 void InsetText::ToggleInsetCursor(BufferView * bv)
1186 {
1187         if (the_locking_inset) {
1188                 the_locking_inset->ToggleInsetCursor(bv);
1189                 return;
1190         }
1191
1192         LyXFont const font(TEXT(bv)->GetFont(bv->buffer(), cpar(bv), cpos(bv)));
1193
1194         int const asc = lyxfont::maxAscent(font);
1195         int const desc = lyxfont::maxDescent(font);
1196   
1197         if (isCursorVisible())
1198                 bv->hideLockedInsetCursor();
1199         else
1200                 bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1201         toggleCursorVisible();
1202 }
1203
1204
1205 void InsetText::ShowInsetCursor(BufferView * bv, bool show)
1206 {
1207         if (the_locking_inset) {
1208                 the_locking_inset->ShowInsetCursor(bv);
1209                 return;
1210         }
1211         if (!isCursorVisible()) {
1212                 LyXFont const font =
1213                         TEXT(bv)->GetFont(bv->buffer(), cpar(bv), cpos(bv));
1214         
1215                 int const asc = lyxfont::maxAscent(font);
1216                 int const desc = lyxfont::maxDescent(font);
1217
1218                 bv->fitLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1219                 if (show)
1220                         bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1221                 setCursorVisible(true);
1222         }
1223 }
1224
1225
1226 void InsetText::HideInsetCursor(BufferView * bv)
1227 {
1228         if (isCursorVisible()) {
1229                 bv->hideLockedInsetCursor();
1230                 setCursorVisible(false);
1231         }
1232         if (the_locking_inset)
1233                 the_locking_inset->HideInsetCursor(bv);
1234 }
1235
1236
1237 UpdatableInset::RESULT
1238 InsetText::moveRight(BufferView * bv, bool activate_inset, bool selecting)
1239 {
1240         if (TEXT(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
1241                 return moveLeftIntern(bv, false, activate_inset, selecting);
1242         else
1243                 return moveRightIntern(bv, false, activate_inset, selecting);
1244 }
1245
1246 UpdatableInset::RESULT
1247 InsetText::moveLeft(BufferView * bv, bool activate_inset, bool selecting)
1248 {
1249         if (TEXT(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
1250                 return moveRightIntern(bv, true, activate_inset, selecting);
1251         else
1252                 return moveLeftIntern(bv, true, activate_inset, selecting);
1253 }
1254
1255
1256 UpdatableInset::RESULT
1257 InsetText::moveRightIntern(BufferView * bv, bool behind, 
1258                            bool activate_inset, bool selecting)
1259 {
1260         if (!cpar(bv)->next() && (cpos(bv) >= cpar(bv)->size()))
1261                 return FINISHED;
1262         if (activate_inset && checkAndActivateInset(bv, behind))
1263                 return DISPATCHED;
1264         TEXT(bv)->CursorRight(bv);
1265         if (!selecting)
1266                 TEXT(bv)->sel_cursor = TEXT(bv)->cursor;
1267         return DISPATCHED_NOUPDATE;
1268 }
1269
1270
1271 UpdatableInset::RESULT
1272 InsetText::moveLeftIntern(BufferView * bv, bool behind,
1273                           bool activate_inset, bool selecting)
1274 {
1275         if (!cpar(bv)->previous() && (cpos(bv) <= 0))
1276                 return FINISHED;
1277         TEXT(bv)->CursorLeft(bv);
1278         if (!selecting)
1279                 TEXT(bv)->sel_cursor = TEXT(bv)->cursor;
1280         if (activate_inset && checkAndActivateInset(bv, behind))
1281                 return DISPATCHED;
1282         return DISPATCHED_NOUPDATE;
1283 }
1284
1285
1286 UpdatableInset::RESULT
1287 InsetText::moveUp(BufferView * bv)
1288 {
1289         if (!crow(bv)->previous())
1290                 return FINISHED;
1291         TEXT(bv)->CursorUp(bv);
1292         return DISPATCHED_NOUPDATE;
1293 }
1294
1295
1296 UpdatableInset::RESULT
1297 InsetText::moveDown(BufferView * bv)
1298 {
1299         if (!crow(bv)->next())
1300                 return FINISHED;
1301         TEXT(bv)->CursorDown(bv);
1302         return DISPATCHED_NOUPDATE;
1303 }
1304
1305
1306 bool InsetText::InsertInset(BufferView * bv, Inset * inset)
1307 {
1308         if (the_locking_inset) {
1309                 if (the_locking_inset->InsertInsetAllowed(inset))
1310                         return the_locking_inset->InsertInset(bv, inset);
1311                 return false;
1312         }
1313         bv->text->SetUndo(bv->buffer(), Undo::INSERT,
1314                           bv->text->cursor.par()->previous(),
1315                           bv->text->cursor.par()->next());
1316         inset->setOwner(this);
1317         HideInsetCursor(bv);
1318         TEXT(bv)->InsertInset(bv, inset);
1319 #if 0
1320         if ((cpar(bv)->GetChar(cpos(bv)) != LyXParagraph::META_INSET) ||
1321                 (cpar(bv)->GetInset(cpos(bv)) != inset))
1322                 TEXT(bv)->CursorLeft(bv);
1323 #endif
1324         bv->fitCursor(TEXT(bv));
1325         UpdateLocal(bv, CURSOR_PAR|CURSOR, true);
1326         ShowInsetCursor(bv);
1327         return true;
1328 }
1329
1330
1331 UpdatableInset * InsetText::GetLockingInset()
1332 {
1333         return the_locking_inset ? the_locking_inset->GetLockingInset() : this;
1334 }
1335
1336
1337 UpdatableInset * InsetText::GetFirstLockingInsetOfType(Inset::Code c)
1338 {
1339         if (c == LyxCode())
1340                 return this;
1341         if (the_locking_inset)
1342                 return the_locking_inset->GetFirstLockingInsetOfType(c);
1343         return 0;
1344 }
1345
1346
1347 bool InsetText::ShowInsetDialog(BufferView * bv) const
1348 {
1349         if (the_locking_inset)
1350                 return the_locking_inset->ShowInsetDialog(bv);
1351         return false;
1352 }
1353
1354
1355 std::vector<string> const InsetText::getLabelList() const 
1356 {
1357         std::vector<string> label_list;
1358
1359         LyXParagraph * tpar = par;
1360         while (tpar) {
1361                 LyXParagraph::inset_iterator beg = tpar->inset_iterator_begin();
1362                 LyXParagraph::inset_iterator end = tpar->inset_iterator_end();
1363                 for (; beg != end; ++beg) {
1364                         std::vector<string> const l = (*beg)->getLabelList();
1365                         label_list.insert(label_list.end(), l.begin(), l.end());
1366                 }
1367                 tpar = tpar->next();
1368         }
1369         return label_list;
1370 }
1371
1372
1373 void InsetText::SetFont(BufferView * bv, LyXFont const & font, bool toggleall)
1374 {
1375         if (TEXT(bv)->selection) {
1376                 bv->text->SetUndo(bv->buffer(), Undo::EDIT,
1377                                   bv->text->cursor.par()->previous(),
1378                                   bv->text->cursor.par()->next());
1379         }
1380         TEXT(bv)->SetFont(bv, font, toggleall);
1381         bv->fitCursor(TEXT(bv));
1382         UpdateLocal(bv, CURSOR_PAR, true);
1383 }
1384
1385
1386 bool InsetText::checkAndActivateInset(BufferView * bv, bool behind)
1387 {
1388         if (cpar(bv)->GetChar(cpos(bv)) == LyXParagraph::META_INSET) {
1389                 unsigned int x;
1390                 unsigned int y;
1391                 Inset * inset =
1392                         static_cast<UpdatableInset*>(cpar(bv)->GetInset(cpos(bv)));
1393                 if (!inset || inset->Editable() != Inset::HIGHLY_EDITABLE)
1394                         return false;
1395                 LyXFont const font =
1396                         TEXT(bv)->GetFont(bv->buffer(), cpar(bv), cpos(bv));
1397                 if (behind) {
1398                         x = inset->width(bv, font);
1399                         y = font.isRightToLeft() ? 0 : inset->descent(bv, font);
1400                 } else {
1401                         x = 0;
1402                         y = font.isRightToLeft() ? inset->descent(bv, font) : 0;
1403                 }
1404                 //inset_x = cx(bv) - top_x + drawTextXOffset;
1405                 //inset_y = cy(bv) + drawTextYOffset;
1406                 inset->Edit(bv, x, y, 0);
1407                 if (!the_locking_inset)
1408                         return false;
1409                 UpdateLocal(bv, CURSOR, false);
1410                 return true;
1411         }
1412         return false;
1413 }
1414
1415
1416 bool InsetText::checkAndActivateInset(BufferView * bv, int x, int y,
1417                                       int button)
1418 {
1419         int dummyx, dummyy;
1420
1421         dummyx = x = x - drawTextXOffset;
1422         dummyy = y + insetAscent;
1423         Inset * inset = bv->checkInsetHit(TEXT(bv), dummyx, dummyy, button);
1424
1425         if (inset) {
1426                 if (x < 0)
1427                         x = insetWidth;
1428                 if (y < 0)
1429                         y = insetDescent;
1430                 inset_x = cx(bv) - top_x + drawTextXOffset;
1431                 inset_y = cy(bv) + drawTextYOffset;
1432                 inset->Edit(bv, x - inset_x, y - inset_y, button);
1433                 if (!the_locking_inset)
1434                         return false;
1435                 UpdateLocal(bv, CURSOR, false);
1436                 return true;
1437         }
1438         return false;
1439 }
1440
1441
1442 int InsetText::getMaxWidth(BufferView * bv, UpdatableInset const * inset) const
1443 {
1444         int w = UpdatableInset::getMaxWidth(bv, inset);
1445         if (w < 0) {
1446                 return w;
1447         }
1448         if (owner()) {
1449                 w = w - top_x + owner()->x();
1450                 return w;
1451         }
1452         w -= (2 * TEXT_TO_INSET_OFFSET);
1453         return w - top_x;
1454 //    return  w - (2*TEXT_TO_INSET_OFFSET);
1455 }
1456
1457
1458 void InsetText::SetParagraphData(LyXParagraph * p)
1459 {
1460         // delete all instances of LyXText before deleting the paragraps used
1461         // by it.
1462         for (Cache::iterator cit = cache.begin(); cit != cache.end(); ++cit){
1463                 delete (*cit).second;
1464                 (*cit).second = 0;
1465         }
1466
1467         while (par) {
1468                 LyXParagraph * tmp = par->next();
1469                 delete par;
1470                 par = tmp;
1471         }
1472
1473         par = new LyXParagraph(*p);
1474         par->SetInsetOwner(this);
1475         LyXParagraph * np = par;
1476         while (p->next()) {
1477                 p = p->next();
1478                 np->next(new LyXParagraph(*p));
1479                 np->next()->previous(np);
1480                 np = np->next();
1481                 np->SetInsetOwner(this);
1482         }
1483
1484         need_update = INIT;
1485 }
1486
1487
1488 void InsetText::SetText(string const & data)
1489 {
1490         clear();
1491         LyXFont font(LyXFont::ALL_SANE);
1492         for (unsigned int i=0; i < data.length(); ++i)
1493                 par->InsertChar(i, data[i], font);
1494 }
1495
1496
1497 void InsetText::SetAutoBreakRows(bool flag)
1498 {
1499         if (flag != autoBreakRows) {
1500                 autoBreakRows = flag;
1501                 need_update = FULL;
1502                 if (!flag)
1503                         removeNewlines();
1504         }
1505 }
1506
1507
1508 void InsetText::SetDrawFrame(BufferView * bv, DrawFrame how)
1509 {
1510         if (how != drawFrame_) {
1511                 drawFrame_ = how;
1512                 if (bv)
1513                         UpdateLocal(bv, DRAW_FRAME, false);
1514         }
1515 }
1516
1517
1518 void InsetText::SetFrameColor(BufferView * bv, LColor::color col)
1519 {
1520         if (frame_color != col) {
1521                 frame_color = col;
1522                 if (bv)
1523                         UpdateLocal(bv, DRAW_FRAME, false);
1524         }
1525 }
1526
1527
1528 int InsetText::cx(BufferView * bv) const
1529 {
1530         LyXText * text = TEXT(bv);
1531         int x = text->cursor.x() + top_x + TEXT_TO_INSET_OFFSET;
1532         if (the_locking_inset) {
1533                 LyXFont font = text->GetFont(bv->buffer(),
1534                                              text->cursor.par(),
1535                                              text->cursor.pos());
1536                 if (font.isVisibleRightToLeft())
1537                         x -= the_locking_inset->width(bv, font);
1538         }
1539         return x;
1540 }
1541
1542
1543 int InsetText::cy(BufferView * bv) const
1544 {
1545         LyXFont font;
1546         return TEXT(bv)->cursor.y() - ascent(bv, font) + TEXT_TO_INSET_OFFSET;
1547 }
1548
1549
1550 LyXParagraph::size_type InsetText::cpos(BufferView * bv) const
1551 {
1552         return TEXT(bv)->cursor.pos();
1553 }
1554
1555
1556 LyXParagraph * InsetText::cpar(BufferView * bv) const
1557 {
1558         return TEXT(bv)->cursor.par();
1559 }
1560
1561 bool InsetText::cboundary(BufferView * bv) const
1562 {
1563         return TEXT(bv)->cursor.boundary();
1564 }
1565
1566
1567 Row * InsetText::crow(BufferView * bv) const
1568 {
1569         return TEXT(bv)->cursor.row();
1570 }
1571
1572
1573 LyXText * InsetText::getLyXText(BufferView const * lbv,
1574                                 bool const recursive) const
1575 {
1576         // Super UGLY! (Lgb)
1577         BufferView * bv = const_cast<BufferView *>(lbv);
1578         
1579         if ((cache.find(bv) != cache.end()) && cache[bv]) {
1580                 if (recursive && the_locking_inset)
1581                         return the_locking_inset->getLyXText(bv);
1582                 return cache[bv];
1583         }
1584         LyXText * lt = new LyXText(const_cast<InsetText *>(this));
1585         lt->init(bv);
1586         cache[bv] = lt;
1587         if (the_locking_inset) {
1588                 lt->SetCursor(bv, inset_par, inset_pos, true, inset_boundary);
1589                 if (recursive)
1590                         return the_locking_inset->getLyXText(bv);
1591         }
1592         return lt;
1593 }
1594
1595
1596 void InsetText::deleteLyXText(BufferView * bv, bool recursive) const
1597 {
1598         if ((cache.find(bv) == cache.end()) || !cache[bv])
1599                 return;
1600         delete cache[bv];
1601         cache.erase(bv);
1602         if (recursive) {
1603                 /// then remove all LyXText in text-insets
1604                 LyXParagraph * p = par;
1605                 for (; p; p = p->next()) {
1606                         p->deleteInsetsLyXText(bv);
1607                 }
1608         }
1609 }
1610
1611
1612 void InsetText::resizeLyXText(BufferView * bv) const
1613 {
1614         if (!par->next() && !par->size()) // resize not neccessary!
1615                 return;
1616         if ((cache.find(bv) == cache.end()) || !cache[bv])
1617                 return;
1618
1619         LyXParagraph * lpar = 0;
1620         LyXParagraph * selstartpar = 0;
1621         LyXParagraph * selendpar = 0;
1622         LyXParagraph::size_type pos = 0;
1623         LyXParagraph::size_type selstartpos = 0;
1624         LyXParagraph::size_type selendpos = 0;
1625         bool boundary = false;
1626         bool selstartboundary = false;
1627         bool selendboundary = false;
1628         int selection = 0;
1629         int mark_set = 0;
1630
1631 //    ProhibitInput(bv);
1632
1633         if (locked) {
1634                 lpar = TEXT(bv)->cursor.par();
1635                 pos = TEXT(bv)->cursor.pos();
1636                 boundary = TEXT(bv)->cursor.boundary();
1637                 selstartpar = TEXT(bv)->sel_start_cursor.par();
1638                 selstartpos = TEXT(bv)->sel_start_cursor.pos();
1639                 selstartboundary = TEXT(bv)->sel_start_cursor.boundary();
1640                 selendpar = TEXT(bv)->sel_end_cursor.par();
1641                 selendpos = TEXT(bv)->sel_end_cursor.pos();
1642                 selendboundary = TEXT(bv)->sel_end_cursor.boundary();
1643                 selection = TEXT(bv)->selection;
1644                 mark_set = TEXT(bv)->mark_set;
1645         }
1646         deleteLyXText(bv, (the_locking_inset == 0));
1647
1648         if (lpar) {
1649                 TEXT(bv)->selection = true;
1650                 /* at this point just to avoid the Delete-Empty-Paragraph
1651                  * Mechanism when setting the cursor */
1652                 TEXT(bv)->mark_set = mark_set;
1653                 if (selection) {
1654                         TEXT(bv)->SetCursor(bv, selstartpar, selstartpos,
1655                                             true, selstartboundary);
1656                         TEXT(bv)->sel_cursor = TEXT(bv)->cursor;
1657                         TEXT(bv)->SetCursor(bv, selendpar, selendpos,
1658                                             true, selendboundary);
1659                         TEXT(bv)->SetSelection(bv);
1660                         TEXT(bv)->SetCursor(bv, lpar, pos);
1661                 } else {
1662                         TEXT(bv)->SetCursor(bv, lpar, pos, true, boundary);
1663                         TEXT(bv)->sel_cursor = TEXT(bv)->cursor;
1664                         TEXT(bv)->selection = false;
1665                 }
1666         }
1667         if (bv->screen())
1668                 TEXT(bv)->first = bv->screen()->TopCursorVisible(TEXT(bv));
1669         // this will scroll the screen such that the cursor becomes visible 
1670         bv->updateScrollbar();
1671 //    AllowInput(bv);
1672         if (the_locking_inset) {
1673                 /// then resize all LyXText in text-insets
1674                 inset_x = cx(bv) - top_x + drawTextXOffset;
1675                 inset_y = cy(bv) + drawTextYOffset;
1676                 for (LyXParagraph * p = par; p; p = p->next()) {
1677                         p->resizeInsetsLyXText(bv);
1678                 }
1679         }
1680         need_update = FULL;
1681 }
1682
1683
1684 void InsetText::removeNewlines()
1685 {
1686         for (LyXParagraph * p = par; p; p = p->next()) {
1687                 for (int i = 0; i < p->size(); ++i) {
1688                         if (p->GetChar(i) == LyXParagraph::META_NEWLINE)
1689                                 p->Erase(i);
1690                 }
1691         }
1692 }
1693
1694 bool InsetText::nodraw() const
1695 {
1696         if (the_locking_inset)
1697                 return the_locking_inset->nodraw();
1698         return UpdatableInset::nodraw();
1699 }
1700
1701 int InsetText::scroll(bool recursive) const
1702 {
1703         int sx = UpdatableInset::scroll(false);
1704
1705         if (recursive && the_locking_inset)
1706                 sx += the_locking_inset->scroll(recursive);
1707
1708         return sx;
1709 }
1710
1711 bool InsetText::doClearArea() const
1712 {
1713         return !locked || (need_update & (FULL|INIT));
1714 }
1715 /* Emacs:
1716  * Local variables:
1717  * tab-width: 4
1718  * End:
1719  * vi:set tabstop=4:
1720  */