X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ftext2.C;h=97fc51aa5b048f91b88c6b82dfdd8765816c54b7;hb=c96136c04080415efdfb6df9b3d25f9e2e732782;hp=b86338ad45a27e2282254cc0fab801f32ab4318e;hpb=9a7cef54a67135eb241506be444ccfb0aee2cf5d;p=lyx.git diff --git a/src/text2.C b/src/text2.C index b86338ad45..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 @@ -59,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_ = endRow(); -} - - -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_ = endRow(); } @@ -87,8 +89,7 @@ void LyXText::init(BufferView * bview) width = 0; height = 0; - anchor_row_ = endRow(); - anchor_row_offset_ = 0; + anchor_y_ = 0; current_font = getFont(beg, 0); @@ -281,7 +282,7 @@ void LyXText::toggleInset() else inset->open(bv()); - bv()->updateInset(); + bv()->updateInset(inset); } @@ -543,60 +544,69 @@ void LyXText::setFont(LyXFont const & font, bool toggleall) } -// rebreaks all paragraphs between the specified pars -// This function is needed after SetLayout and SetFont etc. -void LyXText::redoParagraphs(ParagraphList::iterator start, - ParagraphList::iterator end) -{ - for ( ; start != end; ++start) - redoParagraph(start); -} - - -void LyXText::redoParagraph(ParagraphList::iterator pit) +int LyXText::redoParagraphInternal(ParagraphList::iterator pit) { RowList::iterator rit = pit->rows.begin(); RowList::iterator end = pit->rows.end(); - // remove rows of paragraph - int anchor_cnt = -1; - for (int i = 0; rit != end; ++rit, ++i) { - if (rit == anchor_row_) - anchor_cnt = i; + // remove rows of paragraph, keep track of height changes + for (int i = 0; rit != end; ++rit, ++i) height -= rit->height(); - } pit->rows.clear(); + // 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); + } + // rebreak the paragraph - // insert a new row, starting at position 0 + 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); + } - pos_type z = 0; - pit->rows.push_back(Row(z)); - bool done = false; - while (!done) { - z = rowBreakPoint(pit, pit->rows.back()); + 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 tmprow = boost::prior(pit->rows.end()); + //lyxerr << "redoParagraph: " << pit->rows.size() << " rows\n"; + return par_width; +} - if (z >= pit->size()) - done = true; - else { - ++z; - pit->rows.push_back(Row(z)); - } - tmprow->fill(fill(pit, tmprow, workWidth())); - setHeightOfRow(pit, tmprow); +int LyXText::redoParagraphs(ParagraphList::iterator start, + ParagraphList::iterator end) +{ + 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; +} - if (anchor_cnt == -1) { - if (anchor_cnt >= pit->rows.size()) - anchor_cnt = pit->rows.size(); - anchor_row_ = pit->rows.begin(); - advance(anchor_row_, anchor_cnt); - } - //lyxerr << "redoParagraph: " << pit->rows.size() << " rows\n"; +void LyXText::redoParagraph(ParagraphList::iterator pit) +{ + redoParagraphInternal(pit); + updateRowPositions(); } @@ -610,34 +620,16 @@ void LyXText::fullRebreak() 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 - width = 0; - height = 0; - - anchor_row_ = endRow(); - anchor_row_offset_ = 0; - - ParagraphList::iterator pit = ownerParagraphs().begin(); - ParagraphList::iterator end = ownerParagraphs().end(); - - for (; pit != end; ++pit) { - pit->rows.clear(); - - 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); - } + width = 0; + ///height = 0; - redoParagraph(pit); - } + //anchor_y_ = 0; + width = redoParagraphs(ownerParagraphs().begin(), ownerParagraphs().end()); // final dimension dim.asc = firstRow()->ascent_of_text(); @@ -683,21 +675,12 @@ void LyXText::cursorEnd() return; RowList::iterator rit = cursorRow(); - RowList::iterator next_rit = boost::next(rit); - RowList::iterator end = boost::next(rit); ParagraphList::iterator pit = cursor.par(); - pos_type last_pos = lastPos(*pit, rit); - - if (next_rit == end) { - ++last_pos; - } else { - if (pit->empty() || - (pit->getChar(last_pos) != ' ' && !pit->isNewline(last_pos))) { - ++last_pos; - } - } - - setCursor(pit, last_pos); + pos_type pos = lastPos(*pit, rit); + /* cursor should be before a hard newline only */ + if (!pit->isNewline(pos)) + ++pos; + setCursor(pit, pos); } @@ -761,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; @@ -856,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()) { @@ -921,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; @@ -929,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. @@ -940,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"; @@ -994,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) { @@ -1011,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; } } @@ -1033,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; @@ -1079,7 +1063,7 @@ 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(); @@ -1100,7 +1084,7 @@ void LyXText::insertInset(InsetOld * inset) // The character will not be inserted a second time insertChar(Paragraph::META_INSET); // If we enter a highly editable inset the cursor should be before - // the inset. After an Undo LyX tries to call inset->edit(...) + // 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)) @@ -1119,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()) @@ -1184,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()) @@ -1364,23 +1348,15 @@ void LyXText::setCursor(LyXCursor & cur, ParagraphList::iterator pit, return; // get the cursor y position in text - int y = 0; - RowList::iterator row = getRow(pit, pos, y); + + 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 != pit->rows.begin() - && pos - && 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(); @@ -1414,33 +1390,18 @@ void LyXText::setCursor(LyXCursor & cur, ParagraphList::iterator pit, 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(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(pit, rit, x, fill_separator, fill_hfill, - fill_label_hfill); - - 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; @@ -1523,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); @@ -1540,12 +1501,10 @@ void LyXText::setCurrentFont() 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(pit, 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(*pit, rit); @@ -1626,7 +1585,7 @@ pos_type LyXText::getColumnNearX(ParagraphList::iterator pit, bool const rtl = (bidi_level(c) % 2 == 1); if (left_side == rtl) { ++c; - boundary = isBoundary(bv()->buffer(), *pit, c); + boundary = isBoundary(*bv()->buffer(), *pit, c); } } @@ -1646,38 +1605,10 @@ pos_type LyXText::getColumnNearX(ParagraphList::iterator pit, 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); - RowList::iterator next = boost::next(row); - - if (next == cur.par()->rows.end() || next->pos() != cur.pos()) - 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); } @@ -1685,23 +1616,19 @@ void LyXText::setCursorFromCoordinates(LyXCursor & cur, int x, int y) { // Get the row first. ParagraphList::iterator pit; - RowList::iterator row = getRowNearY(y, pit); + RowList::iterator rit = getRowNearY(y, pit); + y = rit->y(); + bool bound = false; - pos_type const column = getColumnNearX(pit, row, x, bound); + pos_type const column = getColumnNearX(pit, rit, x, bound); cur.par(pit); - cur.pos(row->pos() + column); + cur.pos(rit->pos() + column); cur.x(x); - cur.y(y + row->baseline()); - -// if (beforeFullRowInset(*this, cur)) { -// pos_type const last = lastPrintablePos(*this, pit, row); -// RowList::iterator next_row = nextRow(row); -// cur.ix(int(getCursorX(pit, next_row, cur.pos(), last, bound))); -// cur.iy(y + row->height() + next_row->baseline()); -// } else { - cur.iy(cur.y()); - cur.ix(cur.x()); -// } + cur.y(y + rit->baseline()); + + cur.iy(cur.y()); + cur.ix(cur.x()); + cur.boundary(bound); } @@ -1712,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 @@ -1733,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); @@ -1747,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; @@ -1773,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; @@ -1852,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 @@ -1916,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; @@ -1931,7 +1858,7 @@ bool LyXText::deleteEmptyParagraphMechanism(LyXCursor const & old_cursor) 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; @@ -1961,17 +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; + return inset_owner != 0; }