]> git.lyx.org Git - lyx.git/blobdiff - src/text.C
cosmetic fix
[lyx.git] / src / text.C
index 632370f5991e47c4c9f11e6733cdf74ca7e39b73..179c6db01de1f03d008b8ebdd2ae716d18e63b32 100644 (file)
 #include "language.h"
 #include "ParagraphParameters.h"
 #include "undo_funcs.h"
+#include "text_funcs.h"
 #include "WordLangTuple.h"
 #include "paragraph_funcs.h"
 #include "rowpainter.h"
 #include "lyxrow_funcs.h"
+#include "metricsinfo.h"
 
 #include "insets/insettext.h"
 
 
 #include <algorithm>
 
+using namespace lyx::support;
+
 using std::max;
 using std::min;
 using std::endl;
 using std::pair;
+
 using lyx::pos_type;
+using lyx::word_location;
+
 using namespace bv_funcs;
 
 /// top, right, bottom pixel margin
@@ -62,14 +69,14 @@ extern int bibitemMaxWidth(BufferView *, LyXFont const &);
 
 BufferView * LyXText::bv()
 {
-       lyx::Assert(bv_owner != 0);
+       Assert(bv_owner != 0);
        return bv_owner;
 }
 
 
 BufferView * LyXText::bv() const
 {
-       lyx::Assert(bv_owner != 0);
+       Assert(bv_owner != 0);
        return bv_owner;
 }
 
@@ -87,7 +94,7 @@ void LyXText::updateRowPositions()
 
 int LyXText::top_y() const
 {
-       if (anchor_row_ == rowlist_.end() )
+       if (anchor_row_ == rowlist_.end())
                return 0;
 
        return anchor_row_->y() + anchor_row_offset_;
@@ -119,7 +126,7 @@ void LyXText::top_y(int newy)
        anchor_row_offset_ = newy - y;
        lyxerr[Debug::GUI] << "changing reference to row: " << &*anchor_row_
               << " offset: " << anchor_row_offset_ << endl;
-       postPaint(0);
+       postPaint();
 }
 
 
@@ -137,21 +144,22 @@ void LyXText::anchor_row(RowList::iterator rit)
 
 int LyXText::workWidth() const
 {
-       if (inset_owner) {
-               // FIXME: pass (const ?) ref
-               return inset_owner->textWidth(bv());
-       }
-       return bv()->workWidth();
+       return inset_owner ? inset_owner->textWidth() : bv()->workWidth();
 }
 
 
