]> git.lyx.org Git - lyx.git/blobdiff - src/insets/insettext.C
Revert this change as it sneaked in and wasn't discussed yet.
[lyx.git] / src / insets / insettext.C
index b0e85b677eaff165305f293a48f2d51f0b571164..c4062bdba881a83ec654e4b534fedb05db367e3a 100644 (file)
@@ -187,7 +187,7 @@ void InsetText::init(InsetText const * ins, bool same_id)
        insetDescent = 0;
        insetWidth = 0;
        old_max_width = 0;
-       no_selection = false;
+       no_selection = true;
        need_update = FULL;
        drawTextXOffset = 0;
        drawTextYOffset = 0;
@@ -424,8 +424,8 @@ void InsetText::draw(BufferView * bv, LyXFont const & f,
 
        if (the_locking_inset && (cpar(bv) == inset_par)
                && (cpos(bv) == inset_pos)) {
-               inset_x = cx(bv) - top_x + drawTextXOffset;
-               inset_y = cy(bv) + drawTextYOffset;
+               inset_x = cix(bv) - top_x + drawTextXOffset;
+               inset_y = ciy(bv) + drawTextYOffset;
        }
        if (!cleared && (need_update == CURSOR)
            && !getLyXText(bv)->selection.set()) {
@@ -451,15 +451,35 @@ void InsetText::draw(BufferView * bv, LyXFont const & f,
                first += row->height();
                row = row->next();
        }
-       if (y_offset < 0)
-               y_offset = y;
-       lt->first_y = first;
+       if (y_offset < 0) {
+               lt->first_y = -y_offset;
+               first = y;
+               y_offset = 0;
+       } else {
+               lt->first_y = first;
+               first = 0;
+       }
        if (cleared || (need_update&(INIT|FULL))) {
-               int yf = y_offset;
+               int yf = y_offset + first;
                y = 0;
                while ((row != 0) && (yf < ph)) {
-                       lt->getVisibleRow(bv, y+y_offset, int(x), row,
-                                               y+first, cleared);
+                       lt->getVisibleRow(bv, y + y_offset + first, int(x),
+                                         row, y + lt->first_y, cleared);
+                       if (bv->text->status() == LyXText::CHANGED_IN_DRAW) {
+                               lt->need_break_row = row;
+                               lt->fullRebreak(bv);
+                               lt->setCursor(bv, lt->cursor.par(),
+                                             lt->cursor.pos());
+                               if (lt->selection.set()) {
+                                       lt->setCursor(bv, lt->selection.start,
+                                                     lt->selection.start.par(),
+                                                     lt->selection.start.pos());
+                                       lt->setCursor(bv, lt->selection.end,
+                                                     lt->selection.end.par(),
+                                                     lt->selection.end.pos());
+                               }
+                               break;
+                       }
                        y += row->height();
                        yf += row->height();
                        row = row->next();
@@ -553,9 +573,13 @@ void InsetText::update(BufferView * bv, LyXFont const & font, bool reinit)
                in_update = false;
                return;
        }
+
+       if (!autoBreakRows && par->next())
+               collapseParagraphs(bv);
+
        if (the_locking_inset) {
-               inset_x = cx(bv) - top_x + drawTextXOffset;
-               inset_y = cy(bv) + drawTextYOffset;
+               inset_x = cix(bv) - top_x + drawTextXOffset;
+               inset_y = ciy(bv) + drawTextYOffset;
                the_locking_inset->update(bv, font, reinit);
        }
 
@@ -606,7 +630,7 @@ void InsetText::setUpdateStatus(BufferView * bv, int what) const
 void InsetText::updateLocal(BufferView * bv, int what, bool mark_dirty) const
 {
        if (!autoBreakRows && par->next())
-               collapseParagraphs(bv->buffer()->params);
+               collapseParagraphs(bv);
        bool clear = false;
        if (!lt) {
                lt = getLyXText(bv);
@@ -614,16 +638,24 @@ void InsetText::updateLocal(BufferView * bv, int what, bool mark_dirty) const
        }
        lt->fullRebreak(bv);
        setUpdateStatus(bv, what);
-       bool flag = (((need_update != CURSOR) && (need_update != NONE)) ||
-                    (lt->status() != LyXText::UNCHANGED) || lt->selection.set());
+       bool flag = mark_dirty ||
+               (((need_update != CURSOR) && (need_update != NONE)) ||
+                (lt->status() != LyXText::UNCHANGED) || lt->selection.set());
        if (!lt->selection.set())
                lt->selection.cursor = lt->cursor;
        if (clear)
                lt = 0;
+#if 0
+       // IMO this is not anymore needed as we do this in fitInsetCursor!
+       // and we always get "true" as returnvalue of this function in the
+       // case of a locking inset (Jug 20020412)
+       if (locked && (need_update & CURSOR) && bv->fitCursor())
+               need_update |= FULL;
+#else
+       bv->fitCursor();
+#endif
        if (flag)
                bv->updateInset(const_cast<InsetText *>(this), mark_dirty);
-       else
-               bv->fitCursor();
 
        if (need_update == CURSOR)
                need_update = NONE;
@@ -663,9 +695,11 @@ void InsetText::edit(BufferView * bv, int x, int y, unsigned int button)
                lt = getLyXText(bv);
                clear = true;
        }
-       if (!checkAndActivateInset(bv, x, tmp_y, button))
+       if (!checkAndActivateInset(bv, x, tmp_y, button)) {
                lt->setCursorFromCoordinates(bv, x - drawTextXOffset,
                                            y + insetAscent);
+               lt->cursor.x_fix(lt->cursor.x());
+       }
        lt->clearSelection();
        finishUndo();
        // If the inset is empty set the language of the current font to the
@@ -677,7 +711,6 @@ void InsetText::edit(BufferView * bv, int x, int y, unsigned int button)
                font.setLanguage(bv->getParentLanguage(this));
                setFont(bv, font, false);
        }
-//     showInsetCursor(bv);
        if (clear)
                lt = 0;
 
@@ -685,6 +718,7 @@ void InsetText::edit(BufferView * bv, int x, int y, unsigned int button)
        if (drawFrame_ == LOCKED)
                code = CURSOR|DRAW_FRAME;
        updateLocal(bv, code, false);
+       showInsetCursor(bv);
 
        // Tell the paragraph dialog that we've entered an insettext.
        bv->owner()->getDialogs()->updateParagraph();
@@ -729,13 +763,13 @@ void InsetText::edit(BufferView * bv, bool front)
                font.setLanguage(bv->getParentLanguage(this));
                setFont(bv, font, false);
        }
-//     showInsetCursor(bv);
        if (clear)
                lt = 0;
        int code = CURSOR;
        if (drawFrame_ == LOCKED)
                code = CURSOR|DRAW_FRAME;
        updateLocal(bv, code, false);
+       showInsetCursor(bv);
 }
 
 
