]> git.lyx.org Git - lyx.git/blobdiff - src/insets/insettext.C
clear()->erase() ; lots of using directives for cxx
[lyx.git] / src / insets / insettext.C
index f7703842b4ee722d45bf859eb9ef0a62a725ba11..e0b8f1f5b35ef77a7f2bdc85ec5bb3384fbc66f5 100644 (file)
@@ -4,7 +4,7 @@
  * 
  *           LyX, The Document Processor
  *
- *           Copyright 1998 The LyX Team.
+ *           Copyright 1998-2000 The LyX Team.
  *
  * ======================================================
  */
@@ -13,9 +13,6 @@
 
 #include <fstream>
 #include <algorithm>
-using std::ifstream;
-using std::min;
-using std::max;
 
 #include <cstdlib>
 
@@ -52,40 +49,59 @@ using std::max;
 #include "Painter.h"
 #include "lyx_gui_misc.h"
 #include "support/LAssert.h"
+#include "lyxtext.h"
+#include "lyxcursor.h"
+#include "CutAndPaste.h"
+#include "font.h"
+#include "minibuffer.h"
+#include "toolbar.h"
+
+using std::ostream;
+using std::ifstream;
+using std::endl;
+using std::min;
+using std::max;
 
 extern unsigned char getCurrentTextClass(Buffer *);
+extern LyXTextClass::size_type current_layout;
+
 
 InsetText::InsetText(Buffer * buf)
 {
     par = new LyXParagraph();
-    the_locking_inset = 0;
-    buffer = buf;
-    cursor_visible = false;
-    maxWidth = old_x = -1;
-    actpos = selection_start = selection_end = 0;
-    interline_space = 1;
-    no_selection = false;
-    init_inset = true;
-    maxAscent = maxDescent = insetWidth = widthOffset = 0;
-    autoBreakRows = false;
-    xpos = 0.0;
+    init(buf);
 }
 
 
 InsetText::InsetText(InsetText const & ins, Buffer * buf)
 {
-    par = new LyXParagraph(ins.par);
+    par = 0;
+    init(buf, &ins);
+    autoBreakRows = ins.autoBreakRows;
+}
+
+
+void InsetText::init(Buffer * buf, InsetText const * ins)
+{
     the_locking_inset = 0;
     buffer = buf;
     cursor_visible = false;
-    maxWidth = old_x = -1;
-    actpos = selection_start = selection_end = 0;
+    cursor.x_fix = -1;
     interline_space = 1;
     no_selection = false;
     init_inset = true;
-    maxAscent = maxDescent = insetWidth = widthOffset = 0;
+    maxAscent = maxDescent = insetWidth = 0;
+    drawTextXOffset = drawTextYOffset = 0;
     autoBreakRows = false;
     xpos = 0.0;
+    if (ins) {
+       SetParagraphData(ins->par);
+       autoBreakRows = ins->autoBreakRows;
+    }
+    par->SetInsetOwner(this);
+    cursor.par = par;
+    cursor.pos = 0;
+    selection_start_cursor = selection_end_cursor = cursor;
 }
 
 
@@ -127,6 +143,7 @@ void InsetText::Read(LyXLex & lex)
 
     delete par;
     par = new LyXParagraph;
