X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FText.cpp;h=3b47413b49b1a179af2d529988e7129457bc7b45;hb=30506f8e116e5d65860c354df88b404884835ee3;hp=7a677f1849974625b516d4e943dbcbcb4e0c3c6d;hpb=cc30726cc4350c24959f2a457608255cac8f6447;p=lyx.git diff --git a/src/Text.cpp b/src/Text.cpp index 7a677f1849..3b47413b49 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -118,7 +118,7 @@ void readParToken(Buffer const & buf, Paragraph & par, Lexer & lex, #endif } else if (token == "\\begin_layout") { lex.eatLine(); - string layoutname = lex.getString(); + docstring layoutname = lex.getDocString(); font = Font(Font::ALL_INHERIT, bp.language); change = Change(Change::UNCHANGED); @@ -134,14 +134,14 @@ void readParToken(Buffer const & buf, Paragraph & par, Lexer & lex, if (!hasLayout) { errorList.push_back(ErrorItem(_("Unknown layout"), bformat(_("Layout '%1$s' does not exist in textclass '%2$s'\nTrying to use the default instead.\n"), - from_utf8(layoutname), from_utf8(tclass.name())), par.id(), 0, par.size())); + layoutname, from_utf8(tclass.name())), par.id(), 0, par.size())); layoutname = tclass.defaultLayoutName(); } par.layout(bp.getTextClass()[layoutname]); // Test whether the layout is obsolete. - Layout_ptr const & layout = par.layout(); + LayoutPtr const & layout = par.layout(); if (!layout->obsoleted_by().empty()) par.layout(bp.getTextClass()[layout->obsoleted_by()]); @@ -344,6 +344,13 @@ void readParagraph(Buffer const & buf, Paragraph & par, Lexer & lex, } // namespace anon +bool Text::empty() const +{ + return pars_.empty() || (pars_.size() == 1 && pars_[0].empty() + // FIXME: Should we consider the labeled type as empty too? + && pars_[0].layout()->labeltype == LABEL_NO_LABEL); +} + double Text::spacing(Buffer const & buffer, Paragraph const & par) const @@ -354,40 +361,6 @@ double Text::spacing(Buffer const & buffer, } -int Text::singleWidth(Buffer const & buffer, Paragraph const & par, - pos_type pos) const -{ - return singleWidth(par, pos, par.getChar(pos), - getFont(buffer, par, pos)); -} - - -int Text::singleWidth(Paragraph const & par, - pos_type pos, char_type c, Font const & font) const -{ - // The most common case is handled first (Asger) - if (isPrintable(c)) { - Language const * language = font.language(); - if (language->rightToLeft()) { - if (language->lang() == "arabic" || - language->lang() == "farsi") { - if (Encodings::isComposeChar_arabic(c)) - return 0; - c = par.transformChar(c, pos); - } else if (language->lang() == "hebrew" && - Encodings::isComposeChar_hebrew(c)) - return 0; - } - return theFontMetrics(font).width(c); - } - - if (c == Paragraph::META_INSET) - return par.getInset(pos)->width(); - - return theFontMetrics(font).width(c); -} - - int Text::leftMargin(Buffer const & buffer, int max_width, pit_type pit) const { BOOST_ASSERT(pit >= 0); @@ -406,18 +379,17 @@ int Text::leftMargin(Buffer const & buffer, int max_width, BOOST_ASSERT(pos <= par.size()); //lyxerr << "Text::leftMargin: pit: " << pit << " pos: " << pos << endl; TextClass const & tclass = buffer.params().getTextClass(); - Layout_ptr const & layout = par.layout(); + LayoutPtr const & layout = par.layout(); - string parindent = layout->parindent; + docstring parindent = layout->parindent; int l_margin = 0; if (isMainText(buffer)) l_margin += changebarMargin(); - // FIXME UNICODE - docstring leftm = from_utf8(tclass.leftmargin()); - l_margin += theFontMetrics(buffer.params().getFont()).signedWidth(leftm); + l_margin += theFontMetrics(buffer.params().getFont()).signedWidth( + tclass.leftmargin()); if (par.getDepth() != 0) { // find the next level paragraph @@ -448,55 +420,41 @@ int Text::leftMargin(Buffer const & buffer, int max_width, switch (layout->margintype) { case MARGIN_DYNAMIC: if (!layout->leftmargin.empty()) { - // FIXME UNICODE - docstring leftm = from_utf8(layout->leftmargin); - l_margin += theFontMetrics(buffer.params().getFont()).signedWidth(leftm); + l_margin += theFontMetrics(buffer.params().getFont()).signedWidth( + layout->leftmargin); } if (!par.getLabelstring().empty()) { - // FIXME UNICODE - docstring labin = from_utf8(layout->labelindent); - l_margin += labelfont_metrics.signedWidth(labin); - docstring labstr = par.getLabelstring(); - l_margin += labelfont_metrics.width(labstr); - docstring labsep = from_utf8(layout->labelsep); - l_margin += labelfont_metrics.width(labsep); + l_margin += labelfont_metrics.signedWidth(layout->labelindent); + l_margin += labelfont_metrics.width(par.getLabelstring()); + l_margin += labelfont_metrics.width(layout->labelsep); } break; case MARGIN_MANUAL: { - // FIXME UNICODE - docstring labin = from_utf8(layout->labelindent); - l_margin += labelfont_metrics.signedWidth(labin); + l_margin += labelfont_metrics.signedWidth(layout->labelindent); // The width of an empty par, even with manual label, should be 0 if (!par.empty() && pos >= par.beginOfBody()) { if (!par.getLabelWidthString().empty()) { docstring labstr = par.getLabelWidthString(); l_margin += labelfont_metrics.width(labstr); - docstring labsep = from_utf8(layout->labelsep); - l_margin += labelfont_metrics.width(labsep); + l_margin += labelfont_metrics.width(layout->labelsep); } } break; } case MARGIN_STATIC: { - // FIXME UNICODE - docstring leftm = from_utf8(layout->leftmargin); - l_margin += theFontMetrics(buffer.params().getFont()).signedWidth(leftm) - * 4 / (par.getDepth() + 4); + l_margin += theFontMetrics(buffer.params().getFont()). + signedWidth(layout->leftmargin) * 4 / (par.getDepth() + 4); break; } case MARGIN_FIRST_DYNAMIC: if (layout->labeltype == LABEL_MANUAL) { if (pos >= par.beginOfBody()) { - // FIXME UNICODE - l_margin += labelfont_metrics.signedWidth( - from_utf8(layout->leftmargin)); + l_margin += labelfont_metrics.signedWidth(layout->leftmargin); } else { - // FIXME UNICODE - l_margin += labelfont_metrics.signedWidth( - from_utf8(layout->labelindent)); + l_margin += labelfont_metrics.signedWidth(layout->labelindent); } } else if (pos != 0 // Special case to fix problems with @@ -504,14 +462,13 @@ int Text::leftMargin(Buffer const & buffer, int max_width, || (layout->labeltype == LABEL_STATIC && layout->latextype == LATEX_ENVIRONMENT && !isFirstInSequence(pit, pars_))) { - // FIXME UNICODE - l_margin += labelfont_metrics.signedWidth(from_utf8(layout->leftmargin)); + l_margin += labelfont_metrics.signedWidth(layout->leftmargin); } else if (layout->labeltype != LABEL_TOP_ENVIRONMENT && layout->labeltype != LABEL_BIBLIO && layout->labeltype != LABEL_CENTERED_TOP_ENVIRONMENT) { - l_margin += labelfont_metrics.signedWidth(from_utf8(layout->labelindent)); - l_margin += labelfont_metrics.width(from_utf8(layout->labelsep)); + l_margin += labelfont_metrics.signedWidth(layout->labelindent); + l_margin += labelfont_metrics.width(layout->labelsep); l_margin += labelfont_metrics.width(par.getLabelstring()); } break; @@ -522,9 +479,7 @@ int Text::leftMargin(Buffer const & buffer, int max_width, // row in this paragraph. RowList::iterator rit = par.rows().begin(); RowList::iterator end = par.rows().end(); -#ifdef WITH_WARNINGS -#warning This is wrong. -#endif + // FIXME: This is wrong. int minfill = max_width; for ( ; rit != end; ++rit) if (rit->fill() < minfill) @@ -568,8 +523,8 @@ int Text::leftMargin(Buffer const & buffer, int max_width, || buffer.params().paragraph_separation == BufferParams::PARSEP_INDENT)) { - docstring din = from_utf8(parindent); - l_margin += theFontMetrics(buffer.params().getFont()).signedWidth(din); + l_margin += theFontMetrics(buffer.params().getFont()).signedWidth( + parindent); } return l_margin; @@ -590,7 +545,7 @@ void Text::breakParagraph(Cursor & cur, bool keep_layout) pit_type cpit = cur.pit(); TextClass const & tclass = cur.buffer().params().getTextClass(); - Layout_ptr const & layout = cpar.layout(); + LayoutPtr const & layout = cpar.layout(); // this is only allowed, if the current paragraph is not empty // or caption and if it has not the keepempty flag active @@ -643,12 +598,7 @@ void Text::breakParagraph(Cursor & cur, bool keep_layout) break; // the character couldn't be deleted physically due to change tracking } - ParIterator current_it(cur); - ParIterator last_it(cur); - ++last_it; - ++last_it; - - updateLabels(cur.buffer(), current_it, last_it); + updateLabels(cur.buffer()); // A singlePar update is not enough in this case. cur.updateFlags(Update::Force); @@ -870,7 +820,6 @@ void Text::selectWord(Cursor & cur, word_location loc) cur.resetAnchor(); setCursor(cur, to.pit(), to.pos()); cur.setSelection(); - cap::saveSelection(cur); } @@ -992,36 +941,8 @@ void Text::acceptOrRejectChanges(Cursor & cur, ChangeOp op) void Text::acceptChanges(BufferParams const & bparams) { - pit_type pars_size = static_cast(pars_.size()); - - // first, accept changes within each individual paragraph - // (do not consider end-of-par) - for (pit_type pit = 0; pit < pars_size; ++pit) { - if (!pars_[pit].empty()) // prevent assertion failure - pars_[pit].acceptChanges(bparams, 0, pars_[pit].size()); - } - - // next, accept imaginary end-of-par characters - for (pit_type pit = 0; pit < pars_size; ++pit) { - pos_type pos = pars_[pit].size(); - - if (pars_[pit].isInserted(pos)) { - pars_[pit].setChange(pos, Change(Change::UNCHANGED)); - } else if (pars_[pit].isDeleted(pos)) { - if (pit == pars_size - 1) { - // we cannot remove a par break at the end of the last - // paragraph; instead, we mark it unchanged - pars_[pit].setChange(pos, Change(Change::UNCHANGED)); - } else { - mergeParagraph(bparams, pars_, pit); - --pit; - --pars_size; - } - } - } - - // finally, invoke the DEPM - deleteEmptyParagraphMechanism(0, pars_size - 1, bparams.trackChanges); + lyx::acceptChanges(pars_, bparams); + deleteEmptyParagraphMechanism(0, pars_.size() - 1, bparams.trackChanges); } @@ -1261,7 +1182,7 @@ bool Text::erase(Cursor & cur) recordUndo(cur, Undo::DELETE); if(!par.eraseChar(cur.pos(), cur.buffer().params().trackChanges)) { // the character has been logically deleted only => skip it - cur.forwardPosNoDescend(); + cur.top().forwardPos(); } checkBufferStructure(cur.buffer(), cur); needsUpdate = true; @@ -1392,7 +1313,7 @@ bool Text::backspace(Cursor & cur) bool Text::dissolveInset(Cursor & cur) { BOOST_ASSERT(this == cur.text()); - if (isMainText(*cur.bv().buffer()) || cur.inset().nargs() != 1) + if (isMainText(cur.bv().buffer()) || cur.inset().nargs() != 1) return false; recordUndoInset(cur); @@ -1421,7 +1342,7 @@ bool Text::dissolveInset(Cursor & cur) { b.getLanguage()); } - pasteParagraphList(cur, plist, b.params().textclass, + pasteParagraphList(cur, plist, b.params().getTextClass_ptr(), b.errorList("Paste")); // restore position cur.pit() = std::min(cur.lastpit(), spit); @@ -1528,7 +1449,7 @@ void Text::drawRowSelection(PainterInfo & pi, int x, Row const & row, bool drawOnBegMargin, bool drawOnEndMargin) const { BufferView & bv = *pi.base.bv; - Buffer & buffer = *bv.buffer(); + Buffer & buffer = bv.buffer(); TextMetrics const & tm = bv.textMetrics(this); DocIterator cur = beg; int x1 = cursorX(bv, beg.top(), beg.boundary()); @@ -1663,6 +1584,10 @@ void Text::write(Buffer const & buf, std::ostream & os) const depth_type dth = 0; for (; pit != end; ++pit) pit->write(buf, os, buf.params(), dth); + + // Close begin_deeper + for(; dth > 0; --dth) + os << "\n\\end_deeper"; } @@ -1737,7 +1662,7 @@ int Text::cursorX(BufferView const & bv, CursorSlice const & sl, pos_type cursor_vpos = 0; - Buffer const & buffer = *bv.buffer(); + Buffer const & buffer = bv.buffer(); RowMetrics const m = tm.computeRowMetrics(pit, row); double x = m.x; Bidi bidi; @@ -1745,6 +1670,12 @@ int Text::cursorX(BufferView const & bv, CursorSlice const & sl, pos_type const row_pos = row.pos(); pos_type const end = row.endpos(); + // Spaces at logical line breaks in bidi text must be skipped during + // cursor positioning. However, they may appear visually in the middle + // of a row; they must be skipped, wherever they are... + // * logically "abc_[HEBREW_\nHEBREW]" + // * visually "abc_[_WERBEH\nWERBEH]" + pos_type skipped_sep_vpos = -1; if (end <= row_pos) cursor_vpos = row_pos; @@ -1767,17 +1698,23 @@ int Text::cursorX(BufferView const & bv, CursorSlice const & sl, // Use font span to speed things up, see below FontSpan font_span; Font font; - FontMetrics const & labelfm = theFontMetrics( - getLabelFont(buffer, par)); + // If the last logical character is a separator, skip it, unless + // it's in the last row of a paragraph; see skipped_sep_vpos declaration + if (end > 0 && end < par.size() && par.isSeparator(end - 1)) + skipped_sep_vpos = bidi.log2vis(end - 1); + for (pos_type vpos = row_pos; vpos < cursor_vpos; ++vpos) { + // Skip the separator which is at the logical end of the row + if (vpos == skipped_sep_vpos) + continue; pos_type pos = bidi.vis2log(vpos); if (body_pos > 0 && pos == body_pos - 1) { - // FIXME UNICODE - docstring const lsep = from_utf8(par.layout()->labelsep); - x += m.label_hfill + labelfm.width(lsep); + FontMetrics const & labelfm = theFontMetrics( + getLabelFont(buffer, par)); + x += m.label_hfill + labelfm.width(par.layout()->labelsep); if (par.isLineSeparator(body_pos - 1)) - x -= singleWidth(buffer, par, body_pos - 1); + x -= tm.singleWidth(pit, body_pos - 1); } // Use font span to speed things up, see above @@ -1786,7 +1723,7 @@ int Text::cursorX(BufferView const & bv, CursorSlice const & sl, font = getFont(buffer, par, pos); } - x += singleWidth(par, pos, par.getChar(pos), font); + x += pm.singleWidth(pos, font); if (par.hfillExpansion(row, pos)) x += (pos >= body_pos) ? m.hfill : m.label_hfill; @@ -1797,9 +1734,9 @@ int Text::cursorX(BufferView const & bv, CursorSlice const & sl, // see correction above if (boundary_correction) { if (isRTL(buffer, sl, boundary)) - x -= singleWidth(buffer, par, ppos); + x -= tm.singleWidth(pit, ppos); else - x += singleWidth(buffer, par, ppos); + x += tm.singleWidth(pit, ppos); } return int(x); @@ -1913,7 +1850,7 @@ docstring Text::getPossibleLabel(Cursor & cur) const { pit_type pit = cur.pit(); - Layout_ptr layout = pars_[pit].layout(); + LayoutPtr layout = pars_[pit].layout(); docstring text; docstring par_text = pars_[pit].asString(cur.buffer(), false); @@ -1937,7 +1874,7 @@ docstring Text::getPossibleLabel(Cursor & cur) const // For section, subsection, etc... if (layout->latextype == LATEX_PARAGRAPH && pit != 0) { - Layout_ptr const & layout2 = pars_[pit - 1].layout(); + LayoutPtr const & layout2 = pars_[pit - 1].layout(); if (layout2->latextype != LATEX_PARAGRAPH) { --pit; layout = layout2;