#include "support/debug.h"
#include "support/lassert.h"
+#include "support/lstrings.h"
#include "support/lyxalgo.h"
#include <ostream>
namespace lyx {
+using support::rtrim;
using frontend::FontMetrics;
double Row::Element::pos2x(pos_type const i) const
}
-bool Row::Element::breakAt(int w)
+bool Row::Element::breakAt(int w, bool force)
{
if (type != STRING || dim.wid <= w)
return false;
bool const rtl = font.isVisibleRightToLeft();
- if (rtl)
- w = dim.wid - w;
- pos_type new_pos = x2pos(w);
- if (new_pos == pos)
- return false;
- str = str.substr(0, new_pos - pos);
- if (rtl)
- dim.wid -= w;
- else
- dim.wid = w;
- endpos = new_pos;
- return true;
+ FontMetrics const & fm = theFontMetrics(font);
+ int x = w;
+ if(fm.breakAt(str, x, rtl, force)) {
+ dim.wid = x;
+ endpos = pos + str.length();
+ //lyxerr << "breakAt(" << w << ") Row element Broken at " << x << "(w(str)=" << fm.width(str) << "): e=" << *this << endl;
+ return true;
+ }
+ return false;
}
elt.final = true;
if (elt.type == STRING) {
+ dim_.wid -= elt.dim.wid;
elt.dim.wid = theFontMetrics(elt.font).width(elt.str);
dim_.wid += elt.dim.wid;
}
Element e(STRING, pos, f, ch);
elements_.push_back(e);
}
+ dim_.wid -= back().dim.wid;
back().str += c;
back().endpos = pos + 1;
+ back().dim.wid = theFontMetrics(back().font).width(back().str);
+ dim_.wid += back().dim.wid;
}
{
if (empty() || width() <= w)
return;
-
Elements::iterator const beg = elements_.begin();
Elements::iterator const end = elements_.end();
- Elements::iterator last_sep = elements_.end();
- int last_width = 0;
int wid = left_margin;
Elements::iterator cit = beg;
for ( ; cit != end ; ++cit) {
- if (cit->type == SEPARATOR && cit->pos >= keep) {
- last_sep = cit;
- last_width = wid;
- }
- if (wid + cit->dim.wid > w)
+ if (cit->endpos >= keep && wid + cit->dim.wid > w)
break;
wid += cit->dim.wid;
}
- if (last_sep != end) {
- // We have found a suitable separator. This is the
- // common case.
- end_ = last_sep->endpos;
- dim_.wid = last_width;
- elements_.erase(last_sep, end);
- return;
- }
-
if (cit == end) {
// This should not happen since the row is too long.
LYXERR0("Something is wrong cannot shorten row: " << *this);
wid -= cit->dim.wid;
}
+ // Try to break this row cleanly (at word boundary)
+ if (cit->breakAt(w - wid, false)) {
+ end_ = cit->endpos;
+ // after breakAt, there may be spaces at the end of the
+ // string, but they are not counted in the string length
+ // (qtextlayout feature, actually). We remove them, but do not
+ // change the endo of the row, since the spaces at row break
+ // are invisible.
+ cit->str = rtrim(cit->str);
+ cit->endpos = cit->pos + cit->str.length();
+ dim_.wid = wid + cit->dim.wid;
+ // If there are other elements, they should be removed.
+ elements_.erase(next(cit, 1), end);
+ return;
+ }
+
if (cit != beg) {
- // There is no separator, but several elements (probably
- // insets) have been added. We can cut at this place.
+ // There is no separator, but several elements have been
+ // added. We can cut right here.
end_ = cit->pos;
dim_.wid = wid;
elements_.erase(cit, end);
return;
}
- /* If we are here, it means that we have not found a separator
- * to shorten the row. There is one case where we can do
- * something: when we have one big string, maybe with some
- * other things after it.
+ /* If we are here, it means that we have not found a separator to
+ * shorten the row. Let's try to break it again, but not at word
+ * boundary this time.
*/
- if (cit->breakAt(w - left_margin)) {
+ if (cit->breakAt(w - wid, true)) {
end_ = cit->endpos;
- dim_.wid = left_margin + cit->dim.wid;
+ // See comment above.
+ cit->str = rtrim(cit->str);
+ cit->endpos = cit->pos + cit->str.length();
+ dim_.wid = wid + cit->dim.wid;
// If there are other elements, they should be removed.
elements_.erase(next(cit, 1), end);
}
// or the end of the par, then build a representation of the row.
pos_type i = pos;
FontIterator fi = FontIterator(*this, par, pit, pos);
- while (i < end && row.width() < width) {
+ while (i < end && row.width() <= width) {
char_type c = par.getChar(i);
// The most special cases are handled first.
if (par.isInset(i)) {
int const add = max(fm.width(par.layout().labelsep),
labelEnd(pit) - row.width());
row.addSpace(i, add, *fi, par.lookupChange(i));
- } else if (par.isLineSeparator(i)) {
- // In theory, no inset has this property. If
- // this is done, a new addSeparator which
- // takes an inset as parameter should be
- // added.
- LATTEST(!par.isInset(i));
- row.addSeparator(i, c, *fi, par.lookupChange(i));
} else if (c == '\t')
row.addSpace(i, theFontMetrics(*fi).width(from_ascii(" ")),
*fi, par.lookupChange(i));
// make sure that the RTL elements are in reverse ordering
row.reverseRTL(is_rtl);
+ //LYXERR0("breakrow: row is " << row);
}