X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ftext.C;h=8e68a70a32f797702cf157a8266ab2fa36d220dd;hb=fe390e9da1538e20eabbc98977d845295f8e563d;hp=24e3c11d026335781d4f11d534345221b7a9dc12;hpb=33aab6ed79d84d0be429224807f878d361344eda;p=lyx.git diff --git a/src/text.C b/src/text.C index 24e3c11d02..8e68a70a32 100644 --- a/src/text.C +++ b/src/text.C @@ -30,6 +30,7 @@ #include "language.h" #include "ParagraphParameters.h" #include "undo_funcs.h" +#include "text_funcs.h" #include "WordLangTuple.h" #include "paragraph_funcs.h" #include "rowpainter.h" @@ -43,11 +44,16 @@ #include +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,31 +68,35 @@ 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; } +void LyXText::updateRowPositions() +{ + RowList::iterator rit = rows().begin(); + RowList::iterator rend = rows().end(); + for (int y = 0; rit != rend ; ++rit) { + rit->y(y); + y += rit->height(); + } +} + + int LyXText::top_y() const { if (anchor_row_ == rowlist_.end()) return 0; - int y = 0; - - RowList::iterator rit = rowlist_.begin(); - RowList::iterator end = rowlist_.end(); - for (; rit != end && rit != anchor_row_; ++rit) { - y += rit->height(); - } - return y + anchor_row_offset_; + return anchor_row_->y() + anchor_row_offset_; } @@ -94,6 +104,13 @@ void LyXText::top_y(int newy) { if (rows().empty()) return; + + if (isInInset()) { + anchor_row_ = rows().begin(); + anchor_row_offset_ = newy; + return; + } + lyxerr[Debug::GUI] << "setting top y = " << newy << endl; int y = newy; @@ -134,13 +151,15 @@ int LyXText::workWidth() const } -int LyXText::workWidth(Inset * inset) const +int LyXText::workWidth(Inset const * inset) const { - Paragraph * par = inset->parOwner(); - lyx::Assert(par); + ParagraphList::iterator par = std::find(ownerParagraphs().begin(), + ownerParagraphs().end(), + *inset->parOwner()); + //Assert(par); pos_type pos = par->getPositionOfInset(inset); - lyx::Assert(pos != -1); + Assert(pos != -1); LyXLayout_ptr const & layout = par->layout(); @@ -199,11 +218,15 @@ unsigned char LyXText::transformChar(unsigned char c, Paragraph const & par, unsigned char const prev_char = pos > 0 ? par.getChar(pos - 1) : ' '; unsigned char next_char = ' '; - for (pos_type i = pos + 1; i < par.size(); ++i) - if (!Encodings::IsComposeChar_arabic(par.getChar(i))) { - next_char = par.getChar(i); + pos_type const par_size = par.size(); + + for (pos_type i = pos + 1; i < par_size; ++i) { + unsigned char const par_char = par.getChar(i); + if (!Encodings::IsComposeChar_arabic(par_char)) { + next_char = par_char; break; } + } if (Encodings::is_arabic(next_char)) { if (Encodings::is_arabic(prev_char) && @@ -349,7 +372,9 @@ void LyXText::computeBidiTables(Buffer const * buf, return; } - Inset * inset = row->par()->inInset(); + ParagraphList::iterator row_par = row->par(); + + Inset * inset = row_par->inInset(); if (inset && inset->owner() && inset->owner()->lyxCode() == Inset::ERT_CODE) { bidi_start = -1; @@ -379,25 +404,25 @@ void LyXText::computeBidiTables(Buffer const * buf, pos_type stack[2]; bool const rtl_par = - row->par()->isRightToLeftPar(buf->params); + row_par->isRightToLeftPar(buf->params); int level = 0; bool rtl = false; bool rtl0 = false; - pos_type const body_pos = row->par()->beginningOfBody(); + pos_type const body_pos = row_par->beginningOfBody(); for (pos_type lpos = bidi_start; lpos <= bidi_end; ++lpos) { - bool is_space = row->par()->isLineSeparator(lpos); + bool is_space = row_par->isLineSeparator(lpos); pos_type const pos = (is_space && lpos + 1 <= bidi_end && - !row->par()->isLineSeparator(lpos + 1) && - !row->par()->isNewline(lpos + 1)) + !row_par->isLineSeparator(lpos + 1) && + !row_par->isNewline(lpos + 1)) ? lpos + 1 : lpos; - LyXFont font = row->par()->getFontSettings(buf->params, pos); + LyXFont font = row_par->getFontSettings(buf->params, pos); if (pos != lpos && 0 < lpos && rtl0 && font.isRightToLeft() && font.number() == LyXFont::ON && - row->par()->getFontSettings(buf->params, lpos - 1).number() + row_par->getFontSettings(buf->params, lpos - 1).number() == LyXFont::ON) { - font = row->par()->getFontSettings(buf->params, lpos); + font = row_par->getFontSettings(buf->params, lpos); is_space = false; } @@ -468,7 +493,7 @@ void LyXText::computeBidiTables(Buffer const * buf, // This method requires a previous call to ComputeBidiTables() -bool LyXText::isBoundary(Buffer const * buf, Paragraph * par, +bool LyXText::isBoundary(Buffer const * buf, Paragraph const & par, pos_type pos) const { if (!lyxrc.rtl_support || pos == 0) @@ -483,12 +508,12 @@ bool LyXText::isBoundary(Buffer const * buf, Paragraph * par, bool const rtl = bidi_level(pos - 1) % 2; bool const rtl2 = bidi_InRange(pos) ? bidi_level(pos) % 2 - : par->isRightToLeftPar(buf->params); + : par.isRightToLeftPar(buf->params); return rtl != rtl2; } -bool LyXText::isBoundary(Buffer const * buf, Paragraph * par, +bool LyXText::isBoundary(Buffer const * buf, Paragraph const & par, pos_type pos, LyXFont const & font) const { if (!lyxrc.rtl_support) @@ -497,7 +522,7 @@ bool LyXText::isBoundary(Buffer const * buf, Paragraph * par, bool const rtl = font.isVisibleRightToLeft(); bool const rtl2 = bidi_InRange(pos) ? bidi_level(pos) % 2 - : par->isRightToLeftPar(buf->params); + : par.isRightToLeftPar(buf->params); return rtl != rtl2; } @@ -528,30 +553,34 @@ int LyXText::leftMargin(Row const & row) const if (!row.par()->getDepth()) { if (row.par()->layout() == tclass.defaultLayout()) { // find the previous same level paragraph - if (row.par()->previous()) { - Paragraph * newpar = row.par() - ->depthHook(row.par()->getDepth()); - if (newpar && - newpar->layout()->nextnoindent) + if (row.par() != ownerParagraphs().begin()) { + ParagraphList::iterator newpit = + depthHook(row.par(), ownerParagraphs(), + row.par()->getDepth()); + if (newpit == row.par() && + newpit->layout()->nextnoindent) parindent.erase(); } } } else { // find the next level paragraph - Paragraph * newpar = row.par()->outerHook(); + ParagraphList::iterator newpar = outerHook(row.par(), + ownerParagraphs()); // make a corresponding row. Needed to call leftMargin() // check wether it is a sufficent paragraph - if (newpar && newpar->layout()->isEnvironment()) { + if (newpar != ownerParagraphs().end() && + newpar->layout()->isEnvironment()) { Row dummyrow; dummyrow.par(newpar); dummyrow.pos(newpar->size()); x = leftMargin(dummyrow); } - if (newpar && row.par()->layout() == tclass.defaultLayout()) { + if (newpar != ownerParagraphs().end() && + row.par()->layout() == tclass.defaultLayout()) { if (newpar->params().noindent()) parindent.erase(); else { @@ -561,7 +590,7 @@ int LyXText::leftMargin(Row const & row) const } } - LyXFont const labelfont = getLabelFont(bv()->buffer(), &*row.par()); + LyXFont const labelfont = getLabelFont(bv()->buffer(), row.par()); switch (layout->margintype) { case MARGIN_DYNAMIC: if (!layout->leftmargin.empty()) { @@ -605,7 +634,7 @@ int LyXText::leftMargin(Row const & row) const // theorems (JMarc) || (layout->labeltype == LABEL_STATIC && layout->latextype == LATEX_ENVIRONMENT - && ! row.par()->isFirstInSequence())) { + && !isFirstInSequence(row.par(), ownerParagraphs()))) { x += font_metrics::signedWidth(layout->leftmargin, labelfont); } else if (layout->labeltype != LABEL_TOP_ENVIRONMENT @@ -656,7 +685,7 @@ int LyXText::leftMargin(Row const & row) const x += len.inPixels(tw); } - LyXAlignment align; // wrong type + LyXAlignment align; if (row.par()->params().align() == LYX_ALIGN_LAYOUT) align = layout->align; @@ -670,7 +699,7 @@ int LyXText::leftMargin(Row const & row) const || layout->labeltype == LABEL_CENTERED_TOP_ENVIRONMENT || (layout->labeltype == LABEL_STATIC && layout->latextype == LATEX_ENVIRONMENT - && ! row.par()->isFirstInSequence())) + && !isFirstInSequence(row.par(), ownerParagraphs()))) && align == LYX_ALIGN_BLOCK && !row.par()->params().noindent() // in tabulars and ert paragraphs are never indented! @@ -734,21 +763,20 @@ int LyXText::labelEnd(Row const & row) const namespace { // this needs special handling - only newlines count as a break point -pos_type addressBreakPoint(pos_type i, Paragraph * par) +pos_type addressBreakPoint(pos_type i, Paragraph const & par) { - for (; i < par->size(); ++i) { - if (par->isNewline(i)) + for (; i < par.size(); ++i) { + if (par.isNewline(i)) return i; } - return par->size(); + return par.size(); } }; -pos_type -LyXText::rowBreakPoint(Row const & row) const +pos_type LyXText::rowBreakPoint(Row const & row) const { ParagraphList::iterator pit = row.par(); @@ -763,7 +791,7 @@ LyXText::rowBreakPoint(Row const & row) const LyXLayout_ptr const & layout = pit->layout(); if (layout->margintype == MARGIN_RIGHT_ADDRESS_BOX) - return addressBreakPoint(row.pos(), &*pit); + return addressBreakPoint(row.pos(), *pit); pos_type const pos = row.pos(); pos_type const body_pos = pit->beginningOfBody(); @@ -777,11 +805,12 @@ 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)); + int const left = leftMargin(row); int x = left; // pixel width since last breakpoint int chunkwidth = 0; + bool fullrow = false; pos_type i = pos; for (; i < last; ++i) { @@ -792,21 +821,27 @@ LyXText::rowBreakPoint(Row const & row) const char const c = pit->getChar(i); - int thiswidth = singleWidth(pit, i, c); + int thiswidth; // add the auto-hfill from label end to the body if (body_pos && i == body_pos) { - thiswidth += font_metrics::width(layout->labelsep, - getLabelFont(bv()->buffer(), &*pit)); + thiswidth = font_metrics::width(layout->labelsep, + getLabelFont(bv()->buffer(), pit)); if (pit->isLineSeparator(i - 1)) thiswidth -= singleWidth(pit, i - 1); + int left_margin = labelEnd(row); + if (thiswidth + x < left_margin) + thiswidth = left_margin - x; + thiswidth += singleWidth(pit, i, c); + } else { + thiswidth = singleWidth(pit, i, c); } x += thiswidth; chunkwidth += thiswidth; Inset * in = pit->isInset(i) ? pit->getInset(i) : 0; - bool fullrow = (in && (in->display() || in->needFullRow())); + fullrow = (in && (in->display() || in->needFullRow())); // break before a character that will fall off // the right of the row @@ -847,7 +882,8 @@ LyXText::rowBreakPoint(Row const & row) const } else { point = i - 1; } - break; + + return point; } if (point == last && x >= width) { @@ -859,8 +895,10 @@ LyXText::rowBreakPoint(Row const & row) const point = last; } - // manual labels cannot be broken in LaTeX - if (body_pos && point < body_pos) + // manual labels cannot be broken in LaTeX. But we + // want to make our on-screen rendering of footnotes + // etc. still break + if (!fullrow && body_pos && point < body_pos) point = body_pos - 1; return point; @@ -877,8 +915,11 @@ int LyXText::fill(RowList::iterator row, int paper_width) const // get the pure distance pos_type const last = lastPrintablePos(*this, row); + ParagraphList::iterator pit = row->par(); + LyXLayout_ptr const & layout = pit->layout(); + // special handling of the right address boxes - if (row->par()->layout()->margintype == MARGIN_RIGHT_ADDRESS_BOX) { + if (layout->margintype == MARGIN_RIGHT_ADDRESS_BOX) { int const tmpfill = row->fill(); row->fill(0); // the minfill in MarginLeft() w = leftMargin(*row); @@ -886,15 +927,12 @@ int LyXText::fill(RowList::iterator row, int paper_width) const } else w = leftMargin(*row); - ParagraphList::iterator pit = row->par(); - LyXLayout_ptr const & layout = pit->layout(); - 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)); + 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); @@ -905,7 +943,7 @@ int LyXText::fill(RowList::iterator row, int paper_width) const ++i; } if (body_pos > 0 && body_pos > last) { - w += font_metrics::width(layout->labelsep, getLabelFont(bv()->buffer(), &*pit)); + w += font_metrics::width(layout->labelsep, getLabelFont(bv()->buffer(), pit)); if (last >= 0 && pit->isLineSeparator(last)) w -= singleWidth(pit, last); int const left_margin = labelEnd(*row); @@ -914,6 +952,20 @@ int LyXText::fill(RowList::iterator row, int paper_width) const } int const fill = paper_width - w - rightMargin(*bv()->buffer(), *row); + + // If this case happens, it means that our calculation + // of the widths of the chars when we do rowBreakPoint() + // went wrong for some reason. Typically in list bodies. + // Things just about hobble on anyway, though you'll end + // up with a "fill_separator" less than zero, which corresponds + // to inter-word spacing being too small. Hopefully this problem + // will die when the label hacks die. + if (lyxerr.debugging() && fill < 0) { + lyxerr[Debug::GUI] << "Eek, fill() was < 0: " << fill + << " w " << w << " paper_width " << paper_width + << " right margin " << rightMargin(*bv()->buffer(), *row) << endl; + } + return fill; } @@ -921,29 +973,31 @@ int LyXText::fill(RowList::iterator row, int paper_width) const // returns the minimum space a manual label needs on the screen in pixel int LyXText::labelFill(Row const & row) const { - pos_type last = row.par()->beginningOfBody(); + ParagraphList::iterator pit = row.par(); + + 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. --last; // a separator at this end does not count - if (row.par()->isLineSeparator(last)) + if (pit->isLineSeparator(last)) --last; int w = 0; pos_type i = row.pos(); while (i <= last) { - w += singleWidth(row.par(), i); + w += singleWidth(pit, i); ++i; } int fill = 0; - string const & labwidstr = row.par()->params().labelWidthString(); + string const & labwidstr = pit->params().labelWidthString(); if (!labwidstr.empty()) { - LyXFont const labfont = getLabelFont(bv()->buffer(), &*row.par()); + LyXFont const labfont = getLabelFont(bv()->buffer(), pit); int const labwidth = font_metrics::width(labwidstr, labfont); fill = max(labwidth - w, 0); } @@ -963,13 +1017,9 @@ LColor::color LyXText::backgroundColor() const void LyXText::setHeightOfRow(RowList::iterator rit) { - // No need to do anything then... - if (rit == rows().end()) - return; + Assert(rit != rows().end()); // get the maximum ascent and the maximum descent - int asc = 0; - int desc = 0; float layoutasc = 0; float layoutdesc = 0; float tmptop = 0; @@ -984,24 +1034,23 @@ void LyXText::setHeightOfRow(RowList::iterator rit) // Correction: only the fontsize count. The other properties // are taken from the layoutfont. Nicer on the screen :) ParagraphList::iterator pit = rit->par(); - ParagraphList::iterator firstpit = pit; - LyXLayout_ptr const & layout = firstpit->layout(); + LyXLayout_ptr const & layout = pit->layout(); // as max get the first character of this row then it can increase but not // decrease the height. Just some point to start with so we don't have to // do the assignment below too often. - LyXFont font = getFont(bv()->buffer(), &*pit, rit->pos()); + LyXFont font = getFont(bv()->buffer(), pit, rit->pos()); LyXFont::FONT_SIZE const tmpsize = font.size(); - font = getLayoutFont(bv()->buffer(), &*pit); + font = getLayoutFont(bv()->buffer(), pit); LyXFont::FONT_SIZE const size = font.size(); font.setSize(tmpsize); - LyXFont labelfont = getLabelFont(bv()->buffer(), &*pit); + LyXFont labelfont = getLabelFont(bv()->buffer(), pit); float spacing_val = 1.0; - if (!rit->par()->params().spacing().isDefault()) { - spacing_val = rit->par()->params().spacing().getValue(); + if (!pit->params().spacing().isDefault()) { + spacing_val = pit->params().spacing().getValue(); } else { spacing_val = bv()->buffer()->params.spacing.getValue(); } @@ -1018,25 +1067,25 @@ void LyXText::setHeightOfRow(RowList::iterator rit) int labeladdon = 0; int maxwidth = 0; - if (!rit->par()->empty()) { + if (!pit->empty()) { // Check if any insets are larger for (pos_type pos = rit->pos(); pos <= pos_end; ++pos) { - if (rit->par()->isInset(pos)) { - tmpfont = getFont(bv()->buffer(), &*rit->par(), pos); - tmpinset = rit->par()->getInset(pos); + if (pit->isInset(pos)) { + tmpfont = getFont(bv()->buffer(), pit, pos); + tmpinset = pit->getInset(pos); if (tmpinset) { #if 1 // this is needed for deep update on initialitation #warning inset->update FIXME tmpinset->update(bv()); #endif - asc = tmpinset->ascent(bv(), tmpfont); - desc = tmpinset->descent(bv(), tmpfont); maxwidth += tmpinset->width(bv(), tmpfont); - maxasc = max(maxasc, asc); - maxdesc = max(maxdesc, desc); + maxasc = max(maxasc, + tmpinset->ascent(bv(), tmpfont)); + maxdesc = max(maxdesc, + tmpinset->descent(bv(), tmpfont)); } } else { - maxwidth += singleWidth(rit->par(), pos); + maxwidth += singleWidth(pit, pos); } } } @@ -1045,16 +1094,11 @@ void LyXText::setHeightOfRow(RowList::iterator rit) // This is not completely correct, but we can live with the small, // cosmetic error for now. LyXFont::FONT_SIZE maxsize = - rit->par()->highestFontInRange(rit->pos(), pos_end, size); + pit->highestFontInRange(rit->pos(), pos_end, size); if (maxsize > font.size()) { font.setSize(maxsize); - - asc = font_metrics::maxAscent(font); - desc = font_metrics::maxDescent(font); - if (asc > maxasc) - maxasc = asc; - if (desc > maxdesc) - maxdesc = desc; + maxasc = max(maxasc, font_metrics::maxAscent(font)); + maxdesc = max(maxdesc, font_metrics::maxDescent(font)); } // This is nicer with box insets: @@ -1064,20 +1108,20 @@ void LyXText::setHeightOfRow(RowList::iterator rit) rit->ascent_of_text(maxasc); // is it a top line? - if (!rit->pos() && (rit->par() == firstpit)) { + if (!rit->pos()) { // some parksips VERY EASY IMPLEMENTATION if (bv()->buffer()->params.paragraph_separation == BufferParams::PARSEP_SKIP) { if (layout->isParagraph() - && firstpit->getDepth() == 0 - && firstpit->previous()) + && pit->getDepth() == 0 + && pit != ownerParagraphs().begin()) { maxasc += bv()->buffer()->params.getDefSkip().inPixels(*bv()); - } else if (firstpit->previous() && - firstpit->previous()->layout()->isParagraph() && - firstpit->previous()->getDepth() == 0) + } else if (pit != ownerParagraphs().begin() && + boost::prior(pit)->layout()->isParagraph() && + boost::prior(pit)->getDepth() == 0) { // is it right to use defskip here too? (AS) maxasc += bv()->buffer()->params.getDefSkip().inPixels(*bv()); @@ -1085,23 +1129,23 @@ void LyXText::setHeightOfRow(RowList::iterator rit) } // the top margin - if (!rit->par()->previous() && !isInInset()) + if (pit == ownerParagraphs().begin() && !isInInset()) maxasc += PAPER_MARGIN; // add the vertical spaces, that the user added - maxasc += getLengthMarkerHeight(*bv(), firstpit->params().spaceTop()); + maxasc += getLengthMarkerHeight(*bv(), pit->params().spaceTop()); // do not forget the DTP-lines! // there height depends on the font of the nearest character - if (firstpit->params().lineTop()) + if (pit->params().lineTop()) maxasc += 2 * font_metrics::ascent('x', getFont(bv()->buffer(), - &*firstpit, 0)); + pit, 0)); // and now the pagebreaks - if (firstpit->params().pagebreakTop()) + if (pit->params().pagebreakTop()) maxasc += 3 * defaultRowHeight(); - if (firstpit->params().startOfAppendix()) + if (pit->params().startOfAppendix()) maxasc += 3 * defaultRowHeight(); // This is special code for the chapter, since the label of this @@ -1110,8 +1154,8 @@ void LyXText::setHeightOfRow(RowList::iterator rit) && bv()->buffer()->params.secnumdepth >= 0) { float spacing_val = 1.0; - if (!rit->par()->params().spacing().isDefault()) { - spacing_val = rit->par()->params().spacing().getValue(); + if (!pit->params().spacing().isDefault()) { + spacing_val = pit->params().spacing().getValue(); } else { spacing_val = bv()->buffer()->params.spacing.getValue(); } @@ -1128,12 +1172,12 @@ void LyXText::setHeightOfRow(RowList::iterator rit) if ((layout->labeltype == LABEL_TOP_ENVIRONMENT || layout->labeltype == LABEL_BIBLIO || layout->labeltype == LABEL_CENTERED_TOP_ENVIRONMENT) - && rit->par()->isFirstInSequence() - && !rit->par()->getLabelstring().empty()) + && isFirstInSequence(pit, ownerParagraphs()) + && !pit->getLabelstring().empty()) { float spacing_val = 1.0; - if (!rit->par()->params().spacing().isDefault()) { - spacing_val = rit->par()->params().spacing().getValue(); + if (!pit->params().spacing().isDefault()) { + spacing_val = pit->params().spacing().getValue(); } else { spacing_val = bv()->buffer()->params.spacing.getValue(); } @@ -1149,44 +1193,41 @@ void LyXText::setHeightOfRow(RowList::iterator rit) + layout->labelbottomsep * defaultRowHeight()); } - // and now the layout spaces, for example before and after a section, - // or between the items of a itemize or enumerate environment - - if (!firstpit->params().pagebreakTop()) { - Paragraph * prev = rit->par()->previous(); - if (prev) - prev = rit->par()->depthHook(rit->par()->getDepth()); - if (prev && prev->layout() == firstpit->layout() && - prev->getDepth() == firstpit->getDepth() && - prev->getLabelWidthString() == firstpit->getLabelWidthString()) + // And now the layout spaces, for example before and after + // a section, or between the items of a itemize or enumerate + // environment. + + if (!pit->params().pagebreakTop()) { + ParagraphList::iterator prev = + depthHook(pit, ownerParagraphs(), + pit->getDepth()); + if (prev != pit && prev->layout() == layout && + prev->getDepth() == pit->getDepth() && + prev->getLabelWidthString() == pit->getLabelWidthString()) { layoutasc = (layout->itemsep * defaultRowHeight()); } else if (rit != rows().begin()) { tmptop = layout->topsep; - if (boost::prior(rit)->par()->getDepth() >= rit->par()->getDepth()) + if (boost::prior(pit)->getDepth() >= pit->getDepth()) tmptop -= boost::prior(rit)->par()->layout()->bottomsep; if (tmptop > 0) layoutasc = (tmptop * defaultRowHeight()); - } else if (rit->par()->params().lineTop()) { + } else if (pit->params().lineTop()) { tmptop = layout->topsep; if (tmptop > 0) layoutasc = (tmptop * defaultRowHeight()); } - prev = rit->par()->outerHook(); - if (prev) { + prev = outerHook(pit, ownerParagraphs()); + if (prev != ownerParagraphs().end()) { maxasc += int(prev->layout()->parsep * defaultRowHeight()); - } else { - if (firstpit->previous() && - firstpit->previous()->getDepth() == 0 && - firstpit->previous()->layout() != - firstpit->layout()) - { - // avoid parsep - } else if (firstpit->previous()) { + } else if (pit != ownerParagraphs().begin()) { + ParagraphList::iterator prior_pit = boost::prior(pit); + if (prior_pit->getDepth() != 0 || + prior_pit->layout() == layout) { maxasc += int(layout->parsep * defaultRowHeight()); } } @@ -1194,42 +1235,42 @@ void LyXText::setHeightOfRow(RowList::iterator rit) } // is it a bottom line? - if (rit->par() == pit - && (boost::next(rit) == rows().end() || - boost::next(rit)->par() != rit->par())) { + RowList::iterator next_rit = boost::next(rit); + if (next_rit == rows().end() || + next_rit->par() != pit) { // the bottom margin - if (boost::next(pit) == ownerParagraphs().end() && + ParagraphList::iterator nextpit = boost::next(pit); + if (nextpit == ownerParagraphs().end() && !isInInset()) maxdesc += PAPER_MARGIN; // add the vertical spaces, that the user added - maxdesc += getLengthMarkerHeight(*bv(), firstpit->params().spaceBottom()); + maxdesc += getLengthMarkerHeight(*bv(), pit->params().spaceBottom()); // do not forget the DTP-lines! // there height depends on the font of the nearest character - if (firstpit->params().lineBottom()) + if (pit->params().lineBottom()) maxdesc += 2 * font_metrics::ascent('x', getFont(bv()->buffer(), - &*pit, + pit, max(pos_type(0), pit->size() - 1))); // and now the pagebreaks - if (firstpit->params().pagebreakBottom()) + if (pit->params().pagebreakBottom()) maxdesc += 3 * defaultRowHeight(); // and now the layout spaces, for example before and after // a section, or between the items of a itemize or enumerate // environment - if (!firstpit->params().pagebreakBottom() - && rit->par()->next()) { - ParagraphList::iterator nextpit = boost::next(rit->par()); - ParagraphList::iterator comparepit = rit->par(); + if (!pit->params().pagebreakBottom() + && nextpit != ownerParagraphs().end()) { + ParagraphList::iterator comparepit = pit; float usual = 0; float unusual = 0; if (comparepit->getDepth() > nextpit->getDepth()) { usual = (comparepit->layout()->bottomsep * defaultRowHeight()); - comparepit = comparepit->depthHook(nextpit->getDepth()); + comparepit = depthHook(comparepit, ownerParagraphs(), nextpit->getDepth()); if (comparepit->layout()!= nextpit->layout() || nextpit->getLabelWidthString() != comparepit->getLabelWidthString()) @@ -1251,8 +1292,8 @@ void LyXText::setHeightOfRow(RowList::iterator rit) } // incalculate the layout spaces - maxasc += int(layoutasc * 2 / (2 + firstpit->getDepth())); - maxdesc += int(layoutdesc * 2 / (2 + firstpit->getDepth())); + maxasc += int(layoutasc * 2 / (2 + pit->getDepth())); + maxdesc += int(layoutdesc * 2 / (2 + pit->getDepth())); // calculate the new height of the text height -= rit->height(); @@ -1288,7 +1329,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; @@ -1318,7 +1359,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; @@ -1328,13 +1369,15 @@ void LyXText::breakAgain(RowList::iterator rit) RowList::iterator end = rows().end(); if (z < rit->par()->size()) { - if (boost::next(rit) == end || - (boost::next(rit) != end && - boost::next(rit)->par() != rit->par())) { + RowList::iterator next_rit = boost::next(rit); + + if (next_rit == end || + (next_rit != end && + next_rit->par() != rit->par())) { // insert a new row ++z; Row newrow(rit->par(), z); - rit = rowlist_.insert(boost::next(rit), newrow); + rit = rowlist_.insert(next_rit, newrow); } else { ++rit; ++z; @@ -1369,20 +1412,22 @@ 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; RowList::iterator end = rows().end(); if (z < rit->par()->size()) { - if (boost::next(rit) == end || - (boost::next(rit) != end && - boost::next(rit)->par() != rit->par())) { + RowList::iterator next_rit = boost::next(rit); + + if (next_rit == end || + (next_rit != end && + next_rit->par() != rit->par())) { // insert a new row ++z; Row newrow(rit->par(), z); - rit = rowlist_.insert(boost::next(rit), newrow); + rit = rowlist_.insert(next_rit, newrow); } else { ++rit; ++z; @@ -1421,13 +1466,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(), &*boost::next(cursor.par())); + setUndo(bv(), Undo::FINISH, cursor.par()); // Always break behind a space // @@ -1447,7 +1491,7 @@ 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()); + bool const isempty = (cursor.par()->allowEmpty() && cursor.par()->empty()); ::breakParagraph(bv()->buffer()->params, paragraphs, cursor.par(), cursor.pos(), keep_layout); @@ -1458,25 +1502,27 @@ void LyXText::breakParagraph(ParagraphList & paragraphs, char keep_layout) cursor.par()->applyLayout(tclass.defaultLayout()); else // set to standard-layout - cursor.par()->next()->applyLayout(tclass.defaultLayout()); + boost::next(cursor.par())->applyLayout(tclass.defaultLayout()); } // if the cursor is at the beginning of a row without prior newline, // 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(); + int y = cursor.y() - cursorRow()->baseline(); // Do not forget the special right address boxes if (layout->margintype == MARGIN_RIGHT_ADDRESS_BOX) { - RowList::iterator r = cursor.row(); - while (r != rows().begin() && boost::prior(r)->par() == r->par()) { + RowList::iterator r = cursorRow(); + RowList::iterator beg = rows().begin(); + + while (r != beg && boost::prior(r)->par() == r->par()) { --r; y -= r->height(); } @@ -1484,33 +1530,34 @@ void LyXText::breakParagraph(ParagraphList & paragraphs, char keep_layout) 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 // ensure that the correct ParagraphList is used. Today that is not // the case and the Buffer::paragraphs is used. Not good. (Lgb) - while (!cursor.par()->next()->empty() - && cursor.par()->next()->isNewline(0)) - cursor.par()->next()->erase(0); + ParagraphList::iterator next_par = boost::next(cursor.par()); + + while (!next_par->empty() && next_par->isNewline(0)) + next_par->erase(0); - insertParagraph(cursor.par()->next(), boost::next(cursor.row())); + insertParagraph(next_par, boost::next(cursorRow())); updateCounters(); // This check is necessary. Otherwise the new empty paragraph will // be deleted automatically. And it is more friendly for the user! if (cursor.pos() || isempty) - setCursor(cursor.par()->next(), 0); + setCursor(next_par, 0); 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(); } @@ -1520,7 +1567,7 @@ void LyXText::breakParagraph(ParagraphList & paragraphs, char keep_layout) void LyXText::redoParagraph() { clearSelection(); - redoParagraphs(cursor, cursor.par()->next()); + redoParagraphs(cursor, boost::next(cursor.par())); setCursorIntern(cursor.par(), cursor.pos()); } @@ -1529,13 +1576,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(), &*boost::next(cursor.par())); + setUndo(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 = "+-/*"; @@ -1548,10 +1595,10 @@ void LyXText::insertChar(char c) cursor.pos() >= 1 && cursor.pos() < cursor.par()->size() && getFont(bv()->buffer(), - &*cursor.par(), + cursor.par(), cursor.pos()).number() == LyXFont::ON && getFont(bv()->buffer(), - &*cursor.par(), + cursor.par(), cursor.pos() - 1).number() == LyXFont::ON) ) number(bv()); // Set current_font.number to OFF @@ -1567,16 +1614,16 @@ void LyXText::insertChar(char c) cursor.par()->isNewline(cursor.pos() - 2)) ) { setCharFont(bv()->buffer(), - &*cursor.par(), + cursor.par(), cursor.pos() - 1, current_font); } else if (contains(number_seperators, c) && cursor.pos() >= 2 && getFont(bv()->buffer(), - &*cursor.par(), + cursor.par(), cursor.pos() - 2).number() == LyXFont::ON) { setCharFont(bv()->buffer(), - &*cursor.par(), + cursor.par(), cursor.pos() - 1, current_font); } @@ -1629,23 +1676,23 @@ 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())) { + Inset * 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(); + RowList::iterator row = cursorRow(); int y = cursor.y() - row->baseline(); if (c != Paragraph::META_INSET) { // Here case LyXText::InsertInset already insertet the character cursor.par()->insertChar(cursor.pos(), c); } - setCharFont(bv()->buffer(), &*cursor.par(), cursor.pos(), rawtmpfont); + setCharFont(bv()->buffer(), cursor.par(), cursor.pos(), rawtmpfont); if (!jumped_over_space) { // refresh the positions @@ -1664,7 +1711,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)); @@ -1690,9 +1737,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(); @@ -1716,13 +1764,18 @@ void LyXText::insertChar(char c) if (c == Paragraph::META_INSET || row->fill() < 0) { postPaint(y); 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; @@ -1730,13 +1783,16 @@ void LyXText::insertChar(char c) setCursor(cursor.par(), cursor.pos() + 1, false, cursor.boundary()); - if (isBoundary(bv()->buffer(), &*cursor.par(), cursor.pos()) + if (isBoundary(bv()->buffer(), *cursor.par(), cursor.pos()) != 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 { @@ -1776,7 +1832,7 @@ void LyXText::insertChar(char c) void LyXText::charInserted() { // Here we could call FinishUndo for every 20 characters inserted. - // This is from my experience how emacs does it. + // This is from my experience how emacs does it. (Lgb) static unsigned int counter; if (counter < 20) { ++counter; @@ -1793,16 +1849,16 @@ void LyXText::prepareToPrint(RowList::iterator rit, float & x, float & fill_label_hfill, bool bidi) const { - float nlh; - float w = rit->fill(); fill_hfill = 0; fill_label_hfill = 0; fill_separator = 0; fill_label_hfill = 0; + ParagraphList::iterator pit = rit->par(); + bool const is_rtl = - rit->par()->isRightToLeftPar(bv()->buffer()->params); + pit->isRightToLeftPar(bv()->buffer()->params); if (is_rtl) { x = (workWidth() > 0) ? rightMargin(*bv()->buffer(), *rit) : 0; @@ -1811,22 +1867,22 @@ void LyXText::prepareToPrint(RowList::iterator rit, float & x, ? leftMargin(*rit) : 0; // is there a manual margin with a manual label - LyXLayout_ptr const & layout = rit->par()->layout(); + LyXLayout_ptr const & layout = pit->layout(); if (layout->margintype == MARGIN_MANUAL && layout->labeltype == LABEL_MANUAL) { /// We might have real hfills in the label part - nlh = numberOfLabelHfills(*this, rit); + float nlh = numberOfLabelHfills(*this, rit); // A manual label par (e.g. List) has an auto-hfill // between the label text and the body of the // paragraph too. // But we don't want to do this auto hfill if the par // is empty. - if (!rit->par()->empty()) + if (!pit->empty()) ++nlh; - if (nlh && !rit->par()->getLabelWidthString().empty()) { + if (nlh && !pit->getLabelWidthString().empty()) { fill_label_hfill = labelFill(*rit) / nlh; } } @@ -1844,22 +1900,22 @@ void LyXText::prepareToPrint(RowList::iterator rit, float & x, // is it block, flushleft or flushright? // set x how you need it int align; - if (rit->par()->params().align() == LYX_ALIGN_LAYOUT) { + if (pit->params().align() == LYX_ALIGN_LAYOUT) { align = layout->align; } else { - align = rit->par()->params().align(); + align = pit->params().align(); } // center displayed insets Inset * inset = 0; - if (rit->pos() < rit->par()->size() - && rit->par()->isInset(rit->pos()) - && (inset = rit->par()->getInset(rit->pos())) + 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) ? LYX_ALIGN_BLOCK : LYX_ALIGN_CENTER; // ERT insets should always be LEFT ALIGNED on screen - inset = rit->par()->inInset(); + inset = pit->inInset(); if (inset && inset->owner() && inset->owner()->lyxCode() == Inset::ERT_CODE) { @@ -1871,13 +1927,14 @@ void LyXText::prepareToPrint(RowList::iterator rit, float & x, { float const ns = numberOfSeparators(*this, rit); RowList::iterator next_row = boost::next(rit); + ParagraphList::iterator next_pit = next_row->par(); if (ns && next_row != rowlist_.end() && - next_row->par() == rit->par() && - !(next_row->par()->isNewline(next_row->pos() - 1)) - && !(next_row->par()->isInset(next_row->pos()) && - next_row->par()->getInset(next_row->pos()) && - next_row->par()->getInset(next_row->pos())->display()) + next_pit == pit && + !(next_pit->isNewline(next_row->pos() - 1)) + && !(next_pit->isInset(next_row->pos()) && + next_pit->getInset(next_row->pos()) && + next_pit->getInset(next_row->pos())->display()) ) { fill_separator = w / ns; } else if (is_rtl) { @@ -1898,15 +1955,15 @@ void LyXText::prepareToPrint(RowList::iterator rit, float & x, computeBidiTables(bv()->buffer(), rit); if (is_rtl) { - pos_type body_pos = rit->par()->beginningOfBody(); + pos_type body_pos = pit->beginningOfBody(); pos_type last = lastPos(*this, rit); if (body_pos > 0 && (body_pos - 1 > last || - !rit->par()->isLineSeparator(body_pos - 1))) { + !pit->isLineSeparator(body_pos - 1))) { x += font_metrics::width(layout->labelsep, getLabelFont(bv()->buffer(), - &*rit->par())); + pit)); if (body_pos - 1 <= last) x += fill_label_hfill; } @@ -1923,33 +1980,8 @@ void LyXText::prepareToPrint(RowList::iterator rit, float & x, void LyXText::cursorRightOneWord() { - // treat floats, HFills and Insets as words - LyXCursor tmpcursor = cursor; - // CHECK See comment on top of text.C - - if (tmpcursor.pos() == tmpcursor.par()->size() - && tmpcursor.par()->next()) { - tmpcursor.par(tmpcursor.par()->next()); - tmpcursor.pos(0); - } else { - int steps = 0; - - // Skip through initial nonword stuff. - while (tmpcursor.pos() < tmpcursor.par()->size() && - ! tmpcursor.par()->isWord(tmpcursor.pos())) { - // printf("Current pos1 %d", tmpcursor.pos()) ; - tmpcursor.pos(tmpcursor.pos() + 1); - ++steps; - } - // Advance through word. - while (tmpcursor.pos() < tmpcursor.par()->size() && - tmpcursor.par()->isWord(tmpcursor.pos())) { - // printf("Current pos2 %d", tmpcursor.pos()) ; - tmpcursor.pos(tmpcursor.pos() + 1); - ++steps; - } - } - setCursor(tmpcursor.par(), tmpcursor.pos()); + ::cursorRightOneWord(cursor, ownerParagraphs()); + setCursor(cursor.par(), cursor.pos()); } @@ -1958,96 +1990,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 - cur = cursor; - while (cur.pos() - && (cur.par()->isSeparator(cur.pos() - 1) - || cur.par()->isKomma(cur.pos() - 1) - || cur.par()->isNewline(cur.pos() - 1)) - && !(cur.par()->isHfill(cur.pos() - 1) - || cur.par()->isInset(cur.pos() - 1))) - cur.pos(cur.pos() - 1); - - if (cur.pos() - && (cur.par()->isInset(cur.pos() - 1) - || cur.par()->isHfill(cur.pos() - 1))) { - cur.pos(cur.pos() - 1); - } else if (!cur.pos()) { - if (cur.par()->previous()) { - cur.par(cur.par()->previous()); - cur.pos(cur.par()->size()); - } - } else { // Here, cur != 0 - while (cur.pos() > 0 && - cur.par()->isWord(cur.pos() - 1)) - cur.pos(cur.pos() - 1); - } -} - - -// 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) @@ -2075,16 +2027,14 @@ void LyXText::acceptChange() if (!selection.set() && cursor.par()->size()) return; - bv()->hideCursor(); - if (selection.start.par() == selection.end.par()) { LyXCursor & startc = selection.start; LyXCursor & endc = selection.end; - setUndo(bv(), Undo::INSERT, &*startc.par(), &*boost::next(startc.par())); + setUndo(bv(), Undo::INSERT, startc.par()); startc.par()->acceptChange(startc.pos(), endc.pos()); finishUndo(); clearSelection(); - redoParagraphs(startc, startc.par()->next()); + redoParagraphs(startc, boost::next(startc.par())); setCursorIntern(startc.par(), 0); } #warning handle multi par selection @@ -2096,17 +2046,14 @@ void LyXText::rejectChange() if (!selection.set() && cursor.par()->size()) return; - bv()->hideCursor(); - if (selection.start.par() == selection.end.par()) { LyXCursor & startc = selection.start; LyXCursor & endc = selection.end; - setUndo(bv(), Undo::INSERT, &*startc.par(), - &*boost::next(startc.par())); + setUndo(bv(), Undo::INSERT, startc.par()); startc.par()->rejectChange(startc.pos(), endc.pos()); finishUndo(); clearSelection(); - redoParagraphs(startc, startc.par()->next()); + redoParagraphs(startc, boost::next(startc.par())); setCursorIntern(startc.par(), 0); } #warning handle multi par selection @@ -2127,9 +2074,9 @@ LyXText::selectNextWordToSpellcheck(float & value) } // we have to go on checking so move cursor to the next char if (cursor.pos() == cursor.par()->size()) { - if (!cursor.par()->next()) + if (boost::next(cursor.par()) == ownerParagraphs().end()) return word; - cursor.par(cursor.par()->next()); + cursor.par(boost::next(cursor.par())); cursor.pos(0); } else cursor.pos(cursor.pos() + 1); @@ -2139,7 +2086,7 @@ LyXText::selectNextWordToSpellcheck(float & value) // If this is not the very first word, skip rest of // current word because we are probably in the middle // of a word if there is text here. - if (cursor.pos() || cursor.par()->previous()) { + if (cursor.pos() || cursor.par() != ownerParagraphs().begin()) { while (cursor.pos() < cursor.par()->size() && cursor.par()->isLetter(cursor.pos())) cursor.pos(cursor.pos() + 1); @@ -2161,11 +2108,11 @@ LyXText::selectNextWordToSpellcheck(float & value) bool const is_good_inset = cpit->isInset(cpos) && cpit->getInset(cpos)->allowSpellcheck(); - - if (!isDeletedText(*cpit, cpos) + + if (!isDeletedText(*cpit, cpos) && (is_good_inset || cpit->isLetter(cpos))) - break; - + break; + cursor.pos(cpos + 1); } @@ -2173,7 +2120,8 @@ LyXText::selectNextWordToSpellcheck(float & value) if (cursor.pos() < cursor.par()->size() && cursor.par()->isInset(cursor.pos())) { // lock the inset! - cursor.par()->getInset(cursor.pos())->edit(bv()); + FuncRequest cmd(bv(), LFUN_INSET_EDIT, "left"); + cursor.par()->getInset(cursor.pos())->localDispatch(cmd); // now call us again to do the above trick // but obviously we have to start from down below ;) return bv()->text->selectNextWordToSpellcheck(value); @@ -2189,7 +2137,7 @@ LyXText::selectNextWordToSpellcheck(float & value) selection.cursor = cursor; string lang_code( - getFont(bv()->buffer(), &*cursor.par(), cursor.pos()) + getFont(bv()->buffer(), cursor.par(), cursor.pos()) .language()->code()); // and find the end of the word (insets like optional hyphens // and ligature break are part of a word) @@ -2243,7 +2191,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()); @@ -2264,7 +2211,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()); @@ -2286,7 +2232,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()); @@ -2312,13 +2257,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(), &*boost::next(to.par())); + setUndo(bv(), Undo::FINISH, from.par(), to.par()); pos_type pos = from.pos(); ParagraphList::iterator pit = from.par(); @@ -2347,13 +2291,13 @@ void LyXText::changeCase(LyXText::TextCase action) } #warning changes pit->setChar(pos, c); - checkParagraph(&*pit, pos); + checkParagraph(pit, pos); ++pos; } - if (to.row() != from.row()) - postPaint(from.y() - from.row()->baseline()); + if (getRow(to) != getRow(from)) + postPaint(from.y() - getRow(from)->baseline()); } @@ -2363,8 +2307,9 @@ void LyXText::Delete() LyXCursor old_cursor = cursor; int const old_cur_par_id = old_cursor.par()->id(); - int const old_cur_par_prev_id = old_cursor.par()->previous() ? - old_cursor.par()->previous()->id() : -1; + int const old_cur_par_prev_id = + (old_cursor.par() != ownerParagraphs().begin() ? + boost::prior(old_cursor.par())->id() : -1); // just move to the right cursorRight(bv()); @@ -2375,7 +2320,7 @@ void LyXText::Delete() // and that can very well delete the par or par->previous in // old_cursor. Will a solution where we compare paragraph id's //work better? - if ((cursor.par()->previous() ? cursor.par()->previous()->id() : -1) + if ((cursor.par() != ownerParagraphs().begin() ? boost::prior(cursor.par())->id() : -1) == old_cur_par_prev_id && cursor.par()->id() != old_cur_par_id) { // delete-empty-paragraph-mechanism has done it @@ -2387,8 +2332,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(), &*boost::next(cursor.par())); + setUndo(bv(), Undo::DELETE, cursor.par()); cursor = tmpcursor; backspace(); } @@ -2421,36 +2365,37 @@ void LyXText::backspace() // left and let the DeleteEmptyParagraphMechanism handle the actual deletion // of the paragraph. - if (cursor.par()->previous()) { - Paragraph * tmppar = cursor.par()->previous(); - if (cursor.par()->layout() == tmppar->layout() - && cursor.par()->getAlign() == tmppar->getAlign()) { + if (cursor.par() != ownerParagraphs().begin()) { + ParagraphList::iterator tmppit = boost::prior(cursor.par()); + if (cursor.par()->layout() == tmppit->layout() + && cursor.par()->getAlign() == tmppit->getAlign()) { // Inherit bottom DTD from the paragraph below. // (the one we are deleting) - tmppar->params().lineBottom(cursor.par()->params().lineBottom()); - tmppar->params().spaceBottom(cursor.par()->params().spaceBottom()); - tmppar->params().pagebreakBottom(cursor.par()->params().pagebreakBottom()); + tmppit->params().lineBottom(cursor.par()->params().lineBottom()); + tmppit->params().spaceBottom(cursor.par()->params().spaceBottom()); + tmppit->params().pagebreakBottom(cursor.par()->params().pagebreakBottom()); } 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(cursor.y() - cursorRow()->baseline()); } return; } } - if (cursor.par()->previous()) { + if (cursor.par() != ownerParagraphs().begin()) { setUndo(bv(), Undo::DELETE, - cursor.par()->previous(), cursor.par()->next()); + 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 @@ -2492,7 +2437,7 @@ void LyXText::backspace() if (cursor.pos()) cursor.pos(cursor.pos() - 1); - postPaint(cursor.y() - cursor.row()->baseline()); + postPaint(cursor.y() - cursorRow()->baseline()); // remove the lost paragraph // This one is not safe, since the paragraph that the tmprow and the @@ -2503,7 +2448,7 @@ void LyXText::backspace() //RemoveRow(tmprow); // This rebuilds the rows. - appendParagraph(cursor.row()); + appendParagraph(cursorRow()); updateCounters(); // the row may have changed, block, hfills etc. @@ -2512,8 +2457,7 @@ void LyXText::backspace() } else { // this is the code for a normal backspace, not pasting // any paragraphs - setUndo(bv(), Undo::DELETE, - &*cursor.par(), &*boost::next(cursor.par())); + setUndo(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, @@ -2532,7 +2476,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 @@ -2540,7 +2484,7 @@ void LyXText::backspace() if (cursor.pos() < lastPos(*this, row) || !cursor.par()->isLineSeparator(cursor.pos())) { row->fill(row->fill() + singleWidth( - &*cursor.par(), + cursor.par(), cursor.pos())); } @@ -2561,7 +2505,7 @@ void LyXText::backspace() if (cursor.pos() < cursor.par()->size() && !cursor.par()->isSeparator(cursor.pos())) { cursor.par()->insertChar(cursor.pos(), ' '); - setCharFont(bv()->buffer(), &*cursor.par(), + setCharFont(bv()->buffer(), cursor.par(), cursor.pos(), current_font); // refresh the positions tmprow = row; @@ -2688,7 +2632,7 @@ void LyXText::backspace() // current_font = rawtmpfont; // real_current_font = realtmpfont; - if (isBoundary(bv()->buffer(), &*cursor.par(), cursor.pos()) + if (isBoundary(bv()->buffer(), *cursor.par(), cursor.pos()) != cursor.boundary()) setCursor(cursor.par(), cursor.pos(), false, !cursor.boundary()); @@ -2711,9 +2655,45 @@ void LyXText::backspace() } +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(Paragraph * par, pos_type pos, int & y) const +LyXText::getRow(ParagraphList::iterator pit, pos_type pos, int & y) const { y = 0; @@ -2723,7 +2703,7 @@ LyXText::getRow(Paragraph * par, pos_type pos, int & y) const // 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() != par) { + while (boost::next(rit) != end && rit->par() != pit) { y += rit->height(); ++rit; } @@ -2731,7 +2711,7 @@ LyXText::getRow(Paragraph * par, pos_type pos, int & y) const // now find the wanted row while (rit->pos() < pos && boost::next(rit) != end - && boost::next(rit)->par() == par + && boost::next(rit)->par() == pit && boost::next(rit)->pos() <= pos) { y += rit->height(); ++rit; @@ -2743,18 +2723,41 @@ LyXText::getRow(Paragraph * par, pos_type pos, int & y) const RowList::iterator LyXText::getRowNearY(int & y) const { - // If possible we should optimize this method. (Lgb) - int tmpy = 0; - RowList::iterator rit = rowlist_.begin(); - RowList::iterator end = rowlist_.end(); + RowList::iterator rit = anchor_row_; + RowList::iterator const beg = rows().begin(); + RowList::iterator const end = rows().end(); - while (rit != end && boost::next(rit) != end && tmpy + rit->height() <= y) { - tmpy += rit->height(); - ++rit; + if (rows().empty()) { + y = 0; + return end; + } + if (rit == end) + rit = beg; + + int tmpy = rit->y(); + + if (tmpy <= y) { + while (rit != end && tmpy <= y) { + tmpy += rit->height(); + ++rit; + } + if (rit != beg) { + --rit; + tmpy -= rit->height(); + } + } else { + while (rit != beg && tmpy > y) { + --rit; + tmpy -= rit->height(); + } + } + if (tmpy < 0 || rit == end) { + tmpy = 0; + rit = beg; } - // return the real y + // return the rel y y = tmpy; return rit;