-int LyXText::workWidth(Inset * inset) const
+int LyXText::workWidth(InsetOld const * inset) const
 {
-       Paragraph * par = inset->parOwner();
-       lyx::Assert(par);
+       ParagraphList::iterator par = std::find(ownerParagraphs().begin(),
+                                               ownerParagraphs().end(),
+                                               *inset->parOwner());
+       if (par == ownerParagraphs().end()) {
+               lyxerr[Debug::GUI] << "LyXText::workWidth: unexpected\n";
+               return -1;
+       }
 
        pos_type pos = par->getPositionOfInset(inset);
-       lyx::Assert(pos != -1);
+       Assert(pos != -1);
 
        LyXLayout_ptr const & layout = par->layout();
 
@@ -276,14 +284,14 @@ int LyXText::singleWidth(ParagraphList::iterator pit,
        if (pos >= pit->size())
                return 0;
 
-       LyXFont const font = getFont(bv()->buffer(), pit, pos);
+       LyXFont const font = getFont(bv()->buffer(), pit, pos);
 
        // The most common case is handled first (Asger)
        if (IsPrintable(c)) {
                if (font.language()->RightToLeft()) {
-                       if (font.language()->lang() == "arabic" &&
-                           (lyxrc.font_norm_type == LyXRC::ISO_8859_6_8 ||
-                            lyxrc.font_norm_type == LyXRC::ISO_10646_1)) {
+                       if ((lyxrc.font_norm_type == LyXRC::ISO_8859_6_8 ||
+                            lyxrc.font_norm_type == LyXRC::ISO_10646_1)
+                           && font.language()->lang() == "arabic") {
                                if (Encodings::IsComposeChar_arabic(c))
                                        return 0;
                                else
@@ -293,24 +301,28 @@ int LyXText::singleWidth(ParagraphList::iterator pit,
                                return 0;
                }
                return font_metrics::width(c, font);
-
        }
 
        if (c == Paragraph::META_INSET) {
-               Inset * tmpinset = pit->getInset(pos);
+               InsetOld * tmpinset = pit->getInset(pos);
                if (tmpinset) {
-                       if (tmpinset->lyxCode() == Inset::HFILL_CODE) {
+                       if (tmpinset->lyxCode() == InsetOld::HFILL_CODE) {
                                // Because of the representation as vertical lines
                                return 3;
                        }
-#if 1
+#if 0
 #warning inset->update FIXME
                        // this IS needed otherwise on initialitation we don't get the fill
                        // of the row right (ONLY on initialization if we read a file!)
                        // should be changed! (Jug 20011204)
-                       tmpinset->update(bv());
+                       //tmpinset->update(bv());
+                       Dimension dim;
+                       MetricsInfo mi(bv(), font, workWidth());
+                       tmpinset->metrics(mi, dim);
+                       return dim.wid;
+#else
+                       return tmpinset->width();
 #endif
-                       return tmpinset->width(bv(), font);
                }
                return 0;
        }
@@ -366,9 +378,9 @@ void LyXText::computeBidiTables(Buffer const * buf,
 
        ParagraphList::iterator row_par = row->par();
 
-       Inset * inset = row_par->inInset();
+       InsetOld * inset = row_par->inInset();
        if (inset && inset->owner() &&
-           inset->owner()->lyxCode() == Inset::ERT_CODE) {
+           inset->owner()->lyxCode() == InsetOld::ERT_CODE) {
                bidi_start = -1;
                return;
        }
@@ -521,7 +533,7 @@ bool LyXText::isBoundary(Buffer const * buf, Paragraph const & par,
 
 int LyXText::leftMargin(Row const & row) const
 {
-       Inset * ins;
+       InsetOld * ins;
 
        if (row.pos() < row.par()->size())
                if ((row.par()->getChar(row.pos()) == Paragraph::META_INSET) &&
@@ -696,8 +708,8 @@ int LyXText::leftMargin(Row const & row) const
                    && !row.par()->params().noindent()
                        // in tabulars and ert paragraphs are never indented!
                        && (!row.par()->inInset() || !row.par()->inInset()->owner() ||
-                               (row.par()->inInset()->owner()->lyxCode() != Inset::TABULAR_CODE &&
-                                row.par()->inInset()->owner()->lyxCode() != Inset::ERT_CODE))
+                               (row.par()->inInset()->owner()->lyxCode() != InsetOld::TABULAR_CODE &&
+                                row.par()->inInset()->owner()->lyxCode() != InsetOld::ERT_CODE))
                    && (row.par()->layout() != tclass.defaultLayout() ||
                        bv()->buffer()->params.paragraph_separation ==
                        BufferParams::PARSEP_INDENT)) {
@@ -715,7 +727,7 @@ int LyXText::leftMargin(Row const & row) const
 
 int LyXText::rightMargin(Buffer const & buf, Row const & row) const
 {
-       Inset * ins;
+       InsetOld * ins;
 
        if (row.pos() < row.par()->size())
                if ((row.par()->getChar(row.pos()) == Paragraph::META_INSET) &&
@@ -768,8 +780,7 @@ pos_type addressBreakPoint(pos_type i, Paragraph const & par)
 };
 
 
-pos_type
-LyXText::rowBreakPoint(Row const & row) const
+pos_type LyXText::rowBreakPoint(Row const & row) const
 {
        ParagraphList::iterator pit = row.par();
 
@@ -798,7 +809,7 @@ LyXText::rowBreakPoint(Row const & row) const
        // or the end of the par, then choose the possible break
        // nearest that.
 
-       int const left = leftMargin(const_cast<Row&>(row));
+       int const left = leftMargin(row);
        int x = left;
 
        // pixel width since last breakpoint
@@ -806,6 +817,11 @@ LyXText::rowBreakPoint(Row const & row) const
        bool fullrow = false;
 
        pos_type i = pos;
+
+       // We re-use the font resolution for the entire font span when possible
+       LyXFont font = getFont(bv()->buffer(), pit, i);
+       lyx::pos_type endPosOfFontSpan = pit->getEndPosOfFontSpan(i);
+
        for (; i < last; ++i) {
                if (pit->isNewline(i)) {
                        point = i;
@@ -827,13 +843,33 @@ LyXText::rowBreakPoint(Row const & row) const
                                thiswidth = left_margin - x;
                        thiswidth += singleWidth(pit, i, c);
                } else {
-                       thiswidth = singleWidth(pit, i, c);
+                       // Manual inlined optimised version of common case of "thiswidth = singleWidth(pit, i, c);"
+                       if (IsPrintable(c)) {
+                               if (pos > endPosOfFontSpan) {
+                                       // We need to get the next font
+                                       font = getFont(bv()->buffer(), pit, i);
+                                       endPosOfFontSpan = pit->getEndPosOfFontSpan(i);
+                               }
+                               if (! font.language()->RightToLeft()) {
+                                       thiswidth = font_metrics::width(c, font);
+                               } else {
+                                       // Fall-back to normal case
+                                       thiswidth = singleWidth(pit, i, c);
+                                       // And flush font cache
+                                       endPosOfFontSpan = 0;
+                               }
+                       } else {
+                               // Fall-back to normal case
+                               thiswidth = singleWidth(pit, i, c);
+                               // And flush font cache
+                               endPosOfFontSpan = 0;
+                       }
                }
 
                x += thiswidth;
                chunkwidth += thiswidth;
 
-               Inset * in = pit->isInset(i) ? pit->getInset(i) : 0;
+               InsetOld * in = pit->isInset(i) ? pit->getInset(i) : 0;
                fullrow = (in && (in->display() || in->needFullRow()));
 
                // break before a character that will fall off
@@ -923,17 +959,45 @@ int LyXText::fill(RowList::iterator row, int paper_width) const
        pos_type const body_pos = pit->beginningOfBody();
        pos_type i = row->pos();
 
-       while (i <= last) {
-               if (body_pos > 0 && i == body_pos) {
-                       w += font_metrics::width(layout->labelsep, getLabelFont(bv()->buffer(), pit));
-                       if (pit->isLineSeparator(i - 1))
-                               w -= singleWidth(pit, i - 1);
-                       int left_margin = labelEnd(*row);
-                       if (w < left_margin)
-                               w = left_margin;
+       if (! pit->empty() && i <= last) {
+               // We re-use the font resolution for the entire span when possible
+               LyXFont font = getFont(bv()->buffer(), pit, i);
+               lyx::pos_type endPosOfFontSpan = pit->getEndPosOfFontSpan(i);
+               while (i <= last) {
+                       if (body_pos > 0 && i == body_pos) {
+                               w += font_metrics::width(layout->labelsep, getLabelFont(bv()->buffer(), pit));
+                               if (pit->isLineSeparator(i - 1))
+                                       w -= singleWidth(pit, i - 1);
+                               int left_margin = labelEnd(*row);
+                               if (w < left_margin)
+                                       w = left_margin;
+                       }
+                       { // Manual inlined an optimised version of the common case of "w += singleWidth(pit, i);"
+                               char const c = pit->getChar(i);
+
+                               if (IsPrintable(c)) {
+                                       if (i > endPosOfFontSpan) {
+                                               // We need to get the next font
+                                               font = getFont(bv()->buffer(), pit, i);
+                                               endPosOfFontSpan = pit->getEndPosOfFontSpan(i);
+                                       }
+                                       if (! font.language()->RightToLeft()) {
+                                               w += font_metrics::width(c, font);
+                                       } else {
+                                               // Fall-back to the normal case
+                                               w += singleWidth(pit, i, c);
+                                               // And flush font cache
+                                               endPosOfFontSpan = 0;
+                                       }
+                               } else {
+                                       // Fall-back to the normal case
+                                       w += singleWidth(pit, i, c);
+                                       // And flush font cache
+                                       endPosOfFontSpan = 0;
+                               }
+                       }
+                       ++i;
                }
-               w += singleWidth(pit, i);
-               ++i;
        }
        if (body_pos > 0 && body_pos > last) {
                w += font_metrics::width(layout->labelsep, getLabelFont(bv()->buffer(), pit));
@@ -970,7 +1034,7 @@ int LyXText::labelFill(Row const & row) const
 
        pos_type last = pit->beginningOfBody();
 
-       lyx::Assert(last > 0);
+       Assert(last > 0);
 
        // -1 because a label ends either with a space that is in the label,
        // or with the beginning of a footnote that is outside the label.
@@ -1010,16 +1074,14 @@ LColor::color LyXText::backgroundColor() const
 
 void LyXText::setHeightOfRow(RowList::iterator rit)
 {
-       lyx::Assert(rit != rows().end());
+       Assert(rit != rows().end());
 
        // get the maximum ascent and the maximum descent
        float layoutasc = 0;
        float layoutdesc = 0;
        float tmptop = 0;
-       LyXFont tmpfont;
-       Inset * tmpinset = 0;
 
-       // ok , let us initialize the maxasc and maxdesc value.
+       // ok, let us initialize the maxasc and maxdesc value.
        // This depends in LaTeX of the font of the last character
        // in the paragraph. The hack below is necessary because
        // of the possibility of open footnotes
@@ -1061,24 +1123,59 @@ void LyXText::setHeightOfRow(RowList::iterator rit)
        int maxwidth = 0;
 
        if (!pit->empty()) {
+               // We re-use the font resolution for the entire font span when possible
+               LyXFont font = getFont(bv()->buffer(), pit, rit->pos());
+               lyx::pos_type endPosOfFontSpan = pit->getEndPosOfFontSpan(rit->pos());
+
+               // Optimisation
+               Paragraph const & par = *pit;
+
                // Check if any insets are larger
                for (pos_type pos = rit->pos(); pos <= pos_end; ++pos) {
-                       if (pit->isInset(pos)) {
-                               tmpfont = getFont(bv()->buffer(), pit, pos);
-                               tmpinset = pit->getInset(pos);
-                               if (tmpinset) {
+                       // Manual inlined optimised version of common case of "maxwidth += singleWidth(pit, pos);"
+                       char const c = par.getChar(pos);
+
+                       if (IsPrintable(c)) {
+                               if (pos > endPosOfFontSpan) {
+                                       // We need to get the next font
+                                       font = getFont(bv()->buffer(), pit, pos);
+                                       endPosOfFontSpan = par.getEndPosOfFontSpan(pos);
+                               }
+                               if (! font.language()->RightToLeft()) {
+                                       maxwidth += font_metrics::width(c, font);
+                               } else {
+                                       // Fall-back to normal case
+                                       maxwidth += singleWidth(pit, pos, c);
+                                       // And flush font cache
+                                       endPosOfFontSpan = 0;
+                               }
+                       } else {
+                               // Special handling of insets - are any larger?
+                               if (par.isInset(pos)) {
+                                       LyXFont const tmpfont = getFont(bv()->buffer(), pit, pos);
+                                       InsetOld const * tmpinset = par.getInset(pos);
+                                       if (tmpinset) {
 #if 1 // this is needed for deep update on initialitation
 #warning inset->update FIXME
-                                       tmpinset->update(bv());
+                                               //tmpinset->update(bv());
+                                               Dimension dim;
+                                               MetricsInfo mi(bv(), tmpfont, workWidth());
+                                               tmpinset->metrics(mi, dim);
+                                               maxwidth += dim.wid;
+                                               maxasc = max(maxasc, dim.asc);
+                                               maxdesc = max(maxdesc, dim.des);
+#else
+                                               maxwidth += tmpinset->width();
+                                               maxasc = max(maxasc, tmpinset->ascent());
+                                               maxdesc = max(maxdesc, tmpinset->descent());
 #endif
-                                       maxwidth += tmpinset->width(bv(), tmpfont);
-                                       maxasc = max(maxasc,
-                                                    tmpinset->ascent(bv(), tmpfont));
-                                       maxdesc = max(maxdesc,
-                                                     tmpinset->descent(bv(), tmpfont));
+                                       } 
+                               } else {
+                                       // Fall-back to normal case
+                                       maxwidth += singleWidth(pit, pos, c);
+                                       // And flush font cache
+                                       endPosOfFontSpan = 0;
                                }
-                       } else {
-                               maxwidth += singleWidth(pit, pos);
                        }
                }
        }
@@ -1229,8 +1326,7 @@ void LyXText::setHeightOfRow(RowList::iterator rit)
 
        // is it a bottom line?
        RowList::iterator next_rit = boost::next(rit);
-       if (next_rit == rows().end() ||
-           next_rit->par() != pit) {
+       if (next_rit == rows().end() || next_rit->par() != pit) {
                // the bottom margin
                ParagraphList::iterator nextpit = boost::next(pit);
                if (nextpit == ownerParagraphs().end() &&
@@ -1298,9 +1394,9 @@ void LyXText::setHeightOfRow(RowList::iterator rit)
 
        rit->top_of_text(rit->baseline() - font_metrics::maxAscent(font));
 
-       float x = 0;
+       int x = 0;
        if (layout->margintype != MARGIN_RIGHT_ADDRESS_BOX) {
-               float dummy;
+               int dummy;
                // this IS needed
                rit->width(maxwidth);
                prepareToPrint(rit, x, dummy, dummy, dummy, false);
@@ -1322,7 +1418,7 @@ void LyXText::setHeightOfRow(RowList::iterator rit)
 // start at the implicit given position
 void LyXText::appendParagraph(RowList::iterator rowit)
 {
-       lyx::Assert(rowit != rowlist_.end());
+       Assert(rowit != rowlist_.end());
 
        pos_type const last = rowit->par()->size();
        bool done = false;
@@ -1352,7 +1448,7 @@ void LyXText::appendParagraph(RowList::iterator rowit)
 
 void LyXText::breakAgain(RowList::iterator rit)
 {
-       lyx::Assert(rit != rows().end());
+       Assert(rit != rows().end());
 
        bool not_ready = true;
 
@@ -1405,7 +1501,7 @@ void LyXText::breakAgain(RowList::iterator rit)
 // this is just a little changed version of break again
 void LyXText::breakAgainOneRow(RowList::iterator rit)
 {
-       lyx::Assert(rit != rows().end());
+       Assert(rit != rows().end());
 
        pos_type z = rowBreakPoint(*rit);
        RowList::iterator tmprit = rit;
@@ -1459,13 +1555,12 @@ void LyXText::breakParagraph(ParagraphList & paragraphs, char keep_layout)
        LyXLayout_ptr const & layout = cursor.par()->layout();
 
        // this is only allowed, if the current paragraph is not empty or caption
-       // and if it has not the keepempty flag aktive
-       if (cursor.par()->empty()
-          && layout->labeltype != LABEL_SENSITIVE
-          && !layout->keepempty)
+       // and if it has not the keepempty flag active
+       if (cursor.par()->empty() && !cursor.par()->allowEmpty()
+          && layout->labeltype != LABEL_SENSITIVE)
                return;
 
-       setUndo(bv(), Undo::FINISH, cursor.par());
+       recordUndo(bv(), Undo::ATOMIC, cursor.par());
 
        // Always break behind a space
        //
@@ -1485,9 +1580,9 @@ void LyXText::breakParagraph(ParagraphList & paragraphs, char keep_layout)
        // breakParagraph call should return a bool if it inserts the
        // paragraph before or behind and we should react on that one
        // but we can fix this in 1.3.0 (Jug 20020509)
-       bool const isempty = (layout->keepempty && cursor.par()->empty());
-       ::breakParagraph(bv()->buffer()->params, paragraphs, cursor.par(), cursor.pos(),
-                      keep_layout);
+       bool const isempty = (cursor.par()->allowEmpty() && cursor.par()->empty());
+       ::breakParagraph(bv()->buffer()->params, paragraphs, cursor.par(),
+                        cursor.pos(), keep_layout);
 
        // well this is the caption hack since one caption is really enough
        if (layout->labeltype == LABEL_SENSITIVE) {
@@ -1503,33 +1598,20 @@ void LyXText::breakParagraph(ParagraphList & paragraphs, char keep_layout)
        // move one row up!
        // This touches only the screen-update. Otherwise we would may have
        // an empty row on the screen
-       if (cursor.pos() && cursor.row()->pos() == cursor.pos()
-           && !cursor.row()->par()->isNewline(cursor.pos() - 1))
+       if (cursor.pos() && cursorRow()->pos() == cursor.pos()
+           && !cursorRow()->par()->isNewline(cursor.pos() - 1))
        {
                cursorLeft(bv());
        }
 
-       int y = cursor.y() - cursor.row()->baseline();
+       postPaint();
 
-       // Do not forget the special right address boxes
-       if (layout->margintype == MARGIN_RIGHT_ADDRESS_BOX) {
-               RowList::iterator r = cursor.row();
-               RowList::iterator beg = rows().begin();
-
-               while (r != beg && boost::prior(r)->par() == r->par()) {
-                       --r;
-                       y -= r->height();
-               }
-       }
-
-       postPaint(y);
-
-       removeParagraph(cursor.row());
+       removeParagraph(cursorRow());
 
        // set the dimensions of the cursor row
-       cursor.row()->fill(fill(cursor.row(), workWidth()));
+       cursorRow()->fill(fill(cursorRow(), workWidth()));
 
-       setHeightOfRow(cursor.row());
+       setHeightOfRow(cursorRow());
 
 #warning Trouble Point! (Lgb)
        // When ::breakParagraph is called from within an inset we must
@@ -1540,7 +1622,7 @@ void LyXText::breakParagraph(ParagraphList & paragraphs, char keep_layout)
        while (!next_par->empty() && next_par->isNewline(0))
                next_par->erase(0);
 
-       insertParagraph(next_par, boost::next(cursor.row()));
+       insertParagraph(next_par, boost::next(cursorRow()));
        updateCounters();
 
        // This check is necessary. Otherwise the new empty paragraph will
@@ -1550,8 +1632,8 @@ void LyXText::breakParagraph(ParagraphList & paragraphs, char keep_layout)
        else
                setCursor(cursor.par(), 0);
 
-       if (boost::next(cursor.row()) != rows().end())
-               breakAgain(boost::next(cursor.row()));
+       if (boost::next(cursorRow()) != rows().end())
+               breakAgain(boost::next(cursorRow()));
 
        need_break_row = rows().end();
 }
@@ -1570,13 +1652,13 @@ void LyXText::redoParagraph()
 // same Paragraph one to the right and make a rebreak
 void LyXText::insertChar(char c)
 {
-       setUndo(bv(), Undo::INSERT, cursor.par());
+       recordUndo(bv(), Undo::INSERT, cursor.par());
 
        // When the free-spacing option is set for the current layout,
        // disable the double-space checking
 
-       bool const freeSpacing = cursor.row()->par()->layout()->free_spacing ||
-               cursor.row()->par()->isFreeSpacing();
+       bool const freeSpacing = cursorRow()->par()->layout()->free_spacing ||
+               cursorRow()->par()->isFreeSpacing();
 
        if (lyxrc.auto_number) {
                static string const number_operators = "+-/*";
@@ -1670,20 +1752,19 @@ void LyXText::insertChar(char c)
        }
 
        // the display inset stuff
-       if (cursor.row()->pos() < cursor.row()->par()->size()
-           && cursor.row()->par()->isInset(cursor.row()->pos())) {
-               Inset * inset = cursor.row()->par()->getInset(cursor.row()->pos());
+       if (cursorRow()->pos() < cursorRow()->par()->size()
+           && cursorRow()->par()->isInset(cursorRow()->pos())) {
+               InsetOld * inset = cursorRow()->par()->getInset(cursorRow()->pos());
                if (inset && (inset->display() || inset->needFullRow())) {
                        // force a new break
-                       cursor.row()->fill(-1); // to force a new break
+                       cursorRow()->fill(-1); // to force a new break
                }
        }
 
        // get the cursor row fist
-       RowList::iterator row = cursor.row();
-       int y = cursor.y() - row->baseline();
+       RowList::iterator row = cursorRow();
        if (c != Paragraph::META_INSET) {
-               // Here case LyXText::InsertInset  already insertet the character
+               // Here case LyXText::InsertInset  already inserted the character
                cursor.par()->insertChar(cursor.pos(), c);
        }
        setCharFont(bv()->buffer(), cursor.par(), cursor.pos(), rawtmpfont);
@@ -1705,7 +1786,7 @@ void LyXText::insertChar(char c)
                || cursor.par()->isNewline(cursor.pos())
                || ((cursor.pos() + 1 < cursor.par()->size()) &&
                    cursor.par()->isInset(cursor.pos() + 1))
-               || cursor.row()->fill() == -1))
+               || cursorRow()->fill() == -1))
        {
                pos_type z = rowBreakPoint(*boost::prior(row));
 
@@ -1719,9 +1800,7 @@ void LyXText::insertChar(char c)
 
                        setHeightOfRow(boost::prior(row));
 
-                       y -= boost::prior(row)->height();
-
-                       postPaint(y);
+                       postPaint();
 
                        breakAgainOneRow(row);
 
@@ -1731,9 +1810,10 @@ void LyXText::insertChar(char c)
                                  false, cursor.boundary());
                        // cursor MUST be in row now.
 
-                       if (boost::next(row) != rows().end() &&
-                           boost::next(row)->par() == row->par())
-                               need_break_row = boost::next(row);
+                       RowList::iterator next_row = boost::next(row);
+                       if (next_row != rows().end() &&
+                           next_row->par() == row->par())
+                               need_break_row = next_row;
                        else
                                need_break_row = rows().end();
 
@@ -1755,15 +1835,20 @@ void LyXText::insertChar(char c)
        }
 
        if (c == Paragraph::META_INSET || row->fill() < 0) {
-               postPaint(y);
+               postPaint();
                breakAgainOneRow(row);
+
+               RowList::iterator next_row = boost::next(row);
+
                // will the cursor be in another row now?
                if (lastPos(*this, row) <= cursor.pos() + 1 &&
-                   boost::next(row) != rows().end()) {
-                       if (boost::next(row) != rows().end() &&
-                           boost::next(row)->par() == row->par())
+                   next_row != rows().end()) {
+                       if (next_row != rows().end() &&
+                           next_row->par() == row->par()) {
                                // this should always be true
                                ++row;
+                       }
+
                        breakAgainOneRow(row);
                }
                current_font = rawtmpfont;
@@ -1775,22 +1860,18 @@ void LyXText::insertChar(char c)
                    != cursor.boundary())
                        setCursor(cursor.par(), cursor.pos(), false,
                          !cursor.boundary());
-               if (boost::next(row) != rows().end() &&
-                   boost::next(row)->par() == row->par())
-                       need_break_row = boost::next(row);
+
+               next_row = boost::next(row);
+
+               if (next_row != rows().end() &&
+                   next_row->par() == row->par())
+                       need_break_row = next_row;
                else
                        need_break_row = rows().end();
        } else {
                // FIXME: similar code is duplicated all over - make resetHeightOfRow
-               int const tmpheight = row->height();
-
                setHeightOfRow(row);
-
-               if (tmpheight == row->height()) {
-                       postRowPaint(row, y);
-               } else {
-                       postPaint(y);
-               }
+               postPaint();
 
                current_font = rawtmpfont;
                real_current_font = realtmpfont;
@@ -1802,12 +1883,6 @@ void LyXText::insertChar(char c)
        if (cursor.pos() && cursor.pos() == cursor.par()->size()
            && rawparfont != rawtmpfont) {
                redoHeightOfParagraph();
-       } else {
-               // now the special right address boxes
-               if (cursor.par()->layout()->margintype
-                   == MARGIN_RIGHT_ADDRESS_BOX) {
-                       redoDrawingOfParagraph(cursor);
-               }
        }
 
        charInserted();
@@ -1828,13 +1903,13 @@ void LyXText::charInserted()
 }
 
 
-void LyXText::prepareToPrint(RowList::iterator rit, float & x,
-                            float & fill_separator,
-                            float & fill_hfill,
-                            float & fill_label_hfill,
+void LyXText::prepareToPrint(RowList::iterator rit, int & x,
+                            int & fill_separator,
+                            int & fill_hfill,
+                            int & fill_label_hfill,
                             bool bidi) const
 {
-       float w = rit->fill();
+       int w = rit->fill();
        fill_hfill = 0;
        fill_label_hfill = 0;
        fill_separator = 0;
@@ -1844,12 +1919,10 @@ void LyXText::prepareToPrint(RowList::iterator rit, float & x,
 
        bool const is_rtl =
                pit->isRightToLeftPar(bv()->buffer()->params);
-       if (is_rtl) {
-               x = (workWidth() > 0)
-                       ? rightMargin(*bv()->buffer(), *rit) : 0;
-       } else
-               x = (workWidth() > 0)
-                       ? leftMargin(*rit) : 0;
+       if (is_rtl)
+               x = workWidth() > 0 ? rightMargin(*bv()->buffer(), *rit) : 0;
+       else
+               x = workWidth() > 0 ? leftMargin(*rit) : 0;
 
        // is there a manual margin with a manual label
        LyXLayout_ptr const & layout = pit->layout();
@@ -1857,7 +1930,7 @@ void LyXText::prepareToPrint(RowList::iterator rit, float & x,
        if (layout->margintype == MARGIN_MANUAL
            && layout->labeltype == LABEL_MANUAL) {
                /// We might have real hfills in the label part
-               float nlh = numberOfLabelHfills(*this, rit);
+               int nlh = numberOfLabelHfills(*this, rit);
 
                // A manual label par (e.g. List) has an auto-hfill
                // between the label text and the body of the
@@ -1868,12 +1941,12 @@ void LyXText::prepareToPrint(RowList::iterator rit, float & x,
                        ++nlh;
 
                if (nlh && !pit->getLabelWidthString().empty()) {
-                       fill_label_hfill = labelFill(*rit) / nlh;
+                       fill_label_hfill = int(labelFill(*rit) / nlh);
                }
        }
 
        // are there any hfills in the row?
-       float const nh = numberOfHfills(*this, rit);
+       int const nh = numberOfHfills(*this, rit);
 
        if (nh) {
                if (w > 0)
@@ -1881,7 +1954,7 @@ void LyXText::prepareToPrint(RowList::iterator rit, float & x,
        // we don't have to look at the alignment if it is ALIGN_LEFT and
        // if the row is already larger then the permitted width as then
        // we force the LEFT_ALIGN'edness!
-       } else if (static_cast<int>(rit->width()) < workWidth()) {
+       } else if (int(rit->width()) < workWidth()) {
                // is it block, flushleft or flushright?
                // set x how you need it
                int align;
@@ -1892,17 +1965,17 @@ void LyXText::prepareToPrint(RowList::iterator rit, float & x,
                }
 
                // center displayed insets
-               Inset * inset = 0;
+               InsetOld * inset = 0;
                if (rit->pos() < pit->size()
                    && pit->isInset(rit->pos())
                    && (inset = pit->getInset(rit->pos()))
                    && (inset->display())) // || (inset->scroll() < 0)))
-                   align = (inset->lyxCode() == Inset::MATHMACRO_CODE)
+                   align = (inset->lyxCode() == InsetOld::MATHMACRO_CODE)
                        ? LYX_ALIGN_BLOCK : LYX_ALIGN_CENTER;
                // ERT insets should always be LEFT ALIGNED on screen
                inset = pit->inInset();
                if (inset && inset->owner() &&
-                       inset->owner()->lyxCode() == Inset::ERT_CODE)
+                       inset->owner()->lyxCode() == InsetOld::ERT_CODE)
                {
                        align = LYX_ALIGN_LEFT;
                }
@@ -1910,7 +1983,7 @@ void LyXText::prepareToPrint(RowList::iterator rit, float & x,
                switch (align) {
            case LYX_ALIGN_BLOCK:
            {
-                       float const ns = numberOfSeparators(*this, rit);
+                       int const ns = numberOfSeparators(*this, rit);
                        RowList::iterator next_row = boost::next(rit);
                        ParagraphList::iterator next_pit = next_row->par();
 
@@ -1965,27 +2038,8 @@ void LyXText::prepareToPrint(RowList::iterator rit, float & x,
 
 void LyXText::cursorRightOneWord()
 {
-       // treat floats, HFills and Insets as words
-       ParagraphList::iterator pit = cursor.par();
-       pos_type pos = cursor.pos();
-
-       // CHECK See comment on top of text.C
-
-       if (pos == pit->size()
-           && boost::next(pit) != ownerParagraphs().end()) {
-               ++pit;
-               pos = 0;
-       } else {
-               // Skip through initial nonword stuff.
-               while (pos < pit->size() && !pit->isWord(pos)) {
-                       ++pos;
-               }
-               // Advance through word.
-               while (pos < pit->size() && pit->isWord(pos)) {
-                       ++pos;
-               }
-       }
-       setCursor(pit, pos);
+       ::cursorRightOneWord(cursor, ownerParagraphs());
+       setCursor(cursor.par(), cursor.pos());
 }
 
 
@@ -1994,102 +2048,16 @@ void LyXText::cursorRightOneWord()
 void LyXText::cursorLeftOneWord()
 {
        LyXCursor tmpcursor = cursor;
-       cursorLeftOneWord(tmpcursor);
+       ::cursorLeftOneWord(tmpcursor, ownerParagraphs());
        setCursor(tmpcursor.par(), tmpcursor.pos());
 }
 
 
-void LyXText::cursorLeftOneWord(LyXCursor & cur)
-{
-       // treat HFills, floats and Insets as words
-
-       ParagraphList::iterator pit = cursor.par();
-       pos_type pos = cursor.pos();
-
-       while (pos &&
-              (pit->isSeparator(pos - 1) ||
-               pit->isKomma(pos - 1) ||
-               pit->isNewline(pos - 1)) &&
-              !(pit->isHfill(pos - 1) ||
-                pit->isInset(pos - 1)))
-               --pos;
-
-       if (pos &&
-           (pit->isInset(pos - 1) ||
-            pit->isHfill(pos - 1))) {
-               --pos;
-       } else if (!pos) {
-               if (pit != ownerParagraphs().begin()) {
-                       --pit;
-                       pos = pit->size();
-               }
-       } else {                // Here, cur != 0
-               while (pos > 0 &&
-                      pit->isWord(pos - 1))
-                       --pos;
-       }
-
-       cur.par(pit);
-       cur.pos(pos);
-}
-
-
-// Select current word. This depends on behaviour of
-// CursorLeftOneWord(), so it is patched as well.
-void LyXText::getWord(LyXCursor & from, LyXCursor & to,
-                     word_location const loc)
-{
-       // first put the cursor where we wana start to select the word
-       from = cursor;
-       switch (loc) {
-       case WHOLE_WORD_STRICT:
-               if (cursor.pos() == 0 || cursor.pos() == cursor.par()->size()
-                   || cursor.par()->isSeparator(cursor.pos())
-                   || cursor.par()->isKomma(cursor.pos())
-                   || cursor.par()->isNewline(cursor.pos())
-                   || cursor.par()->isSeparator(cursor.pos() - 1)
-                   || cursor.par()->isKomma(cursor.pos() - 1)
-                   || cursor.par()->isNewline(cursor.pos() - 1)) {
-                       to = from;
-                       return;
-               }
-               // no break here, we go to the next
-
-       case WHOLE_WORD:
-               // Move cursor to the beginning, when not already there.
-               if (from.pos() && !from.par()->isSeparator(from.pos() - 1)
-                   && !(from.par()->isKomma(from.pos() - 1)
-                        || from.par()->isNewline(from.pos() - 1)))
-                       cursorLeftOneWord(from);
-               break;
-       case PREVIOUS_WORD:
-               // always move the cursor to the beginning of previous word
-               cursorLeftOneWord(from);
-               break;
-       case NEXT_WORD:
-               lyxerr << "LyXText::getWord: NEXT_WORD not implemented yet\n";
-               break;
-       case PARTIAL_WORD:
-               break;
-       }
-       to = from;
-       while (to.pos() < to.par()->size()
-              && !to.par()->isSeparator(to.pos())
-              && !to.par()->isKomma(to.pos())
-              && !to.par()->isNewline(to.pos())
-              && !to.par()->isHfill(to.pos())
-              && !to.par()->isInset(to.pos()))
-       {
-               to.pos(to.pos() + 1);
-       }
-}
-
-
 void LyXText::selectWord(word_location loc)
 {
-       LyXCursor from;
+       LyXCursor from = cursor;
        LyXCursor to;
-       getWord(from, to, loc);
+       ::getWord(from, to, loc, ownerParagraphs());
        if (cursor != from)
                setCursor(from.par(), from.pos());
        if (to == from)
@@ -2120,7 +2088,7 @@ void LyXText::acceptChange()
        if (selection.start.par() == selection.end.par()) {
                LyXCursor & startc = selection.start;
                LyXCursor & endc = selection.end;
-               setUndo(bv(), Undo::INSERT, startc.par());
+               recordUndo(bv(), Undo::INSERT, startc.par());
                startc.par()->acceptChange(startc.pos(), endc.pos());
                finishUndo();
                clearSelection();
@@ -2139,7 +2107,7 @@ void LyXText::rejectChange()
        if (selection.start.par() == selection.end.par()) {
                LyXCursor & startc = selection.start;
                LyXCursor & endc = selection.end;
-               setUndo(bv(), Undo::INSERT, startc.par());
+               recordUndo(bv(), Undo::INSERT, startc.par());
                startc.par()->rejectChange(startc.pos(), endc.pos());
                finishUndo();
                clearSelection();
@@ -2281,7 +2249,6 @@ void LyXText::deleteWordForward()
                cursorRight(bv());
        else {
                LyXCursor tmpcursor = cursor;
-               tmpcursor.row(0); // ??
                selection.set(true); // to avoid deletion
                cursorRightOneWord();
                setCursor(tmpcursor, tmpcursor.par(), tmpcursor.pos());
@@ -2302,7 +2269,6 @@ void LyXText::deleteWordBackward()
                cursorLeft(bv());
        else {
                LyXCursor tmpcursor = cursor;
-               tmpcursor.row(0); // ??
                selection.set(true); // to avoid deletion
                cursorLeftOneWord();
                setCursor(tmpcursor, tmpcursor.par(), tmpcursor.pos());
@@ -2324,7 +2290,6 @@ void LyXText::deleteLineForward()
                LyXCursor tmpcursor = cursor;
                // We can't store the row over a regular setCursor
                // so we set it to 0 and reset it afterwards.
-               tmpcursor.row(0); // ??
                selection.set(true); // to avoid deletion
                cursorEnd();
                setCursor(tmpcursor, tmpcursor.par(), tmpcursor.pos());
@@ -2350,13 +2315,12 @@ void LyXText::changeCase(LyXText::TextCase action)
                from = selection.start;
                to = selection.end;
        } else {
-               getWord(from, to, PARTIAL_WORD);
+               from = cursor;
+               ::getWord(from, to, lyx::PARTIAL_WORD, ownerParagraphs());
                setCursor(to.par(), to.pos() + 1);
        }
 
-       lyx::Assert(from <= to);
-
-       setUndo(bv(), Undo::FINISH, from.par(), to.par());
+       recordUndo(bv(), Undo::ATOMIC, from.par(), to.par());
 
        pos_type pos = from.pos();
        ParagraphList::iterator pit = from.par();
@@ -2390,8 +2354,8 @@ void LyXText::changeCase(LyXText::TextCase action)
                ++pos;
        }
 
-       if (to.row() != from.row())
-               postPaint(from.y() - from.row()->baseline());
+       if (getRow(to) != getRow(from))
+               postPaint();
 }
 
 
@@ -2426,7 +2390,7 @@ void LyXText::Delete()
                LyXCursor tmpcursor = cursor;
                // to make sure undo gets the right cursor position
                cursor = old_cursor;
-               setUndo(bv(), Undo::DELETE, cursor.par());
+               recordUndo(bv(), Undo::DELETE, cursor.par());
                cursor = tmpcursor;
                backspace();
        }
@@ -2473,23 +2437,22 @@ void LyXText::backspace()
                                cursorLeft(bv());
 
                                // the layout things can change the height of a row !
-                               int const tmpheight = cursor.row()->height();
-                               setHeightOfRow(cursor.row());
-                               if (cursor.row()->height() != tmpheight) {
-                                       postPaint(cursor.y() - cursor.row()->baseline());
-                               }
+                               int const tmpheight = cursorRow()->height();
+                               setHeightOfRow(cursorRow());
+                               if (cursorRow()->height() != tmpheight)
+                                       postPaint();
                                return;
                        }
                }
 
                if (cursor.par() != ownerParagraphs().begin()) {
-                       setUndo(bv(), Undo::DELETE,
+                       recordUndo(bv(), Undo::DELETE,
                                boost::prior(cursor.par()),
                                cursor.par());
                }
 
                ParagraphList::iterator tmppit = cursor.par();
-               RowList::iterator tmprow = cursor.row();
+               RowList::iterator tmprow = cursorRow();
 
                // We used to do cursorLeftIntern() here, but it is
                // not a good idea since it triggers the auto-delete
@@ -2531,7 +2494,7 @@ void LyXText::backspace()
                                if (cursor.pos())
                                        cursor.pos(cursor.pos() - 1);
 
-                       postPaint(cursor.y() - cursor.row()->baseline());
+                       postPaint();
 
                        // remove the lost paragraph
                        // This one is not safe, since the paragraph that the tmprow and the
@@ -2542,7 +2505,7 @@ void LyXText::backspace()
                        //RemoveRow(tmprow);
 
                        // This rebuilds the rows.
-                       appendParagraph(cursor.row());
+                       appendParagraph(cursorRow());
                        updateCounters();
 
                        // the row may have changed, block, hfills etc.
@@ -2551,7 +2514,7 @@ void LyXText::backspace()
        } else {
                // this is the code for a normal backspace, not pasting
                // any paragraphs
-               setUndo(bv(), Undo::DELETE, cursor.par());
+               recordUndo(bv(), Undo::DELETE, cursor.par());
                // We used to do cursorLeftIntern() here, but it is
                // not a good idea since it triggers the auto-delete
                // mechanism. So we do a cursorLeftIntern()-lite,
@@ -2570,7 +2533,7 @@ void LyXText::backspace()
                        }
                }
 
-               RowList::iterator row = cursor.row();
+               RowList::iterator row = cursorRow();
                int y = cursor.y() - row->baseline();
                pos_type z;
                // remember that a space at the end of a row doesnt count
@@ -2662,8 +2625,7 @@ void LyXText::backspace()
                                y -= tmprow->height();
                                tmprow->fill(fill(tmprow, workWidth()));
                                setHeightOfRow(tmprow);
-
-                               postPaint(y);
+                               postPaint();
 
                                setCursor(cursor.par(), cursor.pos(),
                                          false, cursor.boundary());
@@ -2691,7 +2653,7 @@ void LyXText::backspace()
                        if (lastPos(*this, row) == row->par()->size() - 1)
                                removeRow(boost::next(row));
 
-                       postPaint(y);
+                       postPaint();
 
                        breakAgainOneRow(row);
                        // will the cursor be in another row now?
@@ -2712,13 +2674,8 @@ void LyXText::backspace()
                } else  {
                        // set the dimensions of the row
                        row->fill(fill(row, workWidth()));
-                       int const tmpheight = row->height();
                        setHeightOfRow(row);
-                       if (tmpheight == row->height()) {
-                               postRowPaint(row, y);
-                       } else {
-                               postPaint(y);
-                       }
+                       postPaint();
                        setCursor(cursor.par(), cursor.pos(), false, cursor.boundary());
                }
        }
@@ -2739,16 +2696,47 @@ void LyXText::backspace()
        if (rawparfont !=
            cursor.par()->getFontSettings(bv()->buffer()->params, lastpos - 1)) {
                redoHeightOfParagraph();
-       } else {
-               // now the special right address boxes
-               if (cursor.par()->layout()->margintype
-                   == MARGIN_RIGHT_ADDRESS_BOX) {
-                       redoDrawingOfParagraph(cursor);
-               }
        }
 }
 
 
+RowList::iterator LyXText::cursorRow() const
+{
+       return getRow(cursor.par(), cursor.pos());
+}
+
+
+RowList::iterator LyXText::getRow(LyXCursor const & cur) const
+{
+       return getRow(cur.par(), cur.pos());
+}
+
+
+RowList::iterator
+LyXText::getRow(ParagraphList::iterator pit, pos_type pos) const
+{
+       if (rows().empty())
+               return rowlist_.end();
+
+       // find the first row of the specified paragraph
+       RowList::iterator rit = rowlist_.begin();
+       RowList::iterator end = rowlist_.end();
+       while (boost::next(rit) != end && rit->par() != pit) {
+               ++rit;
+       }
+
+       // now find the wanted row
+       while (rit->pos() < pos
+              && boost::next(rit) != end
+              && boost::next(rit)->par() == pit
+              && boost::next(rit)->pos() <= pos) {
+               ++rit;
+       }
+
+       return rit;
+}
+
+
 // returns pointer to a specified row
 RowList::iterator
 LyXText::getRow(ParagraphList::iterator pit, pos_type pos, int & y) const
@@ -2779,9 +2767,16 @@ LyXText::getRow(ParagraphList::iterator pit, pos_type pos, int & y) const
 }
 
 
-RowList::iterator LyXText::getRowNearY(int & y) const
+// returns pointer to some fancy row 'below' specified row
+RowList::iterator LyXText::cursorIRow() const
 {
+       int y = 0;
+       return getRow(cursor.par(), cursor.pos(), y);
+}
+
 
+RowList::iterator LyXText::getRowNearY(int & y) const
+{
        RowList::iterator rit = anchor_row_;
        RowList::iterator const beg = rows().begin();
        RowList::iterator const end = rows().end();