@@ -744,15 +778,21 @@ void InsetText::insetUnlock(BufferView * bv)
        if (the_locking_inset) {
                the_locking_inset->insetUnlock(bv);
                the_locking_inset = 0;
+               updateLocal(bv, CURSOR_PAR, false);
        }
        hideInsetCursor(bv);
-       no_selection = false;
+       no_selection = true;
        locked = false;
-       int code;
+       int code = NONE;
+#if 0
        if (drawFrame_ == LOCKED)
                code = CURSOR|CLEAR_FRAME;
        else
                code = CURSOR;
+#else
+       if (drawFrame_ == LOCKED)
+               code = CLEAR_FRAME;
+#endif
        bool clear = false;
        if (!lt) {
                lt = getLyXText(bv);
@@ -774,14 +814,53 @@ void InsetText::insetUnlock(BufferView * bv)
        }
        if (clear)
                lt = 0;
+#if 0
        updateLocal(bv, code, false);
+#else
+       if (code != NONE)
+               setUpdateStatus(bv, code);
+#endif
 }
 
+
+void InsetText::lockInset(BufferView * bv)
+{
+       locked = true;
+       the_locking_inset = 0;
+       inset_pos = inset_x = inset_y = 0;
+       inset_boundary = false;
+       inset_par = 0;
+       old_par = 0;
+       bool clear = false;
+       if (!lt) {
+               lt = getLyXText(bv);
+               clear = true;
+       }
+       lt->setCursor(bv, par, 0);
+       lt->clearSelection();
+       finishUndo();
+       // If the inset is empty set the language of the current font to the
+       // language to the surronding text (if different).
+       if (par->size() == 0 && !par->next() &&
+               bv->getParentLanguage(this) != lt->current_font.language()) {
+               LyXFont font(LyXFont::ALL_IGNORE);
+               font.setLanguage(bv->getParentLanguage(this));
+               setFont(bv, font, false);
+       }
+       if (clear)
+               lt = 0;
+       int code = CURSOR;
+       if (drawFrame_ == LOCKED)
+               code = CURSOR|DRAW_FRAME;
+       setUpdateStatus(bv, code);
+}
+
+
 void InsetText::lockInset(BufferView * bv, UpdatableInset * inset)
 {
        the_locking_inset = inset;
-       inset_x = cx(bv) - top_x + drawTextXOffset;
-       inset_y = cy(bv) + drawTextYOffset;
+       inset_x = cix(bv) - top_x + drawTextXOffset;
+       inset_y = ciy(bv) + drawTextYOffset;
        inset_pos = cpos(bv);
        inset_par = cpar(bv);
        inset_boundary = cboundary(bv);
@@ -826,8 +905,8 @@ bool InsetText::lockInsetInInset(BufferView * bv, UpdatableInset * inset)
        } else if (the_locking_inset && (the_locking_inset == inset)) {
                if (cpar(bv) == inset_par && cpos(bv) == inset_pos) {
                        lyxerr[Debug::INSETS] << "OK" << endl;
-                       inset_x = cx(bv) - top_x + drawTextXOffset;
-                       inset_y = cy(bv) + drawTextYOffset;
+                       inset_x = cix(bv) - top_x + drawTextXOffset;
+                       inset_y = ciy(bv) + drawTextYOffset;
                } else {
                        lyxerr[Debug::INSETS] << "cursor.pos != inset_pos" << endl;
                }
@@ -865,7 +944,7 @@ bool InsetText::unlockInsetInInset(BufferView * bv, UpdatableInset * inset,
 bool InsetText::updateInsetInInset(BufferView * bv, Inset * inset)
 {
        if (!autoBreakRows && par->next())
-               collapseParagraphs(bv->buffer()->params);
+               collapseParagraphs(bv);
        if (inset == this)
                return true;
        bool clear = false;
@@ -904,8 +983,8 @@ bool InsetText::updateInsetInInset(BufferView * bv, Inset * inset)
                if (the_locking_inset &&
                    cpar(bv) == inset_par && cpos(bv) == inset_pos)
                {
-                       inset_x = cx(bv) - top_x + drawTextXOffset;
-                       inset_y = cy(bv) + drawTextYOffset;
+                       inset_x = cix(bv) - top_x + drawTextXOffset;
+                       inset_y = ciy(bv) + drawTextYOffset;
                }
        }
        return found;
@@ -920,6 +999,9 @@ void InsetText::insetButtonPress(BufferView * bv, int x, int y, int button)
        mouse_x = x;
        mouse_y = y;
 
+       if (!locked)
+               lockInset(bv);
+
        int tmp_x = x - drawTextXOffset;
        int tmp_y = y + insetAscent - getLyXText(bv)->first_y;
        Inset * inset = bv->checkInsetHit(getLyXText(bv), tmp_x, tmp_y);
@@ -931,41 +1013,41 @@ void InsetText::insetButtonPress(BufferView * bv, int x, int y, int button)
                                                            x - inset_x,
                                                            y - inset_y,
                                                            button);
-                       no_selection = false;
                        return;
-               } else if (inset) {
+               }
+#if 0
+               else if (inset) {
                        // otherwise unlock the_locking_inset and lock the new inset
                        the_locking_inset->insetUnlock(bv);
-                       inset_x = cx(bv) - top_x + drawTextXOffset;
-                       inset_y = cy(bv) + drawTextYOffset;
+                       inset_x = cix(bv) - top_x + drawTextXOffset;
+                       inset_y = ciy(bv) + drawTextYOffset;
                        the_locking_inset = 0;
                        inset->insetButtonPress(bv, x - inset_x,
                                                y - inset_y, button);
 //                     inset->edit(bv, x - inset_x, y - inset_y, button);
                        if (the_locking_inset)
                                updateLocal(bv, CURSOR, false);
-                       no_selection = false;
                        return;
                }
