#include "support/debug.h"
#include "support/docstring_list.h"
+#include "support/gettext.h"
#include "support/lassert.h"
#include <cstdlib>
TextMetrics::TextMetrics(BufferView * bv, Text * text)
: bv_(bv), text_(text)
{
- LASSERT(bv_, /**/);
+ LBUFERR(bv_);
max_width_ = bv_->workWidth();
dim_.wid = max_width_;
dim_.asc = 10;
pair<pit_type, ParagraphMetrics const *> TextMetrics::last() const
{
- LASSERT(!par_metrics_.empty(), /**/);
+ LBUFERR(!par_metrics_.empty());
ParMetricsCache::const_reverse_iterator it = par_metrics_.rbegin();
return make_pair(it->first, &it->second);
}
bool TextMetrics::metrics(MetricsInfo & mi, Dimension & dim, int min_width)
{
- LASSERT(mi.base.textwidth > 0, /**/);
+ LBUFERR(mi.base.textwidth > 0);
max_width_ = mi.base.textwidth;
// backup old dimension.
Dimension const old_dim = dim_;
{
FontInfo lf(font_.fontInfo());
lf.reduce(bv_->buffer().params().getFont().fontInfo());
- font.fontInfo().realize(lf);
+ font.fontInfo().realize(lf);
}
Font TextMetrics::displayFont(pit_type pit, pos_type pos) const
{
- LASSERT(pos >= 0, /**/);
+ LASSERT(pos >= 0, { static Font f; return f; });
ParagraphList const & pars = text_->paragraphs();
Paragraph const & par = pars[pit];
// no RTL boundary at line break:
// abc|\n -> move right -> abc\n (and not: abc\n|
// FED FED| FED )
- if (startpos == pos && endpos == pos && endpos != par.size()
- && (par.isNewline(pos - 1)
- || par.isLineSeparator(pos - 1)
+ if (startpos == pos && endpos == pos && endpos != par.size()
+ && (par.isNewline(pos - 1)
+ || par.isLineSeparator(pos - 1)
|| par.isSeparator(pos - 1)))
return false;
-
+
bool left = font.isVisibleRightToLeft();
bool right;
if (pos == par.size())
right = par.isRTL(bv_->buffer().params());
else
right = displayFont(pit, pos).isVisibleRightToLeft();
-
+
return left != right;
}
main_text_ = (text_ == &buffer.text());
bool changed = false;
+ // Check whether there are InsetBibItems that need fixing
// FIXME: This check ought to be done somewhere else. It is the reason
- // why text_ is not const. But then, where else to do it?
+ // why text_ is not const. But then, where else to do it?
// Well, how can you end up with either (a) a biblio environment that
// has no InsetBibitem or (b) a biblio environment with more than one
// InsetBibitem? I think the answer is: when paragraphs are merged;
// when layout is set; when material is pasted.
- int const moveCursor = par.checkBiblio(buffer);
- if (moveCursor > 0)
- const_cast<Cursor &>(bv_->cursor()).posForward();
- else if (moveCursor < 0) {
- Cursor & cursor = const_cast<Cursor &>(bv_->cursor());
- if (cursor.pos() >= -moveCursor)
- cursor.posBackward();
+ if (par.brokenBiblio()) {
+ Cursor & cur = const_cast<Cursor &>(bv_->cursor());
+ // In some cases, we do not know how to record undo
+ if (&cur.inset() == &text_->inset())
+ cur.recordUndo(ATOMIC_UNDO, pit, pit);
+
+ int const moveCursor = par.fixBiblio(buffer);
+
+ // Is it necessary to update the cursor?
+ if (&cur.inset() == &text_->inset() && cur.pit() == pit) {
+ if (moveCursor > 0)
+ cur.posForward();
+ else if (moveCursor < 0 && cur.pos() >= -moveCursor)
+ cur.posBackward();
+ }
}
// Optimisation: this is used in the next two loops
// should be.
bv_->buffer().updateBuffer();
parPos = text_->macrocontextPosition();
- LASSERT(!parPos.empty(), /**/);
+ LBUFERR(!parPos.empty());
parPos.pit() = pit;
}
case LYX_ALIGN_CENTER:
case LYX_ALIGN_LEFT:
case LYX_ALIGN_RIGHT:
- if (align == LYX_ALIGN_NONE
+ if (align == LYX_ALIGN_NONE
|| align == LYX_ALIGN_BLOCK)
align = owner.contentAlignment();
break;
Paragraph const & par = text_->getPar(pit);
pos_type last = par.beginOfBody();
- LASSERT(last > 0, /**/);
+ LBUFERR(last > 0);
// -1 because a label ends with a space that is in the label
--last;
#if 0
-// Not used, see TextMetrics::rowBreakPoint.
+// Not used, see TextMetrics::rowBreakPoint.
// this needs special handling - only newlines count as a break point
static pos_type addressBreakPoint(pos_type i, Paragraph const & par)
{
FontIterator & operator++()
{
++pos_;
- if (pos_ > endspan_ || pos_ == bodypos_) {
+ if (pos_ < par_.size() && (pos_ > endspan_ || pos_ == bodypos_)) {
font_ = tm_.displayFont(pit_, pos_);
endspan_ = par_.fontSpan(pos_).last;
}
Layout const & layout = par.layout();
#if 0
- //FIXME: As long as leftMargin() is not correctly implemented for
+ //FIXME: As long as leftMargin() is not correctly implemented for
// MARGIN_RIGHT_ADDRESS_BOX, we should also not do this here.
// Otherwise, long rows will be painted off the screen.
if (layout.margintype == MARGIN_RIGHT_ADDRESS_BOX)
ParagraphList const & pars_ = text_->paragraphs();
bool const draw_par_end_marker = lyxrc.paragraph_markers
&& size_type(pit + 1) < pars_.size();
-
+
for ( ; i < end; ++i, ++fi) {
int thiswidth = pm.singleWidth(i, *fi);
-
+
if (draw_par_end_marker && i == end - 1)
// enlarge the last character to hold the end-of-par marker
thiswidth += par_marker_width;
w -= singleWidth(pit, i - 1);
w = max(w, label_end);
}
-
- // a line separator at the end of a line (but not at the end of a
+
+ // a line separator at the end of a line (but not at the end of a
// paragraph) will not be drawn and should therefore not count for
// the row width.
if (!par.isLineSeparator(i) || i != end - 1 || end == par.size())
if (par.params().startOfAppendix())
maxasc += int(3 * dh);
- // This is special code for the chapter, since the label of this
- // layout is printed in an extra row
- if (layout.counter == "chapter"
- && !par.params().labelString().empty()) {
- labeladdon = int(labelfont_metrics.maxHeight()
- * layout.spacing.getValue()
- * text_->spacing(par));
- }
-
// special code for the top label
- if ((layout.labeltype == LABEL_TOP_ENVIRONMENT
- || layout.labeltype == LABEL_BIBLIO
- || layout.labeltype == LABEL_CENTERED_TOP_ENVIRONMENT)
- && text_->isFirstInSequence(pit)
+ if (layout.labelIsAbove()
+ && (!layout.isParagraphGroup() || text_->isFirstInSequence(pit))
&& !par.labelString().empty())
{
labeladdon = int(
// the value of rtl.
bool const rtl_on_lastrow = lastrow ? text_->isRTL(par) : false;
- // if the first character is a separator, and we are in RTL
- // text, this character will not be painted on screen
- // and thus we should not count it and skip to the next. Only
- // in freespacing paragraphs, this first character is painted.
- if (!par.isFreeSpacing() && par.isSeparator(bidi.vis2log(vc)))
- ++vc;
-
while (vc < end && tmpx <= x) {
c = bidi.vis2log(vc);
last_tmpx = tmpx;
left_side = true;
}
- LASSERT(vc <= end, /**/); // This shouldn't happen.
+ // This shouldn't happen. But we can reset and try to continue.
+ LASSERT(vc <= end, vc = end);
boundary = false;
// upDownInText() while in selection mode.
ParagraphMetrics const & pm = parMetrics(pit);
- LASSERT(row < int(pm.rows().size()), /**/);
+ LBUFERR(row < int(pm.rows().size()));
bool bound = false;
Row const & r = pm.rows()[row];
return r.pos() + getColumnNearX(pit, r, x, bound);
int yy = -1;
ParMetricsCache::const_iterator it = par_metrics_.begin();
ParMetricsCache::const_iterator et = par_metrics_.end();
- ParMetricsCache::const_iterator last = et; last--;
+ ParMetricsCache::const_iterator last = et;
+ --last;
ParagraphMetrics const & pm = it->second;
ParagraphMetrics const & pm = par_metrics_[pit];
int yy = pm.position() - pm.ascent();
- LASSERT(!pm.rows().empty(), /**/);
+ LBUFERR(!pm.rows().empty());
RowList::const_iterator rit = pm.rows().begin();
RowList::const_iterator rlast = pm.rows().end();
--rlast;
}
pit_type pit = getPitNearY(y);
LASSERT(pit != -1, return 0);
-
+
int yy = y; // is modified by getPitAndRowNearY
Row const & row = getPitAndRowNearY(yy, pit, assert_in_view, up);
Inset * inset = checkInsetHit(x, yy);
//lyxerr << "inset " << inset << " hit at x: " << x << " y: " << y << endl;
if (!inset) {
- // Either we deconst editXY or better we move current_font
- // and real_current_font to Cursor
- // FIXME: what is needed now that current_font and real_current_font
- // are transferred?
cur.setCurrentFont();
return 0;
}
// This should be just before or just behind the
// cursor position set above.
- LASSERT(inset == inset_before
+ LASSERT(inset == inset_before
|| inset == pars[pit].getInset(pos), return 0);
// Make sure the cursor points to the position before
void TextMetrics::setCursorFromCoordinates(Cursor & cur, int const x, int const y)
{
- LASSERT(text_ == cur.text(), /**/);
- pit_type pit = getPitNearY(y);
+ LASSERT(text_ == cur.text(), return);
+ pit_type const pit = getPitNearY(y);
LASSERT(pit != -1, return);
ParagraphMetrics const & pm = par_metrics_[pit];
" pit: " << pit << " yy: " << yy);
int r = 0;
- LASSERT(pm.rows().size(), /**/);
+ LBUFERR(pm.rows().size());
for (; r < int(pm.rows().size()) - 1; ++r) {
Row const & row = pm.rows()[r];
if (int(yy + row.height()) > y)
int TextMetrics::cursorX(CursorSlice const & sl,
bool boundary) const
{
- LASSERT(sl.text() == text_, /**/);
+ LASSERT(sl.text() == text_, return 0);
pit_type const pit = sl.pit();
Paragraph const & par = text_->paragraphs()[pit];
ParagraphMetrics const & pm = par_metrics_[pit];
bool TextMetrics::cursorHome(Cursor & cur)
{
- LASSERT(text_ == cur.text(), /**/);
+ LASSERT(text_ == cur.text(), return false);
ParagraphMetrics const & pm = par_metrics_[cur.pit()];
Row const & row = pm.getRow(cur.pos(),cur.boundary());
return text_->setCursor(cur, cur.pit(), row.pos());
bool TextMetrics::cursorEnd(Cursor & cur)
{
- LASSERT(text_ == cur.text(), /**/);
+ LASSERT(text_ == cur.text(), return false);
// if not on the last row of the par, put the cursor before
// the final space exept if I have a spanning inset or one string
// is so long that we force a break.
void TextMetrics::deleteLineForward(Cursor & cur)
{
- LASSERT(text_ == cur.text(), /**/);
+ LASSERT(text_ == cur.text(), return);
if (cur.lastpos() == 0) {
// Paragraph is empty, so we just go forward
text_->cursorForward(cur);
int TextMetrics::leftMargin(int max_width, pit_type pit) const
{
- LASSERT(pit >= 0, /**/);
- LASSERT(pit < int(text_->paragraphs().size()), /**/);
return leftMargin(max_width, pit, text_->paragraphs()[pit].size());
}
{
ParagraphList const & pars = text_->paragraphs();
- LASSERT(pit >= 0, /**/);
- LASSERT(pit < int(pars.size()), /**/);
+ LASSERT(pit >= 0, return 0);
+ LASSERT(pit < int(pars.size()), return 0);
Paragraph const & par = pars[pit];
- LASSERT(pos >= 0, /**/);
- LASSERT(pos <= par.size(), /**/);
+ LASSERT(pos >= 0, return 0);
+ LASSERT(pos <= par.size(), return 0);
Buffer const & buffer = bv_->buffer();
//lyxerr << "TextMetrics::leftMargin: pit: " << pit << " pos: " << pos << endl;
DocumentClass const & tclass = buffer.params().documentClass();
&& layout.latextype == LATEX_ENVIRONMENT
&& !text_->isFirstInSequence(pit))) {
l_margin += labelfont_metrics.signedWidth(layout.leftmargin);
- } else if (layout.labeltype != LABEL_TOP_ENVIRONMENT
- && layout.labeltype != LABEL_BIBLIO
- && layout.labeltype !=
- LABEL_CENTERED_TOP_ENVIRONMENT) {
+ } else if (!layout.labelIsAbove()) {
l_margin += labelfont_metrics.signedWidth(layout.labelindent);
l_margin += labelfont_metrics.width(layout.labelsep);
l_margin += labelfont_metrics.width(par.labelString());
// The left margin depends on the widest row in this paragraph.
// This code is wrong because it depends on the rows, but at the
// same time this function is used in redoParagraph to construct
- // the rows.
+ // the rows.
ParagraphMetrics const & pm = par_metrics_[pit];
RowList::const_iterator rit = pm.rows().begin();
RowList::const_iterator end = pm.rows().end();
// set the correct parindent
if (pos == 0
&& (layout.labeltype == LABEL_NO_LABEL
- || layout.labeltype == LABEL_TOP_ENVIRONMENT
- || layout.labeltype == LABEL_CENTERED_TOP_ENVIRONMENT
+ || layout.labeltype == LABEL_ABOVE
+ || layout.labeltype == LABEL_CENTERED
|| (layout.labeltype == LABEL_STATIC
&& layout.latextype == LATEX_ENVIRONMENT
&& !text_->isFirstInSequence(pit)))
&& par.getInset(pos)->display())
&& (!(tclass.isDefaultLayout(par.layout())
|| tclass.isPlainLayout(par.layout()))
- || buffer.params().paragraph_separation
+ || buffer.params().paragraph_separation
== BufferParams::ParagraphIndentSeparation)
)
{
else
l_margin += buffer.params().getIndentation().inPixels(*bv_);
}
-
+
return l_margin;
}
// We store the begin and end pos of the selection relative to this par
DocIterator sel_beg_par = cur.selectionBegin();
DocIterator sel_end_par = cur.selectionEnd();
-
+
// We care only about visible selection.
if (selection) {
if (pit != sel_beg.pit()) {
row.setSelectionAndMargins(sel_beg_par, sel_end_par);
else
row.setSelection(-1, -1);
-
+
// The row knows nothing about the paragraph, so we have to check
// whether this row is the first or last and update the margins.
if (row.selection()) {
pi.pain.fillRectangle(x, y - row.ascent(),
width(), row.height(), pi.background_color);
}
-
+
// Instrumentation for testing row cache (see also
// 12 lines lower):
if (lyxerr.debugging(Debug::PAINTING) && inside