X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ftext.C;h=da326879c5cc2c15f1fddf8e00f71e23b5337bc0;hb=ae348f8af96100a154b3792d27732d621d44ec89;hp=2ef4adb2a11ca99c936f34cbb2b1f1a21552f141;hpb=9d6cad3fe60696d795280a886623fdc9a89f9de6;p=lyx.git diff --git a/src/text.C b/src/text.C index 2ef4adb2a1..da326879c5 100644 --- a/src/text.C +++ b/src/text.C @@ -24,6 +24,7 @@ #include "bufferparams.h" #include "BufferView.h" #include "cursor.h" +#include "pariterator.h" #include "coordcache.h" #include "CutAndPaste.h" #include "debug.h" @@ -74,6 +75,7 @@ #include +using lyx::char_type; using lyx::pit_type; using lyx::pos_type; using lyx::word_location; @@ -133,7 +135,7 @@ int numberOfLabelHfills(Paragraph const & par, Row const & row) int numberOfHfills(Paragraph const & par, Row const & row) { - pos_type const last = row.endpos() - 1; + pos_type const last = row.endpos(); pos_type first = row.pos(); // hfill *DO* count at the beginning of paragraphs! @@ -195,13 +197,13 @@ void readParToken(Buffer const & buf, Paragraph & par, LyXLex & lex, } else if (token == "\\end_layout") { lyxerr << BOOST_CURRENT_FUNCTION - << ": Solitary \\end_layout in line " - << lex.getLineNo() << "\n" + << ": Solitary \\end_layout in line " + << lex.getLineNo() << "\n" << "Missing \\begin_layout?.\n"; } else if (token == "\\end_inset") { lyxerr << BOOST_CURRENT_FUNCTION - << ": Solitary \\end_inset in line " - << lex.getLineNo() << "\n" + << ": Solitary \\end_inset in line " + << lex.getLineNo() << "\n" << "Missing \\begin_inset?.\n"; } else if (token == "\\begin_inset") { InsetBase * inset = readInset(lex, buf); @@ -323,17 +325,31 @@ void readParToken(Buffer const & buf, Paragraph & par, LyXLex & lex, } else if (token == "\\change_inserted") { lex.eatLine(); std::istringstream is(lex.getString()); - int aid; + unsigned int aid; lyx::time_type ct; is >> aid >> ct; - change = Change(Change::INSERTED, bp.author_map[aid], ct); + if (aid >= bp.author_map.size()) { + buf.error(ErrorItem(_("Change tracking error"), + bformat(_("Unknown author index for insertion: %1$d\n"), aid), + par.id(), 0, par.size())); + + change = Change(Change::UNCHANGED); + } else + change = Change(Change::INSERTED, bp.author_map[aid], ct); } else if (token == "\\change_deleted") { lex.eatLine(); std::istringstream is(lex.getString()); - int aid; + unsigned int aid; lyx::time_type ct; is >> aid >> ct; - change = Change(Change::DELETED, bp.author_map[aid], ct); + if (aid >= bp.author_map.size()) { + buf.error(ErrorItem(_("Change tracking error"), + bformat(_("Unknown author index for deletion: %1$d\n"), aid), + par.id(), 0, par.size())); + + change = Change(Change::UNCHANGED); + } else + change = Change(Change::DELETED, bp.author_map[aid], ct); } else { lex.eatLine(); buf.error(ErrorItem(_("Unknown token"), @@ -378,8 +394,8 @@ void readParagraph(Buffer const & buf, Paragraph & par, LyXLex & lex) } } // Final change goes to paragraph break: - par.setChangeFull(par.size(), change); - + par.setChange(par.size(), change); + // Initialize begin_of_body_ on load; redoParagraph maintains par.setBeginOfBody(); } @@ -423,20 +439,20 @@ int LyXText::singleWidth(Paragraph const & par, pos_type pos) const int LyXText::singleWidth(Paragraph const & par, - pos_type pos, char c, LyXFont const & font) const + pos_type pos, char_type c, LyXFont const & font) const { // The most common case is handled first (Asger) - if (IsPrintable(c)) { + if (isPrintable(c)) { Language const * language = font.language(); - if (language->RightToLeft()) { + if (language->rightToLeft()) { if ((lyxrc.font_norm_type == LyXRC::ISO_8859_6_8 || lyxrc.font_norm_type == LyXRC::ISO_10646_1) && language->lang() == "arabic") { - if (Encodings::IsComposeChar_arabic(c)) + if (Encodings::isComposeChar_arabic(c)) return 0; c = par.transformChar(c, pos); } else if (language->lang() == "hebrew" && - Encodings::IsComposeChar_hebrew(c)) + Encodings::isComposeChar_hebrew(c)) return 0; } return font_metrics::width(c, font); @@ -465,8 +481,8 @@ int LyXText::leftMargin(pit_type const pit, pos_type const pos) const BOOST_ASSERT(pos >= 0); BOOST_ASSERT(pos <= par.size()); //lyxerr << "LyXText::leftMargin: pit: " << pit << " pos: " << pos << endl; - LyXTextClass const & tclass = - bv()->buffer()->params().getLyXTextClass(); + BufferParams const & params = bv()->buffer()->params(); + LyXTextClass const & tclass = params.getLyXTextClass(); LyXLayout_ptr const & layout = par.layout(); string parindent = layout->parindent; @@ -476,7 +492,7 @@ int LyXText::leftMargin(pit_type const pit, pos_type const pos) const if (isMainText()) l_margin += changebarMargin(); - l_margin += font_metrics::signedWidth(tclass.leftmargin(), tclass.defaultfont()); + l_margin += font_metrics::signedWidth(tclass.leftmargin(), params.getFont()); if (par.getDepth() != 0) { // find the next level paragraph @@ -506,7 +522,7 @@ int LyXText::leftMargin(pit_type const pit, pos_type const pos) const case MARGIN_DYNAMIC: if (!layout->leftmargin.empty()) l_margin += font_metrics::signedWidth(layout->leftmargin, - tclass.defaultfont()); + params.getFont()); if (!par.getLabelstring().empty()) { l_margin += font_metrics::signedWidth(layout->labelindent, labelfont); @@ -529,7 +545,7 @@ int LyXText::leftMargin(pit_type const pit, pos_type const pos) const break; case MARGIN_STATIC: - l_margin += font_metrics::signedWidth(layout->leftmargin, tclass.defaultfont()) * 4 + l_margin += font_metrics::signedWidth(layout->leftmargin, params.getFont()) * 4 / (par.getDepth() + 4); break; @@ -576,7 +592,7 @@ int LyXText::leftMargin(pit_type const pit, pos_type const pos) const if (rit->fill() < minfill) minfill = rit->fill(); l_margin += font_metrics::signedWidth(layout->leftmargin, - tclass.defaultfont()); + params.getFont()); l_margin += minfill; #endif // also wrong, but much shorter. @@ -601,8 +617,8 @@ int LyXText::leftMargin(pit_type const pit, pos_type const pos) const || layout->labeltype == LABEL_TOP_ENVIRONMENT || layout->labeltype == LABEL_CENTERED_TOP_ENVIRONMENT || (layout->labeltype == LABEL_STATIC - && layout->latextype == LATEX_ENVIRONMENT - && !isFirstInSequence(pit, pars_))) + && layout->latextype == LATEX_ENVIRONMENT + && !isFirstInSequence(pit, pars_))) && align == LYX_ALIGN_BLOCK && !par.params().noindent() // in some insets, paragraphs are never indented @@ -612,10 +628,10 @@ int LyXText::leftMargin(pit_type const pit, pos_type const pos) const && par.isInset(pos) && par.getInset(pos)->display()) && (par.layout() != tclass.defaultLayout() - || bv()->buffer()->params().paragraph_separation == - BufferParams::PARSEP_INDENT)) + || bv()->buffer()->params().paragraph_separation == + BufferParams::PARSEP_INDENT)) { - l_margin += font_metrics::signedWidth(parindent, tclass.defaultfont()); + l_margin += font_metrics::signedWidth(parindent, params.getFont()); } return l_margin; @@ -628,13 +644,14 @@ int LyXText::rightMargin(Paragraph const & par) const if (bv()->text() != this) return 0; - LyXTextClass const & tclass = bv()->buffer()->params().getLyXTextClass(); + BufferParams const & params = bv()->buffer()->params(); + LyXTextClass const & tclass = params.getLyXTextClass(); int const r_margin = ::rightMargin() + font_metrics::signedWidth(tclass.rightmargin(), - tclass.defaultfont()) + params.getFont()) + font_metrics::signedWidth(par.layout()->rightmargin, - tclass.defaultfont()) + params.getFont()) * 4 / (par.getDepth() + 4); return r_margin; @@ -709,7 +726,7 @@ void LyXText::rowBreakPoint(pit_type const pit, Row & row) const pos_type point = end; pos_type i = pos; for ( ; i < end; ++i, ++fi) { - char const c = par.getChar(i); + char_type const c = par.getChar(i); int thiswidth = singleWidth(par, i, c, *fi); // add the auto-hfill from label end to the body @@ -802,7 +819,7 @@ void LyXText::setRowWidth(pit_type const pit, Row & row) const w -= singleWidth(par, i - 1); w = max(w, labelEnd(pit)); } - char const c = par.getChar(i); + char_type const c = par.getChar(i); w += singleWidth(par, i, c, *fi); } } @@ -920,7 +937,7 @@ void LyXText::setHeightOfRow(pit_type const pit, Row & row) && pit != 0 && ((layout->isParagraph() && par.getDepth() == 0) || (pars_[pit - 1].layout()->isParagraph() - && pars_[pit - 1].getDepth() == 0))) + && pars_[pit - 1].getDepth() == 0))) { maxasc += bufparams.getDefSkip().inPixels(*bv()); } @@ -933,8 +950,8 @@ void LyXText::setHeightOfRow(pit_type const pit, Row & row) if (layout->counter == "chapter" && !par.params().labelString().empty()) { labeladdon = int(font_metrics::maxHeight(labelfont) - * layout->spacing.getValue() - * spacing(par)); + * layout->spacing.getValue() + * spacing(par)); } // special code for the top label @@ -1087,11 +1104,16 @@ void LyXText::breakParagraph(LCursor & cur, bool keep_layout) while (!pars_[next_par].empty() && pars_[next_par].isNewline(0)) pars_[next_par].erase(0); - updateCounters(cur.buffer()); + ParIterator current_it(cur); + ParIterator last_it(cur); + ++last_it; + ++last_it; + + updateLabels(cur.buffer(), current_it, last_it); // Mark "carriage return" as inserted if change tracking: if (cur.buffer().params().tracking_changes) { - cur.paragraph().setChange(cur.paragraph().size(), + cur.paragraph().setChange(cur.paragraph().size(), Change::INSERTED); } @@ -1106,7 +1128,7 @@ void LyXText::breakParagraph(LCursor & cur, bool keep_layout) // insert a character, moves all the following breaks in the // same Paragraph one to the right and make a rebreak -void LyXText::insertChar(LCursor & cur, char c) +void LyXText::insertChar(LCursor & cur, char_type c) { BOOST_ASSERT(this == cur.text()); BOOST_ASSERT(c != Paragraph::META_INSET); @@ -1126,7 +1148,7 @@ void LyXText::insertChar(LCursor & cur, char c) static string const number_seperators = ".,:"; if (current_font.number() == LyXFont::ON) { - if (!IsDigit(c) && !contains(number_operators, c) && + if (!isDigit(c) && !contains(number_operators, c) && !(contains(number_seperators, c) && cur.pos() != 0 && cur.pos() != cur.lastpos() && @@ -1134,12 +1156,12 @@ void LyXText::insertChar(LCursor & cur, char c) getFont(par, cur.pos() - 1).number() == LyXFont::ON) ) number(cur); // Set current_font.number to OFF - } else if (IsDigit(c) && + } else if (isDigit(c) && real_current_font.isVisibleRightToLeft()) { number(cur); // Set current_font.number to ON if (cur.pos() != 0) { - char const c = par.getChar(cur.pos() - 1); + char_type const c = par.getChar(cur.pos() - 1); if (contains(number_unary_operators, c) && (cur.pos() == 1 || par.isSeparator(cur.pos() - 2) @@ -1163,7 +1185,7 @@ void LyXText::insertChar(LCursor & cur, char c) // When the free-spacing option is set for the current layout, // disable the double-space checking - if (!freeSpacing && IsLineSeparatorChar(c)) { + if (!freeSpacing && isLineSeparatorChar(c)) { if (cur.pos() == 0) { static bool sent_space_message = false; if (!sent_space_message) { @@ -1400,14 +1422,14 @@ void LyXText::acceptChange(LCursor & cur) return; recordUndoSelection(cur, Undo::INSERT); - + DocIterator it = cur.selectionBegin(); DocIterator et = cur.selectionEnd(); pit_type pit = it.pit(); - Change::Type const type = pars_[pit].lookupChange(it.pos()); + Change::Type const type = pars_[pit].lookupChange(it.pos()).type; for (; pit <= et.pit(); ++pit) { pos_type left = ( pit == it.pit() ? it.pos() : 0 ); - pos_type right = + pos_type right = ( pit == et.pit() ? et.pos() : pars_[pit].size() + 1 ); pars_[pit].acceptChange(left, right); } @@ -1416,9 +1438,9 @@ void LyXText::acceptChange(LCursor & cur) if (it.pit() + 1 < et.pit()) pars_.erase(boost::next(plist.begin(), it.pit() + 1), boost::next(plist.begin(), et.pit())); - + // Paragraph merge if appropriate: - if (pars_[it.pit()].lookupChange(pars_[it.pit()].size()) + if (pars_[it.pit()].lookupChange(pars_[it.pit()].size()) == Change::DELETED) { setCursorIntern(cur, it.pit() + 1, 0); backspacePos0(cur); @@ -1441,10 +1463,10 @@ void LyXText::rejectChange(LCursor & cur) DocIterator it = cur.selectionBegin(); DocIterator et = cur.selectionEnd(); pit_type pit = it.pit(); - Change::Type const type = pars_[pit].lookupChange(it.pos()); + Change::Type const type = pars_[pit].lookupChange(it.pos()).type; for (; pit <= et.pit(); ++pit) { pos_type left = ( pit == it.pit() ? it.pos() : 0 ); - pos_type right = + pos_type right = ( pit == et.pit() ? et.pos() : pars_[pit].size() + 1 ); pars_[pit].rejectChange(left, right); } @@ -1454,7 +1476,7 @@ void LyXText::rejectChange(LCursor & cur) pars_.erase(boost::next(plist.begin(), it.pit() + 1), boost::next(plist.begin(), et.pit())); // Paragraph merge if appropriate: - if (pars_[it.pit()].lookupChange(pars_[it.pit()].size()) + if (pars_[it.pit()].lookupChange(pars_[it.pit()].size()) == Change::INSERTED) { setCursorIntern(cur, it.pit() + 1, 0); backspacePos0(cur); @@ -1546,7 +1568,7 @@ void LyXText::changeCase(LCursor & cur, LyXText::TextCase action) pos = 0; continue; } - unsigned char c = pars_[pit].getChar(pos); + char_type c = pars_[pit].getChar(pos); if (c != Paragraph::META_INSET) { switch (action) { case text_lowercase: @@ -1570,7 +1592,7 @@ void LyXText::changeCase(LCursor & cur, LyXText::TextCase action) } -bool LyXText::Delete(LCursor & cur) +bool LyXText::erase(LCursor & cur) { BOOST_ASSERT(this == cur.text()); bool needsUpdate = false; @@ -1579,17 +1601,21 @@ bool LyXText::Delete(LCursor & cur) recordUndo(cur, Undo::DELETE, cur.pit()); setCursorIntern(cur, cur.pit(), cur.pos() + 1, false, cur.boundary()); needsUpdate = backspace(cur); - Paragraph & par = cur.paragraph(); - if (cur.pos() < par.size() - && par.lookupChange(cur.pos()) == Change::DELETED) + if (cur.paragraph().lookupChange(cur.pos()) == Change::DELETED) cur.posRight(); } else if (cur.pit() != cur.lastpit()) { LCursor scur = cur; - setCursorIntern(cur, cur.pit()+1, 0, false, false); + setCursorIntern(cur, cur.pit() + 1, 0, false, false); if (pars_[cur.pit()].layout() == pars_[scur.pit()].layout()) { recordUndo(scur, Undo::DELETE, scur.pit()); needsUpdate = backspace(cur); + if (cur.buffer().params().tracking_changes) { + // move forward after the paragraph break is DELETED + Paragraph & par = cur.paragraph(); + if (par.lookupChange(par.size()) == Change::DELETED) + setCursorIntern(cur, cur.pit() + 1, 0); + } } else { setCursorIntern(scur, scur.pit(), scur.pos(), false, scur.boundary()); } @@ -1623,7 +1649,7 @@ bool LyXText::backspacePos0(LCursor & cur) BufferParams const & bparams = buf.params(); par.layout(bparams.getLyXTextClass().defaultLayout()); } - + cursorLeft(cur); return true; } @@ -1656,7 +1682,7 @@ bool LyXText::backspacePos0(LCursor & cur) if (cpit != tmppit && (pars_[cpit].layout() == pars_[tmppit].layout() - || pars_[tmppit].layout() == tclass.defaultLayout())) + || pars_[tmppit].layout() == tclass.defaultLayout())) { mergeParagraph(bufparams, pars_, cpit); needsUpdate = true; @@ -1665,7 +1691,9 @@ bool LyXText::backspacePos0(LCursor & cur) --cur.pos(); // the counters may have changed - updateCounters(cur.buffer()); + ParIterator par_it(cur); + updateLabels(cur.buffer(), par_it); + setCursor(cur, cur.pit(), cur.pos(), false); } return needsUpdate; @@ -1681,7 +1709,7 @@ bool LyXText::backspace(LCursor & cur) // the the backspace will collapse two paragraphs into // one. - if (cur.buffer().params().tracking_changes) { + if (cur.pit() != 0 && cur.buffer().params().tracking_changes) { // Previous paragraph, mark "carriage return" as // deleted: Paragraph & par = pars_[cur.pit() - 1]; @@ -1735,7 +1763,7 @@ bool LyXText::redoParagraph(pit_type const pit) // Insist on it being in pos 0 && par.getChar(0) == Paragraph::META_INSET) { InsetBase * inset = par.insetlist.begin()->inset; - if (inset->lyxCode() == InsetBase::BIBITEM_CODE) + if (inset->lyxCode() == InsetBase::BIBITEM_CODE) hasbibitem = true; } if (!hasbibitem) { @@ -1792,7 +1820,7 @@ bool LyXText::redoParagraph(pit_type const pit) par.rows().push_back(row); dim.des += row.height(); } - + dim.asc += par.rows()[0].ascent(); dim.des -= par.rows()[0].ascent(); @@ -1917,9 +1945,9 @@ void LyXText::drawSelection(PainterInfo & pi, int x, int) const return; lyxerr[Debug::DEBUG] - << BOOST_CURRENT_FUNCTION - << "draw selection at " << x - << endl; + << BOOST_CURRENT_FUNCTION + << "draw selection at " << x + << endl; DocIterator beg = cur.selectionBegin(); DocIterator end = cur.selectionEnd(); @@ -2193,7 +2221,7 @@ int LyXText::cursorX(CursorSlice const & sl, bool boundary) const else if (par.isSeparator(pos) && pos >= body_pos) x += m.separator; } - + // see correction above if (boundary_correction) if (getFont(par, ppos).isVisibleRightToLeft()) @@ -2208,7 +2236,7 @@ int LyXText::cursorX(CursorSlice const & sl, bool boundary) const if (!boundary && font.isVisibleRightToLeft() && par.isInset(sl.pos())) x -= par.getInset(sl.pos())->width(); - } + } return int(x); } @@ -2217,6 +2245,9 @@ int LyXText::cursorY(CursorSlice const & sl, bool boundary) const { //lyxerr << "LyXText::cursorY: boundary: " << boundary << std::endl; Paragraph const & par = getPar(sl.pit()); + if (par.rows().empty()) + return 0; + int h = 0; h -= pars_[0].rows()[0].ascent(); for (pit_type pit = 0; pit < sl.pit(); ++pit) @@ -2247,7 +2278,7 @@ string LyXText::currentState(LCursor & cur) os << "[C] "; if (show_change) { - Change change = par.lookupChangeFull(cur.pos()); + Change change = par.lookupChange(cur.pos()); Author const & a = buf.params().authors().get(change.author); os << _("Change: ") << a.name(); if (!a.email().empty()) @@ -2408,11 +2439,11 @@ bool LyXText::setCursorFromCoordinates(LCursor & cur, int const x, int const y) pit_type pit = getPitNearY(y); int yy = theCoords.get(this, pit).y_ - pars_[pit].ascent(); lyxerr[Debug::DEBUG] - << BOOST_CURRENT_FUNCTION - << ": x: " << x - << " y: " << y + << BOOST_CURRENT_FUNCTION + << ": x: " << x + << " y: " << y << " pit: " << pit - << " yy: " << yy << endl; + << " yy: " << yy << endl; Paragraph const & par = pars_[pit]; int r = 0; @@ -2427,20 +2458,20 @@ bool LyXText::setCursorFromCoordinates(LCursor & cur, int const x, int const y) Row const & row = par.rows()[r]; lyxerr[Debug::DEBUG] - << BOOST_CURRENT_FUNCTION - << ": row " << r - << " from pos: " << row.pos() - << endl; + << BOOST_CURRENT_FUNCTION + << ": row " << r + << " from pos: " << row.pos() + << endl; bool bound = false; int xx = x; pos_type const pos = row.pos() + getColumnNearX(pit, row, xx, bound); - lyxerr[Debug::DEBUG] - << BOOST_CURRENT_FUNCTION - << ": setting cursor pit: " << pit - << " pos: " << pos - << endl; - + lyxerr[Debug::DEBUG] + << BOOST_CURRENT_FUNCTION + << ": setting cursor pit: " << pit + << " pos: " << pos + << endl; + return setCursor(cur, pit, pos, true, bound); }