+#endif
                // otherwise only unlock the_locking_inset
                the_locking_inset->insetUnlock(bv);
                the_locking_inset = 0;
        }
+       if (!inset)
+               no_selection = false;
+
        if (bv->theLockingInset()) {
                if (isHighlyEditableInset(inset)) {
+                       // We just have to lock the inset before calling a
+                       // PressEvent on it!
                        UpdatableInset * uinset = static_cast<UpdatableInset*>(inset);
-                       inset_x = cx(bv) - top_x + drawTextXOffset;
-                       inset_y = cy(bv) + drawTextYOffset;
-                       inset_pos = cpos(bv);
-                       inset_par = cpar(bv);
-                       inset_boundary = cboundary(bv);
-                       the_locking_inset = uinset;
-                       uinset->insetButtonPress(bv, x - inset_x, y - inset_y,
-                                                button);
-                       uinset->edit(bv, x - inset_x, y - inset_y, 0);
+                       if (!bv->lockInset(uinset)) {
+                               lyxerr[Debug::INSETS] << "Cannot lock inset" << endl;
+                       }
+                       inset->insetButtonPress(bv, x - inset_x, y - inset_y, button);
                        if (the_locking_inset)
                                updateLocal(bv, CURSOR, false);
-                       no_selection = false;
                        return;
                }
        }
