X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ftext2.C;h=97fc51aa5b048f91b88c6b82dfdd8765816c54b7;hb=c96136c04080415efdfb6df9b3d25f9e2e732782;hp=2cd1c61f69c6d82f85ac939cbfbfa9282cc5ea05;hpb=f86ab4de32daf3e583342879debbb212093cc9c2;p=lyx.git diff --git a/src/text2.C b/src/text2.C index 2cd1c61f69..97fc51aa5b 100644 --- a/src/text2.C +++ b/src/text2.C @@ -1,12 +1,21 @@ -/* This file is part of - * ====================================================== +/** + * \file text2.C + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. * - * LyX, The Document Processor + * \author Asger Alstrup + * \author Lars Gullik Bjønnes + * \author Alfredo Braunstein + * \author Jean-Marc Lasgouttes + * \author Angus Leeming + * \author John Levon + * \author André Pönitz + * \author Allan Rae + * \author Dekel Tsur + * \author Jürgen Vigna * - * Copyright 1995 Matthias Ettrich - * Copyright 1995-2001 The LyX Team. - * - * ====================================================== */ + * Full author contact details are available in file CREDITS. + */ #include @@ -28,7 +37,6 @@ #include "frontends/font_metrics.h" #include "debug.h" #include "lyxrc.h" -#include "lyxrow.h" #include "FloatList.h" #include "language.h" #include "ParagraphParameters.h" @@ -60,19 +68,12 @@ using std::pair; using lyx::pos_type; -LyXText::LyXText(BufferView * bv) - : height(0), width(0), anchor_row_offset_(0), - inset_owner(0), the_locking_inset(0), bv_owner(bv) -{ - anchor_row_ = rows().end(); -} - - -LyXText::LyXText(BufferView * bv, InsetText * inset) - : height(0), width(0), anchor_row_offset_(0), - inset_owner(inset), the_locking_inset(0), bv_owner(bv) +LyXText::LyXText(BufferView * bv, InsetText * inset, bool ininset, + ParagraphList & paragraphs) + : height(0), width(0), anchor_y_(0), + inset_owner(inset), the_locking_inset(0), bv_owner(bv), + in_inset_(ininset), paragraphs_(paragraphs) { - anchor_row_ = rows().end(); } @@ -80,17 +81,20 @@ void LyXText::init(BufferView * bview) { bv_owner = bview; - rowlist_.clear(); - width = height = 0; + ParagraphList::iterator const beg = ownerParagraphs().begin(); + ParagraphList::iterator const end = ownerParagraphs().end(); + for (ParagraphList::iterator pit = beg; pit != end; ++pit) + pit->rows.clear(); - anchor_row_ = rows().end(); - anchor_row_offset_ = 0; + width = 0; + height = 0; - current_font = getFont(ownerParagraphs().begin(), 0); + anchor_y_ = 0; - redoParagraphs(ownerParagraphs().begin(), ownerParagraphs().end()); + current_font = getFont(beg, 0); - setCursorIntern(rowlist_.begin()->par(), 0); + redoParagraphs(beg, end); + setCursorIntern(beg, 0); selection.cursor = cursor; updateCounters(); @@ -102,8 +106,6 @@ void LyXText::init(BufferView * bview) // The difference is that this one is used for displaying, and thus we // are allowed to make cosmetic improvements. For instance make footnotes // smaller. (Asger) -// If position is -1, we get the layout font of the paragraph. -// If position is -2, we get the font of the manual label of the paragraph. LyXFont LyXText::getFont(ParagraphList::iterator pit, pos_type pos) const { Assert(pos >= 0); @@ -243,51 +245,6 @@ void LyXText::setCharFont( } -// removes the row and reset the touched counters -void LyXText::removeRow(RowList::iterator rit) -{ - if (anchor_row_ == rit) { - if (rit != rows().begin()) { - anchor_row_ = boost::prior(rit); - anchor_row_offset_ += anchor_row_->height(); - } else { - anchor_row_ = boost::next(rit); - anchor_row_offset_ -= rit->height(); - } - } - - // the text becomes smaller - height -= rit->height(); - - rowlist_.erase(rit); -} - - -// remove all following rows of the paragraph of the specified row. -void LyXText::removeParagraph(RowList::iterator rit) -{ - ParagraphList::iterator tmppit = rit->par(); - ++rit; - - while (rit != rows().end() && rit->par() == tmppit) { - RowList::iterator tmprit = boost::next(rit); - removeRow(rit); - rit = tmprit; - } -} - - -void LyXText::insertParagraph(ParagraphList::iterator pit, - RowList::iterator rit) -{ - // insert a new row, starting at position 0 - rit = rowlist_.insert(rit, Row(pit, 0)); - - // and now append the whole paragraph before the new row - appendParagraph(rit); -} - - InsetOld * LyXText::getInset() const { ParagraphList::iterator pit = cursor.par(); @@ -325,7 +282,7 @@ void LyXText::toggleInset() else inset->open(bv()); - bv()->updateInset(); + bv()->updateInset(inset); } @@ -384,11 +341,10 @@ LyXText::setLayout(LyXCursor & cur, LyXCursor & sstart_cur, do { pit->applyLayout(lyxlayout); makeFontEntriesLayoutSpecific(bv()->buffer()->params, *pit); - ParagraphList::iterator fppit = pit; - fppit->params().spaceTop(lyxlayout->fill_top ? + pit->params().spaceTop(lyxlayout->fill_top ? VSpace(VSpace::VFILL) : VSpace(VSpace::NONE)); - fppit->params().spaceBottom(lyxlayout->fill_bottom ? + pit->params().spaceBottom(lyxlayout->fill_bottom ? VSpace(VSpace::VFILL) : VSpace(VSpace::NONE)); if (lyxlayout->margintype == MARGIN_MANUAL) @@ -450,8 +406,8 @@ void LyXText::setLayout(string const & layout) bool LyXText::changeDepth(bv_funcs::DEPTH_CHANGE type, bool test_only) { - ParagraphList::iterator pit(cursor.par()); - ParagraphList::iterator end(cursor.par()); + ParagraphList::iterator pit = cursor.par(); + ParagraphList::iterator end = cursor.par(); ParagraphList::iterator start = pit; if (selection.set()) { @@ -479,10 +435,8 @@ bool LyXText::changeDepth(bv_funcs::DEPTH_CHANGE type, bool test_only) if (depth < prev_after_depth && pit->layout()->labeltype != LABEL_BIBLIO) { changed = true; - if (!test_only) { + if (!test_only) pit->params().depth(depth + 1); - } - } } else if (depth) { changed = true; @@ -502,7 +456,6 @@ bool LyXText::changeDepth(bv_funcs::DEPTH_CHANGE type, bool test_only) if (test_only) return changed; - redoParagraphs(start, pastend); // We need to actually move the text->cursor. I don't @@ -591,164 +544,100 @@ void LyXText::setFont(LyXFont const & font, bool toggleall) } -void LyXText::redoHeightOfParagraph() +int LyXText::redoParagraphInternal(ParagraphList::iterator pit) { - RowList::iterator tmprow = cursorRow(); + RowList::iterator rit = pit->rows.begin(); + RowList::iterator end = pit->rows.end(); - setHeightOfRow(tmprow); + // remove rows of paragraph, keep track of height changes + for (int i = 0; rit != end; ++rit, ++i) + height -= rit->height(); + pit->rows.clear(); - while (tmprow != rows().begin() - && boost::prior(tmprow)->par() == tmprow->par()) { - --tmprow; - setHeightOfRow(tmprow); + // redo insets + InsetList::iterator ii = pit->insetlist.begin(); + InsetList::iterator iend = pit->insetlist.end(); + for (; ii != iend; ++ii) { + Dimension dim; + MetricsInfo mi(bv(), getFont(pit, ii->pos), workWidth()); + ii->inset->metrics(mi, dim); } - setCursor(cursor.par(), cursor.pos(), false, cursor.boundary()); -} + // rebreak the paragraph + for (pos_type z = 0; z < pit->size() + 1; ) { + Row row(z); + z = rowBreakPoint(pit, row) + 1; + row.end(z); + pit->rows.push_back(row); + } + int par_width = 0; + // set height and fill and width of rows + int const ww = workWidth(); + for (rit = pit->rows.begin(); rit != end; ++rit) { + int const f = fill(pit, rit, ww); + int const w = ww - f; + par_width = std::max(par_width, w); + rit->fill(f); + rit->width(w); + prepareToPrint(pit, rit); + setHeightOfRow(pit, rit); + height += rit->height(); + } -RowList::iterator LyXText::firstRow(ParagraphList::iterator pit) -{ - RowList::iterator rit; - for (rit = rows().begin(); rit != rows().end(); ++rit) - if (rit->par() == pit) - break; - return rit; + //lyxerr << "redoParagraph: " << pit->rows.size() << " rows\n"; + return par_width; } -// rebreaks all paragraphs between the specified pars -// This function is needed after SetLayout and SetFont etc. -void LyXText::redoParagraphs(ParagraphList::iterator start, +int LyXText::redoParagraphs(ParagraphList::iterator start, ParagraphList::iterator end) { - for ( ; start != end; ++start) - redoParagraph(start); + int pars_width = 0; + for ( ; start != end; ++start) { + int par_width = redoParagraphInternal(start); + pars_width = std::max(par_width, pars_width); + } + updateRowPositions(); + return pars_width; } void LyXText::redoParagraph(ParagraphList::iterator pit) { - RowList::iterator rit = firstRow(pit); - - // remove paragraph from rowlist - while (rit != rows().end() && rit->par() == pit) { - RowList::iterator rit2 = rit++; - removeRow(rit2); - } - - // reinsert the paragraph - // insert a new row, starting at position 0 - Row newrow(pit, 0); - rit = rowlist_.insert(rit, newrow); - //newrow.dump("newrow: "); - - // and now append the whole paragraph before the new row - pos_type const last = rit->par()->size(); - bool done = false; - - do { - pos_type z = rowBreakPoint(*rit); - - RowList::iterator tmprow = rit; - //tmprow->dump("tmprow: "); - - if (z < last) { - ++z; - Row newrow(rit->par(), z); - //newrow.dump("newrow2: "); - rit = rowlist_.insert(boost::next(rit), newrow); - } else { - done = true; - } - - // Set the dimensions of the row - // fixed fill setting now by calling inset->update() in - // SingleWidth when needed! - //tmprow->dump("tmprow 1: "); - tmprow->fill(fill(tmprow, workWidth())); - //tmprow->dump("tmprow 2: "); - setHeightOfRow(tmprow); - //tmprow->dump("tmprow 3: "); - height += rit->height(); - - } while (!done); - - setHeightOfRow(rows().begin()); + redoParagraphInternal(pit); + updateRowPositions(); } void LyXText::fullRebreak() { - lyxerr << "fullRebreak" << endl; redoParagraphs(ownerParagraphs().begin(), ownerParagraphs().end()); - setCursorIntern(cursor.par(), cursor.pos()); + redoCursor(); selection.cursor = cursor; } void LyXText::metrics(MetricsInfo & mi, Dimension & dim) { - //lyxerr << "LyXText::metrics: width: " << mi.base.textwidth << endl; + //lyxerr << "LyXText::metrics: width: " << mi.base.textwidth + // << " workWidth: " << workWidth() << endl; //Assert(mi.base.textwidth); // rebuild row cache - rowlist_.clear(); - width = height = 0; + width = 0; + ///height = 0; - anchor_row_ = rows().end(); - anchor_row_offset_ = 0; - - ParagraphList::iterator pit = ownerParagraphs().begin(); - ParagraphList::iterator end = ownerParagraphs().end(); - - for (; pit != end; ++pit) { - InsetList::iterator ii = pit->insetlist.begin(); - InsetList::iterator iend = pit->insetlist.end(); - for (; ii != iend; ++ii) { - Dimension dim; - MetricsInfo m = mi; -#warning FIXME: pos != 0 - m.base.font = getFont(pit, 0); - ii->inset->metrics(m, dim); - } - -#if 1 - // insert a new row, starting at position 0 - Row newrow(pit, 0); - RowList::iterator rit = rowlist_.insert(rowlist_.end(), newrow); - - // and now append the whole paragraph before the new row - appendParagraph(rit); -#else - redoParagraph(pit); -#endif - } - - // compute height - //lyxerr << "height 0: " << height << endl; - //for (RowList::iterator rit = rows().begin(); rit != rows().end(); ++rit) { - // height += rit->height(); - //} - //lyxerr << "height 1: " << height << endl; + //anchor_y_ = 0; + width = redoParagraphs(ownerParagraphs().begin(), ownerParagraphs().end()); // final dimension - dim.asc = rows().begin()->ascent_of_text(); + dim.asc = firstRow()->ascent_of_text(); dim.des = height - dim.asc; dim.wid = std::max(mi.base.textwidth, int(width)); } -void LyXText::partialRebreak() -{ - if (rows().empty()) { - init(bv()); - return; - } - breakAgain(rows().begin()); -} - - // important for the screen @@ -786,20 +675,12 @@ void LyXText::cursorEnd() return; RowList::iterator rit = cursorRow(); - RowList::iterator next_rit = boost::next(rit); - ParagraphList::iterator pit = rit->par(); - pos_type last_pos = lastPos(*this, rit); - - if (next_rit == rows().end() || next_rit->par() != pit) { - ++last_pos; - } else { - if (pit->empty() || - (pit->getChar(last_pos) != ' ' && !pit->isNewline(last_pos))) { - ++last_pos; - } - } - - setCursor(pit, last_pos); + ParagraphList::iterator pit = cursor.par(); + pos_type pos = lastPos(*pit, rit); + /* cursor should be before a hard newline only */ + if (!pit->isNewline(pos)) + ++pos; + setCursor(pit, pos); } @@ -863,7 +744,7 @@ string LyXText::getStringToIndex() else if (selection.start.par() != selection.end.par()) bv()->owner()->message(_("Cannot index more than one paragraph!")); else - idxstring = selectionAsString(bv()->buffer(), false); + idxstring = selectionAsString(*bv()->buffer(), false); // Reset cursors to their original position. cursor = reset_cursor; @@ -879,8 +760,8 @@ string LyXText::getStringToIndex() // the DTP switches for paragraphs. LyX will store them in the first -// physicla paragraph. When a paragraph is broken, the top settings rest, -// the bottom settings are given to the new one. So I can make shure, +// physical paragraph. When a paragraph is broken, the top settings rest, +// the bottom settings are given to the new one. So I can make sure, // they do not duplicate themself and you cannnot make dirty things with // them! @@ -958,14 +839,14 @@ void LyXText::setParagraph(bool line_top, bool line_bottom, setSelection(); setCursor(tmpcursor.par(), tmpcursor.pos()); if (inset_owner) - bv()->updateInset(); + bv()->updateInset(inset_owner); } // set the counter of a paragraph. This includes the labels -void LyXText::setCounter(Buffer const * buf, ParagraphList::iterator pit) +void LyXText::setCounter(Buffer const & buf, ParagraphList::iterator pit) { - LyXTextClass const & textclass = buf->params.getLyXTextClass(); + LyXTextClass const & textclass = buf.params.getLyXTextClass(); LyXLayout_ptr const & layout = pit->layout(); if (pit != ownerParagraphs().begin()) { @@ -984,13 +865,12 @@ void LyXText::setCounter(Buffer const * buf, ParagraphList::iterator pit) pit->itemdepth = 0; } - /* Maybe we have to increment the enumeration depth. - * BUT, enumeration in a footnote is considered in isolation from its - * surrounding paragraph so don't increment if this is the - * first line of the footnote - * AND, bibliographies can't have their depth changed ie. they - * are always of depth 0 - */ + // Maybe we have to increment the enumeration depth. + // BUT, enumeration in a footnote is considered in isolation from its + // surrounding paragraph so don't increment if this is the + // first line of the footnote + // AND, bibliographies can't have their depth changed ie. they + // are always of depth 0 if (pit != ownerParagraphs().begin() && boost::prior(pit)->getDepth() < pit->getDepth() && boost::prior(pit)->layout()->labeltype == LABEL_COUNTER_ENUMI @@ -1012,9 +892,8 @@ void LyXText::setCounter(Buffer const * buf, ParagraphList::iterator pit) } if (layout->margintype == MARGIN_MANUAL) { - if (pit->params().labelWidthString().empty()) { + if (pit->params().labelWidthString().empty()) pit->setLabelWidthString(layout->labelstring()); - } } else { pit->setLabelWidthString(string()); } @@ -1025,7 +904,7 @@ void LyXText::setCounter(Buffer const * buf, ParagraphList::iterator pit) ostringstream s; - if (i >= 0 && i <= buf->params.secnumdepth) { + if (i >= 0 && i <= buf.params.secnumdepth) { string numbertype; string langtype; @@ -1033,9 +912,9 @@ void LyXText::setCounter(Buffer const * buf, ParagraphList::iterator pit) // Is there a label? Useful for Chapter layout if (!pit->params().appendix()) { - s << buf->B_(layout->labelstring()); + s << buf.B_(layout->labelstring()); } else { - s << buf->B_(layout->labelstring_appendix()); + s << buf.B_(layout->labelstring_appendix()); } // Use of an integer is here less than elegant. For now. @@ -1044,7 +923,7 @@ void LyXText::setCounter(Buffer const * buf, ParagraphList::iterator pit) numbertype = "sectioning"; } else { numbertype = "appendix"; - if (pit->isRightToLeftPar(buf->params)) + if (pit->isRightToLeftPar(buf.params)) langtype = "hebrew"; else langtype = "latin"; @@ -1098,7 +977,7 @@ void LyXText::setCounter(Buffer const * buf, ParagraphList::iterator pit) } // In biblio should't be following counters but... } else { - string s = buf->B_(layout->labelstring()); + string s = buf.B_(layout->labelstring()); // the caption hack: if (layout->labeltype == LABEL_SENSITIVE) { @@ -1115,9 +994,10 @@ void LyXText::setCounter(Buffer const * buf, ParagraphList::iterator pit) isOK = true; break; } else { + Paragraph const * owner = &ownerPar(buf, in); tmppit = ownerParagraphs().begin(); for ( ; tmppit != end; ++tmppit) - if (&*tmppit == in->parOwner()) + if (&*tmppit == owner) break; } } @@ -1137,7 +1017,7 @@ void LyXText::setCounter(Buffer const * buf, ParagraphList::iterator pit) textclass.counters().step(fl.type()); // Doesn't work... yet. - s = bformat(_("%1$s #:"), buf->B_(fl.name())); + s = bformat(_("%1$s #:"), buf.B_(fl.name())); } else { // par->SetLayout(0); // s = layout->labelstring; @@ -1167,18 +1047,12 @@ void LyXText::setCounter(Buffer const * buf, ParagraphList::iterator pit) // Updates all counters. Paragraphs with changed label string will be rebroken void LyXText::updateCounters() { - RowList::iterator rowit = rows().begin(); - ParagraphList::iterator pit = rowit->par(); - - // CHECK if this is really needed. (Lgb) + // start over bv()->buffer()->params.getLyXTextClass().counters().reset(); ParagraphList::iterator beg = ownerParagraphs().begin(); ParagraphList::iterator end = ownerParagraphs().end(); - for (; pit != end; ++pit) { - while (rowit->par() != pit) - ++rowit; - + for (ParagraphList::iterator pit = beg; pit != end; ++pit) { string const oldLabel = pit->params().labelString(); size_t maxdepth = 0; @@ -1189,14 +1063,12 @@ void LyXText::updateCounters() pit->params().depth(maxdepth); // setCounter can potentially change the labelString. - setCounter(bv()->buffer(), pit); + setCounter(*bv()->buffer(), pit); string const & newLabel = pit->params().labelString(); - if (oldLabel.empty() && !newLabel.empty()) { - removeParagraph(rowit); - appendParagraph(rowit); - } + if (oldLabel != newLabel) + redoParagraph(pit); } } @@ -1211,14 +1083,12 @@ void LyXText::insertInset(InsetOld * inset) // Just to rebreak and refresh correctly. // The character will not be inserted a second time insertChar(Paragraph::META_INSET); - // If we enter a highly editable inset the cursor should be to before - // the inset. This couldn't happen before as Undo was not handled inside - // inset now after the Undo LyX tries to call inset->Edit(...) again - // and cannot do this as the cursor is behind the inset and GetInset + // If we enter a highly editable inset the cursor should be before + // the inset. After an Undo LyX tries to call inset->edit(...) + // and fails if the cursor is behind the inset and getInset // does not return the inset! - if (isHighlyEditableInset(inset)) { + if (isHighlyEditableInset(inset)) cursorLeft(true); - } unFreezeUndo(); } @@ -1233,7 +1103,7 @@ void LyXText::cutSelection(bool doclear, bool realcut) // finished. The solution used currently just works, to make it // faster we need to be more clever and probably also have more // calls to stuffClipboard. (Lgb) - bv()->stuffClipboard(selectionAsString(bv()->buffer(), true)); + bv()->stuffClipboard(selectionAsString(*bv()->buffer(), true)); // This doesn't make sense, if there is no selection if (!selection.set()) @@ -1260,7 +1130,6 @@ void LyXText::cutSelection(bool doclear, bool realcut) recordUndo(bv(), Undo::DELETE, selection.start.par(), boost::prior(undoendpit)); - endpit = selection.end.par(); int endpos = selection.end.pos(); @@ -1299,7 +1168,7 @@ void LyXText::cutSelection(bool doclear, bool realcut) void LyXText::copySelection() { // stuff the selection onto the X clipboard, from an explicit copy request - bv()->stuffClipboard(selectionAsString(bv()->buffer(), true)); + bv()->stuffClipboard(selectionAsString(*bv()->buffer(), true)); // this doesnt make sense, if there is no selection if (!selection.set()) @@ -1450,38 +1319,6 @@ void LyXText::insertStringAsParagraphs(string const & str) } -void LyXText::checkParagraph(ParagraphList::iterator pit, pos_type pos) -{ - breakAgain(getRow(pit, pos)); - setCursorIntern(cursor.par(), cursor.pos(), false, cursor.boundary()); -} - - -// returns false if inset wasn't found -bool LyXText::updateInset(InsetOld * inset) -{ - // first check the current paragraph - int pos = cursor.par()->getPositionOfInset(inset); - if (pos != -1) { - checkParagraph(cursor.par(), pos); - return true; - } - - // check every paragraph - ParagraphList::iterator par = ownerParagraphs().begin(); - ParagraphList::iterator end = ownerParagraphs().end(); - for (; par != end; ++par) { - pos = par->getPositionOfInset(inset); - if (pos != -1) { - checkParagraph(par, pos); - return true; - } - } - - return false; -} - - bool LyXText::setCursor(ParagraphList::iterator pit, pos_type pos, bool setfont, bool boundary) @@ -1492,6 +1329,13 @@ bool LyXText::setCursor(ParagraphList::iterator pit, } +void LyXText::redoCursor() +{ +#warning maybe the same for selections? + setCursor(cursor, cursor.par(), cursor.pos(), cursor.boundary()); +} + + void LyXText::setCursor(LyXCursor & cur, ParagraphList::iterator pit, pos_type pos, bool boundary) { @@ -1500,41 +1344,30 @@ void LyXText::setCursor(LyXCursor & cur, ParagraphList::iterator pit, cur.par(pit); cur.pos(pos); cur.boundary(boundary); - if (rows().empty()) + if (noRows()) return; // get the cursor y position in text - int y = 0; - RowList::iterator row = getRow(pit, pos, y); - RowList::iterator beg = rows().begin(); + + RowList::iterator row = getRow(pit, pos); + int y = row->y(); RowList::iterator old_row = row; // if we are before the first char of this row and are still in the // same paragraph and there is a previous row then put the cursor on // the end of the previous row cur.iy(y + row->baseline()); - if (row != beg && - pos && - boost::prior(row)->par() == row->par() && - pos < pit->size() && - pit->getChar(pos) == Paragraph::META_INSET) { - InsetOld * ins = pit->getInset(pos); - if (ins && (ins->needFullRow() || ins->display())) { - --row; - y -= row->height(); - } - } // y is now the beginning of the cursor row y += row->baseline(); // y is now the cursor baseline cur.y(y); - pos_type last = lastPrintablePos(*this, old_row); + pos_type last = lastPrintablePos(*pit, old_row); // None of these should happen, but we're scaredy-cats if (pos > pit->size()) { - lyxerr << "dont like 1 please report" << endl; + lyxerr << "dont like 1, pos: " << pos << " size: " << pit->size() << endl; pos = 0; cur.pos(0); } else if (pos > last + 1) { @@ -1549,60 +1382,44 @@ void LyXText::setCursor(LyXCursor & cur, ParagraphList::iterator pit, } // now get the cursors x position - float x = getCursorX(row, pos, last, boundary); + float x = getCursorX(pit, row, pos, last, boundary); cur.x(int(x)); cur.x_fix(cur.x()); if (old_row != row) { - x = getCursorX(old_row, pos, last, boundary); + x = getCursorX(pit, old_row, pos, last, boundary); cur.ix(int(x)); } else cur.ix(cur.x()); -/* We take out this for the time being because 1) the redraw code is not - prepared to this yet and 2) because some good policy has yet to be decided - while editting: for instance how to act on rows being created/deleted - because of DEPM. -*/ -#if 0 - //if the cursor is in a visible row, anchor to it - int topy = top_y(); - if (topy < y && y < topy + bv()->workHeight()) - anchor_row(row); -#endif } -float LyXText::getCursorX(RowList::iterator rit, +float LyXText::getCursorX(ParagraphList::iterator pit, RowList::iterator rit, pos_type pos, pos_type last, bool boundary) const { - pos_type cursor_vpos = 0; - double x; - double fill_separator; - double fill_hfill; - double fill_label_hfill; - // This call HAS to be here because of the BidiTables!!! - prepareToPrint(rit, x, fill_separator, fill_hfill, - fill_label_hfill); - - ParagraphList::iterator rit_par = rit->par(); - pos_type const rit_pos = rit->pos(); + pos_type cursor_vpos = 0; + double x = rit->x(); + double fill_separator = rit->fill_separator(); + double fill_hfill = rit->fill_hfill(); + double fill_label_hfill = rit->fill_label_hfill(); + pos_type const rit_pos = rit->pos(); if (last < rit_pos) cursor_vpos = rit_pos; else if (pos > last && !boundary) - cursor_vpos = (rit_par->isRightToLeftPar(bv()->buffer()->params)) + cursor_vpos = (pit->isRightToLeftPar(bv()->buffer()->params)) ? rit_pos : last + 1; else if (pos > rit_pos && (pos > last || boundary)) - /// Place cursor after char at (logical) position pos - 1 + // Place cursor after char at (logical) position pos - 1 cursor_vpos = (bidi_level(pos - 1) % 2 == 0) ? log2vis(pos - 1) + 1 : log2vis(pos - 1); else - /// Place cursor before char at (logical) position pos + // Place cursor before char at (logical) position pos cursor_vpos = (bidi_level(pos) % 2 == 0) ? log2vis(pos) : log2vis(pos) + 1; - pos_type body_pos = rit_par->beginningOfBody(); + pos_type body_pos = pit->beginningOfBody(); if (body_pos > 0 && - (body_pos - 1 > last || !rit_par->isLineSeparator(body_pos - 1))) + (body_pos - 1 > last || !pit->isLineSeparator(body_pos - 1))) body_pos = 0; for (pos_type vpos = rit_pos; vpos < cursor_vpos; ++vpos) { @@ -1610,23 +1427,23 @@ float LyXText::getCursorX(RowList::iterator rit, if (body_pos > 0 && pos == body_pos - 1) { x += fill_label_hfill + font_metrics::width( - rit_par->layout()->labelsep, getLabelFont(rit_par)); - if (rit_par->isLineSeparator(body_pos - 1)) - x -= singleWidth(rit_par, body_pos - 1); + pit->layout()->labelsep, getLabelFont(pit)); + if (pit->isLineSeparator(body_pos - 1)) + x -= singleWidth(pit, body_pos - 1); } - if (hfillExpansion(*this, rit, pos)) { - x += singleWidth(rit_par, pos); + if (hfillExpansion(*pit, rit, pos)) { + x += singleWidth(pit, pos); if (pos >= body_pos) x += fill_hfill; else x += fill_label_hfill; - } else if (rit_par->isSeparator(pos)) { - x += singleWidth(rit_par, pos); + } else if (pit->isSeparator(pos)) { + x += singleWidth(pit, pos); if (pos >= body_pos) x += fill_separator; } else - x += singleWidth(rit_par, pos); + x += singleWidth(pit, pos); } return x; } @@ -1635,32 +1452,6 @@ float LyXText::getCursorX(RowList::iterator rit, void LyXText::setCursorIntern(ParagraphList::iterator pit, pos_type pos, bool setfont, bool boundary) { - UpdatableInset * it = pit->inInset(); - if (it) { - if (it != inset_owner) { - lyxerr[Debug::INSETS] << "InsetText is " << it - << endl - << "inset_owner is " - << inset_owner << endl; -#ifdef WITH_WARNINGS -#warning I believe this code is wrong. (Lgb) -#warning Jürgen, have a look at this. (Lgb) -#warning Hmmm, I guess you are right but we -#warning should verify when this is needed -#endif - // Jürgen, would you like to have a look? - // I guess we need to move the outer cursor - // and open and lock the inset (bla bla bla) - // stuff I don't know... so can you have a look? - // (Lgb) - // I moved the lyxerr stuff in here so we can see if - // this is actually really needed and where! - // (Jug) - // it->getLyXText(bv())->setCursorIntern(bv(), par, pos, setfont, boundary); - return; - } - } - setCursor(cursor, pit, pos, boundary); if (setfont) setCurrentFont(); @@ -1693,7 +1484,7 @@ void LyXText::setCurrentFont() real_current_font = getFont(pit, pos); if (cursor.pos() == pit->size() && - isBoundary(bv()->buffer(), *pit, cursor.pos()) && + isBoundary(*bv()->buffer(), *pit, cursor.pos()) && !cursor.boundary()) { Language const * lang = pit->getParLanguage(bv()->buffer()->params); @@ -1707,35 +1498,31 @@ void LyXText::setCurrentFont() // returns the column near the specified x-coordinate of the row // x is set to the real beginning of this column -pos_type -LyXText::getColumnNearX(RowList::iterator rit, int & x, bool & boundary) const +pos_type LyXText::getColumnNearX(ParagraphList::iterator pit, + RowList::iterator rit, int & x, bool & boundary) const { - double tmpx = 0; - double fill_separator; - double fill_hfill; - double fill_label_hfill; - - prepareToPrint(rit, tmpx, fill_separator, fill_hfill, fill_label_hfill); + double tmpx = rit->x(); + double fill_separator = rit->fill_separator(); + double fill_hfill = rit->fill_hfill(); + double fill_label_hfill = rit->fill_label_hfill(); pos_type vc = rit->pos(); - pos_type last = lastPrintablePos(*this, rit); + pos_type last = lastPrintablePos(*pit, rit); pos_type c = 0; - - ParagraphList::iterator rit_par = rit->par(); - LyXLayout_ptr const & layout = rit->par()->layout(); + LyXLayout_ptr const & layout = pit->layout(); bool left_side = false; - pos_type body_pos = rit_par->beginningOfBody(); + pos_type body_pos = pit->beginningOfBody(); double last_tmpx = tmpx; if (body_pos > 0 && (body_pos - 1 > last || - !rit_par->isLineSeparator(body_pos - 1))) + !pit->isLineSeparator(body_pos - 1))) body_pos = 0; // check for empty row - if (!rit_par->size()) { + if (!pit->size()) { x = int(tmpx); return 0; } @@ -1745,23 +1532,23 @@ LyXText::getColumnNearX(RowList::iterator rit, int & x, bool & boundary) const last_tmpx = tmpx; if (body_pos > 0 && c == body_pos - 1) { tmpx += fill_label_hfill + - font_metrics::width(layout->labelsep, getLabelFont(rit_par)); - if (rit_par->isLineSeparator(body_pos - 1)) - tmpx -= singleWidth(rit_par, body_pos - 1); + font_metrics::width(layout->labelsep, getLabelFont(pit)); + if (pit->isLineSeparator(body_pos - 1)) + tmpx -= singleWidth(pit, body_pos - 1); } - if (hfillExpansion(*this, rit, c)) { - tmpx += singleWidth(rit_par, c); + if (hfillExpansion(*pit, rit, c)) { + tmpx += singleWidth(pit, c); if (c >= body_pos) tmpx += fill_hfill; else tmpx += fill_label_hfill; - } else if (rit_par->isSeparator(c)) { - tmpx += singleWidth(rit_par, c); + } else if (pit->isSeparator(c)) { + tmpx += singleWidth(pit, c); if (c >= body_pos) tmpx += fill_separator; } else { - tmpx += singleWidth(rit_par, c); + tmpx += singleWidth(pit, c); } ++vc; } @@ -1776,21 +1563,18 @@ LyXText::getColumnNearX(RowList::iterator rit, int & x, bool & boundary) const boundary = false; // This (rtl_support test) is not needed, but gives - // some speedup if rtl_support=false - RowList::iterator next_rit = boost::next(rit); - - bool const lastrow = lyxrc.rtl_support && - (next_rit == rowlist_.end() || - next_rit->par() != rit_par); + // some speedup if rtl_support == false + bool const lastrow = lyxrc.rtl_support + && boost::next(rit) == pit->rows.end(); // If lastrow is false, we don't need to compute // the value of rtl. bool const rtl = (lastrow) - ? rit_par->isRightToLeftPar(bv()->buffer()->params) + ? pit->isRightToLeftPar(bv()->buffer()->params) : false; if (lastrow && - ((rtl && left_side && vc == rit->pos() && x < tmpx - 5) || - (!rtl && !left_side && vc == last + 1 && x > tmpx + 5))) + ((rtl && left_side && vc == rit->pos() && x < tmpx - 5) || + (!rtl && !left_side && vc == last + 1 && x > tmpx + 5))) c = last + 1; else if (vc == rit->pos()) { c = vis2log(vc); @@ -1801,16 +1585,15 @@ LyXText::getColumnNearX(RowList::iterator rit, int & x, bool & boundary) const bool const rtl = (bidi_level(c) % 2 == 1); if (left_side == rtl) { ++c; - boundary = isBoundary(bv()->buffer(), *rit_par, c); + boundary = isBoundary(*bv()->buffer(), *pit, c); } } - if (rit->pos() <= last && c > last - && rit_par->isNewline(last)) { + if (rit->pos() <= last && c > last && pit->isNewline(last)) { if (bidi_level(last) % 2 == 0) - tmpx -= singleWidth(rit_par, last); + tmpx -= singleWidth(pit, last); else - tmpx += singleWidth(rit_par, last); + tmpx += singleWidth(pit, last); c = last; } @@ -1822,68 +1605,30 @@ LyXText::getColumnNearX(RowList::iterator rit, int & x, bool & boundary) const void LyXText::setCursorFromCoordinates(int x, int y) { - //LyXCursor old_cursor = cursor; + LyXCursor old_cursor = cursor; setCursorFromCoordinates(cursor, x, y); setCurrentFont(); -#warning DEPM disabled, otherwise crash when entering new table - //deleteEmptyParagraphMechanism(old_cursor); -} - - -namespace { - - /** - * return true if the cursor given is at the end of a row, - * and the next row is filled by an inset that spans an entire - * row. - */ - bool beforeFullRowInset(LyXText & lt, LyXCursor const & cur) - { - RowList::iterator row = lt.getRow(cur); - if (boost::next(row) == lt.rows().end()) - return false; - - Row const & next = *boost::next(row); - - if (next.pos() != cur.pos() || next.par() != cur.par()) - return false; - - if (cur.pos() == cur.par()->size() - || !cur.par()->isInset(cur.pos())) - return false; - - InsetOld const * inset = cur.par()->getInset(cur.pos()); - if (inset->needFullRow() || inset->display()) - return true; - - return false; - } + deleteEmptyParagraphMechanism(old_cursor); } void LyXText::setCursorFromCoordinates(LyXCursor & cur, int x, int y) { // Get the row first. + ParagraphList::iterator pit; + RowList::iterator rit = getRowNearY(y, pit); + y = rit->y(); - RowList::iterator row = getRowNearY(y); bool bound = false; - pos_type const column = getColumnNearX(row, x, bound); - cur.par(row->par()); - cur.pos(row->pos() + column); + pos_type const column = getColumnNearX(pit, rit, x, bound); + cur.par(pit); + cur.pos(rit->pos() + column); cur.x(x); - cur.y(y + row->baseline()); + cur.y(y + rit->baseline()); - if (beforeFullRowInset(*this, cur)) { - pos_type const last = lastPrintablePos(*this, row); - RowList::iterator next_row = boost::next(row); + cur.iy(cur.y()); + cur.ix(cur.x()); - float x = getCursorX(next_row, cur.pos(), last, bound); - cur.ix(int(x)); - cur.iy(y + row->height() + next_row->baseline()); - } else { - cur.iy(cur.y()); - cur.ix(cur.x()); - } cur.boundary(bound); } @@ -1894,7 +1639,7 @@ void LyXText::cursorLeft(bool internal) bool boundary = cursor.boundary(); setCursor(cursor.par(), cursor.pos() - 1, true, false); if (!internal && !boundary && - isBoundary(bv()->buffer(), *cursor.par(), cursor.pos() + 1)) + isBoundary(*bv()->buffer(), *cursor.par(), cursor.pos() + 1)) setCursor(cursor.par(), cursor.pos() + 1, true, true); } else if (cursor.par() != ownerParagraphs().begin()) { // steps into the paragraph above @@ -1915,7 +1660,7 @@ void LyXText::cursorRight(bool internal) else if (!at_end) { setCursor(cursor.par(), cursor.pos() + 1, true, false); if (!internal && - isBoundary(bv()->buffer(), *cursor.par(), cursor.pos())) + isBoundary(*bv()->buffer(), *cursor.par(), cursor.pos())) setCursor(cursor.par(), cursor.pos(), true, true); } else if (boost::next(cursor.par()) != ownerParagraphs().end()) setCursor(boost::next(cursor.par()), 0); @@ -1929,7 +1674,7 @@ void LyXText::cursorUp(bool selecting) int y = cursor.y() - cursorRow()->baseline() - 1; setCursorFromCoordinates(x, y); if (!selecting) { - int topy = top_y(); + int topy = bv_owner->top_y(); int y1 = cursor.iy() - topy; int y2 = y1; y -= topy; @@ -1940,8 +1685,10 @@ void LyXText::cursorUp(bool selecting) } } #else - setCursorFromCoordinates(bv(), cursor.x_fix(), - cursor.y() - cursorRow()->baseline() - 1); + lyxerr << "cursorUp: y " << cursor.y() << " bl: " << + cursorRow()->baseline() << endl; + setCursorFromCoordinates(cursor.x_fix(), + cursor.y() - cursorRow()->baseline() - 1); #endif } @@ -1953,7 +1700,7 @@ void LyXText::cursorDown(bool selecting) int y = cursor.y() - cursorRow()->baseline() + cursorRow()->height() + 1; setCursorFromCoordinates(x, y); if (!selecting && cursorRow() == cursorIRow()) { - int topy = top_y(); + int topy = bv_owner->top_y(); int y1 = cursor.iy() - topy; int y2 = y1; y -= topy; @@ -1964,9 +1711,8 @@ void LyXText::cursorDown(bool selecting) } } #else - setCursorFromCoordinates(bv(), cursor.x_fix(), - cursor.y() - cursorRow()->baseline() - + cursorRow()->height() + 1); + setCursorFromCoordinates(cursor.x_fix(), + cursor.y() - cursorRow()->baseline() + cursorRow()->height() + 1); #endif } @@ -1994,8 +1740,7 @@ void LyXText::cursorDownParagraph() // fix the cursor `cur' after a characters has been deleted at `where' // position. Called by deleteEmptyParagraphMechanism -void LyXText::fixCursorAfterDelete(LyXCursor & cur, - LyXCursor const & where) +void LyXText::fixCursorAfterDelete(LyXCursor & cur, LyXCursor const & where) { // if cursor is not in the paragraph where the delete occured, // do nothing @@ -2024,10 +1769,8 @@ bool LyXText::deleteEmptyParagraphMechanism(LyXCursor const & old_cursor) return false; // We allow all kinds of "mumbo-jumbo" when freespacing. - if (old_cursor.par()->layout()->free_spacing - || old_cursor.par()->isFreeSpacing()) { + if (old_cursor.par()->isFreeSpacing()) return false; - } /* Ok I'll put some comments here about what is missing. I have fixed BackSpace (and thus Delete) to not delete @@ -2036,7 +1779,7 @@ bool LyXText::deleteEmptyParagraphMechanism(LyXCursor const & old_cursor) There are still some small problems that can lead to double spaces stored in the document file or space at the beginning of paragraphs. This happens if you have - the cursor betwenn to spaces and then save. Or if you + the cursor between to spaces and then save. Or if you cut and paste and the selection have a space at the beginning and then save right after the paste. I am sure none of these are very hard to fix, but I will @@ -2055,8 +1798,8 @@ bool LyXText::deleteEmptyParagraphMechanism(LyXCursor const & old_cursor) // If the pos around the old_cursor were spaces, delete one of them. if (old_cursor.par() != cursor.par() || old_cursor.pos() != cursor.pos()) { - // Only if the cursor has really moved + // Only if the cursor has really moved if (old_cursor.pos() > 0 && old_cursor.pos() < old_cursor.par()->size() && old_cursor.par()->isLineSeparator(old_cursor.pos()) @@ -2100,7 +1843,7 @@ bool LyXText::deleteEmptyParagraphMechanism(LyXCursor const & old_cursor) if (old_cursor.par()->empty() || (old_cursor.par()->size() == 1 && old_cursor.par()->isLineSeparator(0))) { - // ok, we will delete anything + // ok, we will delete something LyXCursor tmpcursor; deleted = true; @@ -2109,65 +1852,19 @@ bool LyXText::deleteEmptyParagraphMechanism(LyXCursor const & old_cursor) selection.cursor.par() == old_cursor.par() && selection.cursor.pos() == old_cursor.pos()); - if (getRow(old_cursor) != rows().begin()) { - RowList::iterator prevrow = boost::prior(getRow(old_cursor)); - tmpcursor = cursor; - cursor = old_cursor; // that undo can restore the right cursor position - #warning FIXME. --end() iterator is usable here - ParagraphList::iterator endpit = boost::next(old_cursor.par()); - while (endpit != ownerParagraphs().end() && - endpit->getDepth()) { - ++endpit; - } + tmpcursor = cursor; + cursor = old_cursor; // that undo can restore the right cursor position - recordUndo(bv(), Undo::DELETE, old_cursor.par(), - boost::prior(endpit)); - cursor = tmpcursor; - - // delete old row - removeRow(getRow(old_cursor)); - // delete old par - ownerParagraphs().erase(old_cursor.par()); - - /* Breakagain the next par. Needed because of - * the parindent that can occur or dissappear. - * The next row can change its height, if - * there is another layout before */ - RowList::iterator tmprit = boost::next(prevrow); - if (tmprit != rows().end()) { - breakAgain(tmprit); - updateCounters(); - } - setHeightOfRow(prevrow); - } else { - RowList::iterator nextrow = boost::next(getRow(old_cursor)); - - tmpcursor = cursor; - cursor = old_cursor; // that undo can restore the right cursor position -#warning FIXME. --end() iterator is usable here - ParagraphList::iterator endpit = boost::next(old_cursor.par()); - while (endpit != ownerParagraphs().end() && - endpit->getDepth()) { - ++endpit; - } + ParagraphList::iterator endpit = boost::next(old_cursor.par()); + while (endpit != ownerParagraphs().end() && endpit->getDepth()) + ++endpit; - recordUndo(bv(), Undo::DELETE, old_cursor.par(), boost::prior(endpit)); - cursor = tmpcursor; - - // delete old row - removeRow(getRow(old_cursor)); - // delete old par - ownerParagraphs().erase(old_cursor.par()); - - /* Breakagain the next par. Needed because of - the parindent that can occur or dissappear. - The next row can change its height, if - there is another layout before */ - if (nextrow != rows().end()) { - breakAgain(nextrow); - updateCounters(); - } - } + recordUndo(bv(), Undo::DELETE, old_cursor.par(), boost::prior(endpit)); + cursor = tmpcursor; + + // delete old par + ownerParagraphs().erase(old_cursor.par()); + redoParagraph(); // correct cursor y setCursorIntern(cursor.par(), cursor.pos()); @@ -2191,18 +1888,14 @@ bool LyXText::deleteEmptyParagraphMechanism(LyXCursor const & old_cursor) ParagraphList & LyXText::ownerParagraphs() const { - if (inset_owner) { - return inset_owner->paragraphs; - } - return bv_owner->buffer()->paragraphs; + return paragraphs_; } bool LyXText::isInInset() const { - // Sub-level has non-null bv owner and - // non-null inset owner. - return inset_owner != 0 && bv_owner != 0; + // Sub-level has non-null bv owner and non-null inset owner. + return inset_owner != 0; }