+    par->SetInsetOwner(this);
     
     while (lex.IsOK()) {
         lex.nextToken();
@@ -156,11 +173,12 @@ int InsetText::ascent(Painter & pain, LyXFont const & font) const
 {
     if (init_inset) {
        computeTextRows(pain, xpos);
+       resetPos(pain);
        init_inset = false;
     }
     if (maxAscent)
        return maxAscent;
-    return font.maxAscent();
+    return lyxfont::maxAscent(font);
 }
 
 
@@ -168,11 +186,12 @@ int InsetText::descent(Painter & pain, LyXFont const & font) const
 {
     if (init_inset) {
        computeTextRows(pain, xpos);
+       resetPos(pain);
        init_inset = false;
     }
     if (maxDescent)
        return maxDescent;
-    return font.maxDescent();
+    return lyxfont::maxDescent(font);
 }
 
 
@@ -180,6 +199,7 @@ int InsetText::width(Painter & pain, LyXFont const &) const
 {
     if (init_inset) {
        computeTextRows(pain, xpos);
+       resetPos(pain);
        init_inset = false;
     }
     return insetWidth;
@@ -190,24 +210,28 @@ void InsetText::draw(Painter & pain, LyXFont const & f,
                     int baseline, float & x) const
 {
     xpos = x;
-    computeTextRows(pain, x);
     UpdatableInset::draw(pain, f, baseline, x);
     
-    bool do_reset_pos = (x != top_x) || (baseline != top_baseline);
-    top_x = int(x);
-    top_baseline = baseline;
-    computeBaselines(baseline);
+    if (init_inset || (baseline != top_baseline) || (top_x != int(x))) {
+       top_baseline = baseline;
+       if (init_inset || (top_x != int(x))) {
+           top_x = int(x);
+           computeTextRows(pain, x);
+           init_inset = false;
+       }
+       computeBaselines(baseline);
+    }
+    if (the_locking_inset && (cursor.pos == inset_pos)) {
+       resetPos(pain);
+       inset_x = cursor.x - top_x + drawTextXOffset;
+       inset_y = cursor.y + drawTextYOffset;
+    }
     for(RowList::size_type r = 0; r < rows.size() - 1; ++r) {
         drawRowSelection(pain, rows[r].pos, rows[r + 1].pos, r, 
                          rows[r].baseline, x);
         drawRowText(pain, rows[r].pos, rows[r + 1].pos, rows[r].baseline, x);
     }
     x += insetWidth;
-    if (!the_locking_inset && do_reset_pos) {
-//        HideInsetCursor(bv);
-//        resetPos(bv);
-//        ShowInsetCursor(bv);
-    }
 }
 
 
@@ -218,12 +242,12 @@ void InsetText::drawRowSelection(Painter & pain, int startpos, int endpos,
        return;
 
     int s_start, s_end;
-    if (selection_start > selection_end) {
-       s_start = selection_end;
-       s_end = selection_start;
+    if (selection_start_cursor.pos > selection_end_cursor.pos) {
+       s_start = selection_end_cursor.pos;
+       s_end = selection_start_cursor.pos;
     } else {
-       s_start = selection_start;
-       s_end = selection_end;
+       s_start = selection_start_cursor.pos;
+       s_end = selection_end_cursor.pos;
     }
     if ((s_start > endpos) || (s_end < startpos))
        return;
@@ -238,14 +262,14 @@ void InsetText::drawRowSelection(Painter & pain, int startpos, int endpos,
        if ((p >= s_start) && (p <= s_end))
            esel_x = int(x);
        char ch = par->GetChar(p);
-       font = GetFont(par,p);
+       font = GetDrawFont(par,p);
        if (IsFloatChar(ch)) {
            // skip for now
        } else if (ch == LyXParagraph::META_INSET) {
            Inset const * tmpinset = par->GetInset(p);
            x += tmpinset->width(pain, font);
        } else {
-           x += pain.width(ch,font);
+           x += lyxfont::width(ch, font);
        }
     }
     if (p == s_start)
@@ -268,16 +292,45 @@ void InsetText::drawRowText(Painter & pain, int startpos, int endpos,
 
     for(int p = startpos; p < endpos; ++p) {
        char ch = par->GetChar(p);
-       LyXFont font = GetFont(par,p);
+       LyXFont font = GetDrawFont(par,p);
        if (IsFloatChar(ch)) {
            // skip for now
+       } else if (par->IsNewline(p)) {
+               // Draw end-of-line marker
+               int wid = lyxfont::width('n', font);
+               int asc = lyxfont::maxAscent(font);
+               int y = baseline;
+               int xp[3], yp[3];
+               
+               xp[0] = int(x + wid * 0.375);
+               yp[0] = int(y - 0.875 * asc * 0.75);
+               
+               xp[1] = int(x);
+               yp[1] = int(y - 0.500 * asc * 0.75);
+               
+               xp[2] = int(x + wid * 0.375);
+               yp[2] = int(y - 0.125 * asc * 0.75);
+               
+               pain.lines(xp, yp, 3, LColor::eolmarker);
+               
+               xp[0] = int(x);
+               yp[0] = int(y - 0.500 * asc * 0.75);
+               
+               xp[1] = int(x + wid);
+               yp[1] = int(y - 0.500 * asc * 0.75);
+               
+               xp[2] = int(x + wid);
+               yp[2] = int(y - asc * 0.75);
+                       
+               pain.lines(xp, yp, 3, LColor::eolmarker);
+               x += wid;
        } else if (ch == LyXParagraph::META_INSET) {
            Inset * tmpinset = par->GetInset(p);
            if (tmpinset) 
                tmpinset->draw(pain, font, baseline, x);
        } else {
            pain.text(int(x), baseline, ch, font);
-           x += pain.width(ch,font);
+           x += lyxfont::width(ch, font);
        }
     }
 }
@@ -291,33 +344,74 @@ char const * InsetText::EditMessage() const
 
 void InsetText::Edit(BufferView * bv, int x, int y, unsigned int button)
 {
+    par->SetInsetOwner(this);
     UpdatableInset::Edit(bv, x, y, button);
 
-    bv->lockInset(this);
+    if (!bv->lockInset(this)) {
+       lyxerr[Debug::INSETS] << "Cannot lock inset" << endl;
+       return;
+    }
     the_locking_inset = 0;
     inset_pos = inset_x = inset_y = 0;
-    no_selection = true;
-    setPos(bv, x,y);
-    selection_start = selection_end = actpos;
-    current_font = real_current_font = GetFont(par, actpos);
+    setPos(bv->painter(), x, y);
+    checkAndActivateInset(bv, x, y, button);
+    selection_start_cursor = selection_end_cursor = cursor;
+    current_font = real_current_font = GetFont(par, cursor.pos);
+    bv->text->FinishUndo();
+    UpdateLocal(bv, true);
 }
 
 
 void InsetText::InsetUnlock(BufferView * bv)
 {
-    if (the_locking_inset)
+    if (the_locking_inset) {
        the_locking_inset->InsetUnlock(bv);
+       the_locking_inset = 0;
+    }
     HideInsetCursor(bv);
+    lyxerr[Debug::INSETS] << "InsetText::InsetUnlock(" << this <<
+           ")" << endl;
     if (hasSelection()) {
-       selection_start = selection_end = actpos;
+       selection_start_cursor = selection_end_cursor = cursor;
        UpdateLocal(bv, false);
     }
-    the_locking_inset = 0;
     no_selection = false;
 }
 
 
-bool InsetText::UnlockInsetInInset(BufferView * bv, Inset * inset, bool lr)
+bool InsetText::LockInsetInInset(BufferView * bv, UpdatableInset * inset)
+{
+    lyxerr[Debug::INSETS] << "InsetText::LockInsetInInset(" << inset << "): ";
+    if (!inset)
+       return false;
+    if (inset == par->GetInset(cursor.pos)) {
+       lyxerr[Debug::INSETS] << "OK" << endl;
+       the_locking_inset = inset;
+       resetPos(bv->painter());
+       inset_x = cursor.x - top_x + drawTextXOffset;
+       inset_y = cursor.y + drawTextYOffset;
+       inset_pos = cursor.pos;
+       return true;
+    } else if (the_locking_inset && (the_locking_inset == inset)) {
+       if (cursor.pos == inset_pos) {
+           lyxerr[Debug::INSETS] << "OK" << endl;
+           resetPos(bv->painter());
+           inset_x = cursor.x - top_x + drawTextXOffset;
+           inset_y = cursor.y + drawTextYOffset;
+       } else {
+           lyxerr[Debug::INSETS] << "cursor.pos != inset_pos" << endl;
+       }
+    } else if (the_locking_inset) {
+       lyxerr[Debug::INSETS] << "MAYBE" << endl;
+       return the_locking_inset->LockInsetInInset(bv, inset);
+    }
+    lyxerr[Debug::INSETS] << "NOT OK" << endl;
+    return false;
+}
+
+
+bool InsetText::UnlockInsetInInset(BufferView * bv, UpdatableInset * inset,
+                                  bool lr)
 {
     if (!the_locking_inset)
         return false;
@@ -328,7 +422,7 @@ bool InsetText::UnlockInsetInInset(BufferView * bv, Inset * inset, bool lr)
             moveRight(bv, false);
         return true;
     }
-    return the_locking_inset->UnlockInsetInInset(bv, inset,lr);
+    return the_locking_inset->UnlockInsetInInset(bv, inset, lr);
 }
 
 
@@ -338,74 +432,103 @@ bool InsetText::UpdateInsetInInset(BufferView * bv, Inset * inset)
         return false;
     if (the_locking_inset != inset)
         return the_locking_inset->UpdateInsetInInset(bv, inset);
-    float x = inset_x;
-    inset->draw(bv->getPainter(), real_current_font, inset_y, x);
+    lyxerr[Debug::INSETS] << "InsetText::UpdateInsetInInset(" << inset <<
+           ")" << endl;
     UpdateLocal(bv, true);
-    return true;
-}
-
-
-void InsetText::InsetButtonRelease(BufferView * bv, int x, int y, int button)
-{
-    if (the_locking_inset) {
-        the_locking_inset->InsetButtonRelease(bv, x-inset_x, y-inset_y,button);
-        return;
+    if (cursor.pos == inset_pos) {
+       inset_x = cursor.x - top_x + drawTextXOffset;
+       inset_y = cursor.y + drawTextYOffset;
     }
-    no_selection = false;
+    return true;
 }
 
 
 void InsetText::InsetButtonPress(BufferView * bv, int x, int y, int button)
 {
     if (hasSelection()) {
-       selection_start = selection_end = actpos;
+       selection_start_cursor = selection_end_cursor = cursor;
        UpdateLocal(bv, false);
     }
     no_selection = false;
+    setPos(bv->painter(), x, y);
+    cursor.x_fix = -1;
     if (the_locking_inset) {
-       setPos(bv, x, y, false);
        UpdatableInset
            *inset = 0;
-       if (par->GetChar(actpos) == LyXParagraph::META_INSET)
-           inset = static_cast<UpdatableInset*>(par->GetInset(actpos));
+       if (par->GetChar(cursor.pos) == LyXParagraph::META_INSET)
+           inset = static_cast<UpdatableInset*>(par->GetInset(cursor.pos));
        if (the_locking_inset == inset) {
            the_locking_inset->InsetButtonPress(bv,x-inset_x,y-inset_y,button);
            return;
        } else if (inset) {
            // otherwise unlock the_locking_inset and lock the new inset
-           inset_x = cx-top_x;
-           inset_y = cy;
-           inset_pos = actpos;
            the_locking_inset->InsetUnlock(bv);
-           the_locking_inset = inset;
-           the_locking_inset->Edit(bv, x - inset_x, y - inset_y, button);
+           inset_x = cursor.x - top_x + drawTextXOffset;
+           inset_y = cursor.y + drawTextYOffset;
+           inset->InsetButtonPress(bv, x-inset_x, y-inset_y, button);
+           inset->Edit(bv, x - inset_x, y - inset_y, button);
+           UpdateLocal(bv, true);
            return;
        }
        // otherwise only unlock the_locking_inset
        the_locking_inset->InsetUnlock(bv);
+       the_locking_inset = 0;
     }
-    HideInsetCursor(bv);
-    the_locking_inset = 0;
-    setPos(bv, x, y);
-    selection_start = selection_end = actpos;
-    if (!the_locking_inset)
-       ShowInsetCursor(bv);
+    if (bv->the_locking_inset) {
+       if ((par->GetChar(cursor.pos) == LyXParagraph::META_INSET) &&
+           par->GetInset(cursor.pos) &&
+           (par->GetInset(cursor.pos)->Editable() == Inset::HIGHLY_EDITABLE)) {
+           UpdatableInset *inset =
+               static_cast<UpdatableInset*>(par->GetInset(cursor.pos));
+           inset_x = cursor.x - top_x + drawTextXOffset;
+           inset_y = cursor.y + drawTextYOffset;
+           inset->InsetButtonPress(bv, x-inset_x, y-inset_y, button);
+           inset->Edit(bv, x-inset_x, y-inset_y, 0);
+           UpdateLocal(bv, true);
+       }
+    }
+    selection_start_cursor = selection_end_cursor = cursor;
 }
 
 
-void InsetText::InsetMotionNotify(BufferView * bv, int x, int y, int button)
+void InsetText::InsetButtonRelease(BufferView * bv, int x, int y, int button)
+{
+    UpdatableInset * inset = 0;
+
+    if (the_locking_inset) {
+           the_locking_inset->InsetButtonRelease(bv, x-inset_x, y-inset_y,button);
+    } else {
+       if (par->GetChar(cursor.pos) == LyXParagraph::META_INSET) {
+           inset = static_cast<UpdatableInset*>(par->GetInset(cursor.pos));
+           if (inset->Editable()==Inset::HIGHLY_EDITABLE) {
+               inset->InsetButtonRelease(bv, x-inset_x, y-inset_y,button);
+           } else {
+               inset_x = cursor.x - top_x + drawTextXOffset;
+               inset_y = cursor.y + drawTextYOffset;
+               inset->InsetButtonRelease(bv, x-inset_x, y-inset_y,button);
+               inset->Edit(bv, x-inset_x, y-inset_y, button);
+           }
+       }
+    }
+    no_selection = false;
+}
+
+
+void InsetText::InsetMotionNotify(BufferView * bv, int x, int y, int state)
 {
     if (the_locking_inset) {
         the_locking_inset->InsetMotionNotify(bv, x - inset_x,
-                                            y - inset_y,button);
+                                            y - inset_y,state);
         return;
     }
     if (!no_selection) {
-       int old = selection_end;
-       setPos(bv, x, y, false);
-       selection_end = actpos;
-       if (old != selection_end)
+       LyXCursor old = selection_end_cursor;
+       HideInsetCursor(bv);
+       setPos(bv->painter(), x, y);
+       selection_end_cursor = cursor;
+       if (old != selection_end_cursor)
            UpdateLocal(bv, false);
+       ShowInsetCursor(bv);
     }
     no_selection = false;
 }
@@ -425,31 +548,39 @@ InsetText::LocalDispatch(BufferView * bv,
                         int action, string const & arg)
 {
     no_selection = false;
-    if (UpdatableInset::LocalDispatch(bv, action, arg)) {
-       resetPos(bv);
+    UpdatableInset::RESULT
+        result= UpdatableInset::LocalDispatch(bv, action, arg);
+    if (result != UNDISPATCHED) {
+       resetPos(bv->painter());
        return DISPATCHED;
     }
 
-    UpdatableInset::RESULT
-        result=DISPATCHED;
-
+    result=DISPATCHED;
     if ((action < 0) && arg.empty())
         return FINISHED;
 
     if ((action != LFUN_DOWN) && (action != LFUN_UP) &&
         (action != LFUN_DOWNSEL) && (action != LFUN_UPSEL))
-        old_x = -1;
+        cursor.x_fix = -1;
     if (the_locking_inset) {
         result = the_locking_inset->LocalDispatch(bv, action, arg);
-       if (result == DISPATCHED) {
+       if (result == DISPATCHED_NOUPDATE)
+           return result;
+       else if (result == DISPATCHED) {
            the_locking_inset->ToggleInsetCursor(bv);
            UpdateLocal(bv, false);
            the_locking_inset->ToggleInsetCursor(bv);
             return result;
         } else if (result == FINISHED) {
-           if ((action == LFUN_RIGHT) || (action == -1)) {
-               actpos = inset_pos + 1;
-               resetPos(bv);
+           switch(action) {
+           case -1:
+           case LFUN_RIGHT:
+               cursor.pos = inset_pos + 1;
+               resetPos(bv->painter());
+               break;
+           case LFUN_DOWN:
+               moveDown(bv);
+               break;
            }
            the_locking_inset = 0;
            return DISPATCHED;
@@ -457,162 +588,255 @@ InsetText::LocalDispatch(BufferView * bv,
     }
     HideInsetCursor(bv);
     switch (action) {
-        // Normal chars
-      case -1:
-          par->InsertChar(actpos,arg[0]);
-         par->SetFont(actpos,real_current_font);
-         UpdateLocal(bv, true);
-          ++actpos;
-         selection_start = selection_end = actpos;
-          resetPos(bv);
-          break;
+       // Normal chars
+    case -1:
+       bv->text->SetUndo(Undo::INSERT, 
+           bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->previous,
+           bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->next);
+       cutSelection();
+       cursor = selection_start_cursor;
+       par->InsertChar(cursor.pos,arg[0]);
+       SetCharFont(cursor.pos,current_font);
+       ++cursor.pos;
+       selection_start_cursor = selection_end_cursor = cursor;
+       UpdateLocal(bv, true);
+       break;
         // --- Cursor Movements ---------------------------------------------
-      case LFUN_RIGHTSEL:
-          moveRight(bv, false);
-         selection_end = actpos;
-         UpdateLocal(bv, false);
-         break;
-      case LFUN_RIGHT:
-          result= DISPATCH_RESULT(moveRight(bv));
-         if (hasSelection()) {
-             selection_start = selection_end = actpos;
-             UpdateLocal(bv, false);
-         } else {
-             selection_start = selection_end = actpos;
-         }
-          break;
-      case LFUN_LEFTSEL:
-          moveLeft(bv, false);
-         selection_end = actpos;
-         UpdateLocal(bv, false);
-         break;
-      case LFUN_LEFT:
-          result= DISPATCH_RESULT(moveLeft(bv));
-         if (hasSelection()) {
-             selection_start = selection_end = actpos;
-             UpdateLocal(bv, false);
-         } else {
-             selection_start = selection_end = actpos;
-         }
-          break;
-      case LFUN_DOWNSEL:
-          moveDown(bv, false);
-         selection_end = actpos;
-         UpdateLocal(bv, false);
-         break;
-      case LFUN_DOWN:
-          result= DISPATCH_RESULT(moveDown(bv));
-         if (hasSelection()) {
-             selection_start = selection_end = actpos;
-             UpdateLocal(bv, false);
-         } else {
-             selection_start = selection_end = actpos;
-         }
-          break;
-      case LFUN_UPSEL:
-          moveUp(bv, false);
-         selection_end = actpos;
-         UpdateLocal(bv, false);
-         break;
-      case LFUN_UP:
-          result= DISPATCH_RESULT(moveUp(bv));
-         if (hasSelection()) {
-             selection_start = selection_end = actpos;
-             UpdateLocal(bv, false);
-         } else {
-             selection_start = selection_end = actpos;
-         }
-          break;
-      case LFUN_BACKSPACE:
-          if (!actpos || par->IsNewline(actpos-1)) {
-             if (hasSelection()) {
-                 selection_start = selection_end = actpos;
-                 UpdateLocal(bv, false);
-             }
-              break;
-         }
-          moveLeft(bv);
-      case LFUN_DELETE:
-          if (Delete()) { // we need update
-             selection_start = selection_end = actpos;
-             UpdateLocal(bv, true);
-          } else if (hasSelection()) {
-             selection_start = selection_end = actpos;
-             UpdateLocal(bv, false);
-         }
-          break;
-      case LFUN_HOME:
-          for(; actpos > rows[actrow].pos; --actpos)
-              cx -= SingleWidth(bv->getPainter(), par, actpos);
-         cx -= SingleWidth(bv->getPainter(), par, actpos);
-         if (hasSelection()) {
-             selection_start = selection_end = actpos;
-             UpdateLocal(bv, false);
-         } else {
-             selection_start = selection_end = actpos;
-         }
-          break;
-      case LFUN_END:
-          for(; actpos < rows[actrow + 1].pos; ++actpos)
-              cx += SingleWidth(bv->getPainter(), par, actpos);
-         if (hasSelection()) {
-             selection_start = selection_end = actpos;
-             UpdateLocal(bv, false);
-         } else {
-             selection_start = selection_end = actpos;
-         }
-          break;
-      case LFUN_MATH_MODE:   // Open or create a math inset
-          InsertInset(bv, new InsetFormula);
-         if (hasSelection()) {
-             selection_start = selection_end = actpos;
-             UpdateLocal(bv, false);
-         } else {
-             selection_start = selection_end = actpos;
-         }
-          return DISPATCHED;
-      default:
-          result = UNDISPATCHED;
-          break;
+    case LFUN_RIGHTSEL:
+       bv->text->FinishUndo();
+       moveRight(bv, false);
+       selection_end_cursor = cursor;
+       UpdateLocal(bv, false);
+       break;
+    case LFUN_RIGHT:
+       bv->text->FinishUndo();
+       result = moveRight(bv);
+       if (hasSelection()) {
+           selection_start_cursor = selection_end_cursor = cursor;
+           UpdateLocal(bv, false);
+       } else {
+           selection_start_cursor = selection_end_cursor = cursor;
+       }
+       break;
+    case LFUN_LEFTSEL:
+       bv->text->FinishUndo();
+       moveLeft(bv, false);
+       selection_end_cursor = cursor;
+       UpdateLocal(bv, false);
+       break;
+    case LFUN_LEFT:
+       bv->text->FinishUndo();
+       result= moveLeft(bv);
+       if (hasSelection()) {
+               selection_start_cursor = selection_end_cursor = cursor;
+               UpdateLocal(bv, false);
+       } else {
+               selection_start_cursor = selection_end_cursor = cursor;
+       }
+       break;
+    case LFUN_DOWNSEL:
+       bv->text->FinishUndo();
+       moveDown(bv);
+       selection_end_cursor = cursor;
+       UpdateLocal(bv, false);
+       break;
+    case LFUN_DOWN:
+       bv->text->FinishUndo();
+       result = moveDown(bv);
+       if (hasSelection()) {
+           selection_start_cursor = selection_end_cursor = cursor;
+           UpdateLocal(bv, false);
+       } else {
+           selection_start_cursor = selection_end_cursor = cursor;
+       }
+       break;
+    case LFUN_UPSEL:
+       bv->text->FinishUndo();
+       moveUp(bv);
+       selection_end_cursor = cursor;
+       UpdateLocal(bv, false);
+       break;
+    case LFUN_UP:
+       bv->text->FinishUndo();
+       result = moveUp(bv);
+       if (hasSelection()) {
+           selection_start_cursor = selection_end_cursor = cursor;
+           UpdateLocal(bv, false);
+       } else {
+           selection_start_cursor = selection_end_cursor = cursor;
+       }
+       break;
+    case LFUN_BACKSPACE:
+       if (!cursor.pos) {
+           if (hasSelection()) {
+               selection_start_cursor = selection_end_cursor = cursor;
+               UpdateLocal(bv, false);
+           }
+           break;
+       }
+       moveLeft(bv);
+    case LFUN_DELETE:
+    {
+       bv->text->SetUndo(Undo::DELETE, 
+           bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->previous,
+           bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->next);
+       bool ret = true;
+       if (hasSelection()) {
+           LyXParagraph::size_type i = selection_start_cursor.pos;
+           for (; i < selection_end_cursor.pos; ++i) {
+               par->Erase(selection_start_cursor.pos);
+           }
+       } else
+           ret = Delete();
+       if (ret) { // we need update
+           selection_start_cursor = selection_end_cursor = cursor;
+           UpdateLocal(bv, true);
+       } else if (hasSelection()) {
+           selection_start_cursor = selection_end_cursor = cursor;
+           UpdateLocal(bv, false);
+       }
+    }
+    resetPos(bv->painter());
+    break;
+    case LFUN_CUT:
+       bv->text->SetUndo(Undo::DELETE, 
+         bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->previous,
+         bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->next);
+
+       if (cutSelection()) {
+           // we need update
+           cursor = selection_end_cursor = selection_start_cursor;
+           UpdateLocal(bv, true);
+       } else if (hasSelection()) {
+           selection_start_cursor = selection_end_cursor = cursor;
+           UpdateLocal(bv, false);
+       }
+       resetPos(bv->painter());
+       break;
+    case LFUN_COPY:
+       bv->text->FinishUndo();
+       if (copySelection()) {
+           // we need update
+           selection_start_cursor = selection_end_cursor = cursor;
+           UpdateLocal(bv, true);
+       } else if (hasSelection()) {
+           selection_start_cursor = selection_end_cursor = cursor;
+           UpdateLocal(bv, false);
+       }
+       break;
+    case LFUN_PASTE:
+    {
+       bv->text->SetUndo(Undo::INSERT, 
+         bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->previous,
+         bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->next);
+       if (pasteSelection()) {
+           selection_start_cursor = selection_end_cursor = cursor;
+           UpdateLocal(bv, true);
+       }
+    }
+    resetPos(bv->painter());
+    break;
+    case LFUN_HOME:
+       bv->text->FinishUndo();
+       for(; cursor.pos > rows[actrow].pos; --cursor.pos)
+           cursor.x -= SingleWidth(bv->painter(), par, cursor.pos);
+       cursor.x -= SingleWidth(bv->painter(), par, cursor.pos);
+       if (hasSelection()) {
+           selection_start_cursor = selection_end_cursor = cursor;
+           UpdateLocal(bv, false);
+       } else {
+           selection_start_cursor = selection_end_cursor = cursor;
+       }
+       resetPos(bv->painter());
+       break;
+    case LFUN_END:
+    {
+       bv->text->FinishUndo();
+       int checkpos = (int)rows[actrow + 1].pos;
+       if ((actrow + 2) < (int)rows.size())
+           --checkpos;
+       for(; cursor.pos < checkpos; ++cursor.pos)
+           cursor.x += SingleWidth(bv->painter(), par, cursor.pos);
+       if (hasSelection()) {
+           selection_start_cursor = selection_end_cursor = cursor;
+           UpdateLocal(bv, false);
+       } else {
+           selection_start_cursor = selection_end_cursor = cursor;
+       }
+    }
+    resetPos(bv->painter());
+    break;
+    case LFUN_MATH_MODE:
+       InsertInset(bv, new InsetFormula);
+       return DISPATCHED;
+    case LFUN_INSET_ERT:
+       InsertInset(bv, new InsetERT(buffer));
+       return DISPATCHED;
+    case LFUN_BREAKPARAGRAPH:
+    case LFUN_BREAKLINE:
+       if (!autoBreakRows)
+           return DISPATCHED;
+       bv->text->SetUndo(Undo::INSERT, 
+           bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->previous,
+           bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->next);
+       par->InsertChar(cursor.pos,LyXParagraph::META_NEWLINE);
+       SetCharFont(cursor.pos,current_font);
+       UpdateLocal(bv, true);
+       ++cursor.pos;
+       selection_start_cursor = selection_end_cursor = cursor;
+       resetPos(bv->painter());
+       break;
+    case LFUN_LAYOUT:
+    {
+       // Derive layout number from given argument (string)
+       // and current buffer's textclass (number). */    
+       LyXTextClassList::ClassList::size_type tclass =
+           buffer->params.textclass;
+       std::pair <bool, LyXTextClass::size_type> layout = 
+           textclasslist.NumberOfLayout(tclass, arg);
+
+       // If the entry is obsolete, use the new one instead.
+       if (layout.first) {
+           string obs = textclasslist.Style(tclass,layout.second).
+               obsoleted_by();
+           if (!obs.empty()) 
+               layout = textclasslist.NumberOfLayout(tclass, obs);
+       }
+
+       // see if we found the layout number:
+       if (!layout.first) {
+           string msg = string(N_("Layout ")) + arg + N_(" not known");
+
+           bv->owner()->getMiniBuffer()->Set(msg);
+           break;
+       }
+
+       if (current_layout != layout.second) {
+           bv->text->SetLayout(cursor, selection_start_cursor,
+                               selection_end_cursor, layout.second);
+           bv->owner()->getToolbar()->combox->select(cursor.par->GetLayout()+1);
+           UpdateLocal(bv, true);
+       }
+    }
+    break;
+    default:
+       result = UNDISPATCHED;
+       break;
     }
     if (result != FINISHED) {
-       if (!the_locking_inset)
-           ShowInsetCursor(bv);
+       ShowInsetCursor(bv);
     } else
         bv->unlockInset(this);
     return result;
 }
 
 
-int InsetText::Latex(ostream & os, signed char /*fragile*/,
-#ifdef USE_OSTREAM_ONLY
-                    bool) const
-#else
-                    bool free_spc) const
-#endif
-{
-#ifdef USE_OSTREAM_ONLY
-       TexRow texrow;
-       int ret = par->SimpleTeXOnePar(os, texrow);
-       return ret;
-#else
-    string fstr;
-
-    int i = Latex(fstr, fragile, free_spc);
-    os << fstr;
-    return i;
-#endif
-}
-
-
-#ifndef USE_OSTREAM_ONLY
-int InsetText::Latex(string & file, signed char /* fragile */) const
+int InsetText::Latex(ostream & os, bool /*fragile*/, bool /*fp*/) const
 {
     TexRow texrow;
-
-    return par->SimpleTeXOnePar(file, texrow);
+    buffer->latexParagraphs(os, par, 0, texrow);
+    return texrow.rows();
 }
-#endif
 
 
 void InsetText::Validate(LaTeXFeatures & features) const
@@ -624,11 +848,11 @@ void InsetText::Validate(LaTeXFeatures & features) const
 // Returns the width of a character at a certain spot
 int InsetText::SingleWidth(Painter & pain, LyXParagraph * par, int pos) const
 {
-    LyXFont font = GetFont(par, pos);
+    LyXFont font = GetDrawFont(par, pos);
     char c = par->GetChar(pos);
 
     if (IsPrintable(c)) {
-        return font.width(c);
+        return lyxfont::width(c, font);
     } else if (c == LyXParagraph::META_INSET) {
         Inset const * tmpinset = par->GetInset(pos);
         if (tmpinset)
@@ -639,7 +863,7 @@ int InsetText::SingleWidth(Painter & pain, LyXParagraph * par, int pos) const
         c = ' ';
     else if (IsNewlineChar(c))
         c = 'n';
-    return font.width(c);
+    return lyxfont::width(c, font);
 }
 
 
@@ -647,7 +871,7 @@ int InsetText::SingleWidth(Painter & pain, LyXParagraph * par, int pos) const
 void InsetText::SingleHeight(Painter & pain, LyXParagraph * par,int pos,
                             int & asc, int & desc) const
 {
-    LyXFont font = GetFont(par, pos);
+    LyXFont font = GetDrawFont(par, pos);
     char c = par->GetChar(pos);
 
     asc = desc = 0;
@@ -658,8 +882,8 @@ void InsetText::SingleHeight(Painter & pain, LyXParagraph * par,int pos,
            desc = tmpinset->descent(pain, font);
         }
     } else {
-        asc = font.maxAscent();
-        desc = font.maxDescent();
+        asc = lyxfont::maxAscent(font);
+        desc = lyxfont::maxDescent(font);
     }
     return;
 }
@@ -738,6 +962,13 @@ LyXFont InsetText::GetFont(LyXParagraph * par, int pos) const
 }
 
 
+// the font for drawing may be different from the real font
+LyXFont InsetText::GetDrawFont(LyXParagraph * par, int pos) const
+{
+    return GetFont(par, pos);
+}
+
+
 int InsetText::BeginningOfMainBody(LyXParagraph * par) const
 {
     if (textclasslist.Style(buffer->params.textclass,
@@ -750,8 +981,8 @@ int InsetText::BeginningOfMainBody(LyXParagraph * par) const
 
 void InsetText::GetCursorPos(int & x, int & y) const
 {
-    x = cx;
-    y = cy;
+    x = cursor.x;
+    y = cursor.y;
 }
 
 
@@ -760,8 +991,7 @@ int InsetText::InsetInInsetY()
     if (!the_locking_inset)
        return 0;
 
-    int y = inset_y;
-    return (y + the_locking_inset->InsetInInsetY());
+    return (inset_y + the_locking_inset->InsetInInsetY());
 }
 
 
@@ -772,28 +1002,32 @@ void InsetText::ToggleInsetCursor(BufferView * bv)
         return;
     }
 
-    LyXFont font = GetFont(par, actpos);
+    LyXFont font = GetDrawFont(par, cursor.pos);
 
-    int asc = font.maxAscent();
-    int desc = font.maxDescent();
+    int asc = lyxfont::maxAscent(font);
+    int desc = lyxfont::maxDescent(font);
   
     if (cursor_visible)
         bv->hideLockedInsetCursor();
     else
-        bv->showLockedInsetCursor(cx, cy, asc, desc);
+        bv->showLockedInsetCursor(cursor.x, cursor.y, asc, desc);
     cursor_visible = !cursor_visible;
 }
 
 
 void InsetText::ShowInsetCursor(BufferView * bv)
 {
+    if (the_locking_inset) {
+       the_locking_inset->ShowInsetCursor(bv);
+       return;
+    }
     if (!cursor_visible) {
-       LyXFont font = GetFont(par, actpos);
+       LyXFont font = GetDrawFont(par, cursor.pos);
        
-       int asc = font.maxAscent();
-       int desc = font.maxDescent();
-       bv->fitLockedInsetCursor(cx, cy, asc, desc);
-       bv->showLockedInsetCursor(cx, cy, asc, desc);
+       int asc = lyxfont::maxAscent(font);
+       int desc = lyxfont::maxDescent(font);
+       bv->fitLockedInsetCursor(cursor.x, cursor.y, asc, desc);
+       bv->showLockedInsetCursor(cursor.x, cursor.y, asc, desc);
        cursor_visible = true;
     }
 }
@@ -801,165 +1035,162 @@ void InsetText::ShowInsetCursor(BufferView * bv)
 
 void InsetText::HideInsetCursor(BufferView * bv)
 {
-    if (cursor_visible)
-        ToggleInsetCursor(bv);
+    if (cursor_visible) {
+        bv->hideLockedInsetCursor();
+       cursor_visible = false;
+    }
+    if (the_locking_inset)
+       the_locking_inset->HideInsetCursor(bv);
 }
 
 
-void InsetText::setPos(BufferView * bv, int x, int y, bool activate_inset)
+void InsetText::setPos(Painter & pain, int x, int y) const
 {
-       int ox = x;
-       int oy = y;
-       
+    x -= drawTextXOffset;
+    y -= drawTextYOffset;
     // search right X-pos x==0 -> top_x
-    actpos = actrow = 0;
-    cy = top_baseline;
-    y += cy;
+    cursor.pos = actrow = 0;
+    cursor.y = top_baseline;
+    y += cursor.y;
     for(unsigned int i = 1;
-       ((cy + rows[i - 1].desc) < y) && (i < rows.size() - 1); ++i) {
-       cy = rows[i].baseline;
-       actpos = rows[i].pos;
+       (long(cursor.y + rows[i - 1].desc) < y)
+               && (i < rows.size() - 1); ++i) {
+       cursor.y = rows[i].baseline;
+       cursor.pos = rows[i].pos;
        actrow = i;
     }
-    cy -= top_baseline;
-    cx = top_x;
+    cursor.y -= top_baseline;
+    cursor.x = top_x;
     x += top_x;
 
     int swh;
-    int sw = swh = SingleWidth(bv->getPainter(), par,actpos);
-    if (par->GetChar(actpos)!=LyXParagraph::META_INSET)
+    int sw = swh = SingleWidth(pain, par,cursor.pos);
+    if (par->GetChar(cursor.pos)!=LyXParagraph::META_INSET)
        swh /= 2;
-    while ((actpos < (rows[actrow + 1].pos - 1)) && ((cx + swh) < x)) {
-       cx += sw;
-       ++actpos;
-       sw = swh = SingleWidth(bv->getPainter(), par,actpos);
-       if (par->GetChar(actpos)!=LyXParagraph::META_INSET)
+    int checkpos = rows[actrow + 1].pos;
+    if ((actrow+2) < (int)rows.size())
+       --checkpos;
+    while ((cursor.pos < checkpos) && ((cursor.x + swh) < x)) {
+       cursor.x += sw;
+       ++cursor.pos;
+       sw = swh = SingleWidth(pain, par,cursor.pos);
+       if (par->GetChar(cursor.pos)!=LyXParagraph::META_INSET)
            swh /= 2;
     }
-    if (activate_inset && par->GetChar(actpos)==LyXParagraph::META_INSET) {
-        the_locking_inset =
-               static_cast<UpdatableInset*>(par->GetInset(actpos));
-       inset_x = cx - top_x;
-       inset_y = cy;
-       inset_pos = actpos;
-        the_locking_inset->Edit(bv, ox - inset_x, oy - inset_y, 0);
-    }
 }
 
 
-bool InsetText::moveRight(BufferView * bv, bool activate_inset)
+void InsetText::resetPos(Painter & pain) const
 {
-    if (actpos >= par->Last())
-       return false;
-    if (activate_inset && par->GetChar(actpos)==LyXParagraph::META_INSET) {
-       the_locking_inset =
-               static_cast<UpdatableInset*>(par->GetInset(actpos));
-       inset_x = cx - top_x;
-       inset_y = cy;
-       inset_pos = actpos;
-       the_locking_inset->Edit(bv, 0, 0, 0);
-    } else {
-       ++actpos;
-       resetPos(bv);
+    cursor.par = par;
+
+    if (!rows.size())
+       return;
+
+    int old_pos = cursor.pos;
+
+    cursor.y = top_baseline;
+    actrow = 0;
+    for(unsigned int i = 0;
+       (i < (rows.size()-1)) && (rows[i].pos <= cursor.pos);
+       ++i) {
+       cursor.y = rows[i].baseline;
+       actrow = i;
+    }
+    cursor.y -= top_baseline;
+    setPos(pain, 0, cursor.y);
+    cursor.x = top_x;
+    while(cursor.pos < old_pos) {
+       cursor.x += SingleWidth(pain, par,cursor.pos);
+       ++cursor.pos;
     }
-    return true;
 }
 
 
-bool InsetText::moveLeft(BufferView * bv, bool activate_inset)
+UpdatableInset::RESULT
+InsetText::moveRight(BufferView * bv, bool activate_inset)
 {
-    if (actpos <= 0)
-       return false;
-    --actpos;
-    if (activate_inset && par->GetChar(actpos)==LyXParagraph::META_INSET) {
-       the_locking_inset =
-               static_cast<UpdatableInset*>(par->GetInset(actpos));
-       resetPos(bv);
-       inset_x = cx - top_x;
-       inset_y = cy;
-       inset_pos = actpos;
-       the_locking_inset->Edit(bv, the_locking_inset->
-                               width(bv->getPainter(), GetFont(par,actpos)),
-                               0, 0);
-    } else {
-       resetPos(bv);
+    if (cursor.pos >= par->Last())
+       return FINISHED;
+    if (activate_inset && checkAndActivateInset(bv)) {
+       return DISPATCHED;
     }
-    return true;
+    ++cursor.pos;
+    resetPos(bv->painter());
+    real_current_font = current_font = GetFont(par, cursor.pos);
+    return DISPATCHED_NOUPDATE;
 }
 
 
-bool InsetText::moveUp(BufferView * bv, bool activate_inset)
+UpdatableInset::RESULT
+InsetText::moveLeft(BufferView * bv, bool activate_inset)
 {
-    if (!actrow)
-       return false;
-    cy = rows[actrow - 1].baseline - top_baseline;
-    setPos(bv, cx - top_x, cy, activate_inset);
-    return true;
+    if (cursor.pos <= 0)
+       return FINISHED;
+    --cursor.pos;
+    resetPos(bv->painter());
+    if (activate_inset)
+       if (checkAndActivateInset(bv, -1, -1))
+           return DISPATCHED;
+    return DISPATCHED_NOUPDATE;
 }
 
 
-bool InsetText::moveDown(BufferView * bv, bool activate_inset)
+UpdatableInset::RESULT
+InsetText::moveUp(BufferView * bv)
 {
-    if (actrow >= int(rows.size() - 2))
-       return false;
-    cy = rows[actrow + 1].baseline - top_baseline;
-    setPos(bv, cx - top_x, cy, activate_inset);
-    return true;
+    if (!actrow)
+       return FINISHED;
+    cursor.y = rows[actrow - 1].baseline - top_baseline;
+    if (cursor.x_fix < 0)
+       cursor.x_fix = cursor.x;
+    setPos(bv->painter(), cursor.x_fix-top_x+drawTextXOffset, cursor.y);
+    return DISPATCHED_NOUPDATE;
 }
 
 
-void InsetText::resetPos(BufferView * bv)
+UpdatableInset::RESULT
+InsetText::moveDown(BufferView * bv)
 {
-    int old_pos = actpos;
-
-    cy = top_baseline;
-    actrow = 0;
-    for(int i = 0; rows[i].pos <= actpos; ++i) {
-       cy = rows[i].baseline;
-       actrow = i;
-    }
-    cy -= top_baseline;
-    setPos(bv, 0, cy, false);
-    cx = top_x;
-    while(actpos < old_pos) {
-       cx += SingleWidth(bv->getPainter(), par,actpos);
-       ++actpos;
-    }
+    if (actrow >= int(rows.size() - 2))
+       return FINISHED;
+    cursor.y = rows[actrow + 1].baseline - top_baseline;
+    if (cursor.x_fix < 0)
+       cursor.x_fix = cursor.x;
+    setPos(bv->painter(), cursor.x_fix-top_x+drawTextXOffset, cursor.y);
+    return DISPATCHED_NOUPDATE;
 }
 
 
 bool InsetText::Delete()
 {
-    /* some insets are undeletable here */
-    if (par->GetChar(actpos)==LyXParagraph::META_INSET) {
-        /* force complete redo when erasing display insets */ 
-        /* this is a cruel mathod but save..... Matthias */ 
-        if (par->GetInset(actpos)->Deletable() &&
-            par->GetInset(actpos)->display()) {
-            par->Erase(actpos);
-            return true;
-        }
-        return false;
+    if ((par->GetChar(cursor.pos)==LyXParagraph::META_INSET) &&
+       !par->GetInset(cursor.pos)->Deletable()) {
+       return false;
     }
-    par->Erase(actpos);
+    par->Erase(cursor.pos);
     return true;
 }
 
 
 bool InsetText::InsertInset(BufferView * bv, Inset * inset)
 {
+    bv->text->SetUndo(Undo::INSERT, 
+             bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->previous,
+             bv->text->cursor.par->ParFromPos(bv->text->cursor.pos)->next);
     if (inset->Editable() == Inset::IS_EDITABLE) {
        UpdatableInset *i = (UpdatableInset *)inset;
        i->setOwner((UpdatableInset *)this);
     }
-    par->InsertChar(actpos, LyXParagraph::META_INSET);
-    par->InsertInset(actpos, inset);
+    par->InsertChar(cursor.pos, LyXParagraph::META_INSET);
+    par->InsertInset(cursor.pos, inset);
+    if (hasSelection()) {
+       selection_start_cursor = selection_end_cursor = cursor;
+    } else {
+       selection_start_cursor = selection_end_cursor = cursor;
+    }
     UpdateLocal(bv, true);
-    the_locking_inset = static_cast<UpdatableInset*>(inset);
-    inset_x = cx - top_x;
-    inset_y = cy;
-    inset_pos = actpos;
-    inset->Edit(bv, 0, 0, 0);
+    static_cast<UpdatableInset*>(inset)->Edit(bv, 0, 0, 0);
     return true;
 }
 
@@ -976,13 +1207,14 @@ void InsetText::SetFont(BufferView * bv, LyXFont const & font, bool toggleall)
     if (!hasSelection()) {
        // Determine basis font
        LyXFont layoutfont;
-       if (actpos < BeginningOfMainBody(par))
+       if (cursor.pos < BeginningOfMainBody(par))
            layoutfont = GetFont(par, -2);
        else
            layoutfont = GetFont(par, -1);
        
        // Update current font
-       real_current_font.update(font, toggleall);
+       real_current_font.update(font, bv->buffer()->params.language_info,
+                                toggleall);
        
        // Reduce to implicit settings
        current_font = real_current_font;
@@ -993,17 +1225,17 @@ void InsetText::SetFont(BufferView * bv, LyXFont const & font, bool toggleall)
     }
     
     int s_start, s_end;
-    if (selection_start > selection_end) {
-       s_start = selection_end;
-       s_end = selection_start;
+    if (selection_start_cursor.pos > selection_end_cursor.pos) {
+       s_start = selection_end_cursor.pos;
+       s_end = selection_start_cursor.pos;
     } else {
-       s_start = selection_start;
-       s_end = selection_end;
+       s_start = selection_start_cursor.pos;
+       s_end = selection_end_cursor.pos;
     }
     LyXFont newfont;
     while(s_start < s_end) {
        newfont = GetFont(par,s_start);
-       newfont.update(font, toggleall);
+       newfont.update(font, bv->buffer()->params.language_info, toggleall);
        SetCharFont(s_start, newfont);
        ++s_start;
     }
@@ -1080,10 +1312,9 @@ void InsetText::computeTextRows(Painter & pain, float x) const
     }
 
     bool is_first_word_in_row = true;
-
     int cw, lastWordWidth = 0;
+    int maxWidth = getMaxTextWidth(pain, this, x);
 
-    maxWidth = UpdatableInset::getMaxWidth(pain) - widthOffset;
     for(p = 0; p < par->Last(); ++p) {
        cw = SingleWidth(pain, par, p);
        width += cw;
@@ -1091,12 +1322,8 @@ void InsetText::computeTextRows(Painter & pain, float x) const
        SingleHeight(pain, par, p, asc, desc);
        wordAscent = max(wordAscent, asc);
        wordDescent = max(wordDescent, desc);
-       Inset const * inset = 0;
-       if (((p + 1) < par->Last()) &&
-           (par->GetChar(p + 1)==LyXParagraph::META_INSET))
-           inset = par->GetInset(p + 1);
-       if (inset && inset->display()) {
-           if (!is_first_word_in_row && (width >= (maxWidth - x))) {
+       if (par->IsNewline(p)) {
+           if (!is_first_word_in_row && (width >= maxWidth)) {
                // we have to split also the row above
                rows.back().asc = oasc;
                rows.back().desc = odesc;
@@ -1107,26 +1334,57 @@ void InsetText::computeTextRows(Painter & pain, float x) const
                insetWidth = max(insetWidth, owidth);
                width = lastWordWidth;
                lastWordWidth = 0;
-           } else {
-                   oasc = max(oasc, wordAscent);
-                   odesc = max(odesc, wordDescent);
            }
-           rows.back().asc = oasc;
-           rows.back().desc = odesc;
+           rows.back().asc = wordAscent;
+           rows.back().desc = wordDescent;
            row.pos = ++p;
            rows.push_back(row);
-           SingleHeight(pain, par, p, asc, desc);
-           rows.back().asc = asc;
-           rows.back().desc = desc;
-           row.pos = nwp = p + 1;
-           rows.push_back(row);
-           oasc = odesc = width = lastWordWidth = 0;
+           SingleHeight(pain, par, p, oasc, odesc);
+           insetWidth = max(insetWidth, owidth);
+           width = 0;
            is_first_word_in_row = true;
-           wordAscent = wordDescent = 0;
-//         x = 0.0;
+           wordAscent = wordDescent = lastWordWidth = 0;
+           nwp = p;
            continue;
+       }
+       Inset * inset = 0;
+       if (((p + 1) < par->Last()) &&
+           (par->GetChar(p + 1)==LyXParagraph::META_INSET))
+           inset = par->GetInset(p + 1);
+       if (inset) {
+               inset->setOwner(const_cast<InsetText*>(this)); // is this safe?
+           if (inset->display()) {
+               if (!is_first_word_in_row && (width >= maxWidth)) {
+                   // we have to split also the row above
+                   rows.back().asc = oasc;
+                   rows.back().desc = odesc;
+                   row.pos = nwp;
+                   rows.push_back(row);
+                   oasc = wordAscent;
+                   odesc = wordDescent;
+                   insetWidth = max(insetWidth, owidth);
+                   width = lastWordWidth;
+                   lastWordWidth = 0;
+               } else {
+                   oasc = max(oasc, wordAscent);
+                   odesc = max(odesc, wordDescent);
+               }
+               rows.back().asc = oasc;
+               rows.back().desc = odesc;
+               row.pos = ++p;
+               rows.push_back(row);
+               SingleHeight(pain, par, p, asc, desc);
+               rows.back().asc = asc;
+               rows.back().desc = desc;
+               row.pos = nwp = p + 1;
+               rows.push_back(row);
+               oasc = odesc = width = lastWordWidth = 0;
+               is_first_word_in_row = true;
+               wordAscent = wordDescent = 0;
+               continue;
+           }
        } else if (par->IsSeparator(p)) {
-           if (width >= maxWidth - x) {
+           if (width >= maxWidth) {
                if (is_first_word_in_row) {
                    rows.back().asc = wordAscent;
                    rows.back().desc = wordDescent;
@@ -1145,7 +1403,6 @@ void InsetText::computeTextRows(Painter & pain, float x) const
                }
                wordAscent = wordDescent = lastWordWidth = 0;
                nwp = p + 1;
-//             x = 0.0;
                continue;
            }
            owidth = width;
@@ -1158,7 +1415,7 @@ void InsetText::computeTextRows(Painter & pain, float x) const
     }
     // if we have some data in the paragraph we have ascent/descent
     if (p) {
-       if (width >= (maxWidth - x)) {
+       if (width >= maxWidth) {
            // assign upper row
            rows.back().asc = oasc;
            rows.back().desc = odesc;
@@ -1170,8 +1427,6 @@ void InsetText::computeTextRows(Painter & pain, float x) const
            width -= lastWordWidth;
        } else {
            // assign last row data
-//         width = lastWordWidth;
-//         lastWordWidth = 0;
            rows.back().asc = max(oasc, wordAscent);
            rows.back().desc = max(odesc, wordDescent);
        }
@@ -1186,15 +1441,6 @@ void InsetText::computeTextRows(Painter & pain, float x) const
     for (RowList::size_type i = 1; i < rows.size() - 1; ++i) {
        maxDescent += rows[i].asc + rows[i].desc + interline_space;
     }
-#if 0
-    if (the_locking_inset) {
-       computeBaselines(top_baseline);
-       actpos = inset_pos;
-       resetPos(bv);
-       inset_x = cx - top_x;
-       inset_y = cy;
-    }
-#endif
 }
 
 
@@ -1207,8 +1453,112 @@ void InsetText::computeBaselines(int baseline) const
     }
 }
 
-void InsetText::UpdateLocal(BufferView *bv, bool flag)
+
+void InsetText::UpdateLocal(BufferView * bv, bool flag)
 {
-    init_inset = flag;
+    if (flag) {
+       computeTextRows(bv->painter(), xpos);
+       computeBaselines(top_baseline);
+    }
     bv->updateInset(this, flag);
+    if (flag)
+       resetPos(bv->painter());
+    bv->owner()->getToolbar()->combox->select(cursor.par->GetLayout()+1);
+}
+
+
+bool InsetText::cutSelection()
+{
+    if (!hasSelection())
+       return false;
+
+    CutAndPaste cap;
+
+    LyXParagraph * endpar = par;
+    int start, end;
+    if (selection_start_cursor.pos > selection_end_cursor.pos) {
+           start = selection_end_cursor.pos;
+           end = selection_start_cursor.pos;
+    } else {
+           start = selection_start_cursor.pos;
+           end = selection_end_cursor.pos;
+    }
+
+    return cap.cutSelection(par, &endpar, start, end,buffer->params.textclass);
+}
+
+
+bool InsetText::copySelection()
+{
+    if (!hasSelection())
+       return false;
+
+    CutAndPaste cap;
+
+    int start, end;
+    if (selection_start_cursor.pos > selection_end_cursor.pos) {
+           start = selection_end_cursor.pos;
+           end = selection_start_cursor.pos;
+    } else {
+           start = selection_start_cursor.pos;
+           end = selection_end_cursor.pos;
+    }
+    return cap.copySelection(par, par, start, end, buffer->params.textclass);
+}
+
+
+bool InsetText::pasteSelection()
+{
+    CutAndPaste cap;
+
+    if (cap.nrOfParagraphs() > 1) {
+       WriteAlert(_("Impossible operation"),
+                  _("Cannot include more than one paragraph!"),
+                  _("Sorry."));
+       return false;
+    }
+    LyXParagraph *endpar;
+    LyXParagraph *actpar = par;
+
+    return cap.pasteSelection(&actpar, &endpar, cursor.pos,
+                             buffer->params.textclass);
+}
+
+
+bool InsetText::checkAndActivateInset(BufferView * bv, int x, int y,
+                                     int button)
+{
+    if (par->GetChar(cursor.pos) == LyXParagraph::META_INSET) {
+       UpdatableInset * inset =
+           static_cast<UpdatableInset*>(par->GetInset(cursor.pos));
+       LyXFont font = GetFont(par, cursor.pos);
+       if (x < 0)
+           x = inset->width(bv->painter(), font);
+       if (y < 0)
+           y = inset->descent(bv->painter(), font);
+       inset_x = cursor.x - top_x + drawTextXOffset;
+       inset_y = cursor.y + drawTextYOffset;
+       inset->Edit(bv, x-inset_x, y-inset_y, button);
+       if (!the_locking_inset)
+           return false;
+       UpdateLocal(bv, true);
+       return true;
+    }
+    return false;
+}
+
+
+int InsetText::getMaxTextWidth(Painter & pain, UpdatableInset const * inset,
+                              int x) const
+{
+    return getMaxWidth(pain, inset) - x;
+}
+
+void InsetText::SetParagraphData(LyXParagraph *p)
+{
+    if (par)
+       delete par;
+    par = p->Clone();
+    par->SetInsetOwner(this);
+    init_inset = true;
 }