@@ -980,6 +1062,7 @@ void InsetText::insetButtonPress(BufferView * bv, int x, int y, int button)
                        lt = getLyXText(bv);
                        clear = true;
                }
+               int old_first_y = lt->first_y;
 
                lt->setCursorFromCoordinates(bv, x - drawTextXOffset,
                                             y + insetAscent);
@@ -999,6 +1082,9 @@ void InsetText::insetButtonPress(BufferView * bv, int x, int y, int button)
                        updateLocal(bv, CURSOR, false);
                }
                bv->owner()->setLayout(cpar(bv)->layout());
+               // we moved the view we cannot do mouse selection in this case!
+               if (getLyXText(bv)->first_y != old_first_y)
+                       no_selection = true;
                old_par = cpar(bv);
                // Insert primary selection with middle mouse
                // if there is a local selection in the current buffer,
@@ -1014,12 +1100,12 @@ void InsetText::insetButtonPress(BufferView * bv, int x, int y, int button)
                getLyXText(bv)->clearSelection();
        }
        showInsetCursor(bv);
-       no_selection = false;
 }
 
 
 bool InsetText::insetButtonRelease(BufferView * bv, int x, int y, int button)
 {
+       no_selection = true;
        if (the_locking_inset) {
                return the_locking_inset->insetButtonRelease(bv,
                                                             x - inset_x, y - inset_y,
@@ -1034,8 +1120,8 @@ bool InsetText::insetButtonRelease(BufferView * bv, int x, int y, int button)
                        ret = inset->insetButtonRelease(bv, x - inset_x,
                                                        y - inset_y, button);
                } else {
-                       inset_x = cx(bv) - top_x + drawTextXOffset;
-                       inset_y = cy(bv) + drawTextYOffset;
+                       inset_x = cix(bv) - top_x + drawTextXOffset;
+                       inset_y = ciy(bv) + drawTextYOffset;
                        ret = inset->insetButtonRelease(bv, x - inset_x,
                                                        y - inset_y, button);
                        inset->edit(bv, x - inset_x,
@@ -1049,13 +1135,15 @@ bool InsetText::insetButtonRelease(BufferView * bv, int x, int y, int button)
 
 void InsetText::insetMotionNotify(BufferView * bv, int x, int y, int state)
 {
-       if (no_selection || ((mouse_x == x) && (mouse_y == y)))
-               return;
        if (the_locking_inset) {
                the_locking_inset->insetMotionNotify(bv, x - inset_x,
                                                     y - inset_y,state);
                return;
        }
+
+       if (no_selection || ((mouse_x == x) && (mouse_y == y)))
+               return;
+
        bool clear = false;
        if (!lt) {
                lt = getLyXText(bv);
@@ -1064,6 +1152,7 @@ void InsetText::insetMotionNotify(BufferView * bv, int x, int y, int state)
        hideInsetCursor(bv);
        LyXCursor cur = lt->cursor;
        lt->setCursorFromCoordinates(bv, x - drawTextXOffset, y + insetAscent);
+       lt->cursor.x_fix(lt->cursor.x());
        if (cur == lt->cursor) {
                if (clear)
                        lt = 0;
@@ -1139,6 +1228,7 @@ InsetText::localDispatch(BufferView * bv,
 #ifdef WITH_WARNINGS
 #warning I changed this to always return Dispatched maybe it is wrong (20011001 Jug)
 #endif
+                       updateLocal(bv, CURSOR, false);
                        return result;
                }
        }
@@ -1178,7 +1268,7 @@ InsetText::localDispatch(BufferView * bv,
                        }
                }
                lt->selection.cursor = lt->cursor;
-               updwhat = CURSOR_PAR;
+               updwhat = CURSOR | CURSOR_PAR;
                updflag = true;
                result = DISPATCHED_NOUPDATE;
                break;
@@ -1314,7 +1404,7 @@ InsetText::localDispatch(BufferView * bv,
                        break;
                }
                lt->breakParagraph(bv, 0);
-               updwhat = FULL;
+               updwhat = CURSOR | FULL;
                updflag = true;
                break;
        case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
@@ -1323,7 +1413,7 @@ InsetText::localDispatch(BufferView * bv,
                        break;
                }
                lt->breakParagraph(bv, 1);
-               updwhat = FULL;
+               updwhat = CURSOR | FULL;
                updflag = true;
                break;
 
@@ -1335,7 +1425,7 @@ InsetText::localDispatch(BufferView * bv,
                setUndo(bv, Undo::INSERT,
                        lt->cursor.par(), lt->cursor.par()->next());
                lt->insertChar(bv, Paragraph::META_NEWLINE);
-               updwhat = CURSOR_PAR;
+               updwhat = CURSOR | CURSOR_PAR;
                updflag = true;
        }
        break;
@@ -1446,6 +1536,9 @@ InsetText::localDispatch(BufferView * bv,
 
        if (result >= FINISHED)
                bv->unlockInset(this);
+
+       if (result == DISPATCHED_NOUPDATE && (need_update & FULL))
+               result = DISPATCHED;
        return result;
 }
 
@@ -1678,19 +1771,18 @@ int InsetText::beginningOfMainBody(Buffer const * buf, Paragraph * p) const
 }
 
 
-void InsetText::getCursorPos(BufferView * bv,
-                            int & x, int & y) const
+void InsetText::getCursorPos(BufferView * bv, int & x, int & y) const
 {
        if (the_locking_inset) {
                the_locking_inset->getCursorPos(bv, x, y);
                return;
        }
-       x = cx(bv);
-       y = cy(bv);
+       x = cx(bv) - top_x - TEXT_TO_INSET_OFFSET;
+       y = cy(bv) - TEXT_TO_INSET_OFFSET;
 }
 
 
-unsigned int InsetText::insetInInsetY()
+int InsetText::insetInInsetY() const
 {
        if (!the_locking_inset)
                return 0;
@@ -1763,7 +1855,8 @@ void InsetText::fitInsetCursor(BufferView * bv) const
        int const asc = lyxfont::maxAscent(font);
        int const desc = lyxfont::maxDescent(font);
 
-       bv->fitLockedInsetCursor(cx(bv), cy(bv), asc, desc);
+       if (bv->fitLockedInsetCursor(cx(bv), cy(bv), asc, desc))
+               need_update |= FULL;
 }
 
 
@@ -1771,9 +1864,9 @@ UpdatableInset::RESULT
 InsetText::moveRight(BufferView * bv, bool activate_inset, bool selecting)
 {
        if (getLyXText(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
-               return moveLeftIntern(bv, false, activate_inset, selecting);
+               return moveLeftIntern(bv, true, activate_inset, selecting);
        else
-               return moveRightIntern(bv, false, activate_inset, selecting);
+               return moveRightIntern(bv, true, activate_inset, selecting);
 }
 
 
@@ -1781,19 +1874,19 @@ UpdatableInset::RESULT
 InsetText::moveLeft(BufferView * bv, bool activate_inset, bool selecting)
 {
        if (getLyXText(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params))
-               return moveRightIntern(bv, true, activate_inset, selecting);
+               return moveRightIntern(bv, false, activate_inset, selecting);
        else
-               return moveLeftIntern(bv, true, activate_inset, selecting);
+               return moveLeftIntern(bv, false, activate_inset, selecting);
 }
 
 
 UpdatableInset::RESULT
-InsetText::moveRightIntern(BufferView * bv, bool behind,
+InsetText::moveRightIntern(BufferView * bv, bool front,
                           bool activate_inset, bool selecting)
 {
        if (!cpar(bv)->next() && (cpos(bv) >= cpar(bv)->size()))
                return FINISHED_RIGHT;
-       if (activate_inset && checkAndActivateInset(bv, behind))
+       if (activate_inset && checkAndActivateInset(bv, front))
                return DISPATCHED;
        getLyXText(bv)->cursorRight(bv);
        if (!selecting)
@@ -1803,7 +1896,7 @@ InsetText::moveRightIntern(BufferView * bv, bool behind,
 
 
 UpdatableInset::RESULT
-InsetText::moveLeftIntern(BufferView * bv, bool behind,
+InsetText::moveLeftIntern(BufferView * bv, bool front,
                          bool activate_inset, bool selecting)
 {
        if (!cpar(bv)->previous() && (cpos(bv) <= 0))
@@ -1811,7 +1904,7 @@ InsetText::moveLeftIntern(BufferView * bv, bool behind,
        getLyXText(bv)->cursorLeft(bv);
        if (!selecting)
                getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor;
-       if (activate_inset && checkAndActivateInset(bv, behind))
+       if (activate_inset && checkAndActivateInset(bv, front))
                return DISPATCHED;
        return DISPATCHED_NOUPDATE;
 }
@@ -1844,21 +1937,11 @@ bool InsetText::insertInset(BufferView * bv, Inset * inset)
                        return the_locking_inset->insertInset(bv, inset);
                return false;
        }
-       bool clear = false;
-       if (!lt) {
-               lt = getLyXText(bv);
-               clear = true;
-       }
-       setUndo(bv, Undo::FINISH, lt->cursor.par(), lt->cursor.par()->next());
-       freezeUndo();
        inset->setOwner(this);
        hideInsetCursor(bv);
-       lt->insertInset(bv, inset);
+       getLyXText(bv)->insertInset(bv, inset);
        bv->fitCursor();
-       if (clear)
-               lt = 0;
        updateLocal(bv, CURSOR_PAR|CURSOR, true);
-       unFreezeUndo();
        return true;
 }
 
@@ -1960,27 +2043,14 @@ void InsetText::setFont(BufferView * bv, LyXFont const & font, bool toggleall,
 }
 
 
-bool InsetText::checkAndActivateInset(BufferView * bv, bool behind)
+bool InsetText::checkAndActivateInset(BufferView * bv, bool front)
 {
        if (cpar(bv)->isInset(cpos(bv))) {
-               unsigned int x;
-               unsigned int y;
                Inset * inset =
                        static_cast<UpdatableInset*>(cpar(bv)->getInset(cpos(bv)));
                if (!isHighlyEditableInset(inset))
                        return false;
-               LyXFont const font =
-                       getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv));
-               if (behind) {
-                       x = inset->width(bv, font);
-                       y = font.isRightToLeft() ? 0 : inset->descent(bv, font);
-               } else {
-                       x = 0;
-                       y = font.isRightToLeft() ? inset->descent(bv, font) : 0;
-               }
-               //inset_x = cx(bv) - top_x + drawTextXOffset;
-               //inset_y = cy(bv) + drawTextYOffset;
-               inset->edit(bv, x, y, 0);
+               inset->edit(bv, front);
                if (!the_locking_inset)
                        return false;
                updateLocal(bv, CURSOR, false);
@@ -2003,8 +2073,8 @@ bool InsetText::checkAndActivateInset(BufferView * bv, int x, int y,
                        x = insetWidth;
                if (y < 0)
                        y = insetDescent;
-               inset_x = cx(bv) - top_x + drawTextXOffset;
-               inset_y = cy(bv) + drawTextYOffset;
+               inset_x = cix(bv) - top_x + drawTextXOffset;
+               inset_y = ciy(bv) + drawTextYOffset;
                inset->edit(bv, x - inset_x, y - inset_y, button);
                if (!the_locking_inset)
                        return false;
@@ -2059,12 +2129,12 @@ void InsetText::setParagraphData(Paragraph * p, bool same_id)
 }
 
 
-void InsetText::setText(string const & data)
+void InsetText::setText(string const & data, LyXFont const & font)
 {
        clear();
-       LyXFont font(LyXFont::ALL_SANE);
        for (unsigned int i=0; i < data.length(); ++i)
                par->insertChar(i, data[i], font);
+       reinitLyXText();
 }
 
 
@@ -2114,6 +2184,21 @@ int InsetText::cx(BufferView * bv) const
 }
 
 
+int InsetText::cix(BufferView * bv) const
+{
+       // we do nothing dangerous so we use a local cache
+       LyXText * llt = getLyXText(bv);
+       int x = llt->cursor.ix() + top_x + TEXT_TO_INSET_OFFSET;
+       if (the_locking_inset) {
+               LyXFont font = llt->getFont(bv->buffer(), llt->cursor.par(),
+                                           llt->cursor.pos());
+               if (font.isVisibleRightToLeft())
+                       x -= the_locking_inset->width(bv, font);
+       }
+       return x;
+}
+
+
 int InsetText::cy(BufferView * bv) const
 {
        LyXFont font;
@@ -2121,6 +2206,13 @@ int InsetText::cy(BufferView * bv) const
 }
 
 
+int InsetText::ciy(BufferView * bv) const
+{
+       LyXFont font;
+       return getLyXText(bv)->cursor.iy() - ascent(bv, font) + TEXT_TO_INSET_OFFSET;
+}
+
+
 pos_type InsetText::cpos(BufferView * bv) const
 {
        return getLyXText(bv)->cursor.pos();
@@ -2269,8 +2361,8 @@ void InsetText::resizeLyXText(BufferView * bv, bool force) const
        t->init(bv, true);
        restoreLyXTextState(bv, t);
        if (the_locking_inset) {
-               inset_x = cx(bv) - top_x + drawTextXOffset;
-               inset_y = cy(bv) + drawTextYOffset;
+               inset_x = cix(bv) - top_x + drawTextXOffset;
+               inset_y = ciy(bv) + drawTextYOffset;
        }
 
        if (bv->screen()) {
@@ -2310,8 +2402,8 @@ void InsetText::reinitLyXText() const
                t->init(bv, true);
                restoreLyXTextState(bv, t);
                if (the_locking_inset) {
-                       inset_x = cx(bv) - top_x + drawTextXOffset;
-                       inset_y = cy(bv) + drawTextYOffset;
+                       inset_x = cix(bv) - top_x + drawTextXOffset;
+                       inset_y = ciy(bv) + drawTextYOffset;
                }
                if (bv->screen()) {
                        t->first_y = bv->screen()->topCursorVisible(t);
@@ -2643,11 +2735,29 @@ bool InsetText::checkInsertChar(LyXFont & font)
 }
 
 
-void InsetText::collapseParagraphs(BufferParams const & bparams) const
+void InsetText::collapseParagraphs(BufferView * bv) const
 {
+       BufferParams const & bparams = bv->buffer()->params;
+       LyXText * llt = getLyXText(bv);
+
        while(par->next()) {
-               if (!par->isSeparator(par->size()-1))
-                       par->insertChar(par->size()-1, ' ');
+               if (par->size() && par->next()->size() &&
+                       !par->isSeparator(par->size()-1))
+               {
+                       par->insertChar(par->size(), ' ');
+               }
+               if (llt->selection.set()) {
+                       if (llt->selection.start.par() == par->next()) {
+                               llt->selection.start.par(par);
+                               llt->selection.start.pos(
+                                       llt->selection.start.pos() + par->size());
+                       }
+                       if (llt->selection.end.par() == par->next()) {
+                               llt->selection.end.par(par);
+                               llt->selection.end.pos(
+                                       llt->selection.end.pos() + par->size());
+                       }
+               }
                par->pasteParagraph(bparams);
        }
        reinitLyXText();