ParIterator.h \
PDFOptions.h \
Row.h \
+ RowFlags.h \
RowPainter.h \
Server.h \
ServerSocket.h \
Row::Element Row::Element::splitAt(int w, bool force)
{
- if (type != STRING)
+ if (type != STRING || !(row_flags & CanBreakInside))
return Element();
FontMetrics const & fm = theFontMetrics(font);
Element ret(STRING, pos + i, font, change);
ret.str = str.substr(i);
ret.endpos = ret.pos + ret.str.length();
+ ret.row_flags = row_flags & (CanBreakInside | AfterFlags);
str.erase(i);
endpos = pos + i;
//lyxerr << "breakAt(" << w << ") Row element Broken at " << x << "(w(str)=" << fm.width(str) << "): e=" << *this << endl;
void Row::add(pos_type const pos, Inset const * ins, Dimension const & dim,
- Font const & f, Change const & ch)
+ Font const & f, Change const & ch)
{
finalizeLast();
Element e(INSET, pos, f, ch);
e.inset = ins;
e.dim = dim;
+ e.row_flags = ins->rowFlags();
elements_.push_back(e);
dim_.wid += dim.wid;
changebar_ |= ins->isChanged();
void Row::add(pos_type const pos, char_type const c,
- Font const & f, Change const & ch)
+ Font const & f, Change const & ch, bool can_break)
{
if (!sameString(f, ch)) {
finalizeLast();
Element e(STRING, pos, f, ch);
+ e.row_flags = can_break ? CanBreakInside : Inline;
elements_.push_back(e);
}
if (back().str.length() % 30 == 0) {
e.dim.wid = theFontMetrics(f).width(s);
dim_.wid += e.dim.wid;
e.endpos = pos;
+ // Copy after* flags from previous elements, forbid break before element
+ int const prev_row_flags = elements_.empty() ? Inline : elements_.back().row_flags;
+ int const can_inherit = AfterFlags & ~AlwaysBreakAfter;
+ e.row_flags = (prev_row_flags & can_inherit) | NoBreakBefore;
elements_.push_back(e);
finalizeLast();
}
}
-bool Row::shortenIfNeeded(pos_type const keep, int const w, int const next_width)
+bool Row::shortenIfNeeded(int const w, int const next_width)
{
if (empty() || width() <= w)
return false;
// make a copy of the element to work on it.
Element brk = *cit_brk;
/* If the current element is an inset that allows breaking row
- * after itself, and it the row is already short enough after
+ * after itself, and if the row is already short enough after
* this inset, then cut right after this element.
*/
- if (wid_brk <= w && brk.type == INSET
- && brk.inset->rowFlags() & Inset::CanBreakAfter) {
+ if (wid_brk <= w && brk.row_flags & CanBreakAfter) {
end_ = brk.endpos;
dim_.wid = wid_brk;
elements_.erase(cit_brk + 1, end);
* not allowed at the beginning or end of line.
*/
bool const word_wrap = brk.font.language()->wordWrap();
- // When there is text before the body part (think description
- // environment), do not try to break.
- if (brk.pos < keep)
- continue;
/* We have found a suitable separable element. This is the common case.
* Try to break it cleanly (at word boundary) at a length that is both
* - less than the available space on the row
#include "Changes.h"
#include "Dimension.h"
#include "Font.h"
+#include "RowFlags.h"
#include "support/docstring.h"
#include "support/types.h"
Change change;
// is it possible to add contents to this element?
bool final = false;
+ // properties with respect to row breaking (made of RowFlag enums)
+ int row_flags = Inline;
friend std::ostream & operator<<(std::ostream & os, Element const & row);
};
Font const & f, Change const & ch);
///
void add(pos_type pos, char_type const c,
- Font const & f, Change const & ch);
+ Font const & f, Change const & ch, bool can_break);
///
void addVirtual(pos_type pos, docstring const & s,
Font const & f, Change const & ch);
* if row width is too large, remove all elements after last
* separator and update endpos if necessary. If all that
* remains is a large word, cut it to \param width.
- * \param body_pos minimum amount of text to keep.
* \param width maximum width of the row.
* \param available width on next row.
* \return true if the row has been shortened.
*/
- bool shortenIfNeeded(pos_type const body_pos, int const width, int const next_width);
+ bool shortenIfNeeded(int const width, int const next_width);
/**
* If last element of the row is a string, compute its width
--- /dev/null
+// -*- C++ -*-
+/**
+ * \file RowFlags.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Jean-Marc Lasgouttes
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#ifndef ROWFLAGS_H
+#define ROWFLAGS_H
+
+// Do not include anything here
+
+namespace lyx {
+
+/* The list of possible flags, that can be combined.
+ * Some flags that should logically be here (e.g.,
+ * CanBreakBefore), do not exist. This is because the need has not
+ * been identitfied yet.
+ *
+ * Priorities when before/after disagree:
+ * AlwaysBreak* > NoBreak* > Break* or CanBreak*.
+ */
+enum RowFlags {
+ // Do not break before or after this element, except if really
+ // needed (between NoBreak* and CanBreak*).
+ Inline = 0,
+ // break row before this element if the row is not empty
+ BreakBefore = 1 << 0,
+ // Avoid breaking row before this element
+ NoBreakBefore = 1 << 1,
+ // force new (maybe empty) row after this element
+ AlwaysBreakAfter = 1 << 2,
+ // break row after this element if there are more elements
+ BreakAfter = 1 << 3,
+ // break row whenever needed after this element
+ CanBreakAfter = 1 << 4,
+ // Avoid breaking row after this element
+ NoBreakAfter = 1 << 5,
+ // The contents of the row may be broken in two (e.g. string)
+ CanBreakInside = 1 << 6,
+ // specify an alignment (left, right) for a display element
+ // (default is center)
+ AlignLeft = 1 << 7,
+ AlignRight = 1 << 8,
+ // A display element breaks row at both ends
+ Display = BreakBefore | BreakAfter,
+ // Flags that concern breaking after element
+ AfterFlags = AlwaysBreakAfter | BreakAfter | CanBreakAfter | NoBreakAfter
+};
+
+} // namespace lyx
+
+#endif
// Display-style insets should always be on a centered row
if (Inset const * inset = par.getInset(row.pos())) {
- if (inset->rowFlags() & Inset::Display) {
- if (inset->rowFlags() & Inset::AlignLeft)
+ if (inset->rowFlags() & Display) {
+ if (inset->rowFlags() & AlignLeft)
align = LYX_ALIGN_BLOCK;
- else if (inset->rowFlags() & Inset::AlignRight)
+ else if (inset->rowFlags() & AlignRight)
align = LYX_ALIGN_RIGHT;
else
align = LYX_ALIGN_CENTER;
row.addSpace(i, add, *fi, par.lookupChange(i));
} else if (c == '\t')
row.addSpace(i, theFontMetrics(*fi).width(from_ascii(" ")),
- *fi, par.lookupChange(i));
+ *fi, par.lookupChange(i));
else if (c == 0x2028 || c == 0x2029) {
/**
* U+2028 LINE SEPARATOR
// ⤶ U+2936 ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS
// ¶ U+00B6 PILCROW SIGN
char_type const screen_char = (c == 0x2028) ? 0x2936 : 0x00B6;
- row.add(i, screen_char, *fi, par.lookupChange(i));
+ row.add(i, screen_char, *fi, par.lookupChange(i), i >= body_pos);
} else
- row.add(i, c, *fi, par.lookupChange(i));
+ // row elements before body are unbreakable
+ row.add(i, c, *fi, par.lookupChange(i), i >= body_pos);
// add inline completion width
// draw logically behind the previous character
// ⤶ U+2936 ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS
// ¶ U+00B6 PILCROW SIGN
char_type const screen_char = (c == 0x2028) ? 0x2936 : 0x00B6;
- row.add(i, screen_char, *fi, par.lookupChange(i));
+ row.add(i, screen_char, *fi, par.lookupChange(i), i >= body_pos);
} else
- row.add(i, c, *fi, par.lookupChange(i));
+ row.add(i, c, *fi, par.lookupChange(i), i >= body_pos);
// add inline completion width
// draw logically behind the previous character
// - After an inset with BreakAfter
Inset const * prevInset = !row.empty() ? row.back().inset : 0;
Inset const * nextInset = (i + 1 < end) ? par.getInset(i + 1) : 0;
- if ((nextInset && nextInset->rowFlags() & Inset::BreakBefore)
- || (prevInset && prevInset->rowFlags() & Inset::BreakAfter)) {
+ if ((nextInset && nextInset->rowFlags() & BreakBefore)
+ || (prevInset && prevInset->rowFlags() & BreakAfter)) {
row.flushed(true);
// Force a row creation after this one if it is ended by
// an inset that either
// - or (1) did force the row breaking, (2) is at end of
// paragraph and (3) the said paragraph has an end label.
need_new_row = prevInset &&
- (prevInset->rowFlags() & Inset::RowAfter
- || (prevInset->rowFlags() & Inset::BreakAfter && i + 1 == end
+ (prevInset->rowFlags() & AlwaysBreakAfter
+ || (prevInset->rowFlags() & BreakAfter && i + 1 == end
&& text_->getEndLabel(row.pit()) != END_LABEL_NO_LABEL));
++i;
break;
int const next_width = max_width_ - leftMargin(row.pit(), row.endpos())
- rightMargin(row.pit());
- if (row.shortenIfNeeded(body_pos, width, next_width))
+ if (row.shortenIfNeeded(width, next_width))
row.flushed(false);
row.right_boundary(!row.empty() && row.endpos() < end
&& row.back().endpos == row.endpos());
// display style insets do not need indentation
&& !(!par.empty()
&& par.isInset(0)
- && par.getInset(0)->rowFlags() & Inset::Display)
+ && par.getInset(0)->rowFlags() & Display)
&& (!(tclass.isDefaultLayout(par.layout())
|| tclass.isPlainLayout(par.layout()))
|| buffer.params().paragraph_separation
#include "LayoutEnums.h"
#include "OutputEnums.h"
#include "OutputParams.h"
+#include "RowFlags.h"
#include "support/docstring.h"
#include "support/strfwd.h"
virtual CtObject getCtObject(OutputParams const &) const;
- enum RowFlags {
- Inline = 0,
- // break row before this inset
- BreakBefore = 1 << 0,
- // break row after this inset
- BreakAfter = 1 << 1,
- // it is possible to break after this inset
- CanBreakAfter = 1 << 2,
- // force new (maybe empty) row after this inset
- RowAfter = 1 << 3,
- // specify an alignment (left, right) for a display inset
- // (default is center)
- AlignLeft = 1 << 4,
- AlignRight = 1 << 5,
- // A display inset breaks row at both ends
- Display = BreakBefore | BreakAfter
- };
-
- /// How should this inset be displayed in its row?
- virtual RowFlags rowFlags() const { return Inline; }
+ // properties with respect to row breaking (made of RowFLag enums)
+ virtual int rowFlags() const { return Inline; }
/// indentation before this inset (only needed for displayed hull insets with fleqn option)
virtual int indent(BufferView const &) const { return 0; }
///
};
-inline Inset::RowFlags operator|(Inset::RowFlags const d1,
- Inset::RowFlags const d2)
-{
- return static_cast<Inset::RowFlags>(int(d1) | int(d2));
-}
-
-
-inline Inset::RowFlags operator&(Inset::RowFlags const d1,
- Inset::RowFlags const d2)
-{
- return static_cast<Inset::RowFlags>(int(d1) & int(d2));
-}
-
-
} // namespace lyx
#endif
///
InsetCode lyxCode() const override { return BIBTEX_CODE; }
///
- RowFlags rowFlags() const override { return Display; }
+ int rowFlags() const override { return Display; }
///
void latex(otexstream &, OutputParams const &) const override;
///
///
void write(std::ostream & os) const override;
///
- RowFlags rowFlags() const override { return Display; }
+ int rowFlags() const override { return Display; }
///
bool neverIndent() const override { return true; }
///
///
InsetCode lyxCode() const override { return FLOAT_LIST_CODE; }
///
- RowFlags rowFlags() const override { return Display; }
+ int rowFlags() const override { return Display; }
///
void write(std::ostream &) const override;
///
}
-Inset::RowFlags InsetInclude::rowFlags() const
+int InsetInclude::rowFlags() const
{
return type(params()) == INPUT ? Inline : Display;
}
///
void draw(PainterInfo & pi, int x, int y) const override;
///
- RowFlags rowFlags() const override;
+ int rowFlags() const override;
///
InsetCode lyxCode() const override { return INCLUDE_CODE; }
///
///
bool hasSettings() const override;
///
- RowFlags rowFlags() const override { return Display; }
+ int rowFlags() const override { return Display; }
//@}
/// \name Static public methods obligated for InsetCommand derived classes
}
-Inset::RowFlags InsetListings::rowFlags() const
+int InsetListings::rowFlags() const
{
return params().isInline() || params().isFloat() ? Inline : Display | AlignLeft;
}
///
InsetCode lyxCode() const override { return LISTINGS_CODE; }
/// lstinline is inlined, normal listing is displayed
- RowFlags rowFlags() const override;
+ int rowFlags() const override;
///
docstring layoutName() const override;
///
explicit InsetNewline(InsetNewlineParams par) : Inset(0)
{ params_.kind = par.kind; }
///
- RowFlags rowFlags() const override { return BreakAfter | RowAfter; }
+ int rowFlags() const override { return AlwaysBreakAfter; }
///
static void string2params(std::string const &, InsetNewlineParams &);
///
///
void write(std::ostream & os) const override;
///
- RowFlags rowFlags() const override { return (params_.kind == InsetNewpageParams::NOPAGEBREAK) ? Inline : Display; }
+ int rowFlags() const override { return (params_.kind == InsetNewpageParams::NOPAGEBREAK) ? Inline : Display; }
///
docstring insetLabel() const;
///
///
bool hasSettings() const override { return true; }
///
- RowFlags rowFlags() const override { return Display; }
+ int rowFlags() const override { return Display; }
///
void latex(otexstream &, OutputParams const &) const override;
///
return docstring();
}
///
- RowFlags rowFlags() const override { return BreakAfter; }
+ int rowFlags() const override { return BreakAfter; }
private:
///
InsetCode lyxCode() const override { return SEPARATOR_CODE; }
}
-Inset::RowFlags InsetSpace::rowFlags() const
+int InsetSpace::rowFlags() const
{
switch (params_.kind) {
case InsetSpaceParams::PROTECTED:
///
docstring toolTip(BufferView const & bv, int x, int y) const override;
/// unprotected spaces allow line breaking after them
- RowFlags rowFlags() const override;
+ int rowFlags() const override;
///
void metrics(MetricsInfo &, Dimension &) const override;
///
}
-Inset::RowFlags InsetSpecialChar::rowFlags() const
+int InsetSpecialChar::rowFlags() const
{
switch (kind_) {
case ALLOWBREAK:
///
docstring toolTip(BufferView const & bv, int x, int y) const override;
/// some special chars allow line breaking after them
- RowFlags rowFlags() const override;
+ int rowFlags() const override;
///
void metrics(MetricsInfo &, Dimension &) const override;
///
///
docstring layoutName() const override;
///
- RowFlags rowFlags() const override { return Display; }
+ int rowFlags() const override { return Display; }
///
void validate(LaTeXFeatures &) const override;
///
}
-Inset::RowFlags InsetTabular::rowFlags() const
-{
- if (tabular.is_long_tabular) {
- switch (tabular.longtabular_alignment) {
- case Tabular::LYX_LONGTABULAR_ALIGN_LEFT:
- return Display | AlignLeft;
- case Tabular::LYX_LONGTABULAR_ALIGN_CENTER:
- return Display;
- case Tabular::LYX_LONGTABULAR_ALIGN_RIGHT:
- return Display | AlignRight;
- default:
- return Display;
- }
- } else
- return Inline;
+int InsetTabular::rowFlags() const
+{
+ if (tabular.is_long_tabular) {
+ switch (tabular.longtabular_alignment) {
+ case Tabular::LYX_LONGTABULAR_ALIGN_LEFT:
+ return Display | AlignLeft;
+ case Tabular::LYX_LONGTABULAR_ALIGN_CENTER:
+ return Display;
+ case Tabular::LYX_LONGTABULAR_ALIGN_RIGHT:
+ return Display | AlignRight;
+ default:
+ return Display;
+ }
+ } else
+ return Inline;
}
//
bool isTable() const override { return true; }
///
- RowFlags rowFlags() const override;
+ int rowFlags() const override;
///
void latex(otexstream &, OutputParams const &) const override;
///
///
void write(std::ostream & os) const override;
///
- RowFlags rowFlags() const override { return Display; }
+ int rowFlags() const override { return Display; }
///
void doDispatch(Cursor & cur, FuncRequest & cmd) override;
///
}
-Inset::RowFlags InsetMathHull::rowFlags() const
+int InsetMathHull::rowFlags() const
{
switch (type_) {
case hullUnknown:
///
Inset * editXY(Cursor & cur, int x, int y) override;
///
- RowFlags rowFlags() const override;
+ int rowFlags() const override;
/// helper function
bool display() const { return rowFlags() & Display; }