#include "language.h"
#include "ParagraphParameters.h"
#include "undo_funcs.h"
+#include "text_funcs.h"
#include "WordLangTuple.h"
#include "paragraph_funcs.h"
#include "rowpainter.h"
#include "lyxrow_funcs.h"
+#include "metricsinfo.h"
#include "insets/insettext.h"
#include <algorithm>
+using namespace lyx::support;
+
using std::max;
using std::min;
using std::endl;
using std::pair;
+
using lyx::pos_type;
+using lyx::word_location;
+
using namespace bv_funcs;
/// top, right, bottom pixel margin
BufferView * LyXText::bv()
{
- lyx::Assert(bv_owner != 0);
+ Assert(bv_owner != 0);
return bv_owner;
}
BufferView * LyXText::bv() const
{
- lyx::Assert(bv_owner != 0);
+ Assert(bv_owner != 0);
return bv_owner;
}
int LyXText::top_y() const
{
- if (anchor_row_ == rowlist_.end() )
+ if (anchor_row_ == rowlist_.end())
return 0;
return anchor_row_->y() + anchor_row_offset_;
anchor_row_offset_ = newy - y;
lyxerr[Debug::GUI] << "changing reference to row: " << &*anchor_row_
<< " offset: " << anchor_row_offset_ << endl;
- postPaint(0);
+ postPaint();
}
int LyXText::workWidth() const
{
- if (inset_owner) {
- // FIXME: pass (const ?) ref
- return inset_owner->textWidth(bv());
- }
- return bv()->workWidth();
+ return inset_owner ? inset_owner->textWidth() : bv()->workWidth();
}
-int LyXText::workWidth(Inset const * inset) const
+int LyXText::workWidth(InsetOld const * inset) const
{
- ParagraphList::iterator par = ownerParagraphs().find(*inset->parOwner());
- //lyx::Assert(par);
+ ParagraphList::iterator par = std::find(ownerParagraphs().begin(),
+ ownerParagraphs().end(),
+ *inset->parOwner());
+ if (par == ownerParagraphs().end()) {
+ lyxerr[Debug::GUI] << "LyXText::workWidth: unexpected\n";
+ return -1;
+ }
pos_type pos = par->getPositionOfInset(inset);
- lyx::Assert(pos != -1);
+ Assert(pos != -1);
LyXLayout_ptr const & layout = par->layout();
if (pos >= pit->size())
return 0;
- LyXFont const font = getFont(bv()->buffer(), pit, pos);
+ LyXFont const & font = getFont(bv()->buffer(), pit, pos);
// The most common case is handled first (Asger)
if (IsPrintable(c)) {
if (font.language()->RightToLeft()) {
- if (font.language()->lang() == "arabic" &&
- (lyxrc.font_norm_type == LyXRC::ISO_8859_6_8 ||
- lyxrc.font_norm_type == LyXRC::ISO_10646_1)) {
+ if ((lyxrc.font_norm_type == LyXRC::ISO_8859_6_8 ||
+ lyxrc.font_norm_type == LyXRC::ISO_10646_1)
+ && font.language()->lang() == "arabic") {
if (Encodings::IsComposeChar_arabic(c))
return 0;
else
return 0;
}
return font_metrics::width(c, font);
-
}
if (c == Paragraph::META_INSET) {
- Inset * tmpinset = pit->getInset(pos);
+ InsetOld * tmpinset = pit->getInset(pos);
if (tmpinset) {
- if (tmpinset->lyxCode() == Inset::HFILL_CODE) {
+ if (tmpinset->lyxCode() == InsetOld::HFILL_CODE) {
// Because of the representation as vertical lines
return 3;
}
-#if 1
+#if 0
#warning inset->update FIXME
// this IS needed otherwise on initialitation we don't get the fill
// of the row right (ONLY on initialization if we read a file!)
// should be changed! (Jug 20011204)
- tmpinset->update(bv());
+ //tmpinset->update(bv());
+ Dimension dim;
+ MetricsInfo mi(bv(), font, workWidth());
+ tmpinset->metrics(mi, dim);
+ return dim.wid;
+#else
+ return tmpinset->width();
#endif
- return tmpinset->width(bv(), font);
}
return 0;
}
ParagraphList::iterator row_par = row->par();
- Inset * inset = row_par->inInset();
+ InsetOld * inset = row_par->inInset();
if (inset && inset->owner() &&
- inset->owner()->lyxCode() == Inset::ERT_CODE) {
+ inset->owner()->lyxCode() == InsetOld::ERT_CODE) {
bidi_start = -1;
return;
}
int LyXText::leftMargin(Row const & row) const
{
- Inset * ins;
+ InsetOld * ins;
if (row.pos() < row.par()->size())
if ((row.par()->getChar(row.pos()) == Paragraph::META_INSET) &&
&& !row.par()->params().noindent()
// in tabulars and ert paragraphs are never indented!
&& (!row.par()->inInset() || !row.par()->inInset()->owner() ||
- (row.par()->inInset()->owner()->lyxCode() != Inset::TABULAR_CODE &&
- row.par()->inInset()->owner()->lyxCode() != Inset::ERT_CODE))
+ (row.par()->inInset()->owner()->lyxCode() != InsetOld::TABULAR_CODE &&
+ row.par()->inInset()->owner()->lyxCode() != InsetOld::ERT_CODE))
&& (row.par()->layout() != tclass.defaultLayout() ||
bv()->buffer()->params.paragraph_separation ==
BufferParams::PARSEP_INDENT)) {
int LyXText::rightMargin(Buffer const & buf, Row const & row) const
{
- Inset * ins;
+ InsetOld * ins;
if (row.pos() < row.par()->size())
if ((row.par()->getChar(row.pos()) == Paragraph::META_INSET) &&
};
-pos_type
-LyXText::rowBreakPoint(Row const & row) const
+pos_type LyXText::rowBreakPoint(Row const & row) const
{
ParagraphList::iterator pit = row.par();
// or the end of the par, then choose the possible break
// nearest that.
- int const left = leftMargin(const_cast<Row&>(row));
+ int const left = leftMargin(row);
int x = left;
// pixel width since last breakpoint
bool fullrow = false;
pos_type i = pos;
+
+ // We re-use the font resolution for the entire font span when possible
+ LyXFont font = getFont(bv()->buffer(), pit, i);
+ lyx::pos_type endPosOfFontSpan = pit->getEndPosOfFontSpan(i);
+
for (; i < last; ++i) {
if (pit->isNewline(i)) {
point = i;
thiswidth = left_margin - x;
thiswidth += singleWidth(pit, i, c);
} else {
- thiswidth = singleWidth(pit, i, c);
+ // Manual inlined optimised version of common case of "thiswidth = singleWidth(pit, i, c);"
+ if (IsPrintable(c)) {
+ if (pos > endPosOfFontSpan) {
+ // We need to get the next font
+ font = getFont(bv()->buffer(), pit, i);
+ endPosOfFontSpan = pit->getEndPosOfFontSpan(i);
+ }
+ if (! font.language()->RightToLeft()) {
+ thiswidth = font_metrics::width(c, font);
+ } else {
+ // Fall-back to normal case
+ thiswidth = singleWidth(pit, i, c);
+ // And flush font cache
+ endPosOfFontSpan = 0;
+ }
+ } else {
+ // Fall-back to normal case
+ thiswidth = singleWidth(pit, i, c);
+ // And flush font cache
+ endPosOfFontSpan = 0;
+ }
}
x += thiswidth;
chunkwidth += thiswidth;
- Inset * in = pit->isInset(i) ? pit->getInset(i) : 0;
+ InsetOld * in = pit->isInset(i) ? pit->getInset(i) : 0;
fullrow = (in && (in->display() || in->needFullRow()));
// break before a character that will fall off
pos_type const body_pos = pit->beginningOfBody();
pos_type i = row->pos();
- while (i <= last) {
- if (body_pos > 0 && i == body_pos) {
- w += font_metrics::width(layout->labelsep, getLabelFont(bv()->buffer(), pit));
- if (pit->isLineSeparator(i - 1))
- w -= singleWidth(pit, i - 1);
- int left_margin = labelEnd(*row);
- if (w < left_margin)
- w = left_margin;
+ if (! pit->empty() && i <= last) {
+ // We re-use the font resolution for the entire span when possible
+ LyXFont font = getFont(bv()->buffer(), pit, i);
+ lyx::pos_type endPosOfFontSpan = pit->getEndPosOfFontSpan(i);
+ while (i <= last) {
+ if (body_pos > 0 && i == body_pos) {
+ w += font_metrics::width(layout->labelsep, getLabelFont(bv()->buffer(), pit));
+ if (pit->isLineSeparator(i - 1))
+ w -= singleWidth(pit, i - 1);
+ int left_margin = labelEnd(*row);
+ if (w < left_margin)
+ w = left_margin;
+ }
+ { // Manual inlined an optimised version of the common case of "w += singleWidth(pit, i);"
+ char const c = pit->getChar(i);
+
+ if (IsPrintable(c)) {
+ if (i > endPosOfFontSpan) {
+ // We need to get the next font
+ font = getFont(bv()->buffer(), pit, i);
+ endPosOfFontSpan = pit->getEndPosOfFontSpan(i);
+ }
+ if (! font.language()->RightToLeft()) {
+ w += font_metrics::width(c, font);
+ } else {
+ // Fall-back to the normal case
+ w += singleWidth(pit, i, c);
+ // And flush font cache
+ endPosOfFontSpan = 0;
+ }
+ } else {
+ // Fall-back to the normal case
+ w += singleWidth(pit, i, c);
+ // And flush font cache
+ endPosOfFontSpan = 0;
+ }
+ }
+ ++i;
}
- w += singleWidth(pit, i);
- ++i;
}
if (body_pos > 0 && body_pos > last) {
w += font_metrics::width(layout->labelsep, getLabelFont(bv()->buffer(), pit));
pos_type last = pit->beginningOfBody();
- lyx::Assert(last > 0);
+ Assert(last > 0);
// -1 because a label ends either with a space that is in the label,
// or with the beginning of a footnote that is outside the label.
void LyXText::setHeightOfRow(RowList::iterator rit)
{
- lyx::Assert(rit != rows().end());
+ Assert(rit != rows().end());
// get the maximum ascent and the maximum descent
float layoutasc = 0;
float layoutdesc = 0;
float tmptop = 0;
- LyXFont tmpfont;
- Inset * tmpinset = 0;
- // ok , let us initialize the maxasc and maxdesc value.
+ // ok, let us initialize the maxasc and maxdesc value.
// This depends in LaTeX of the font of the last character
// in the paragraph. The hack below is necessary because
// of the possibility of open footnotes
int maxwidth = 0;
if (!pit->empty()) {
+ // We re-use the font resolution for the entire font span when possible
+ LyXFont font = getFont(bv()->buffer(), pit, rit->pos());
+ lyx::pos_type endPosOfFontSpan = pit->getEndPosOfFontSpan(rit->pos());
+
+ // Optimisation
+ Paragraph const & par = *pit;
+
// Check if any insets are larger
for (pos_type pos = rit->pos(); pos <= pos_end; ++pos) {
- if (pit->isInset(pos)) {
- tmpfont = getFont(bv()->buffer(), pit, pos);
- tmpinset = pit->getInset(pos);
- if (tmpinset) {
+ // Manual inlined optimised version of common case of "maxwidth += singleWidth(pit, pos);"
+ char const c = par.getChar(pos);
+
+ if (IsPrintable(c)) {
+ if (pos > endPosOfFontSpan) {
+ // We need to get the next font
+ font = getFont(bv()->buffer(), pit, pos);
+ endPosOfFontSpan = par.getEndPosOfFontSpan(pos);
+ }
+ if (! font.language()->RightToLeft()) {
+ maxwidth += font_metrics::width(c, font);
+ } else {
+ // Fall-back to normal case
+ maxwidth += singleWidth(pit, pos, c);
+ // And flush font cache
+ endPosOfFontSpan = 0;
+ }
+ } else {
+ // Special handling of insets - are any larger?
+ if (par.isInset(pos)) {
+ LyXFont const tmpfont = getFont(bv()->buffer(), pit, pos);
+ InsetOld const * tmpinset = par.getInset(pos);
+ if (tmpinset) {
#if 1 // this is needed for deep update on initialitation
#warning inset->update FIXME
- tmpinset->update(bv());
+ //tmpinset->update(bv());
+ Dimension dim;
+ MetricsInfo mi(bv(), tmpfont, workWidth());
+ tmpinset->metrics(mi, dim);
+ maxwidth += dim.wid;
+ maxasc = max(maxasc, dim.asc);
+ maxdesc = max(maxdesc, dim.des);
+#else
+ maxwidth += tmpinset->width();
+ maxasc = max(maxasc, tmpinset->ascent());
+ maxdesc = max(maxdesc, tmpinset->descent());
#endif
- maxwidth += tmpinset->width(bv(), tmpfont);
- maxasc = max(maxasc,
- tmpinset->ascent(bv(), tmpfont));
- maxdesc = max(maxdesc,
- tmpinset->descent(bv(), tmpfont));
+ }
+ } else {
+ // Fall-back to normal case
+ maxwidth += singleWidth(pit, pos, c);
+ // And flush font cache
+ endPosOfFontSpan = 0;
}
- } else {
- maxwidth += singleWidth(pit, pos);
}
}
}
// is it a bottom line?
RowList::iterator next_rit = boost::next(rit);
- if (next_rit == rows().end() ||
- next_rit->par() != pit) {
+ if (next_rit == rows().end() || next_rit->par() != pit) {
// the bottom margin
ParagraphList::iterator nextpit = boost::next(pit);
if (nextpit == ownerParagraphs().end() &&
rit->top_of_text(rit->baseline() - font_metrics::maxAscent(font));
- float x = 0;
+ int x = 0;
if (layout->margintype != MARGIN_RIGHT_ADDRESS_BOX) {
- float dummy;
+ int dummy;
// this IS needed
rit->width(maxwidth);
prepareToPrint(rit, x, dummy, dummy, dummy, false);
// start at the implicit given position
void LyXText::appendParagraph(RowList::iterator rowit)
{
- lyx::Assert(rowit != rowlist_.end());
+ Assert(rowit != rowlist_.end());
pos_type const last = rowit->par()->size();
bool done = false;
void LyXText::breakAgain(RowList::iterator rit)
{
- lyx::Assert(rit != rows().end());
+ Assert(rit != rows().end());
bool not_ready = true;
// this is just a little changed version of break again
void LyXText::breakAgainOneRow(RowList::iterator rit)
{
- lyx::Assert(rit != rows().end());
+ Assert(rit != rows().end());
pos_type z = rowBreakPoint(*rit);
RowList::iterator tmprit = rit;
LyXLayout_ptr const & layout = cursor.par()->layout();
// this is only allowed, if the current paragraph is not empty or caption
- // and if it has not the keepempty flag aktive
- if (cursor.par()->empty()
- && layout->labeltype != LABEL_SENSITIVE
- && !layout->keepempty)
+ // and if it has not the keepempty flag active
+ if (cursor.par()->empty() && !cursor.par()->allowEmpty()
+ && layout->labeltype != LABEL_SENSITIVE)
return;
- setUndo(bv(), Undo::FINISH, cursor.par());
+ recordUndo(bv(), Undo::ATOMIC, cursor.par());
// Always break behind a space
//
// breakParagraph call should return a bool if it inserts the
// paragraph before or behind and we should react on that one
// but we can fix this in 1.3.0 (Jug 20020509)
- bool const isempty = (layout->keepempty && cursor.par()->empty());
- ::breakParagraph(bv()->buffer()->params, paragraphs, cursor.par(), cursor.pos(),
- keep_layout);
+ bool const isempty = (cursor.par()->allowEmpty() && cursor.par()->empty());
+ ::breakParagraph(bv()->buffer()->params, paragraphs, cursor.par(),
+ cursor.pos(), keep_layout);
// well this is the caption hack since one caption is really enough
if (layout->labeltype == LABEL_SENSITIVE) {
// move one row up!
// This touches only the screen-update. Otherwise we would may have
// an empty row on the screen
- if (cursor.pos() && cursor.row()->pos() == cursor.pos()
- && !cursor.row()->par()->isNewline(cursor.pos() - 1))
+ if (cursor.pos() && cursorRow()->pos() == cursor.pos()
+ && !cursorRow()->par()->isNewline(cursor.pos() - 1))
{
cursorLeft(bv());
}
- int y = cursor.y() - cursor.row()->baseline();
+ postPaint();
- // Do not forget the special right address boxes
- if (layout->margintype == MARGIN_RIGHT_ADDRESS_BOX) {
- RowList::iterator r = cursor.row();
- RowList::iterator beg = rows().begin();
-
- while (r != beg && boost::prior(r)->par() == r->par()) {
- --r;
- y -= r->height();
- }
- }
-
- postPaint(y);
-
- removeParagraph(cursor.row());
+ removeParagraph(cursorRow());
// set the dimensions of the cursor row
- cursor.row()->fill(fill(cursor.row(), workWidth()));
+ cursorRow()->fill(fill(cursorRow(), workWidth()));
- setHeightOfRow(cursor.row());
+ setHeightOfRow(cursorRow());
#warning Trouble Point! (Lgb)
// When ::breakParagraph is called from within an inset we must
while (!next_par->empty() && next_par->isNewline(0))
next_par->erase(0);
- insertParagraph(next_par, boost::next(cursor.row()));
+ insertParagraph(next_par, boost::next(cursorRow()));
updateCounters();
// This check is necessary. Otherwise the new empty paragraph will
else
setCursor(cursor.par(), 0);
- if (boost::next(cursor.row()) != rows().end())
- breakAgain(boost::next(cursor.row()));
+ if (boost::next(cursorRow()) != rows().end())
+ breakAgain(boost::next(cursorRow()));
need_break_row = rows().end();
}
// same Paragraph one to the right and make a rebreak
void LyXText::insertChar(char c)
{
- setUndo(bv(), Undo::INSERT, cursor.par());
+ recordUndo(bv(), Undo::INSERT, cursor.par());
// When the free-spacing option is set for the current layout,
// disable the double-space checking
- bool const freeSpacing = cursor.row()->par()->layout()->free_spacing ||
- cursor.row()->par()->isFreeSpacing();
+ bool const freeSpacing = cursorRow()->par()->layout()->free_spacing ||
+ cursorRow()->par()->isFreeSpacing();
if (lyxrc.auto_number) {
static string const number_operators = "+-/*";
}
// the display inset stuff
- if (cursor.row()->pos() < cursor.row()->par()->size()
- && cursor.row()->par()->isInset(cursor.row()->pos())) {
- Inset * inset = cursor.row()->par()->getInset(cursor.row()->pos());
+ if (cursorRow()->pos() < cursorRow()->par()->size()
+ && cursorRow()->par()->isInset(cursorRow()->pos())) {
+ InsetOld * inset = cursorRow()->par()->getInset(cursorRow()->pos());
if (inset && (inset->display() || inset->needFullRow())) {
// force a new break
- cursor.row()->fill(-1); // to force a new break
+ cursorRow()->fill(-1); // to force a new break
}
}
// get the cursor row fist
- RowList::iterator row = cursor.row();
- int y = cursor.y() - row->baseline();
+ RowList::iterator row = cursorRow();
if (c != Paragraph::META_INSET) {
- // Here case LyXText::InsertInset already insertet the character
+ // Here case LyXText::InsertInset already inserted the character
cursor.par()->insertChar(cursor.pos(), c);
}
setCharFont(bv()->buffer(), cursor.par(), cursor.pos(), rawtmpfont);
|| cursor.par()->isNewline(cursor.pos())
|| ((cursor.pos() + 1 < cursor.par()->size()) &&
cursor.par()->isInset(cursor.pos() + 1))
- || cursor.row()->fill() == -1))
+ || cursorRow()->fill() == -1))
{
pos_type z = rowBreakPoint(*boost::prior(row));
setHeightOfRow(boost::prior(row));
- y -= boost::prior(row)->height();
-
- postPaint(y);
+ postPaint();
breakAgainOneRow(row);
false, cursor.boundary());
// cursor MUST be in row now.
- if (boost::next(row) != rows().end() &&
- boost::next(row)->par() == row->par())
- need_break_row = boost::next(row);
+ RowList::iterator next_row = boost::next(row);
+ if (next_row != rows().end() &&
+ next_row->par() == row->par())
+ need_break_row = next_row;
else
need_break_row = rows().end();
}
if (c == Paragraph::META_INSET || row->fill() < 0) {
- postPaint(y);
+ postPaint();
breakAgainOneRow(row);
+
+ RowList::iterator next_row = boost::next(row);
+
// will the cursor be in another row now?
if (lastPos(*this, row) <= cursor.pos() + 1 &&
- boost::next(row) != rows().end()) {
- if (boost::next(row) != rows().end() &&
- boost::next(row)->par() == row->par())
+ next_row != rows().end()) {
+ if (next_row != rows().end() &&
+ next_row->par() == row->par()) {
// this should always be true
++row;
+ }
+
breakAgainOneRow(row);
}
current_font = rawtmpfont;
!= cursor.boundary())
setCursor(cursor.par(), cursor.pos(), false,
!cursor.boundary());
- if (boost::next(row) != rows().end() &&
- boost::next(row)->par() == row->par())
- need_break_row = boost::next(row);
+
+ next_row = boost::next(row);
+
+ if (next_row != rows().end() &&
+ next_row->par() == row->par())
+ need_break_row = next_row;
else
need_break_row = rows().end();
} else {
// FIXME: similar code is duplicated all over - make resetHeightOfRow
- int const tmpheight = row->height();
-
setHeightOfRow(row);
-
- if (tmpheight == row->height()) {
- postRowPaint(row, y);
- } else {
- postPaint(y);
- }
+ postPaint();
current_font = rawtmpfont;
real_current_font = realtmpfont;
if (cursor.pos() && cursor.pos() == cursor.par()->size()
&& rawparfont != rawtmpfont) {
redoHeightOfParagraph();
- } else {
- // now the special right address boxes
- if (cursor.par()->layout()->margintype
- == MARGIN_RIGHT_ADDRESS_BOX) {
- redoDrawingOfParagraph(cursor);
- }
}
charInserted();
}
-void LyXText::prepareToPrint(RowList::iterator rit, float & x,
- float & fill_separator,
- float & fill_hfill,
- float & fill_label_hfill,
+void LyXText::prepareToPrint(RowList::iterator rit, int & x,
+ int & fill_separator,
+ int & fill_hfill,
+ int & fill_label_hfill,
bool bidi) const
{
- float w = rit->fill();
+ int w = rit->fill();
fill_hfill = 0;
fill_label_hfill = 0;
fill_separator = 0;
bool const is_rtl =
pit->isRightToLeftPar(bv()->buffer()->params);
- if (is_rtl) {
- x = (workWidth() > 0)
- ? rightMargin(*bv()->buffer(), *rit) : 0;
- } else
- x = (workWidth() > 0)
- ? leftMargin(*rit) : 0;
+ if (is_rtl)
+ x = workWidth() > 0 ? rightMargin(*bv()->buffer(), *rit) : 0;
+ else
+ x = workWidth() > 0 ? leftMargin(*rit) : 0;
// is there a manual margin with a manual label
LyXLayout_ptr const & layout = pit->layout();
if (layout->margintype == MARGIN_MANUAL
&& layout->labeltype == LABEL_MANUAL) {
/// We might have real hfills in the label part
- float nlh = numberOfLabelHfills(*this, rit);
+ int nlh = numberOfLabelHfills(*this, rit);
// A manual label par (e.g. List) has an auto-hfill
// between the label text and the body of the
++nlh;
if (nlh && !pit->getLabelWidthString().empty()) {
- fill_label_hfill = labelFill(*rit) / nlh;
+ fill_label_hfill = int(labelFill(*rit) / nlh);
}
}
// are there any hfills in the row?
- float const nh = numberOfHfills(*this, rit);
+ int const nh = numberOfHfills(*this, rit);
if (nh) {
if (w > 0)
// 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>(rit->width()) < workWidth()) {
+ } else if (int(rit->width()) < workWidth()) {
// is it block, flushleft or flushright?
// set x how you need it
int align;
}
// center displayed insets
- Inset * inset = 0;
+ InsetOld * inset = 0;
if (rit->pos() < pit->size()
&& pit->isInset(rit->pos())
&& (inset = pit->getInset(rit->pos()))
&& (inset->display())) // || (inset->scroll() < 0)))
- align = (inset->lyxCode() == Inset::MATHMACRO_CODE)
+ align = (inset->lyxCode() == InsetOld::MATHMACRO_CODE)
? LYX_ALIGN_BLOCK : LYX_ALIGN_CENTER;
// ERT insets should always be LEFT ALIGNED on screen
inset = pit->inInset();
if (inset && inset->owner() &&
- inset->owner()->lyxCode() == Inset::ERT_CODE)
+ inset->owner()->lyxCode() == InsetOld::ERT_CODE)
{
align = LYX_ALIGN_LEFT;
}
switch (align) {
case LYX_ALIGN_BLOCK:
{
- float const ns = numberOfSeparators(*this, rit);
+ int const ns = numberOfSeparators(*this, rit);
RowList::iterator next_row = boost::next(rit);
ParagraphList::iterator next_pit = next_row->par();
void LyXText::cursorRightOneWord()
{
- // treat floats, HFills and Insets as words
- ParagraphList::iterator pit = cursor.par();
- pos_type pos = cursor.pos();
-
- // CHECK See comment on top of text.C
-
- if (pos == pit->size()
- && boost::next(pit) != ownerParagraphs().end()) {
- ++pit;
- pos = 0;
- } else {
- // Skip through initial nonword stuff.
- while (pos < pit->size() && !pit->isWord(pos)) {
- ++pos;
- }
- // Advance through word.
- while (pos < pit->size() && pit->isWord(pos)) {
- ++pos;
- }
- }
- setCursor(pit, pos);
+ ::cursorRightOneWord(cursor, ownerParagraphs());
+ setCursor(cursor.par(), cursor.pos());
}
void LyXText::cursorLeftOneWord()
{
LyXCursor tmpcursor = cursor;
- cursorLeftOneWord(tmpcursor);
+ ::cursorLeftOneWord(tmpcursor, ownerParagraphs());
setCursor(tmpcursor.par(), tmpcursor.pos());
}
-void LyXText::cursorLeftOneWord(LyXCursor & cur)
-{
- // treat HFills, floats and Insets as words
-
- ParagraphList::iterator pit = cursor.par();
- pos_type pos = cursor.pos();
-
- while (pos &&
- (pit->isSeparator(pos - 1) ||
- pit->isKomma(pos - 1) ||
- pit->isNewline(pos - 1)) &&
- !(pit->isHfill(pos - 1) ||
- pit->isInset(pos - 1)))
- --pos;
-
- if (pos &&
- (pit->isInset(pos - 1) ||
- pit->isHfill(pos - 1))) {
- --pos;
- } else if (!pos) {
- if (pit != ownerParagraphs().begin()) {
- --pit;
- pos = pit->size();
- }
- } else { // Here, cur != 0
- while (pos > 0 &&
- pit->isWord(pos - 1))
- --pos;
- }
-
- cur.par(pit);
- cur.pos(pos);
-}
-
-
-// Select current word. This depends on behaviour of
-// CursorLeftOneWord(), so it is patched as well.
-void LyXText::getWord(LyXCursor & from, LyXCursor & to,
- word_location const loc)
-{
- // first put the cursor where we wana start to select the word
- from = cursor;
- switch (loc) {
- case WHOLE_WORD_STRICT:
- if (cursor.pos() == 0 || cursor.pos() == cursor.par()->size()
- || cursor.par()->isSeparator(cursor.pos())
- || cursor.par()->isKomma(cursor.pos())
- || cursor.par()->isNewline(cursor.pos())
- || cursor.par()->isSeparator(cursor.pos() - 1)
- || cursor.par()->isKomma(cursor.pos() - 1)
- || cursor.par()->isNewline(cursor.pos() - 1)) {
- to = from;
- return;
- }
- // no break here, we go to the next
-
- case WHOLE_WORD:
- // Move cursor to the beginning, when not already there.
- if (from.pos() && !from.par()->isSeparator(from.pos() - 1)
- && !(from.par()->isKomma(from.pos() - 1)
- || from.par()->isNewline(from.pos() - 1)))
- cursorLeftOneWord(from);
- break;
- case PREVIOUS_WORD:
- // always move the cursor to the beginning of previous word
- cursorLeftOneWord(from);
- break;
- case NEXT_WORD:
- lyxerr << "LyXText::getWord: NEXT_WORD not implemented yet\n";
- break;
- case PARTIAL_WORD:
- break;
- }
- to = from;
- while (to.pos() < to.par()->size()
- && !to.par()->isSeparator(to.pos())
- && !to.par()->isKomma(to.pos())
- && !to.par()->isNewline(to.pos())
- && !to.par()->isHfill(to.pos())
- && !to.par()->isInset(to.pos()))
- {
- to.pos(to.pos() + 1);
- }
-}
-
-
void LyXText::selectWord(word_location loc)
{
- LyXCursor from;
+ LyXCursor from = cursor;
LyXCursor to;
- getWord(from, to, loc);
+ ::getWord(from, to, loc, ownerParagraphs());
if (cursor != from)
setCursor(from.par(), from.pos());
if (to == from)
if (selection.start.par() == selection.end.par()) {
LyXCursor & startc = selection.start;
LyXCursor & endc = selection.end;
- setUndo(bv(), Undo::INSERT, startc.par());
+ recordUndo(bv(), Undo::INSERT, startc.par());
startc.par()->acceptChange(startc.pos(), endc.pos());
finishUndo();
clearSelection();
if (selection.start.par() == selection.end.par()) {
LyXCursor & startc = selection.start;
LyXCursor & endc = selection.end;
- setUndo(bv(), Undo::INSERT, startc.par());
+ recordUndo(bv(), Undo::INSERT, startc.par());
startc.par()->rejectChange(startc.pos(), endc.pos());
finishUndo();
clearSelection();
cursorRight(bv());
else {
LyXCursor tmpcursor = cursor;
- tmpcursor.row(0); // ??
selection.set(true); // to avoid deletion
cursorRightOneWord();
setCursor(tmpcursor, tmpcursor.par(), tmpcursor.pos());
cursorLeft(bv());
else {
LyXCursor tmpcursor = cursor;
- tmpcursor.row(0); // ??
selection.set(true); // to avoid deletion
cursorLeftOneWord();
setCursor(tmpcursor, tmpcursor.par(), tmpcursor.pos());
LyXCursor tmpcursor = cursor;
// We can't store the row over a regular setCursor
// so we set it to 0 and reset it afterwards.
- tmpcursor.row(0); // ??
selection.set(true); // to avoid deletion
cursorEnd();
setCursor(tmpcursor, tmpcursor.par(), tmpcursor.pos());
from = selection.start;
to = selection.end;
} else {
- getWord(from, to, PARTIAL_WORD);
+ from = cursor;
+ ::getWord(from, to, lyx::PARTIAL_WORD, ownerParagraphs());
setCursor(to.par(), to.pos() + 1);
}
- lyx::Assert(from <= to);
-
- setUndo(bv(), Undo::FINISH, from.par(), to.par());
+ recordUndo(bv(), Undo::ATOMIC, from.par(), to.par());
pos_type pos = from.pos();
ParagraphList::iterator pit = from.par();
++pos;
}
- if (to.row() != from.row())
- postPaint(from.y() - from.row()->baseline());
+ if (getRow(to) != getRow(from))
+ postPaint();
}
LyXCursor tmpcursor = cursor;
// to make sure undo gets the right cursor position
cursor = old_cursor;
- setUndo(bv(), Undo::DELETE, cursor.par());
+ recordUndo(bv(), Undo::DELETE, cursor.par());
cursor = tmpcursor;
backspace();
}
cursorLeft(bv());
// the layout things can change the height of a row !
- int const tmpheight = cursor.row()->height();
- setHeightOfRow(cursor.row());
- if (cursor.row()->height() != tmpheight) {
- postPaint(cursor.y() - cursor.row()->baseline());
- }
+ int const tmpheight = cursorRow()->height();
+ setHeightOfRow(cursorRow());
+ if (cursorRow()->height() != tmpheight)
+ postPaint();
return;
}
}
if (cursor.par() != ownerParagraphs().begin()) {
- setUndo(bv(), Undo::DELETE,
+ recordUndo(bv(), Undo::DELETE,
boost::prior(cursor.par()),
cursor.par());
}
ParagraphList::iterator tmppit = cursor.par();
- RowList::iterator tmprow = cursor.row();
+ RowList::iterator tmprow = cursorRow();
// We used to do cursorLeftIntern() here, but it is
// not a good idea since it triggers the auto-delete
if (cursor.pos())
cursor.pos(cursor.pos() - 1);
- postPaint(cursor.y() - cursor.row()->baseline());
+ postPaint();
// remove the lost paragraph
// This one is not safe, since the paragraph that the tmprow and the
//RemoveRow(tmprow);
// This rebuilds the rows.
- appendParagraph(cursor.row());
+ appendParagraph(cursorRow());
updateCounters();
// the row may have changed, block, hfills etc.
} else {
// this is the code for a normal backspace, not pasting
// any paragraphs
- setUndo(bv(), Undo::DELETE, cursor.par());
+ recordUndo(bv(), Undo::DELETE, cursor.par());
// We used to do cursorLeftIntern() here, but it is
// not a good idea since it triggers the auto-delete
// mechanism. So we do a cursorLeftIntern()-lite,
}
}
- RowList::iterator row = cursor.row();
+ RowList::iterator row = cursorRow();
int y = cursor.y() - row->baseline();
pos_type z;
// remember that a space at the end of a row doesnt count
y -= tmprow->height();
tmprow->fill(fill(tmprow, workWidth()));
setHeightOfRow(tmprow);
-
- postPaint(y);
+ postPaint();
setCursor(cursor.par(), cursor.pos(),
false, cursor.boundary());
if (lastPos(*this, row) == row->par()->size() - 1)
removeRow(boost::next(row));
- postPaint(y);
+ postPaint();
breakAgainOneRow(row);
// will the cursor be in another row now?
} else {
// set the dimensions of the row
row->fill(fill(row, workWidth()));
- int const tmpheight = row->height();
setHeightOfRow(row);
- if (tmpheight == row->height()) {
- postRowPaint(row, y);
- } else {
- postPaint(y);
- }
+ postPaint();
setCursor(cursor.par(), cursor.pos(), false, cursor.boundary());
}
}
if (rawparfont !=
cursor.par()->getFontSettings(bv()->buffer()->params, lastpos - 1)) {
redoHeightOfParagraph();
- } else {
- // now the special right address boxes
- if (cursor.par()->layout()->margintype
- == MARGIN_RIGHT_ADDRESS_BOX) {
- redoDrawingOfParagraph(cursor);
- }
}
}
+RowList::iterator LyXText::cursorRow() const
+{
+ return getRow(cursor.par(), cursor.pos());
+}
+
+
+RowList::iterator LyXText::getRow(LyXCursor const & cur) const
+{
+ return getRow(cur.par(), cur.pos());
+}
+
+
+RowList::iterator
+LyXText::getRow(ParagraphList::iterator pit, pos_type pos) const
+{
+ if (rows().empty())
+ return rowlist_.end();
+
+ // find the first row of the specified paragraph
+ RowList::iterator rit = rowlist_.begin();
+ RowList::iterator end = rowlist_.end();
+ while (boost::next(rit) != end && rit->par() != pit) {
+ ++rit;
+ }
+
+ // now find the wanted row
+ while (rit->pos() < pos
+ && boost::next(rit) != end
+ && boost::next(rit)->par() == pit
+ && boost::next(rit)->pos() <= pos) {
+ ++rit;
+ }
+
+ return rit;
+}
+
+
// returns pointer to a specified row
RowList::iterator
LyXText::getRow(ParagraphList::iterator pit, pos_type pos, int & y) const
}
-RowList::iterator LyXText::getRowNearY(int & y) const
+// returns pointer to some fancy row 'below' specified row
+RowList::iterator LyXText::cursorIRow() const
{
+ int y = 0;
+ return getRow(cursor.par(), cursor.pos(), y);
+}
+
+RowList::iterator LyXText::getRowNearY(int & y) const
+{
RowList::iterator rit = anchor_row_;
RowList::iterator const beg = rows().begin();
RowList::iterator const end = rows().end();