- dim.wid = w;
- int const i = fm.breakAt(str, dim.wid, isRTL(), force);
- if (i != -1) {
- //Create a second row element to return
- Element ret(STRING, pos + i, font, change);
- ret.str = str.substr(i);
- ret.endpos = ret.pos + ret.str.length();
- // Copy the after flags of the original element to the second one.
- ret.row_flags = row_flags & (CanBreakInside | AfterFlags);
-
- // Now update ourselves
- str.erase(i);
- endpos = pos + i;
- // Row should be broken after the original element
- row_flags = (row_flags & ~AfterFlags) | BreakAfter;
- //LYXERR0("breakAt(" << w << ") Row element Broken at " << w << "(w(str)=" << fm.width(str) << "): e=" << *this);
- return ret;
+
+ // A a string that is not breakable
+ if (!(row_flags & CanBreakInside)) {
+ // has width been computed yet?
+ if (dim.wid == 0)
+ dim.wid = fm.width(str);
+ return false;
+ }
+
+ bool const wrap_any = !font.language()->wordWrap();
+ FontMetrics::Breaks breaks = fm.breakString(str, width, next_width,
+ isRTL(), wrap_any | force);
+
+ // if breaking did not really work, give up
+ if (!force && breaks.front().nspc_wid > width) {
+ if (dim.wid == 0)
+ dim.wid = fm.width(str);
+ return false;
+ }
+
+ Element first_e(STRING, pos, font, change);
+ // should next element eventually replace *this?
+ bool first = true;
+ docstring::size_type i = 0;
+ for (FontMetrics::Break const & brk : breaks) {
+ /* For some reason breakString can decide to break before the
+ * first character (normally we use a 0-width nbsp to prevent
+ * that). Skip leading empty elements, they are never wanted.
+ */
+ if (first && brk.len == 0 && breaks.size() > 1)
+ continue;
+ Element e(STRING, pos + i, font, change);
+ e.str = str.substr(i, brk.len);
+ e.endpos = e.pos + brk.len;
+ e.dim.wid = brk.wid;
+ e.nspc_wid = brk.nspc_wid;
+ e.row_flags = CanBreakInside | BreakAfter;
+ if (first) {
+ // this element eventually goes to *this
+ e.row_flags |= row_flags & ~AfterFlags;
+ first_e = e;
+ first = false;
+ } else
+ tail.push_back(e);
+ i += brk.len;