]> git.lyx.org Git - lyx.git/blob - src/insets/insettext.C
18b49617ed1e7e21ee52dbc88716519c6d1e80c3
[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
18 #ifdef __GNUG__
19 #pragma implementation
20 #endif
21
22 #include "insettext.h"
23 #include "paragraph.h"
24 #include "lyxlex.h"
25 #include "debug.h"
26 #include "lyxfont.h"
27 #include "commandtags.h"
28 #include "buffer.h"
29 #include "LyXView.h"
30 #include "BufferView.h"
31 #include "layout.h"
32 #include "LaTeXFeatures.h"
33 #include "Painter.h"
34 #include "lyx_gui_misc.h"
35 #include "lyxtext.h"
36 #include "lyxcursor.h"
37 #include "CutAndPaste.h"
38 #include "font.h"
39 #include "LColor.h"
40 #include "support/textutils.h"
41 #include "support/LAssert.h"
42 #include "lyxrow.h"
43 #include "lyxrc.h"
44 #include "intl.h"
45 #include "trans_mgr.h"
46 #include "lyxscreen.h"
47 #include "WorkArea.h"
48 #include "gettext.h"
49 #include "lyxfunc.h"
50 #include "ParagraphParameters.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 Paragraph;
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         old_max_width = 0;
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                 Paragraph * 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                 Paragraph * tmp = par->next();
145                 delete par;
146                 par = tmp;
147         }
148         par = new Paragraph;
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);
169 }
170
171
172 void InsetText::read(Buffer const * buf, LyXLex & lex)
173 {
174         string token;
175         int pos = 0;
176         Paragraph * return_par = 0;
177         Paragraph::depth_type depth = 0; 
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                 else if (cleared)
263                         frame_is_visible = false;
264                 need_update = NONE;
265                 return;
266         }
267
268         xpos = x;
269 #if 0
270         UpdatableInset::draw(bv, f, baseline, x, cleared);
271 #else
272         if (!owner())
273                 x += static_cast<float>(scroll());
274 #endif
275 #if 0
276         // update insetWidth and insetHeight with dummy calls
277         (void)ascent(bv, f);
278         (void)descent(bv, f);
279         (void)width(bv, f);
280 #endif
281
282         // if top_x differs we have a rule down and we don't have to clear anything
283         if (!cleared && (top_x == int(x)) &&
284                 ((need_update&(INIT|FULL)) || (top_baseline!=baseline) ||
285                  (last_drawn_width!=insetWidth)))
286         {
287                 clearInset(pain, baseline, cleared);
288         }
289         if (cleared)
290                 frame_is_visible = false;
291
292         if (!cleared && (need_update == NONE))
293                 return;
294
295         if (top_x != int(x)) {
296                 if ((getMaxWidth(bv, this) > 0) &&
297                         (TEXT(bv)->width != old_max_width))
298                 {
299                         resizeLyXText(bv);
300                         need_update |= FULL;
301                         old_max_width = TEXT(bv)->width;
302                         bv->text->status = LyXText::CHANGED_IN_DRAW;
303                 }
304                 top_x = int(x);
305 #if 1
306                 clearInset(pain, baseline, cleared);
307 #else
308                 return;
309 #endif
310         }
311
312 //      lyxerr << "InsetText::draw[" << this << "](" << need_update << ":" << int(x) << ":" << top_x << ")\n";
313
314         if (cleared || (last_drawn_width != insetWidth)) {
315                 need_update |= FULL;
316                 last_drawn_width = insetWidth;
317         }
318
319         top_baseline = baseline;
320         top_y = baseline - ascent(bv, f);
321         last_width = width(bv, f);
322         last_height = ascent(bv, f) + descent(bv, f);
323
324         if (the_locking_inset && (cpar(bv) == inset_par) && (cpos(bv) == inset_pos)) {
325                 inset_x = cx(bv) - top_x + drawTextXOffset;
326                 inset_y = cy(bv) + drawTextYOffset;
327         }
328         if (!cleared && (need_update == CURSOR) && !TEXT(bv)->selection.set()) {
329                 drawFrame(pain, cleared);
330                 x += last_width; // was width(bv, f);
331                 need_update = NONE;
332                 return;
333         }
334         x += TEXT_TO_INSET_OFFSET;
335
336         int y = 0;
337         Row * row = TEXT(bv)->getRowNearY(y);
338         int y_offset = baseline - row->ascent_of_text();
339         int ph = pain.paperHeight();
340         int first = 0;
341         y = y_offset;
342         while ((row != 0) && ((y+row->height()) <= 0)) {
343                 y += row->height();
344                 first += row->height();
345                 row = row->next();
346         }
347         if (y_offset < 0)
348                 y_offset = y;
349         TEXT(bv)->first = first;
350         if (cleared) {
351                 int yf = y_offset;
352                 y = 0;
353                 while ((row != 0) && (yf < ph)) {
354                         TEXT(bv)->getVisibleRow(bv, y+y_offset, int(x), row,
355                                                 y+first, cleared);
356                         y += row->height();
357                         yf += row->height();
358                         row = row->next();
359                 }
360         } else if (!locked) {
361                 if (need_update & CURSOR) {
362                         bv->screen()->ToggleSelection(TEXT(bv), bv, true, y_offset,int(x));
363                         TEXT(bv)->clearSelection(bv);
364                         TEXT(bv)->selection.cursor = TEXT(bv)->cursor;
365                 }
366                 bv->screen()->Update(TEXT(bv), bv, y_offset, int(x));
367         } else {
368                 locked = false;
369                 if (need_update & SELECTION)
370                         bv->screen()->ToggleToggle(TEXT(bv), bv, y_offset, int(x));
371                 else if (need_update & CURSOR) {
372                         bv->screen()->ToggleSelection(TEXT(bv), bv, true, y_offset,int(x));
373                         TEXT(bv)->clearSelection(bv);
374                         TEXT(bv)->selection.cursor = TEXT(bv)->cursor;
375                 }
376                 bv->screen()->Update(TEXT(bv), bv, y_offset, int(x));
377                 locked = true;
378         }
379
380         TEXT(bv)->refresh_y = 0;
381         TEXT(bv)->status = LyXText::UNCHANGED;
382         if ((need_update != CURSOR_PAR) &&
383                 ((drawFrame_ == ALWAYS) || ((drawFrame_ == LOCKED) && locked)))
384                 drawFrame(pain, cleared);
385         else if (need_update & CLEAR_FRAME)
386                 clearFrame(pain, cleared);
387         x += last_width /* was width(bv, f) */ - TEXT_TO_INSET_OFFSET;
388         if (bv->text->status==LyXText::CHANGED_IN_DRAW) {
389                 need_update |= INIT;
390         } else if (need_update != INIT)
391                 need_update = NONE;
392 }
393
394
395 void InsetText::drawFrame(Painter & pain, bool cleared) const
396 {
397         if (!frame_is_visible || cleared) {
398                 pain.rectangle(top_x + 1, top_baseline - insetAscent + 1,
399                                insetWidth - 1, insetAscent + insetDescent - 1,
400                                frame_color);
401                 frame_is_visible = true;
402         }
403 }
404
405
406 void InsetText::clearFrame(Painter & pain, bool cleared) const
407 {
408         if (frame_is_visible) {
409                 if (!cleared) {
410                         pain.rectangle(top_x + 1, top_baseline - insetAscent + 1,
411                                        insetWidth - 1, insetAscent + insetDescent - 1,
412                                        LColor::background);
413                 }
414                 frame_is_visible = false;
415         }
416 }
417
418
419 void InsetText::update(BufferView * bv, LyXFont const & font, bool reinit)
420 {
421 #if 0
422         int ww = TEXT(bv)->width;
423         TEXT(bv)->BreakParagraph(bv);
424         if (ww != TEXT(bv)->width)
425                 reinit = true;
426 #endif
427         if (reinit) {
428                 need_update |= INIT;
429                 resizeLyXText(bv);
430                 if (owner())
431                         owner()->update(bv, font, true);
432                 return;
433         }
434         if (the_locking_inset) {
435                 inset_x = cx(bv) - top_x + drawTextXOffset;
436                 inset_y = cy(bv) + drawTextYOffset;
437                 the_locking_inset->update(bv, font, reinit);
438         }
439 #if 0
440         if (need_update == INIT) {
441                 resizeLyXText(bv);
442                 need_update |= FULL;
443         }
444 #endif
445         int oldw = insetWidth;
446         insetWidth = TEXT(bv)->width + (2 * TEXT_TO_INSET_OFFSET);
447         if (oldw != insetWidth) {
448                 resizeLyXText(bv);
449                 need_update |= FULL;
450 //              update(bv, font, reinit);
451                 return;
452         }
453         if ((need_update&CURSOR_PAR) && (TEXT(bv)->status==LyXText::UNCHANGED) &&
454                 the_locking_inset)
455         {
456                 TEXT(bv)->updateInset(bv, the_locking_inset);
457         }
458         
459         if (TEXT(bv)->status == LyXText::NEED_MORE_REFRESH)
460                 need_update |= FULL;
461 #if 0
462         int y_temp = 0;
463         Row * row = TEXT(bv)->GetRowNearY(y_temp);
464         insetAscent = row->ascent_of_text() + TEXT_TO_INSET_OFFSET;
465         insetDescent = TEXT(bv)->height - row->ascent_of_text() +
466                 TEXT_TO_INSET_OFFSET;
467 #endif
468 }
469
470
471 void InsetText::setUpdateStatus(BufferView * bv, int what) const
472 {
473         need_update |= what;
474         if (TEXT(bv)->status == LyXText::NEED_MORE_REFRESH)
475                 need_update |= FULL;
476         else if (TEXT(bv)->status == LyXText::NEED_VERY_LITTLE_REFRESH)
477                 need_update |= CURSOR_PAR;
478
479         // this to not draw a selection when we redraw all of it!
480         if ((need_update & (INIT|FULL)) && (need_update & CURSOR))
481                 TEXT(bv)->clearSelection(bv);
482 }
483
484
485 void InsetText::updateLocal(BufferView * bv, int what, bool mark_dirty)
486 {
487         TEXT(bv)->fullRebreak(bv);
488         setUpdateStatus(bv, what);
489         if ((need_update != CURSOR) || (TEXT(bv)->status != LyXText::UNCHANGED) ||
490                 TEXT(bv)->selection.set())
491                 bv->updateInset(this, mark_dirty);
492         bv->owner()->showState();
493         if (old_par != cpar(bv)) {
494                 bv->owner()->setLayout(cpar(bv)->getLayout());
495                 old_par = cpar(bv);
496         }
497 }
498
499
500 string const InsetText::editMessage() const
501 {
502         return _("Opened Text Inset");
503 }
504
505
506 void InsetText::edit(BufferView * bv, int x, int y, unsigned int button)
507 {
508 //    par->SetInsetOwner(this);
509         UpdatableInset::edit(bv, x, y, button);
510
511         if (!bv->lockInset(this)) {
512                 lyxerr[Debug::INSETS] << "Cannot lock inset" << endl;
513                 return;
514         }
515         locked = true;
516         the_locking_inset = 0;
517         inset_pos = inset_x = inset_y = 0;
518         inset_boundary = false;
519         inset_par = 0;
520         old_par = 0;
521         int tmp_y = (y < 0)?0:y;
522         if (!checkAndActivateInset(bv, x, tmp_y, button))
523                 TEXT(bv)->setCursorFromCoordinates(bv, x - drawTextXOffset,
524                                                    y + insetAscent);
525         TEXT(bv)->selection.cursor = TEXT(bv)->cursor;
526         bv->text->finishUndo();
527         showInsetCursor(bv);
528         updateLocal(bv, CURSOR, false);
529
530         // If the inset is empty set the language of the current font to the
531         // language to the surronding text (if different).
532         if (par->size() == 0 && !par->next() &&
533                 bv->getParentLanguage(this) != TEXT(bv)->current_font.language())
534         {
535                 LyXFont font(LyXFont::ALL_IGNORE);
536                 font.setLanguage(bv->getParentLanguage(this));
537                 setFont(bv, font, false);
538         }
539 }
540
541
542 void InsetText::insetUnlock(BufferView * bv)
543 {
544         if (the_locking_inset) {
545                 the_locking_inset->insetUnlock(bv);
546                 the_locking_inset = 0;
547         }
548         hideInsetCursor(bv);
549         no_selection = false;
550         locked = false;
551         int code = CURSOR|CLEAR_FRAME;
552         if (TEXT(bv)->selection.set()) {
553                 TEXT(bv)->clearSelection(bv);
554                 code = FULL;
555         } else if (owner())
556                 bv->owner()->setLayout(owner()->getLyXText(bv)
557                                        ->cursor.par()->getLayout());
558         else
559                 bv->owner()->setLayout(bv->text->cursor.par()->getLayout());
560         updateLocal(bv, code, false);
561 }
562
563
564 bool InsetText::lockInsetInInset(BufferView * bv, UpdatableInset * inset)
565 {
566         lyxerr[Debug::INSETS] << "InsetText::LockInsetInInset("
567                               << inset << "): ";
568         if (!inset)
569                 return false;
570         if (inset == cpar(bv)->getInset(cpos(bv))) {
571                 lyxerr[Debug::INSETS] << "OK" << endl;
572                 the_locking_inset = inset;
573                 inset_x = cx(bv) - top_x + drawTextXOffset;
574                 inset_y = cy(bv) + drawTextYOffset;
575                 inset_pos = cpos(bv);
576                 inset_par = cpar(bv);
577                 inset_boundary = cboundary(bv);
578 #if 0
579                 TEXT(bv)->clearSelection(bv);
580                 TEXT(bv)->sel_cursor = TEXT(bv)->cursor;
581                 TEXT(bv)->UpdateInset(bv, the_locking_inset);
582 #else
583                 updateLocal(bv, CURSOR, false);
584 #endif
585                 return true;
586         } else if (the_locking_inset && (the_locking_inset == inset)) {
587                 if (cpar(bv) == inset_par && cpos(bv) == inset_pos) {
588                         lyxerr[Debug::INSETS] << "OK" << endl;
589                         inset_x = cx(bv) - top_x + drawTextXOffset;
590                         inset_y = cy(bv) + drawTextYOffset;
591                 } else {
592                         lyxerr[Debug::INSETS] << "cursor.pos != inset_pos" << endl;
593                 }
594         } else if (the_locking_inset) {
595                 lyxerr[Debug::INSETS] << "MAYBE" << endl;
596                 return the_locking_inset->lockInsetInInset(bv, inset);
597         }
598         lyxerr[Debug::INSETS] << "NOT OK" << endl;
599         return false;
600 }
601
602
603 bool InsetText::unlockInsetInInset(BufferView * bv, UpdatableInset * inset,
604                                    bool lr)
605 {
606         if (!the_locking_inset)
607                 return false;
608         if (the_locking_inset == inset) {
609                 the_locking_inset->insetUnlock(bv);
610                 TEXT(bv)->updateInset(bv, inset);
611                 the_locking_inset = 0;
612                 if (lr)
613                         moveRight(bv, false);
614                 old_par = 0; // force layout setting
615                 if (scroll())
616                         scroll(bv, 0.0F);
617                 else
618                         updateLocal(bv, CURSOR, false);
619                 return true;
620         }
621         return the_locking_inset->unlockInsetInInset(bv, inset, lr);
622 }
623
624
625 bool InsetText::updateInsetInInset(BufferView * bv, Inset * inset)
626 {
627         if (!the_locking_inset)
628                 return false;
629         if (the_locking_inset != inset) {
630                 TEXT(bv)->updateInset(bv, the_locking_inset);
631                 setUpdateStatus(bv, CURSOR_PAR);
632                 return the_locking_inset->updateInsetInInset(bv, inset);
633         }
634 //    updateLocal(bv, FULL, false);
635         if (TEXT(bv)->updateInset(bv, inset))
636                 updateLocal(bv, CURSOR_PAR, false);
637         if (cpar(bv) == inset_par && cpos(bv) == inset_pos) {
638                 inset_x = cx(bv) - top_x + drawTextXOffset;
639                 inset_y = cy(bv) + drawTextYOffset;
640         }
641         return true;
642 }
643
644
645 void InsetText::insetButtonPress(BufferView * bv, int x, int y, int button)
646 {
647         no_selection = true;
648
649         int tmp_x = x - drawTextXOffset;
650         int tmp_y = y + insetAscent - TEXT(bv)->first;
651         Inset * inset = bv->checkInsetHit(TEXT(bv), tmp_x, tmp_y, button);
652
653         hideInsetCursor(bv);
654         if (the_locking_inset) {
655                 if (the_locking_inset == inset) {
656                         the_locking_inset->insetButtonPress(bv,x-inset_x,y-inset_y,button);
657                         no_selection = false;
658                         return;
659                 } else if (inset) {
660                         // otherwise unlock the_locking_inset and lock the new inset
661                         the_locking_inset->insetUnlock(bv);
662                         inset_x = cx(bv) - top_x + drawTextXOffset;
663                         inset_y = cy(bv) + drawTextYOffset;
664                         the_locking_inset = static_cast<UpdatableInset*>(inset);
665                         inset->insetButtonPress(bv, x - inset_x, y - inset_y, button);
666                         inset->edit(bv, x - inset_x, y - inset_y, button);
667                         if (the_locking_inset)
668                                 updateLocal(bv, CURSOR, false);
669                         no_selection = false;
670                         return;
671                 }
672                 // otherwise only unlock the_locking_inset
673                 the_locking_inset->insetUnlock(bv);
674                 the_locking_inset = 0;
675         }
676         if (bv->theLockingInset()) {
677                 if (inset && inset->editable() == Inset::HIGHLY_EDITABLE) {
678                         UpdatableInset * uinset = static_cast<UpdatableInset*>(inset);
679                         inset_x = cx(bv) - top_x + drawTextXOffset;
680                         inset_y = cy(bv) + drawTextYOffset;
681                         inset_pos = cpos(bv);
682                         inset_par = cpar(bv);
683                         inset_boundary = cboundary(bv);
684                         the_locking_inset = uinset;
685                         uinset->insetButtonPress(bv, x - inset_x, y - inset_y,
686                                                  button);
687                         uinset->edit(bv, x - inset_x, y - inset_y, 0);
688                         if (the_locking_inset)
689                                 updateLocal(bv, CURSOR, false);
690                         no_selection = false;
691                         return;
692                 }
693         }
694         if (!inset) { // && (button == 2)) {
695                 bool paste_internally = false;
696                 if ((button == 2) && TEXT(bv)->selection.set()) {
697                         localDispatch(bv, LFUN_COPY, "");
698                         paste_internally = true;
699                 }
700                 TEXT(bv)->setCursorFromCoordinates(bv, x-drawTextXOffset,
701                                                    y + insetAscent);
702                 TEXT(bv)->selection.cursor = TEXT(bv)->cursor;
703                 updateLocal(bv, CURSOR, false);
704                 bv->owner()->setLayout(cpar(bv)->getLayout());
705                 old_par = cpar(bv);
706                 // Insert primary selection with middle mouse
707                 // if there is a local selection in the current buffer,
708                 // insert this
709                 if (button == 2) {
710                         if (paste_internally)
711                                 localDispatch(bv, LFUN_PASTE, "");
712                         else
713                                 localDispatch(bv, LFUN_PASTESELECTION,
714                                               "paragraph");
715                 }
716         }
717         showInsetCursor(bv);
718         no_selection = false;
719 }
720
721
722 void InsetText::insetButtonRelease(BufferView * bv, int x, int y, int button)
723 {
724         UpdatableInset * inset = 0;
725
726         if (the_locking_inset) {
727                 the_locking_inset->insetButtonRelease(bv,
728                                                       x - inset_x, y - inset_y,
729                                                       button);
730         } else {
731                 if (cpar(bv)->getChar(cpos(bv)) == Paragraph::META_INSET) {
732                         inset = static_cast<UpdatableInset*>(cpar(bv)->getInset(cpos(bv)));
733                         if (inset->editable() == Inset::HIGHLY_EDITABLE) {
734                                 inset->insetButtonRelease(bv,
735                                                           x - inset_x,
736                                                           y - inset_y, button);
737                         } else {
738                                 inset_x = cx(bv) - top_x + drawTextXOffset;
739                                 inset_y = cy(bv) + drawTextYOffset;
740                                 inset->insetButtonRelease(bv,
741                                                           x - inset_x,
742                                                           y - inset_y, button);
743                                 inset->edit(bv,
744                                             x - inset_x, y - inset_y, button);
745                         }
746                         updateLocal(bv, CURSOR_PAR, false);
747                 }
748         }
749         no_selection = false;
750 }
751
752
753 void InsetText::insetMotionNotify(BufferView * bv, int x, int y, int state)
754 {
755         if (no_selection)
756                 return;
757         if (the_locking_inset) {
758                 the_locking_inset->insetMotionNotify(bv, x - inset_x,
759                                                      y - inset_y,state);
760                 return;
761         }
762         hideInsetCursor(bv);
763         TEXT(bv)->setCursorFromCoordinates(bv, x - drawTextXOffset,
764                                            y + insetAscent);
765         TEXT(bv)->setSelection(bv);
766         if (TEXT(bv)->toggle_cursor.par()!=TEXT(bv)->toggle_end_cursor.par() ||
767                 TEXT(bv)->toggle_cursor.pos()!=TEXT(bv)->toggle_end_cursor.pos())
768                 updateLocal(bv, SELECTION, false);
769         showInsetCursor(bv);
770 }
771
772
773 void InsetText::insetKeyPress(XKeyEvent * xke)
774 {
775         if (the_locking_inset) {
776                 the_locking_inset->insetKeyPress(xke);
777                 return;
778         }
779 }
780
781
782 UpdatableInset::RESULT
783 InsetText::localDispatch(BufferView * bv,
784                          kb_action action, string const & arg)
785 {
786         no_selection = false;
787         UpdatableInset::RESULT
788                 result= UpdatableInset::localDispatch(bv, action, arg);
789         if (result != UNDISPATCHED) {
790                 return DISPATCHED;
791         }
792
793         result = DISPATCHED;
794         if ((action < 0) && arg.empty())
795                 return FINISHED;
796
797         if (the_locking_inset) {
798                 result = the_locking_inset->localDispatch(bv, action, arg);
799                 if (result == DISPATCHED_NOUPDATE)
800                         return result;
801                 else if (result == DISPATCHED) {
802                         updateLocal(bv, CURSOR_PAR, false);
803                         return result;
804                 } else if (result == FINISHED) {
805                         bool dispatched = false;
806                         switch (action) {
807                         case LFUN_UNKNOWN_ACTION:
808                         case LFUN_BREAKPARAGRAPH:
809                         case LFUN_BREAKLINE:
810                                 moveRightIntern(bv, false, false);
811                                 break;
812                         case LFUN_RIGHT:
813                                 if (!TEXT(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
814                                         moveRightIntern(bv, false, false);
815                                 dispatched = true;
816                                 break;
817                         case LFUN_LEFT:
818                                 if (TEXT(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
819                                         moveRightIntern(bv, false, false);
820                                 dispatched = true;
821                                 break;
822                         default:
823                                 break;
824                         }
825                         the_locking_inset = 0;
826                         if (dispatched)
827                                 return DISPATCHED;
828                 }
829         }
830         hideInsetCursor(bv);
831         switch (action) {
832         // Normal chars
833         case LFUN_SELFINSERT:
834                 if (bv->buffer()->isReadonly()) {
835 //          setErrorMessage(N_("Document is read only"));
836                         break;
837                 }
838                 if (!arg.empty()) {
839                         /* Automatically delete the currently selected
840                          * text and replace it with what is being
841                          * typed in now. Depends on lyxrc settings
842                          * "auto_region_delete", which defaults to
843                          * true (on). */
844
845                         bv->text->setUndo(bv->buffer(), Undo::INSERT,
846                                           bv->text->cursor.par()->previous(),
847                                           bv->text->cursor.par()->next());
848                         bv->setState();
849                         if (lyxrc.auto_region_delete) {
850                                 if (TEXT(bv)->selection.set()) {
851                                         TEXT(bv)->cutSelection(bv, false);
852                                 }
853                         }
854                         TEXT(bv)->clearSelection(bv);
855                         for (string::size_type i = 0; i < arg.length(); ++i) {
856                                 if (greek_kb_flag) {
857                                         if (!math_insert_greek(bv, arg[i])) {
858                                                 bv->owner()->getIntl()->getTrans().TranslateAndInsert(arg[i], TEXT(bv));
859                                         } else if (!the_locking_inset) {
860                                                 (void)moveRight(bv, false);
861                                         }
862                                 } else {
863                                         bv->owner()->getIntl()->getTrans().TranslateAndInsert(arg[i], TEXT(bv));
864                                 }
865                         }
866                 }
867                 TEXT(bv)->selection.cursor = TEXT(bv)->cursor;
868                 updateLocal(bv, CURSOR_PAR, true);
869                 result=DISPATCHED_NOUPDATE;
870                 break;
871                 // --- Cursor Movements -----------------------------------
872         case LFUN_RIGHTSEL:
873                 bv->text->finishUndo();
874                 moveRight(bv, false, true);
875                 TEXT(bv)->setSelection(bv);
876                 updateLocal(bv, SELECTION, false);
877                 break;
878         case LFUN_RIGHT:
879                 result = moveRight(bv);
880                 bv->text->finishUndo();
881                 updateLocal(bv, CURSOR, false);
882                 break;
883         case LFUN_LEFTSEL:
884                 bv->text->finishUndo();
885                 moveLeft(bv, false, true);
886                 TEXT(bv)->setSelection(bv);
887                 updateLocal(bv, SELECTION, false);
888                 break;
889         case LFUN_LEFT:
890                 bv->text->finishUndo();
891                 result = moveLeft(bv);
892                 updateLocal(bv, CURSOR, false);
893                 break;
894         case LFUN_DOWNSEL:
895                 bv->text->finishUndo();
896                 moveDown(bv);
897                 TEXT(bv)->setSelection(bv);
898                 updateLocal(bv, SELECTION, false);
899                 break;
900         case LFUN_DOWN:
901                 bv->text->finishUndo();
902                 result = moveDown(bv);
903                 updateLocal(bv, CURSOR, false);
904                 break;
905         case LFUN_UPSEL:
906                 bv->text->finishUndo();
907                 moveUp(bv);
908                 TEXT(bv)->setSelection(bv);
909                 updateLocal(bv, SELECTION, false);
910                 break;
911         case LFUN_UP:
912                 bv->text->finishUndo();
913                 result = moveUp(bv);
914                 updateLocal(bv, CURSOR, false);
915                 break;
916         case LFUN_HOME:
917                 bv->text->finishUndo();
918                 TEXT(bv)->cursorHome(bv);
919                 updateLocal(bv, CURSOR, false);
920                 break;
921         case LFUN_END:
922                 TEXT(bv)->cursorEnd(bv);
923                 updateLocal(bv, CURSOR, false);
924                 break;
925         case LFUN_BACKSPACE:
926                 bv->text->setUndo(bv->buffer(), Undo::DELETE,
927                                   bv->text->cursor.par()->previous(),
928                                   bv->text->cursor.par()->next());
929                 if (TEXT(bv)->selection.set())
930                         TEXT(bv)->cutSelection(bv);
931                 else
932                         TEXT(bv)->backspace(bv);
933                 updateLocal(bv, CURSOR_PAR, true);
934                 break;
935         case LFUN_DELETE:
936                 bv->text->setUndo(bv->buffer(), Undo::DELETE,
937                                   bv->text->cursor.par()->previous(),
938                                   bv->text->cursor.par()->next());
939                 if (TEXT(bv)->selection.set())
940                         TEXT(bv)->cutSelection(bv);
941                 else
942                         TEXT(bv)->Delete(bv);
943                 updateLocal(bv, CURSOR_PAR, true);
944                 break;
945         case LFUN_CUT:
946                 bv->text->setUndo(bv->buffer(), Undo::DELETE,
947                                   bv->text->cursor.par()->previous(),
948                                   bv->text->cursor.par()->next());
949                 TEXT(bv)->cutSelection(bv);
950                 updateLocal(bv, CURSOR_PAR, true);
951                 break;
952         case LFUN_COPY:
953                 bv->text->finishUndo();
954                 TEXT(bv)->copySelection(bv);
955                 updateLocal(bv, CURSOR_PAR, false);
956                 break;
957         case LFUN_PASTESELECTION:
958         {
959                 string const clip(bv->getClipboard());
960         
961                 if (clip.empty())
962                         break;
963                 if (arg == "paragraph") {
964                         TEXT(bv)->insertStringAsParagraphs(bv, clip);
965                 } else {
966                         TEXT(bv)->insertStringAsLines(bv, clip);
967                 }
968                 updateLocal(bv, CURSOR_PAR, true);
969                 break;
970         }
971         case LFUN_PASTE:
972                 if (!autoBreakRows) {
973                         CutAndPaste cap;
974
975                         if (cap.nrOfParagraphs() > 1) {
976                                 WriteAlert(_("Impossible operation"),
977                                                    _("Cannot include more than one paragraph!"),
978                                                    _("Sorry."));
979                                 break;
980                         }
981                 }
982                 bv->text->setUndo(bv->buffer(), Undo::INSERT,
983                                   bv->text->cursor.par()->previous(),
984                                   bv->text->cursor.par()->next());
985                 TEXT(bv)->pasteSelection(bv);
986                 updateLocal(bv, CURSOR_PAR, true);
987                 break;
988         case LFUN_BREAKPARAGRAPH:
989                 if (!autoBreakRows)
990                         return DISPATCHED;
991                 TEXT(bv)->breakParagraph(bv, 0);
992                 updateLocal(bv, FULL, true);
993                 break;
994         case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
995                 if (!autoBreakRows)
996                         return DISPATCHED;
997                 TEXT(bv)->breakParagraph(bv, 1);
998                 updateLocal(bv, FULL, true);
999                 break;
1000         case LFUN_BREAKLINE:
1001                 if (!autoBreakRows)
1002                         return DISPATCHED;
1003                 bv->text->setUndo(bv->buffer(), Undo::INSERT,
1004                                   bv->text->cursor.par()->previous(),
1005                                   bv->text->cursor.par()->next());
1006                 TEXT(bv)->insertChar(bv, Paragraph::META_NEWLINE);
1007                 updateLocal(bv, CURSOR_PAR, true);
1008                 break;
1009         case LFUN_LAYOUT:
1010                 // do not set layouts on non breakable textinsets
1011                 if (autoBreakRows) {
1012                         LyXTextClass::size_type cur_layout = cpar(bv)->layout;
1013           
1014                         // Derive layout number from given argument (string)
1015                         // and current buffer's textclass (number). */    
1016                         LyXTextClassList::ClassList::size_type tclass =
1017                                 bv->buffer()->params.textclass;
1018                         std::pair <bool, LyXTextClass::size_type> layout = 
1019                                 textclasslist.NumberOfLayout(tclass, arg);
1020
1021                         // If the entry is obsolete, use the new one instead.
1022                         if (layout.first) {
1023                                 string obs = textclasslist.Style(tclass,layout.second).
1024                                         obsoleted_by();
1025                                 if (!obs.empty()) 
1026                                         layout = textclasslist.NumberOfLayout(tclass, obs);
1027                         }
1028
1029                         // see if we found the layout number:
1030                         if (!layout.first) {
1031                                 string const msg = string(N_("Layout ")) + arg + N_(" not known");
1032                                 bv->owner()->getLyXFunc()->Dispatch(LFUN_MESSAGE, msg);
1033                                 break;
1034                         }
1035
1036                         if (cur_layout != layout.second) {
1037                                 cur_layout = layout.second;
1038                                 TEXT(bv)->setLayout(bv, layout.second);
1039                                 bv->owner()->setLayout(cpar(bv)->getLayout());
1040                                 updateLocal(bv, CURSOR_PAR, true);
1041                         }
1042                 } else {
1043                         // reset the layout box
1044                         bv->owner()->setLayout(cpar(bv)->getLayout());
1045                 }
1046                 break;
1047         case LFUN_PARAGRAPH_SPACING:
1048                 // This one is absolutely not working. When fiddling with this
1049                 // it also seems to me that the paragraphs inside the insettext
1050                 // inherit bufferparams/paragraphparams in a strange way. (Lgb)
1051         {
1052                 Paragraph * par = TEXT(bv)->cursor.par();
1053                 Spacing::Space cur_spacing = par->params().spacing().getSpace();
1054                 float cur_value = 1.0;
1055                 if (cur_spacing == Spacing::Other) {
1056                         cur_value = par->params().spacing().getValue();
1057                 }
1058                                 
1059                 std::istringstream istr(arg);
1060                 string tmp;
1061                 istr >> tmp;
1062                 Spacing::Space new_spacing = cur_spacing;
1063                 float new_value = cur_value;
1064                 if (tmp.empty()) {
1065                         lyxerr << "Missing argument to `paragraph-spacing'"
1066                                    << endl;
1067                 } else if (tmp == "single") {
1068                         new_spacing = Spacing::Single;
1069                 } else if (tmp == "onehalf") {
1070                         new_spacing = Spacing::Onehalf;
1071                 } else if (tmp == "double") {
1072                         new_spacing = Spacing::Double;
1073                 } else if (tmp == "other") {
1074                         new_spacing = Spacing::Other;
1075                         float tmpval = 0.0;
1076                         istr >> tmpval;
1077                         lyxerr << "new_value = " << tmpval << endl;
1078                         if (tmpval != 0.0)
1079                                 new_value = tmpval;
1080                 } else if (tmp == "default") {
1081                         new_spacing = Spacing::Default;
1082                 } else {
1083                         lyxerr << _("Unknown spacing argument: ")
1084                                    << arg << endl;
1085                 }
1086                 if (cur_spacing != new_spacing || cur_value != new_value) {
1087                         par->params().spacing(Spacing(new_spacing, new_value));
1088                         //TEXT(bv)->RedoParagraph(owner->view());
1089                         updateLocal(bv, CURSOR_PAR, true);
1090                         //bv->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1091                 }
1092         }
1093         break;
1094         
1095         default:
1096                 if (!bv->Dispatch(action, arg))
1097                         result = UNDISPATCHED;
1098                 break;
1099         }
1100
1101         /// If the action has deleted all text in the inset, we need to change the
1102         // language to the language to the surronding text.
1103         if (par->size() == 0 && !par->next()) {
1104                 LyXFont font(LyXFont::ALL_IGNORE);
1105                 font.setLanguage(bv->getParentLanguage(this));
1106                 setFont(bv, font, false);
1107         }
1108
1109         if (result != FINISHED) {
1110                 showInsetCursor(bv);
1111         } else
1112                 bv->unlockInset(this);
1113         return result;
1114 }
1115
1116
1117 int InsetText::latex(Buffer const * buf, ostream & os, bool, bool) const
1118 {
1119         TexRow texrow;
1120         buf->latexParagraphs(os, par, 0, texrow);
1121         return texrow.rows();
1122 }
1123
1124
1125 int InsetText::ascii(Buffer const * buf, ostream & os, int linelen) const
1126 {
1127         Paragraph * p = par;
1128         unsigned int lines = 0;
1129         
1130         while (p) {
1131                 string const tmp = buf->asciiParagraph(p, linelen);
1132                 lines += countChar(tmp, '\n');
1133                 os << tmp;
1134                 p = p->next();
1135         }
1136         return lines;
1137 }
1138
1139
1140 int InsetText::docBook(Buffer const * buf, ostream & os) const
1141 {
1142         Paragraph * p = par;
1143         unsigned int lines = 0;
1144         int desc = 0;
1145         
1146         string tmp;
1147         while (p) {
1148                 buf->simpleDocBookOnePar(os, tmp, p, desc, 0);
1149                 p = p->next();
1150         }
1151         
1152         return lines;
1153 }
1154
1155
1156 void InsetText::validate(LaTeXFeatures & features) const
1157 {
1158         Paragraph * p = par;
1159         while (p) {
1160                 p->validate(features);
1161                 p = p->next();
1162         }
1163 }
1164
1165
1166 int InsetText::beginningOfMainBody(Buffer const * buf, Paragraph * p) const
1167 {
1168         if (textclasslist.Style(buf->params.textclass,
1169                                 p->getLayout()).labeltype != LABEL_MANUAL)
1170                 return 0;
1171         else
1172                 return p->beginningOfMainBody();
1173 }
1174
1175
1176 void InsetText::getCursorPos(BufferView * bv,
1177                              int & x, int & y) const
1178 {
1179         x = cx(bv);
1180         y = cy(bv);
1181 }
1182
1183
1184 unsigned int InsetText::insetInInsetY()
1185 {
1186         if (!the_locking_inset)
1187                 return 0;
1188
1189         return (inset_y + the_locking_inset->insetInInsetY());
1190 }
1191
1192
1193 void InsetText::toggleInsetCursor(BufferView * bv)
1194 {
1195         if (the_locking_inset) {
1196                 the_locking_inset->toggleInsetCursor(bv);
1197                 return;
1198         }
1199
1200         LyXFont const font(TEXT(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv)));
1201
1202         int const asc = lyxfont::maxAscent(font);
1203         int const desc = lyxfont::maxDescent(font);
1204   
1205         if (isCursorVisible())
1206                 bv->hideLockedInsetCursor();
1207         else
1208                 bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1209         toggleCursorVisible();
1210 }
1211
1212
1213 void InsetText::showInsetCursor(BufferView * bv, bool show)
1214 {
1215         if (the_locking_inset) {
1216                 the_locking_inset->showInsetCursor(bv);
1217                 return;
1218         }
1219         if (!isCursorVisible()) {
1220                 LyXFont const font =
1221                         TEXT(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv));
1222         
1223                 int const asc = lyxfont::maxAscent(font);
1224                 int const desc = lyxfont::maxDescent(font);
1225
1226                 bv->fitLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1227                 if (show)
1228                         bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc);
1229                 setCursorVisible(true);
1230         }
1231 }
1232
1233
1234 void InsetText::hideInsetCursor(BufferView * bv)
1235 {
1236         if (isCursorVisible()) {
1237                 bv->hideLockedInsetCursor();
1238                 setCursorVisible(false);
1239         }
1240         if (the_locking_inset)
1241                 the_locking_inset->hideInsetCursor(bv);
1242 }
1243
1244
1245 UpdatableInset::RESULT
1246 InsetText::moveRight(BufferView * bv, bool activate_inset, bool selecting)
1247 {
1248         if (TEXT(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
1249                 return moveLeftIntern(bv, false, activate_inset, selecting);
1250         else
1251                 return moveRightIntern(bv, false, activate_inset, selecting);
1252 }
1253
1254
1255 UpdatableInset::RESULT
1256 InsetText::moveLeft(BufferView * bv, bool activate_inset, bool selecting)
1257 {
1258         if (TEXT(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
1259                 return moveRightIntern(bv, true, activate_inset, selecting);
1260         else
1261                 return moveLeftIntern(bv, true, activate_inset, selecting);
1262 }
1263
1264
1265 UpdatableInset::RESULT
1266 InsetText::moveRightIntern(BufferView * bv, bool behind, 
1267                            bool activate_inset, bool selecting)
1268 {
1269         if (!cpar(bv)->next() && (cpos(bv) >= cpar(bv)->size()))
1270                 return FINISHED;
1271         if (activate_inset && checkAndActivateInset(bv, behind))
1272                 return DISPATCHED;
1273         TEXT(bv)->cursorRight(bv);
1274         if (!selecting)
1275                 TEXT(bv)->selection.cursor = TEXT(bv)->cursor;
1276         return DISPATCHED_NOUPDATE;
1277 }
1278
1279
1280 UpdatableInset::RESULT
1281 InsetText::moveLeftIntern(BufferView * bv, bool behind,
1282                           bool activate_inset, bool selecting)
1283 {
1284         if (!cpar(bv)->previous() && (cpos(bv) <= 0))
1285                 return FINISHED;
1286         TEXT(bv)->cursorLeft(bv);
1287         if (!selecting)
1288                 TEXT(bv)->selection.cursor = TEXT(bv)->cursor;
1289         if (activate_inset && checkAndActivateInset(bv, behind))
1290                 return DISPATCHED;
1291         return DISPATCHED_NOUPDATE;
1292 }
1293
1294
1295 UpdatableInset::RESULT
1296 InsetText::moveUp(BufferView * bv)
1297 {
1298         if (!crow(bv)->previous())
1299                 return FINISHED;
1300         TEXT(bv)->cursorUp(bv);
1301         return DISPATCHED_NOUPDATE;
1302 }
1303
1304
1305 UpdatableInset::RESULT
1306 InsetText::moveDown(BufferView * bv)
1307 {
1308         if (!crow(bv)->next())
1309                 return FINISHED;
1310         TEXT(bv)->cursorDown(bv);
1311         return DISPATCHED_NOUPDATE;
1312 }
1313
1314
1315 bool InsetText::insertInset(BufferView * bv, Inset * inset)
1316 {
1317         if (the_locking_inset) {
1318                 if (the_locking_inset->insertInsetAllowed(inset))
1319                         return the_locking_inset->insertInset(bv, inset);
1320                 return false;
1321         }
1322         bv->text->setUndo(bv->buffer(), Undo::INSERT,
1323                           bv->text->cursor.par()->previous(),
1324                           bv->text->cursor.par()->next());
1325         inset->setOwner(this);
1326         hideInsetCursor(bv);
1327         TEXT(bv)->insertInset(bv, inset);
1328 #if 0
1329         if ((cpar(bv)->GetChar(cpos(bv)) != Paragraph::META_INSET) ||
1330                 (cpar(bv)->GetInset(cpos(bv)) != inset))
1331                 TEXT(bv)->CursorLeft(bv);
1332 #endif
1333         bv->fitCursor(TEXT(bv));
1334         updateLocal(bv, CURSOR_PAR|CURSOR, true);
1335         showInsetCursor(bv);
1336         return true;
1337 }
1338
1339
1340 UpdatableInset * InsetText::getLockingInset()
1341 {
1342         return the_locking_inset ? the_locking_inset->getLockingInset() : this;
1343 }
1344
1345
1346 UpdatableInset * InsetText::getFirstLockingInsetOfType(Inset::Code c)
1347 {
1348         if (c == lyxCode())
1349                 return this;
1350         if (the_locking_inset)
1351                 return the_locking_inset->getFirstLockingInsetOfType(c);
1352         return 0;
1353 }
1354
1355
1356 bool InsetText::showInsetDialog(BufferView * bv) const
1357 {
1358         if (the_locking_inset)
1359                 return the_locking_inset->showInsetDialog(bv);
1360         return false;
1361 }
1362
1363
1364 std::vector<string> const InsetText::getLabelList() const 
1365 {
1366         std::vector<string> label_list;
1367
1368         Paragraph * tpar = par;
1369         while (tpar) {
1370                 Paragraph::inset_iterator beg = tpar->inset_iterator_begin();
1371                 Paragraph::inset_iterator end = tpar->inset_iterator_end();
1372                 for (; beg != end; ++beg) {
1373                         std::vector<string> const l = (*beg)->getLabelList();
1374                         label_list.insert(label_list.end(), l.begin(), l.end());
1375                 }
1376                 tpar = tpar->next();
1377         }
1378         return label_list;
1379 }
1380
1381
1382 void InsetText::setFont(BufferView * bv, LyXFont const & font, bool toggleall,
1383                         bool selectall)
1384 {
1385         if (the_locking_inset) {
1386                 the_locking_inset->setFont(bv, font, toggleall, selectall);
1387                 return;
1388         }
1389         if (TEXT(bv)->selection.set()) {
1390                 bv->text->setUndo(bv->buffer(), Undo::EDIT,
1391                                   bv->text->cursor.par()->previous(),
1392                                   bv->text->cursor.par()->next());
1393         }
1394         if (selectall)
1395                 selectAll(bv);
1396         TEXT(bv)->setFont(bv, font, toggleall);
1397         if (selectall)
1398                 TEXT(bv)->clearSelection(bv);
1399         bv->fitCursor(TEXT(bv));
1400         if (selectall || TEXT(bv)->selection.set())
1401                 updateLocal(bv, FULL, true);
1402         else
1403                 updateLocal(bv, CURSOR_PAR, true);
1404 }
1405
1406
1407 bool InsetText::checkAndActivateInset(BufferView * bv, bool behind)
1408 {
1409         if (cpar(bv)->getChar(cpos(bv)) == Paragraph::META_INSET) {
1410                 unsigned int x;
1411                 unsigned int y;
1412                 Inset * inset =
1413                         static_cast<UpdatableInset*>(cpar(bv)->getInset(cpos(bv)));
1414                 if (!inset || inset->editable() != Inset::HIGHLY_EDITABLE)
1415                         return false;
1416                 LyXFont const font =
1417                         TEXT(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv));
1418                 if (behind) {
1419                         x = inset->width(bv, font);
1420                         y = font.isRightToLeft() ? 0 : inset->descent(bv, font);
1421                 } else {
1422                         x = 0;
1423                         y = font.isRightToLeft() ? inset->descent(bv, font) : 0;
1424                 }
1425                 //inset_x = cx(bv) - top_x + drawTextXOffset;
1426                 //inset_y = cy(bv) + drawTextYOffset;
1427                 inset->edit(bv, x, y, 0);
1428                 if (!the_locking_inset)
1429                         return false;
1430                 updateLocal(bv, CURSOR, false);
1431                 return true;
1432         }
1433         return false;
1434 }
1435
1436
1437 bool InsetText::checkAndActivateInset(BufferView * bv, int x, int y,
1438                                       int button)
1439 {
1440         x -= drawTextXOffset;
1441         int dummyx = x;
1442         int dummyy = y + insetAscent;
1443         Inset * inset = bv->checkInsetHit(TEXT(bv), dummyx, dummyy, button);
1444
1445         if (inset) {
1446                 if (x < 0)
1447                         x = insetWidth;
1448                 if (y < 0)
1449                         y = insetDescent;
1450                 inset_x = cx(bv) - top_x + drawTextXOffset;
1451                 inset_y = cy(bv) + drawTextYOffset;
1452                 inset->edit(bv, x - inset_x, y - inset_y, button);
1453                 if (!the_locking_inset)
1454                         return false;
1455                 updateLocal(bv, CURSOR, false);
1456                 return true;
1457         }
1458         return false;
1459 }
1460
1461
1462 int InsetText::getMaxWidth(BufferView * bv, UpdatableInset const * inset) const
1463 {
1464         int w = UpdatableInset::getMaxWidth(bv, inset);
1465         if (w < 0) {
1466                 return w;
1467         }
1468         if (owner()) {
1469                 w = w - top_x + owner()->x();
1470                 return w;
1471         }
1472         w -= (2 * TEXT_TO_INSET_OFFSET);
1473         return w - top_x;
1474 //    return  w - (2*TEXT_TO_INSET_OFFSET);
1475 }
1476
1477
1478 void InsetText::setParagraphData(Paragraph * p)
1479 {
1480         // delete all instances of LyXText before deleting the paragraps used
1481         // by it.
1482         for (Cache::iterator cit = cache.begin(); cit != cache.end(); ++cit){
1483                 delete (*cit).second;
1484                 (*cit).second = 0;
1485         }
1486
1487         while (par) {
1488                 Paragraph * tmp = par->next();
1489                 delete par;
1490                 par = tmp;
1491         }
1492
1493         par = new Paragraph(*p);
1494         par->setInsetOwner(this);
1495         Paragraph * np = par;
1496         while (p->next()) {
1497                 p = p->next();
1498                 np->next(new Paragraph(*p));
1499                 np->next()->previous(np);
1500                 np = np->next();
1501                 np->setInsetOwner(this);
1502         }
1503
1504         need_update = INIT;
1505 }
1506
1507
1508 void InsetText::setText(string const & data)
1509 {
1510         clear();
1511         LyXFont font(LyXFont::ALL_SANE);
1512         for (unsigned int i=0; i < data.length(); ++i)
1513                 par->insertChar(i, data[i], font);
1514 }
1515
1516
1517 void InsetText::setAutoBreakRows(bool flag)
1518 {
1519         if (flag != autoBreakRows) {
1520                 autoBreakRows = flag;
1521                 need_update = FULL;
1522                 if (!flag)
1523                         removeNewlines();
1524         }
1525 }
1526
1527
1528 void InsetText::setDrawFrame(BufferView * bv, DrawFrame how)
1529 {
1530         if (how != drawFrame_) {
1531                 drawFrame_ = how;
1532                 if (bv)
1533                         updateLocal(bv, DRAW_FRAME, false);
1534         }
1535 }
1536
1537
1538 void InsetText::setFrameColor(BufferView * bv, LColor::color col)
1539 {
1540         if (frame_color != col) {
1541                 frame_color = col;
1542                 if (bv)
1543                         updateLocal(bv, DRAW_FRAME, false);
1544         }
1545 }
1546
1547
1548 int InsetText::cx(BufferView * bv) const
1549 {
1550         LyXText * text = TEXT(bv);
1551         int x = text->cursor.x() + top_x + TEXT_TO_INSET_OFFSET;
1552         if (the_locking_inset) {
1553                 LyXFont font = text->getFont(bv->buffer(),
1554                                              text->cursor.par(),
1555                                              text->cursor.pos());
1556                 if (font.isVisibleRightToLeft())
1557                         x -= the_locking_inset->width(bv, font);
1558         }
1559         return x;
1560 }
1561
1562
1563 int InsetText::cy(BufferView * bv) const
1564 {
1565         LyXFont font;
1566         return TEXT(bv)->cursor.y() - ascent(bv, font) + TEXT_TO_INSET_OFFSET;
1567 }
1568
1569
1570 Paragraph::size_type InsetText::cpos(BufferView * bv) const
1571 {
1572         return TEXT(bv)->cursor.pos();
1573 }
1574
1575
1576 Paragraph * InsetText::cpar(BufferView * bv) const
1577 {
1578         return TEXT(bv)->cursor.par();
1579 }
1580
1581
1582 bool InsetText::cboundary(BufferView * bv) const
1583 {
1584         return TEXT(bv)->cursor.boundary();
1585 }
1586
1587
1588 Row * InsetText::crow(BufferView * bv) const
1589 {
1590         return TEXT(bv)->cursor.row();
1591 }
1592
1593
1594 LyXText * InsetText::getLyXText(BufferView const * lbv,
1595                                 bool const recursive) const
1596 {
1597         // Super UGLY! (Lgb)
1598         BufferView * bv = const_cast<BufferView *>(lbv);
1599         
1600         if ((cache.find(bv) != cache.end()) && cache[bv]) {
1601                 if (recursive && the_locking_inset)
1602                         return the_locking_inset->getLyXText(bv);
1603                 return cache[bv];
1604         }
1605         LyXText * lt = new LyXText(const_cast<InsetText *>(this));
1606         lt->init(bv);
1607         cache[bv] = lt;
1608         if (the_locking_inset) {
1609                 lt->setCursor(bv, inset_par, inset_pos, true, inset_boundary);
1610                 if (recursive)
1611                         return the_locking_inset->getLyXText(bv);
1612         }
1613         return lt;
1614 }
1615
1616
1617 void InsetText::deleteLyXText(BufferView * bv, bool recursive) const
1618 {
1619         if ((cache.find(bv) == cache.end()) || !cache[bv])
1620                 return;
1621         delete cache[bv];
1622         cache.erase(bv);
1623         if (recursive) {
1624                 /// then remove all LyXText in text-insets
1625                 Paragraph * p = par;
1626                 for (; p; p = p->next()) {
1627                         p->deleteInsetsLyXText(bv);
1628                 }
1629         }
1630 }
1631
1632
1633 void InsetText::resizeLyXText(BufferView * bv, bool force) const
1634 {
1635         if (!par->next() && !par->size()) // no data, resize not neccessary!
1636                 return;
1637         // one endless line, resize normally not necessary
1638         if (!force && getMaxWidth(bv, this) < 0)
1639                 return;
1640         if ((cache.find(bv) == cache.end()) || !cache[bv])
1641                 return;
1642
1643         Paragraph * lpar = 0;
1644         Paragraph * selstartpar = 0;
1645         Paragraph * selendpar = 0;
1646         Paragraph::size_type pos = 0;
1647         Paragraph::size_type selstartpos = 0;
1648         Paragraph::size_type selendpos = 0;
1649         bool boundary = false;
1650         bool selstartboundary = false;
1651         bool selendboundary = false;
1652         bool selection = false;
1653         bool mark_set = false;
1654
1655 //    ProhibitInput(bv);
1656
1657         if (locked) {
1658                 lpar = TEXT(bv)->cursor.par();
1659                 pos = TEXT(bv)->cursor.pos();
1660                 boundary = TEXT(bv)->cursor.boundary();
1661                 selstartpar = TEXT(bv)->selection.start.par();
1662                 selstartpos = TEXT(bv)->selection.start.pos();
1663                 selstartboundary = TEXT(bv)->selection.start.boundary();
1664                 selendpar = TEXT(bv)->selection.end.par();
1665                 selendpos = TEXT(bv)->selection.end.pos();
1666                 selendboundary = TEXT(bv)->selection.end.boundary();
1667                 selection = TEXT(bv)->selection.set();
1668                 mark_set = TEXT(bv)->selection.mark();
1669         }
1670         deleteLyXText(bv, (the_locking_inset == 0) || force);
1671
1672         if (lpar) {
1673                 TEXT(bv)->selection.set(true);
1674                 /* at this point just to avoid the Delete-Empty-Paragraph
1675                  * Mechanism when setting the cursor */
1676                 TEXT(bv)->selection.mark(mark_set);
1677                 if (selection) {
1678                         TEXT(bv)->setCursor(bv, selstartpar, selstartpos,
1679                                             true, selstartboundary);
1680                         TEXT(bv)->selection.cursor = TEXT(bv)->cursor;
1681                         TEXT(bv)->setCursor(bv, selendpar, selendpos,
1682                                             true, selendboundary);
1683                         TEXT(bv)->setSelection(bv);
1684                         TEXT(bv)->setCursor(bv, lpar, pos);
1685                 } else {
1686                         TEXT(bv)->setCursor(bv, lpar, pos, true, boundary);
1687                         TEXT(bv)->selection.cursor = TEXT(bv)->cursor;
1688                         TEXT(bv)->selection.set(false);
1689                 }
1690         }
1691         if (bv->screen())
1692                 TEXT(bv)->first = bv->screen()->TopCursorVisible(TEXT(bv));
1693         // this will scroll the screen such that the cursor becomes visible 
1694         bv->updateScrollbar();
1695 //    AllowInput(bv);
1696         if (the_locking_inset) {
1697                 /// then resize all LyXText in text-insets
1698                 inset_x = cx(bv) - top_x + drawTextXOffset;
1699                 inset_y = cy(bv) + drawTextYOffset;
1700                 for (Paragraph * p = par; p; p = p->next()) {
1701                         p->resizeInsetsLyXText(bv);
1702                 }
1703         }
1704         need_update = FULL;
1705 }
1706
1707
1708 void InsetText::removeNewlines()
1709 {
1710         for (Paragraph * p = par; p; p = p->next()) {
1711                 for (int i = 0; i < p->size(); ++i) {
1712                         if (p->getChar(i) == Paragraph::META_NEWLINE)
1713                                 p->erase(i);
1714                 }
1715         }
1716 }
1717
1718
1719 bool InsetText::nodraw() const
1720 {
1721         if (the_locking_inset)
1722                 return the_locking_inset->nodraw();
1723         return UpdatableInset::nodraw();
1724 }
1725
1726
1727 int InsetText::scroll(bool recursive) const
1728 {
1729         int sx = UpdatableInset::scroll(false);
1730
1731         if (recursive && the_locking_inset)
1732                 sx += the_locking_inset->scroll(recursive);
1733
1734         return sx;
1735 }
1736
1737
1738 bool InsetText::doClearArea() const
1739 {
1740         return !locked || (need_update & (FULL|INIT));
1741 }
1742
1743
1744 void InsetText::selectAll(BufferView * bv)
1745 {
1746         TEXT(bv)->cursorTop(bv);
1747         TEXT(bv)->selection.cursor = TEXT(bv)->cursor;
1748         TEXT(bv)->cursorBottom(bv);
1749         TEXT(bv)->setSelection(bv);
1750 }
1751
1752
1753 void InsetText::clearSelection(BufferView * bv)
1754 {
1755         TEXT(bv)->clearSelection(bv);
1756 }
1757
1758
1759 void InsetText::clearInset(Painter & pain, int baseline, bool & cleared) const
1760 {
1761         int w =  insetWidth;
1762         int h = insetAscent + insetDescent;
1763         int ty = baseline - insetAscent;
1764         
1765         if (ty < 0) {
1766                 h += ty;
1767                 ty = 0;
1768         }
1769         if ((ty + h) > pain.paperHeight())
1770                 h = pain.paperHeight();
1771         if ((top_x + drawTextXOffset + w) > pain.paperWidth())
1772                 w = pain.paperWidth();
1773         pain.fillRectangle(top_x+drawTextXOffset, ty, w, h);
1774         cleared = true;
1775         need_update = FULL;
1776 }
1777 /* Emacs:
1778  * Local variables:
1779  * tab-width: 4
1780  * End:
1781  * vi:set tabstop=4:
1782  */