#include "buffer.h"
#include "buffer_funcs.h"
+#include "bufferlist.h"
#include "bufferparams.h"
#include "BufferView.h"
#include "Bullet.h"
#include "gettext.h"
#include "language.h"
#include "LColor.h"
+#include "lyxfunc.h"
#include "lyxrc.h"
#include "lyxrow.h"
-#include "lyxrow_funcs.h"
#include "paragraph.h"
#include "paragraph_funcs.h"
#include "ParagraphParameters.h"
#include "pariterator.h"
+#include "lyxserver.h"
+#include "lyxsocket.h"
#include "undo.h"
#include "vspace.h"
-#include "frontends/font_metrics.h"
-#include "frontends/LyXView.h"
+#include "frontends/FontMetrics.h"
#include "insets/insetenv.h"
+#include "mathed/InsetMathHull.h"
+
#include "support/textutils.h"
#include <boost/current_function.hpp>
#include <sstream>
-using lyx::pit_type;
-using lyx::pos_type;
+
+namespace lyx {
using std::endl;
using std::ostringstream;
using std::string;
+using std::max;
using std::min;
LyXText::LyXText(BufferView * bv)
: maxwidth_(bv ? bv->workWidth() : 100),
+ current_font(LyXFont::ALL_INHERIT),
background_color_(LColor::background),
- bv_owner(bv),
autoBreakRows_(false)
{}
void LyXText::init(BufferView * bv)
{
BOOST_ASSERT(bv);
- bv_owner = bv;
maxwidth_ = bv->workWidth();
dim_.wid = maxwidth_;
dim_.asc = 10;
for (pit_type pit = 0; pit != end; ++pit)
pars_[pit].rows().clear();
- current_font = getFont(pars_[0], 0);
- updateCounters(*bv->buffer());
+ updateLabels(*bv->buffer());
}
-bool LyXText::isMainText() const
+bool LyXText::isMainText(Buffer const & buffer) const
{
- return &bv()->buffer()->text() == this;
+ return &buffer.text() == this;
}
//takes screen x,y coordinates
-InsetBase * LyXText::checkInsetHit(int x, int y) const
+InsetBase * LyXText::checkInsetHit(BufferView & bv, int x, int y)
{
- pit_type pit = getPitNearY(y);
+ pit_type pit = getPitNearY(bv, y);
BOOST_ASSERT(pit != -1);
Paragraph const & par = pars_[pit];
<< BOOST_CURRENT_FUNCTION
<< ": examining inset " << inset << endl;
- if (theCoords.getInsets().has(inset))
+ if (bv.coordCache().getInsets().has(inset))
lyxerr[Debug::DEBUG]
<< BOOST_CURRENT_FUNCTION
- << ": xo: " << inset->xo() << "..."
- << inset->xo() + inset->width()
- << " yo: " << inset->yo() - inset->ascent()
+ << ": xo: " << inset->xo(bv) << "..."
+ << inset->xo(bv) + inset->width()
+ << " yo: " << inset->yo(bv) - inset->ascent()
<< "..."
- << inset->yo() + inset->descent()
+ << inset->yo(bv) + inset->descent()
<< endl;
else
lyxerr[Debug::DEBUG]
<< BOOST_CURRENT_FUNCTION
<< ": inset has no cached position" << endl;
#endif
- if (inset->covers(x, y)) {
+ if (inset->covers(bv, x, y)) {
lyxerr[Debug::DEBUG]
<< BOOST_CURRENT_FUNCTION
<< ": Hit inset: " << inset << endl;
// The difference is that this one is used for displaying, and thus we
// are allowed to make cosmetic improvements. For instance make footnotes
// smaller. (Asger)
-LyXFont LyXText::getFont(Paragraph const & par, pos_type const pos) const
+LyXFont LyXText::getFont(Buffer const & buffer, Paragraph const & par,
+ pos_type const pos) const
{
BOOST_ASSERT(pos >= 0);
#ifdef WITH_WARNINGS
#warning broken?
#endif
- BufferParams const & params = bv()->buffer()->params();
+ BufferParams const & params = buffer.params();
pos_type const body_pos = par.beginOfBody();
// We specialize the 95% common case:
if (!par.getDepth()) {
LyXFont f = par.getFontSettings(params, pos);
- if (!isMainText())
- applyOuterFont(f);
- if (layout->labeltype == LABEL_MANUAL && pos < body_pos)
- return f.realize(layout->reslabelfont);
- else
- return f.realize(layout->resfont);
+ if (!isMainText(buffer))
+ applyOuterFont(buffer, f);
+ LyXFont lf;
+ LyXFont rlf;
+ if (layout->labeltype == LABEL_MANUAL && pos < body_pos) {
+ lf = layout->labelfont;
+ rlf = layout->reslabelfont;
+ } else {
+ lf = layout->font;
+ rlf = layout->resfont;
+ }
+ // In case the default family has been customized
+ if (lf.family() == LyXFont::INHERIT_FAMILY)
+ rlf.setFamily(params.getFont().family());
+ return f.realize(rlf);
}
// The uncommon case need not be optimized as much
LyXFont font = par.getFontSettings(params, pos);
font.realize(layoutfont);
- if (!isMainText())
- applyOuterFont(font);
+ if (!isMainText(buffer))
+ applyOuterFont(buffer, font);
+
+ // Find the pit value belonging to paragraph. This will not break
+ // even if pars_ would not be a vector anymore.
+ // Performance appears acceptable.
+
+ pit_type pit = pars_.size();
+ for (pit_type it = 0; it < pit; ++it)
+ if (&pars_[it] == &par) {
+ pit = it;
+ break;
+ }
+ // Realize against environment font information
+ // NOTE: the cast to pit_type should be removed when pit_type
+ // changes to a unsigned integer.
+ if (pit < pit_type(pars_.size()))
+ font.realize(outerFont(pit, pars_));
// Realize with the fonts of lesser depth.
- font.realize(defaultfont_);
+ font.realize(params.getFont());
return font;
}
// the pi/mi parameters, and stored locally in a lyxtext in font_.
// This is where the two are integrated in the final fully realized
// font.
-void LyXText::applyOuterFont(LyXFont & font) const {
+void LyXText::applyOuterFont(Buffer const & buffer, LyXFont & font) const {
LyXFont lf(font_);
- lf.reduce(defaultfont_);
+ lf.reduce(buffer.params().getFont());
lf.realize(font);
lf.setLanguage(font.language());
font = lf;
}
-LyXFont LyXText::getLayoutFont(pit_type const pit) const
+LyXFont LyXText::getLayoutFont(Buffer const & buffer, pit_type const pit) const
{
LyXLayout_ptr const & layout = pars_[pit].layout();
- if (!pars_[pit].getDepth())
- return layout->resfont;
+ if (!pars_[pit].getDepth()) {
+ LyXFont lf = layout->resfont;
+ // In case the default family has been customized
+ if (layout->font.family() == LyXFont::INHERIT_FAMILY)
+ lf.setFamily(buffer.params().getFont().family());
+ return lf;
+ }
LyXFont font = layout->font;
// Realize with the fonts of lesser depth.
//font.realize(outerFont(pit, paragraphs()));
- font.realize(defaultfont_);
+ font.realize(buffer.params().getFont());
return font;
}
-LyXFont LyXText::getLabelFont(Paragraph const & par) const
+LyXFont LyXText::getLabelFont(Buffer const & buffer, Paragraph const & par) const
{
LyXLayout_ptr const & layout = par.layout();
- if (!par.getDepth())
- return layout->reslabelfont;
+ if (!par.getDepth()) {
+ LyXFont lf = layout->reslabelfont;
+ // In case the default family has been customized
+ if (layout->labelfont.family() == LyXFont::INHERIT_FAMILY)
+ lf.setFamily(buffer.params().getFont().family());
+ return lf;
+ }
LyXFont font = layout->labelfont;
// Realize with the fonts of lesser depth.
- font.realize(defaultfont_);
+ font.realize(buffer.params().getFont());
return font;
}
-void LyXText::setCharFont(pit_type pit, pos_type pos, LyXFont const & fnt)
+void LyXText::setCharFont(Buffer const & buffer, pit_type pit,
+ pos_type pos, LyXFont const & fnt)
{
LyXFont font = fnt;
LyXLayout_ptr const & layout = pars_[pit].layout();
}
}
- layoutfont.realize(defaultfont_);
+ // Inside inset, apply the inset's font attributes if any
+ // (charstyle!)
+ if (!isMainText(buffer))
+ layoutfont.realize(font_);
+
+ layoutfont.realize(buffer.params().getFont());
// Now, reduce font against full layout font
font.reduce(layoutfont);
}
-// used in setLayout
-// Asger is not sure we want to do this...
-void LyXText::makeFontEntriesLayoutSpecific(BufferParams const & params,
- Paragraph & par)
-{
- LyXLayout_ptr const & layout = par.layout();
- pos_type const psize = par.size();
-
- LyXFont layoutfont;
- for (pos_type pos = 0; pos < psize; ++pos) {
- if (pos < par.beginOfBody())
- layoutfont = layout->labelfont;
- else
- layoutfont = layout->font;
-
- LyXFont tmpfont = par.getFontSettings(params, pos);
- tmpfont.reduce(layoutfont);
- par.setFont(pos, tmpfont);
- }
-}
-
-
// return past-the-last paragraph influenced by a layout change on pit
pit_type LyXText::undoSpan(pit_type pit)
{
}
-void LyXText::setLayout(pit_type start, pit_type end, string const & layout)
+void LyXText::setLayout(Buffer const & buffer, pit_type start, pit_type end,
+ string const & layout)
{
BOOST_ASSERT(start != end);
- BufferParams const & bufparams = bv()->buffer()->params();
+ BufferParams const & bufparams = buffer.params();
LyXLayout_ptr const & lyxlayout = bufparams.getLyXTextClass()[layout];
for (pit_type pit = start; pit != end; ++pit) {
pars_[pit].applyLayout(lyxlayout);
- makeFontEntriesLayoutSpecific(bufparams, pars_[pit]);
if (lyxlayout->margintype == MARGIN_MANUAL)
- pars_[pit].setLabelWidthString(lyxlayout->labelstring());
+ pars_[pit].setLabelWidthString(buffer.translateLabel(lyxlayout->labelstring()));
}
}
if (lyxlayout->is_environment) {
// move everything in a new environment inset
lyxerr[Debug::DEBUG] << "setting layout " << layout << endl;
- bv.owner()->dispatch(FuncRequest(LFUN_HOME));
- bv.owner()->dispatch(FuncRequest(LFUN_ENDSEL));
- bv.owner()->dispatch(FuncRequest(LFUN_CUT));
+ lyx::dispatch(FuncRequest(LFUN_LINE_BEGIN));
+ lyx::dispatch(FuncRequest(LFUN_LINE_END_SELECT));
+ lyx::dispatch(FuncRequest(LFUN_CUT));
InsetBase * inset = new InsetEnvironment(params, layout);
insertInset(cur, inset);
//inset->edit(cur, true);
- //bv.owner()->dispatch(FuncRequest(LFUN_PASTE));
+ //lyx::dispatch(FuncRequest(LFUN_PASTE));
return;
}
pit_type start = cur.selBegin().pit();
pit_type end = cur.selEnd().pit() + 1;
pit_type undopit = undoSpan(end - 1);
- recUndo(start, undopit - 1);
- setLayout(start, end, layout);
- updateCounters(cur.buffer());
+ recUndo(cur, start, undopit - 1);
+ setLayout(cur.buffer(), start, end, layout);
+ updateLabels(cur.buffer());
}
-namespace {
-
-
-bool changeDepthAllowed(LyXText::DEPTH_CHANGE type,
+static bool changeDepthAllowed(LyXText::DEPTH_CHANGE type,
Paragraph const & par, int max_depth)
{
if (par.layout()->labeltype == LABEL_BIBLIO)
}
-}
-
-
bool LyXText::changeDepthAllowed(LCursor & cur, DEPTH_CHANGE type) const
{
BOOST_ASSERT(this == cur.text());
+ // this happens when selecting several cells in tabular (bug 2630)
+ if (cur.selBegin().idx() != cur.selEnd().idx())
+ return false;
+
pit_type const beg = cur.selBegin().pit();
pit_type const end = cur.selEnd().pit() + 1;
int max_depth = (beg != 0 ? pars_[beg - 1].getMaxDepthAfter() : 0);
for (pit_type pit = beg; pit != end; ++pit) {
- if (::changeDepthAllowed(type, pars_[pit], max_depth))
+ if (lyx::changeDepthAllowed(type, pars_[pit], max_depth))
return true;
max_depth = pars_[pit].getMaxDepthAfter();
}
for (pit_type pit = beg; pit != end; ++pit) {
Paragraph & par = pars_[pit];
- if (::changeDepthAllowed(type, par, max_depth)) {
+ if (lyx::changeDepthAllowed(type, par, max_depth)) {
int const depth = par.params().depth();
if (type == INC_DEPTH)
par.params().depth(depth + 1);
}
// this handles the counter labels, and also fixes up
// depth values for follow-on (child) paragraphs
- updateCounters(cur.buffer());
+ updateLabels(cur.buffer());
}
LyXFont layoutfont;
pit_type pit = cur.pit();
if (cur.pos() < pars_[pit].beginOfBody())
- layoutfont = getLabelFont(pars_[pit]);
+ layoutfont = getLabelFont(cur.buffer(), pars_[pit]);
else
- layoutfont = getLayoutFont(pit);
+ layoutfont = getLayoutFont(cur.buffer(), pit);
// Update current font
real_current_font.update(font,
// nested insets.
for (; dit != ditend; dit.forwardPosNoDescend()) {
if (dit.pos() != dit.lastpos()) {
- LyXFont f = getFont(dit.paragraph(), dit.pos());
+ LyXFont f = getFont(cur.buffer(), dit.paragraph(), dit.pos());
f.update(font, params.language, toggleall);
- setCharFont(dit.pit(), dit.pos(), f);
+ setCharFont(cur.buffer(), dit.pit(), dit.pos(), f);
}
}
}
// the cursor set functions have a special mechanism. When they
// realize you left an empty paragraph, they will delete it.
-void LyXText::cursorHome(LCursor & cur)
+bool LyXText::cursorHome(LCursor & cur)
{
BOOST_ASSERT(this == cur.text());
Row const & row = cur.paragraph().getRow(cur.pos(),cur.boundary());
-
- setCursor(cur, cur.pit(), row.pos());
+ return setCursor(cur, cur.pit(), row.pos());
}
-void LyXText::cursorEnd(LCursor & cur)
+bool LyXText::cursorEnd(LCursor & cur)
{
BOOST_ASSERT(this == cur.text());
// if not on the last row of the par, put the cursor before
pos_type end = cur.textRow().endpos();
if (end == 0)
// empty text, end-1 is no valid position
- return;
+ return false;
bool boundary = false;
if (end != cur.lastpos()) {
if (!cur.paragraph().isLineSeparator(end-1)
else
--end;
}
- setCursor(cur, cur.pit(), end, true, boundary);
+ return setCursor(cur, cur.pit(), end, true, boundary);
}
-void LyXText::cursorTop(LCursor & cur)
+bool LyXText::cursorTop(LCursor & cur)
{
BOOST_ASSERT(this == cur.text());
- setCursor(cur, 0, 0);
+ return setCursor(cur, 0, 0);
}
-void LyXText::cursorBottom(LCursor & cur)
+bool LyXText::cursorBottom(LCursor & cur)
{
BOOST_ASSERT(this == cur.text());
- setCursor(cur, cur.lastpit(), boost::prior(paragraphs().end())->size());
+ return setCursor(cur, cur.lastpit(), boost::prior(paragraphs().end())->size());
}
if (font == LyXFont(LyXFont::ALL_IGNORE)) {
// Could only happen with user style
cur.message(_("No font change defined. "
- "Use Character under the Layout menu to define font change."));
+ "Use Character under the Layout menu to define font change."));
return;
}
bool implicitSelection =
font.language() == ignore_language
&& font.number() == LyXFont::IGNORE
- && selectWordWhenUnderCursor(cur, lyx::WHOLE_WORD_STRICT);
+ && selectWordWhenUnderCursor(cur, WHOLE_WORD_STRICT);
// Set font
setFont(cur, font, toggleall);
}
-string LyXText::getStringToIndex(LCursor const & cur)
+docstring LyXText::getStringToIndex(LCursor const & cur)
{
BOOST_ASSERT(this == cur.text());
- string idxstring;
- if (cur.selection()) {
+ docstring idxstring;
+ if (cur.selection())
idxstring = cur.selectionAsString(false);
- } else {
+ else {
// Try implicit word selection. If there is a change
// in the language the implicit word selection is
// disabled.
LCursor tmpcur = cur;
- selectWord(tmpcur, lyx::PREVIOUS_WORD);
+ selectWord(tmpcur, PREVIOUS_WORD);
if (!tmpcur.selection())
cur.message(_("Nothing to index!"));
void LyXText::setParagraph(LCursor & cur,
Spacing const & spacing, LyXAlignment align,
- string const & labelwidthstring, bool noindent)
+ docstring const & labelwidthstring, bool noindent)
{
BOOST_ASSERT(cur.text());
// make sure that the depth behind the selection are restored, too
pit_type undopit = undoSpan(cur.selEnd().pit());
- recUndo(cur.selBegin().pit(), undopit - 1);
+ recUndo(cur, cur.selBegin().pit(), undopit - 1);
for (pit_type pit = cur.selBegin().pit(), end = cur.selEnd().pit();
pit <= end; ++pit) {
{
BOOST_ASSERT(this == cur.text());
BOOST_ASSERT(inset);
- cur.paragraph().insertInset(cur.pos(), inset);
+ cur.paragraph().insertInset(cur.pos(), inset,
+ Change(cur.buffer().params().trackChanges ?
+ Change::INSERTED : Change::UNCHANGED));
}
// needed to insert the selection
-void LyXText::insertStringAsLines(LCursor & cur, string const & str)
+void LyXText::insertStringAsLines(LCursor & cur, docstring const & str)
{
cur.buffer().insertStringAsLines(pars_, cur.pit(), cur.pos(),
current_font, str, autoBreakRows_);
// turn double CR to single CR, others are converted into one
// blank. Then insertStringAsLines is called
-void LyXText::insertStringAsParagraphs(LCursor & cur, string const & str)
+void LyXText::insertStringAsParagraphs(LCursor & cur, docstring const & str)
{
- string linestr = str;
+ docstring linestr = str;
bool newline_inserted = false;
for (string::size_type i = 0, siz = linestr.size(); i < siz; ++i) {
linestr[i] = ' ';
newline_inserted = true;
}
- } else if (IsPrintable(linestr[i])) {
+ } else if (isPrintable(linestr[i])) {
newline_inserted = false;
}
}
void LyXText::setCursorIntern(LCursor & cur,
pit_type par, pos_type pos, bool setfont, bool boundary)
{
+ BOOST_ASSERT(this == cur.text());
cur.boundary(boundary);
setCursor(cur.top(), par, pos);
cur.setTargetX();
BufferParams const & bufparams = cur.buffer().params();
current_font = par.getFontSettings(bufparams, pos);
- real_current_font = getFont(par, pos);
+ real_current_font = getFont(cur.buffer(), par, pos);
if (cur.pos() == cur.lastpos()
&& bidi.isBoundary(cur.buffer(), par, cur.pos())
// x is an absolute screen coord
// returns the column near the specified x-coordinate of the row
// x is set to the real beginning of this column
-pos_type LyXText::getColumnNearX(pit_type const pit,
+pos_type LyXText::getColumnNearX(BufferView const & bv, pit_type const pit,
Row const & row, int & x, bool & boundary) const
{
- int const xo = theCoords.get(this, pit).x_;
+ Buffer const & buffer = *bv.buffer();
+ int const xo = bv.coordCache().get(this, pit).x_;
x -= xo;
- RowMetrics const r = computeRowMetrics(pit, row);
+ RowMetrics const r = computeRowMetrics(buffer, pit, row);
Paragraph const & par = pars_[pit];
pos_type vc = row.pos();
return 0;
}
+ frontend::FontMetrics const & fm
+ = theFontMetrics(getLabelFont(buffer, par));
+
while (vc < end && tmpx <= x) {
c = bidi.vis2log(vc);
last_tmpx = tmpx;
if (body_pos > 0 && c == body_pos - 1) {
- tmpx += r.label_hfill +
- font_metrics::width(layout->labelsep, getLabelFont(par));
+ // FIXME UNICODE
+ docstring const lsep = from_utf8(layout->labelsep);
+ tmpx += r.label_hfill + fm.width(lsep);
if (par.isLineSeparator(body_pos - 1))
- tmpx -= singleWidth(par, body_pos - 1);
+ tmpx -= singleWidth(buffer, par, body_pos - 1);
}
- if (hfillExpansion(par, row, c)) {
- tmpx += singleWidth(par, c);
+ if (par.hfillExpansion(row, c)) {
+ tmpx += singleWidth(buffer, par, c);
if (c >= body_pos)
tmpx += r.hfill;
else
tmpx += r.label_hfill;
} else if (par.isSeparator(c)) {
- tmpx += singleWidth(par, c);
+ tmpx += singleWidth(buffer, par, c);
if (c >= body_pos)
tmpx += r.separator;
} else {
- tmpx += singleWidth(par, c);
+ tmpx += singleWidth(buffer, par, c);
}
++vc;
}
// If lastrow is false, we don't need to compute
// the value of rtl.
- bool const rtl = lastrow ? isRTL(par) : false;
+ bool const rtl = lastrow ? isRTL(buffer, par) : false;
if (lastrow &&
((rtl && left_side && vc == row.pos() && x < tmpx - 5) ||
(!rtl && !left_side && vc == end && x > tmpx + 5)))
bool const rtl = (bidi.level(c) % 2 == 1);
if (left_side == rtl) {
++c;
- boundary = bidi.isBoundary(*bv()->buffer(), par, c);
+ boundary = bidi.isBoundary(buffer, par, c);
}
}
// Newline inset, air gap below:
if (row.pos() < end && c >= end && par.isNewline(end - 1)) {
if (bidi.level(end -1) % 2 == 0)
- tmpx -= singleWidth(par, end - 1);
+ tmpx -= singleWidth(buffer, par, end - 1);
else
- tmpx += singleWidth(par, end - 1);
+ tmpx += singleWidth(buffer, par, end - 1);
c = end - 1;
}
// y is screen coordinate
-pit_type LyXText::getPitNearY(int y) const
+pit_type LyXText::getPitNearY(BufferView & bv, int y)
{
BOOST_ASSERT(!paragraphs().empty());
- BOOST_ASSERT(theCoords.getParPos().find(this) != theCoords.getParPos().end());
- CoordCache::InnerParPosCache const & cc = theCoords.getParPos().find(this)->second;
+ BOOST_ASSERT(bv.coordCache().getParPos().find(this) != bv.coordCache().getParPos().end());
+ CoordCache::InnerParPosCache const & cc = bv.coordCache().getParPos().find(this)->second;
lyxerr[Debug::DEBUG]
<< BOOST_CURRENT_FUNCTION
<< ": y: " << y << " cache size: " << cc.size()
int yy = -1;
CoordCache::InnerParPosCache::const_iterator it = cc.begin();
CoordCache::InnerParPosCache::const_iterator et = cc.end();
+ CoordCache::InnerParPosCache::const_iterator last = et; last--;
+
+ // If we are off-screen (before the visible part)
+ if (y < 0
+ // and even before the first paragraph in the cache.
+ && y < it->second.y_ - int(pars_[it->first].ascent())) {
+ // and we are not at the first paragraph in the inset.
+ if (it->first == 0)
+ return 0;
+ // then this is the paragraph we are looking for.
+ pit = it->first - 1;
+ // rebreak it and update the CoordCache.
+ redoParagraph(bv, pit);
+ bv.coordCache().parPos()[this][pit] =
+ Point(0, it->second.y_ - pars_[it->first].descent());
+ return pit;
+ }
+
+ // If we are off-screen (after the visible part)
+ if (y > bv.workHeight()
+ // and even after the first paragraph in the cache.
+ && y >= last->second.y_ + int(pars_[last->first].descent())) {
+ pit = last->first + 1;
+ // and we are not at the last paragraph in the inset.
+ if (pit == int(pars_.size()))
+ return last->first;
+ // then this is the paragraph we are looking for.
+ // rebreak it and update the CoordCache.
+ redoParagraph(bv, pit);
+ bv.coordCache().parPos()[this][pit] =
+ Point(0, last->second.y_ + pars_[last->first].ascent());
+ return pit;
+ }
+
for (; it != et; ++it) {
lyxerr[Debug::DEBUG]
<< BOOST_CURRENT_FUNCTION
}
-Row const & LyXText::getRowNearY(int y, pit_type pit) const
+Row const & LyXText::getRowNearY(BufferView const & bv, int y, pit_type pit) const
{
Paragraph const & par = pars_[pit];
- int yy = theCoords.get(this, pit).y_ - par.ascent();
+ int yy = bv.coordCache().get(this, pit).y_ - par.ascent();
BOOST_ASSERT(!par.rows().empty());
RowList::const_iterator rit = par.rows().begin();
RowList::const_iterator const rlast = boost::prior(par.rows().end());
// sets cursor recursively descending into nested editable insets
InsetBase * LyXText::editXY(LCursor & cur, int x, int y)
{
- pit_type pit = getPitNearY(y);
+ if (lyxerr.debugging(Debug::WORKAREA)) {
+ lyxerr << "LyXText::editXY(cur, " << x << ", " << y << ")" << std::endl;
+ cur.bv().coordCache().dump();
+ }
+ pit_type pit = getPitNearY(cur.bv(), y);
BOOST_ASSERT(pit != -1);
- Row const & row = getRowNearY(y, pit);
+ // When another window is opened with the same document, rows()
+ // will be cleared so pars_[pit].rows() might be empty when switching
+ // between windwos. A better solution is that each buffer view
+ // has its own rows() for the same buffer.
+ if (pars_[pit].rows().empty())
+ redoParagraph(cur.bv(), pit);
+ Row const & row = getRowNearY(cur.bv(), y, pit);
bool bound = false;
int xx = x; // is modified by getColumnNearX
- pos_type const pos = row.pos() + getColumnNearX(pit, row, xx, bound);
+ pos_type const pos = row.pos()
+ + getColumnNearX(cur.bv(), pit, row, xx, bound);
cur.pit() = pit;
cur.pos() = pos;
cur.boundary(bound);
cur.x_target() = x;
// try to descend into nested insets
- InsetBase * inset = checkInsetHit(x, y);
+ InsetBase * inset = checkInsetHit(cur.bv(), x, y);
//lyxerr << "inset " << inset << " hit at x: " << x << " y: " << y << endl;
if (!inset) {
// Either we deconst editXY or better we move current_font
return 0;
}
+ InsetBase * insetBefore = pos? pars_[pit].getInset(pos - 1): 0;
+ //InsetBase * insetBehind = pars_[pit].getInset(pos);
+
// This should be just before or just behind the
// cursor position set above.
- BOOST_ASSERT((pos != 0 && inset == pars_[pit].getInset(pos - 1))
- || inset == pars_[pit].getInset(pos));
+ BOOST_ASSERT((pos != 0 && inset == insetBefore)
+ || inset == pars_[pit].getInset(pos));
+
// Make sure the cursor points to the position before
// this inset.
- if (inset == pars_[pit].getInset(pos - 1))
+ if (inset == insetBefore)
--cur.pos();
+
+ // Try to descend recursively inside the inset.
inset = inset->editXY(cur, x, y);
+
if (cur.top().text() == this)
setCurrentFont(cur);
return inset;
bool LyXText::cursorLeft(LCursor & cur)
{
+ // Tell BufferView to test for FitCursor in any case!
+ cur.updateFlags(Update::FitCursor);
+
if (!cur.boundary() && cur.pos() > 0 &&
cur.textRow().pos() == cur.pos() &&
!cur.paragraph().isLineSeparator(cur.pos()-1) &&
bool LyXText::cursorRight(LCursor & cur)
{
+ // Tell BufferView to test for FitCursor in any case!
+ cur.updateFlags(Update::FitCursor);
+
if (cur.pos() != cur.lastpos()) {
if (cur.boundary())
return setCursor(cur, cur.pit(), cur.pos(),
bool LyXText::cursorUp(LCursor & cur)
{
+ // Tell BufferView to test for FitCursor in any case!
+ cur.updateFlags(Update::FitCursor);
+
Paragraph const & par = cur.paragraph();
int row;
int const x = cur.targetX();
row = par.pos2row(cur.pos());
if (!cur.selection()) {
- int const y = bv_funcs::getPos(cur, cur.boundary()).y_;
+ int const y = bv_funcs::getPos(cur.bv(), cur, cur.boundary()).y_;
LCursor old = cur;
- editXY(cur, x, y - par.rows()[row].ascent() - 1);
+ // Go to middle of previous row. 16 found to work OK;
+ // 12 = top/bottom margin of display math
+ int const margin = 3 * InsetMathHull::displayMargin() / 2;
+ editXY(cur, x, y - par.rows()[row].ascent() - margin);
cur.clearSelection();
// This happens when you move out of an inset.
if (row > 0) {
updateNeeded |= setCursor(cur, cur.pit(),
- x2pos(cur.pit(), row - 1, x));
+ x2pos(cur.bv(), cur.pit(), row - 1, x));
} else if (cur.pit() > 0) {
--cur.pit();
//cannot use 'par' now
updateNeeded |= setCursor(cur, cur.pit(),
- x2pos(cur.pit(), cur.paragraph().rows().size() - 1, x));
+ x2pos(cur.bv(), cur.pit(), cur.paragraph().rows().size() - 1, x));
}
cur.x_target() = x;
bool LyXText::cursorDown(LCursor & cur)
{
+ // Tell BufferView to test for FitCursor in any case!
+ cur.updateFlags(Update::FitCursor);
+
Paragraph const & par = cur.paragraph();
int row;
int const x = cur.targetX();
row = par.pos2row(cur.pos());
if (!cur.selection()) {
- int const y = bv_funcs::getPos(cur, cur.boundary()).y_;
+ int const y = bv_funcs::getPos(cur.bv(), cur, cur.boundary()).y_;
LCursor old = cur;
- editXY(cur, x, y + par.rows()[row].descent() + 1);
+ // To middle of next row
+ int const margin = 3 * InsetMathHull::displayMargin() / 2;
+ editXY(cur, x, y + par.rows()[row].descent() + margin);
cur.clearSelection();
// This happens when you move out of an inset.
if (row + 1 < int(par.rows().size())) {
updateNeeded |= setCursor(cur, cur.pit(),
- x2pos(cur.pit(), row + 1, x));
+ x2pos(cur.bv(), cur.pit(), row + 1, x));
} else if (cur.pit() + 1 < int(paragraphs().size())) {
++cur.pit();
updateNeeded |= setCursor(cur, cur.pit(),
- x2pos(cur.pit(), 0, x));
+ x2pos(cur.bv(), cur.pit(), 0, x));
}
cur.x_target() = x;
&& old.pos() < oldpar.size()
&& oldpar.isLineSeparator(old.pos())
&& oldpar.isLineSeparator(old.pos() - 1)
- && oldpar.lookupChange(old.pos() - 1) != Change::DELETED) {
- // We need to set the text to Change::INSERTED to
- // get it erased properly
- oldpar.setChange(old.pos() -1, Change::INSERTED);
- oldpar.erase(old.pos() - 1);
+ && !oldpar.isDeleted(old.pos() - 1)) {
+ oldpar.eraseChar(old.pos() - 1, false); // do not track changes in DEPM
+ // rebreak it and update the CoordCache.
+ redoParagraph(cur.bv(), old.pit());
#ifdef WITH_WARNINGS
#warning This will not work anymore when we have multiple views of the same buffer
// In this case, we will have to correct also the cursors held by
if (oldpar.empty() || (oldpar.size() == 1 && oldpar.isLineSeparator(0))) {
// Delete old par.
- recordUndo(old, Undo::ATOMIC, old.pit());
+ recordUndo(old, Undo::ATOMIC,
+ max(old.pit() - 1, pit_type(0)),
+ min(old.pit() + 1, old.lastpit()));
ParagraphList & plist = old.text()->paragraphs();
- plist.erase(plist.begin() + old.pit());
+ plist.erase(boost::next(plist.begin(), old.pit()));
// see #warning above
if (cur.depth() >= old.depth()) {
CursorSlice & curslice = cur[old.depth() - 1];
- if (&curslice.inset() == &old.inset()
+ if (&curslice.inset() == &old.inset()
&& curslice.pit() > old.pit()) {
--curslice.pit();
// since a paragraph has been deleted, all the
cur.resetAnchor();
}
}
- updateCounters(old.buffer());
+ // There is a crash reported by Edwin Leuven (16/04/2006) because of:
+ //ParIterator par_it(old);
+ //updateLabels(old.buffer(), par_it);
+ // So for now we do the full update:
+ updateLabels(old.buffer());
return true;
}
}
-void LyXText::recUndo(pit_type first, pit_type last) const
+void LyXText::recUndo(LCursor & cur, pit_type first, pit_type last) const
{
- recordUndo(bv()->cursor(), Undo::ATOMIC, first, last);
+ recordUndo(cur, Undo::ATOMIC, first, last);
}
-void LyXText::recUndo(pit_type par) const
+void LyXText::recUndo(LCursor & cur, pit_type par) const
{
- recordUndo(bv()->cursor(), Undo::ATOMIC, par, par);
+ recordUndo(cur, Undo::ATOMIC, par, par);
}
int defaultRowHeight()
{
- return int(font_metrics::maxHeight(LyXFont(LyXFont::ALL_SANE)) * 1.2);
+ return int(theFontMetrics(LyXFont(LyXFont::ALL_SANE)).maxHeight() * 1.2);
}
+
+
+} // namespace lyx