#include "lyxtext.h"
#include "lyxrow.h"
-#include "layout.h"
+#include "lyxtextclasslist.h"
#include "paragraph.h"
#include "lyx_gui_misc.h"
#include "gettext.h"
int LyXText::workWidth(BufferView * bview, Inset * inset) const
{
Paragraph * par = 0;
- pos_type pos = 0;
-
- Buffer::inset_iterator it = bview->buffer()->inset_iterator_begin();
-
- for (; it != bview->buffer()->inset_iterator_end(); ++it) {
- if (*it == inset) {
- par = it.getPar();
- pos = it.getPos();
- break;
+ pos_type pos = -1;
+
+ par = inset->parOwner();
+ if (par)
+ pos = par->getPositionOfInset(inset);
+
+ if (!par || pos == -1) {
+ lyxerr << "LyXText::workWidth: something is wrong,"
+ " fall back to the brute force method" << endl;
+ Buffer::inset_iterator it = bview->buffer()->inset_iterator_begin();
+ Buffer::inset_iterator end = bview->buffer()->inset_iterator_end();
+ for ( ; it != end; ++it) {
+ if (*it == inset) {
+ par = it.getPar();
+ pos = it.getPos();
+ break;
+ }
}
}
+
if (!par) {
return workWidth(bview);
}
int dummy_y;
Row * row = getRow(par, pos, dummy_y);
Row * frow = row;
- while(frow->previous() && frow->par() == frow->previous()->par())
+ while (frow->previous() && frow->par() == frow->previous()->par())
frow = frow->previous();
unsigned int maxw = 0;
- while(frow->next() && frow->par() == frow->next()->par()) {
+ while (frow->next() && frow->par() == frow->next()->par()) {
if ((frow != row) && (maxw < frow->width()))
maxw = frow->width();
frow = frow->next();
pos_type pos) const
{
if (!Encodings::is_arabic(c))
- if (lyxrc.font_norm_type == LyXRC::ISO_8859_6_8 && isdigit(c))
+ if (lyxrc.font_norm_type == LyXRC::ISO_8859_6_8 && IsDigit(c))
return c + (0xb0 - '0');
else
return c;
// Returns the paragraph position of the last character in the specified row
pos_type LyXText::rowLast(Row const * row) const
{
- if (!row->next() || row->next()->par() != row->par())
+ if (!row->next() || row->next()->par() != row->par()) {
return row->par()->size() - 1;
- else
+ } else {
return row->next()->pos() - 1;
+ }
}
textclasslist.Style(bview->buffer()->params.textclass,
par->getLayout());
pos_type i = pos;
-
+
if (layout.margintype == MARGIN_RIGHT_ADDRESS_BOX) {
/* special code for right address boxes, only newlines count */
while (i < par->size()) {
while (doitonetime || ((x < width) && (i < last))) {
doitonetime = false;
char const c = par->getChar(i);
+ Inset * in = 0;
+ if (c == Paragraph::META_INSET)
+ in = par->getInset(i);
if (IsNewlineChar(c)) {
last_separator = i;
x = width; // this means break
- } else if (c == Paragraph::META_INSET &&
- par->getInset(i)) {
-
+ } else if (in && !in->isChar()) {
// check wether a Display() inset is
// valid here. if not, change it to
// non-display
- if (par->getInset(i)->display() &&
+ if (in->display() &&
(layout.isCommand() ||
(layout.labeltype == LABEL_MANUAL
- && i < beginningOfMainBody(bview->buffer(), par)))) {
+ && i < beginningOfMainBody(bview->buffer(), par))))
+ {
// display istn't allowd
- par->getInset(i)->display(false);
+ in->display(false);
x += singleWidth(bview, par, i, c);
- } else if (par->getInset(i)->display() ||
- par->getInset(i)->needFullRow()) {
+ } else if (in->display() || in->needFullRow()) {
// So break the line here
if (i == pos) {
if (pos < last-1) {
x = width; // this means break
} else {
x += singleWidth(bview, par, i, c);
+ // we have to check this separately as we could have a
+ // lineseparator and then the algorithm below would prefer
+ // that which IS wrong! We should always break on an inset
+ // if it's too long and not on the last separator.
+ // Maybe the only exeption is insets used as chars but
+ // then we would have to have a special function inside
+ // the inset to tell us this. Till then we leave it as
+ // it is now. (Jug 20020106)
+ if (pos < i && x >= width && last_separator >= 0)
+ last_separator = i - 1;
}
} else {
- if (IsLineSeparatorChar(c))
+ if (IsLineSeparatorChar(c, in))
last_separator = i;
x += singleWidth(bview, par, i, c);
}
x = left_margin;
}
}
+ if ((pos+1 < i) && (last_separator < 0) && (x >= width))
+ last_separator = i - 2;
+ else if ((pos < i) && (last_separator < 0) && (x >= width))
+ last_separator = i - 1;
// end of paragraph is always a suitable separator
- if (i == last && x < width)
+ else if (i == last && x < width)
last_separator = i;
}
{
pos_type const last = rowLast(row);
pos_type first = row->pos();
+
if (first) { /* hfill *DO* count at the beginning
* of paragraphs! */
- while(first <= last && row->par()->isHfill(first))
+ while (first <= last && row->par()->isHfill(first)) {
++first;
+ }
}
first = max(first, beginningOfMainBody(buf, row->par()));
int n = 0;
for (pos_type p = first; p <= last; ++p) {
// last, because the end is ignored!
+
if (row->par()->isHfill(p)) {
++n;
}
pos_type first = row->pos();
if (first) { /* hfill *DO* count at the beginning
* of paragraphs! */
- while(first < last && row->par()->isHfill(first))
+ while (first < last && row->par()->isHfill(first))
++first;
}
maxasc += LYX_PAPER_MARGIN;
// add the vertical spaces, that the user added
- if (firstpar->params().spaceTop().kind() != VSpace::NONE)
- maxasc += int(firstpar->params().spaceTop().inPixels(bview));
-
+ maxasc += getLengthMarkerHeight(bview, firstpar->params().spaceTop());
+
// do not forget the DTP-lines!
// there height depends on the font of the nearest character
if (firstpar->params().lineTop())
maxdesc += LYX_PAPER_MARGIN;
// add the vertical spaces, that the user added
- if (firstpar->params().spaceBottom().kind() != VSpace::NONE)
- maxdesc += int(firstpar->params().spaceBottom().inPixels(bview));
+ maxdesc += getLengthMarkerHeight(bview, firstpar->params().spaceBottom());
// do not forget the DTP-lines!
// there height depends on the font of the nearest character
// and now the layout spaces, for example before and after
// a section, or between the items of a itemize or enumerate
// environment
- if (!firstpar->params().pagebreakBottom() && row_ptr->par()->next()) {
+ if (!firstpar->params().pagebreakBottom()
+ && row_ptr->par()->next()) {
Paragraph * nextpar = row_ptr->par()->next();
Paragraph * comparepar = row_ptr->par();
float usual = 0;
float x = 0;
if (layout.margintype != MARGIN_RIGHT_ADDRESS_BOX) {
float dummy;
+ // this IS needed
+ row_ptr->width(maxwidth);
prepareToPrint(bview, row_ptr, x, dummy, dummy, dummy, false);
}
row_ptr->width(int(maxwidth + x));
if (inset_owner) {
Row * r = firstrow;
width = max(0,workWidth(bview));
- while(r) {
+ while (r) {
if (r->width() > width)
width = r->width();
r = r->next();
static string const number_seperators = ".,:";
if (current_font.number() == LyXFont::ON) {
- if (!isdigit(c) && !contains(number_operators, c) &&
+ if (!IsDigit(c) && !contains(number_operators, c) &&
!(contains(number_seperators, c) &&
cursor.pos() >= 1 &&
cursor.pos() < cursor.par()->size() &&
cursor.pos() - 1).number() == LyXFont::ON)
)
number(bview); // Set current_font.number to OFF
- } else if (isdigit(c) &&
+ } else if (IsDigit(c) &&
real_current_font.isVisibleRightToLeft()) {
number(bview); // Set current_font.number to ON
return;
}
} else if (IsNewlineChar(c)) {
- if (cursor.par() == cursor.par()
- && cursor.pos() <= beginningOfMainBody(bview->buffer(), cursor.par())) {
+ if (cursor.pos() <= beginningOfMainBody(bview->buffer(),
+ cursor.par())) {
charInserted();
return;
}
// Is there a break one row above
if ((cursor.par()->isLineSeparator(cursor.pos())
|| cursor.par()->isNewline(cursor.pos())
+ || ((cursor.pos() < cursor.par()->size()) &&
+ cursor.par()->isInset(cursor.pos()+1))
|| cursor.row()->fill() == -1)
&& row->previous() && row->previous()->par() == row->par()) {
pos_type z = nextBreakPoint(bview,
fill_separator = 0;
fill_label_hfill = 0;
- bool const is_rtl =
+ bool const is_rtl =
row->par()->isRightToLeftPar(bview->buffer()->params);
if (is_rtl) {
x = (workWidth(bview) > 0)
if (nh) {
if (w > 0)
fill_hfill = w / nh;
- } else {
+ // we don't have to look at the alignment if it is ALIGN_LEFT and
+ // if the row is already larger then the permitted width as then
+ // we force the LEFT_ALIGN'edness!
+ } else if (static_cast<int>(row->width()) < workWidth(bview)) {
// is it block, flushleft or flushright?
// set x how you need it
int align;
value += float(cursor.y())/float(height);
return str;
}
-#warning Dekel please have a look on this one RTL? (Jug)
-#warning DEKEL!
- // we have to go on checking so move cusor to the right
+ // we have to go on checking so move cusor to the next char
if (cursor.pos() == cursor.par()->size()) {
if (!cursor.par()->next())
return str;
}
}
+
+int LyXText::getLengthMarkerHeight(BufferView * bv, VSpace const & vsp) const
+{
+ int const arrow_size = 4;
+ int const space_size = int(vsp.inPixels(bv));
+
+ if (vsp.kind() != VSpace::LENGTH) {
+ return space_size;
+ }
+
+ LyXFont font;
+ font.decSize();
+ int const min_size = std::max(3 * arrow_size,
+ lyxfont::maxAscent(font)
+ + lyxfont::maxDescent(font));
+
+ if (vsp.length().len().value() < 0.0)
+ return min_size;
+ else
+ return std::max(min_size, space_size);
+}
+
+
+int LyXText::drawLengthMarker(DrawRowParams & p, string const & prefix,
+ VSpace const & vsp, int start)
+{
+ int const arrow_size = 4;
+ int const size = getLengthMarkerHeight(p.bv, vsp);
+ int const end = start + size;
+
+ // the label to display (if any)
+ string str;
+ // y-values for top arrow
+ int ty1, ty2;
+ // y-values for bottom arrow
+ int by1, by2;
+ switch (vsp.kind()) {
+ case VSpace::LENGTH:
+ {
+ str = prefix + " (" + vsp.asLyXCommand() + ")";
+ // adding or removing space
+ bool const added = !(vsp.length().len().value() < 0.0);
+ ty1 = added ? (start + arrow_size) : start;
+ ty2 = added ? start : (start + arrow_size);
+ by1 = added ? (end - arrow_size) : end;
+ by2 = added ? end : (end - arrow_size);
+ break;
+ }
+ case VSpace:: VFILL:
+ str = prefix + " (vertical fill)";
+ ty1 = ty2 = start;
+ by1 = by2 = end;
+ break;
+ default:
+ // nothing to draw here
+ return size;
+ }
+
+ int const leftx = p.xo + leftMargin(p.bv, p.row);
+ int const midx = leftx + arrow_size;
+ int const rightx = midx + arrow_size;
+
+ // first the string
+ int w = 0;
+ int a = 0;
+ int d = 0;
+
+ LyXFont font;
+ font.setColor(LColor::added_space).decSize();
+ lyxfont::rectText(str, font, w, a, d);
+
+ p.pain->rectText(leftx + 2 * arrow_size + 5,
+ start + ((end - start) / 2) + d,
+ str, font,
+ backgroundColor(),
+ backgroundColor());
+
+ // top arrow
+ p.pain->line(leftx, ty1, midx, ty2, LColor::added_space);
+ p.pain->line(midx, ty2, rightx, ty1, LColor::added_space);
+
+ // bottom arrow
+ p.pain->line(leftx, by1, midx, by2, LColor::added_space);
+ p.pain->line(midx, by2, rightx, by1, LColor::added_space);
+
+ // joining line
+ p.pain->line(midx, ty2, midx, by2, LColor::added_space);
+
+ return size;
+}
+
void LyXText::paintFirstRow(DrawRowParams & p)
{
}
int y_top = 0;
-
+
// think about the margins
if (!p.row->previous() && bv_owner)
y_top += LYX_PAPER_MARGIN;
y_top += 3 * defaultHeight();
}
- // draw a vfill top
- if (parparams.spaceTop().kind() == VSpace::VFILL) {
- int const y1 = p.yo + y_top + 3 * defaultHeight();
- int const y2 = p.yo + 2 + y_top;
-
- p.pain->line(0, y1, LYX_PAPER_MARGIN, y1, LColor::added_space);
-
- p.pain->line(0, y2, LYX_PAPER_MARGIN, y2, LColor::added_space);
-
- int const x = LYX_PAPER_MARGIN / 2;
-
- p.pain->line(x, y2, x, y1, LColor::added_space);
-
- y_top += 3 * defaultHeight();
- } else if (parparams.spaceTop().kind() == VSpace::LENGTH) {
- string str = string(_("Space above")) + " ("
- + parparams.spaceTop().asLyXCommand()
- + ")";
-
- int const space = int(parparams.spaceTop().inPixels(p.bv));
- int const y = p.yo + y_top + space / 2;
-
- p.pain->line(p.xo, y, p.xo + p.width, y,
- LColor::added_space, Painter::line_onoffdash);
-
- int w = 0;
- int a = 0;
- int d = 0;
-
- LyXFont pb_font;
- pb_font.setColor(LColor::added_space).decSize();
- lyxfont::rectText(str, pb_font, w, a, d);
-
- // don't draw if it won't fit
- if (a + d + 4 < space) {
- p.pain->rectText(p.xo + (p.width - w)/2, y + d,
- str, pb_font,
- backgroundColor(),
- backgroundColor());
- }
- }
-
- y_top += int(parparams.spaceTop().inPixels(p.bv));
+ // draw the additional space if needed:
+ y_top += drawLengthMarker(p, _("Space above"),
+ parparams.spaceTop(), p.yo + y_top);
Buffer const * buffer = p.bv->buffer();
y_top += asc;
int const w = (inset_owner ? inset_owner->width(p.bv, font) : ww);
- int const xp = static_cast<int>(inset_owner ? p.x : 0);
- p.pain->line(xp, p.yo + y_top, w, p.yo + y_top,
+ int const xp = static_cast<int>(inset_owner ? p.xo : 0);
+ p.pain->line(xp, p.yo + y_top, xp + w, p.yo + y_top,
LColor::topline, Painter::line_solid,
Painter::line_thick);
lyxfont::width(str, font);
}
- p.pain->text(int(x), p.yo +
+ p.pain->text(int(x),
p.yo + p.row->baseline() -
p.row->ascent_of_text() - maxdesc,
str, font);
if (is_rtl) {
x = ww - leftMargin(p.bv, p.row)
+ lyxfont::width(layout.labelsep, font);
- } else
+ } else {
x = p.x - lyxfont::width(layout.labelsep, font)
- lyxfont::width(str, font);
+ }
p.pain->text(int(x), p.yo + p.row->baseline(), str, font);
}
{
Paragraph * par = p.row->par();
ParagraphParameters const & parparams = par->params();
- int y_bottom = p.row->height();
+ int y_bottom = p.row->height() - 1;
// think about the margins
if (!p.row->next() && bv_owner)
pb_font.setColor(LColor::pagebreak).decSize();
int const y = p.yo + y_bottom - 2 * defaultHeight();
- p.pain->line(p.xo, y, p.xo + p.width, y, LColor::pagebreak, Painter::line_onoffdash);
+ p.pain->line(p.xo, y, p.xo + p.width, y, LColor::pagebreak,
+ Painter::line_onoffdash);
int w = 0;
int a = 0;
y_bottom -= 3 * defaultHeight();
}
- // draw a vfill bottom
- if (parparams.spaceBottom().kind() == VSpace::VFILL) {
- int const x = LYX_PAPER_MARGIN / 2;
- int const x2 = LYX_PAPER_MARGIN;
- int const y = p.yo + y_bottom - 3 * defaultHeight();
- int const y2 = p.yo + y_bottom - 2;
-
- p.pain->line(0, y, x2, y, LColor::added_space);
- p.pain->line(0, y2, x2, y2, LColor::added_space);
- p.pain->line(x, y, x, y2, LColor::added_space);
-
- y_bottom -= 3 * defaultHeight();
- } else if (parparams.spaceBottom().kind() == VSpace::LENGTH) {
- string str = string(_("Space below"))
- + " ("
- + parparams.spaceBottom().asLyXCommand()
- + ")";
-
- int const space = int(parparams.spaceBottom().inPixels(p.bv));
- int const y = p.yo + y_bottom - space / 2;
-
- p.pain->line(p.xo, y, p.xo + p.width, y,
- LColor::added_space, Painter::line_onoffdash);
-
- int w = 0;
- int a = 0;
- int d = 0;
-
- LyXFont pb_font;
- pb_font.setColor(LColor::added_space).decSize();
- lyxfont::rectText(str, pb_font, w, a, d);
-
- // don't draw if it won't fit
- if (a + d + 4 < space) {
- p.pain->rectText(p.xo + (p.width - w) / 2, y + d,
- str, pb_font,
- backgroundColor(),
- backgroundColor());
- }
- }
-
- // think about user added space
- y_bottom -= int(parparams.spaceBottom().inPixels(p.bv));
+ // draw the additional space if needed:
+ int const height = getLengthMarkerHeight(p.bv,
+ parparams.spaceBottom());
+ y_bottom -= drawLengthMarker(p, _("Space below"),
+ parparams.spaceBottom(),
+ p.yo + y_bottom - height);
Buffer const * buffer = p.bv->buffer();
y_bottom -= asc;
int const w = (inset_owner ? inset_owner->width(p.bv, font) : ww);
- int const xp = static_cast<int>(inset_owner ? p.x : 0);
+ int const xp = static_cast<int>(inset_owner ? p.xo : 0);
int const y = p.yo + y_bottom;
- p.pain->line(xp, y, w, y, LColor::topline, Painter::line_solid,
+ p.pain->line(xp, y, xp + w, y, LColor::topline, Painter::line_solid,
Painter::line_thick);
y_bottom -= asc;
}
- pos_type const last = rowLastPrintable(p.row);
bool const is_rtl = p.row->par()->isRightToLeftPar(p.bv->buffer()->params);
int const endlabel = par->getEndLabel(buffer->params);
case END_LABEL_BOX:
case END_LABEL_FILLED_BOX:
{
- LyXFont const font = getFont(buffer, par, last);
+ LyXFont const font = getLabelFont(buffer, par);
int const size = int(0.75 * lyxfont::maxAscent(font));
int const y = (p.yo + p.row->baseline()) - size;
int x = is_rtl ? LYX_PAPER_MARGIN : ww - LYX_PAPER_MARGIN - size;
x += (size - p.row->fill() + 1) * (is_rtl ? -1 : 1);
if (endlabel == END_LABEL_BOX) {
- p.pain->line(x, y, x, y + size, LColor::eolmarker);
- p.pain->line(x + size, y, x + size , y + size, LColor::eolmarker);
- p.pain->line(x, y, x + size, y, LColor::eolmarker);
- p.pain->line(x, y + size, x + size, y + size, LColor::eolmarker);
+ p.pain->rectangle(x, y, size, size, LColor::eolmarker);
} else {
- p.pain->fillRectangle(x, y, size, size, LColor::eolmarker);
+ p.pain->fillRectangle(x, y, size, size,
+ LColor::eolmarker);
}
break;
}