mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-12-26 22:17:41 +00:00
Compare commits
4 Commits
80d731e119
...
6701a5d55c
Author | SHA1 | Date | |
---|---|---|---|
|
6701a5d55c | ||
|
4c72def295 | ||
|
1dbe589b27 | ||
|
91d1ad319d |
@ -1330,12 +1330,13 @@ void Cursor::posVisToRowExtremity(bool left)
|
|||||||
LYXERR(Debug::RTL, "entering extremity: " << pit() << "," << pos() << ","
|
LYXERR(Debug::RTL, "entering extremity: " << pit() << "," << pos() << ","
|
||||||
<< (boundary() ? 1 : 0));
|
<< (boundary() ? 1 : 0));
|
||||||
|
|
||||||
|
// FIXME: no need for metrics here!
|
||||||
TextMetrics const & tm = bv_->textMetrics(text());
|
TextMetrics const & tm = bv_->textMetrics(text());
|
||||||
// Looking for extremities is like clicking on the left or the
|
// Looking for extremities is like clicking on the left or the
|
||||||
// right of the row.
|
// right of the row.
|
||||||
int x = tm.origin().x + (left ? 0 : textRow().width());
|
int x = tm.origin().x + (left ? 0 : textRow().width());
|
||||||
bool b = false;
|
auto [p, b] = tm.getPosNearX(textRow(), x);
|
||||||
pos() = tm.getPosNearX(textRow(), x, b);
|
pos() = p;
|
||||||
boundary(b);
|
boundary(b);
|
||||||
|
|
||||||
LYXERR(Debug::RTL, "leaving extremity: " << pit() << "," << pos() << ","
|
LYXERR(Debug::RTL, "leaving extremity: " << pit() << "," << pos() << ","
|
||||||
@ -2286,9 +2287,9 @@ bool Cursor::upDownInText(bool up)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Row const & real_next_row = tm.parMetrics(pit()).rows()[next_row];
|
Row const & real_next_row = tm.parMetrics(pit()).rows()[next_row];
|
||||||
bool bound = false;
|
auto [b, p] = tm.getPosNearX(real_next_row, xo);
|
||||||
top().pos() = tm.getPosNearX(real_next_row, xo, bound);
|
pos() = p;
|
||||||
boundary(bound);
|
boundary(b);
|
||||||
// When selection==false, this is done by TextMetrics::editXY
|
// When selection==false, this is done by TextMetrics::editXY
|
||||||
setCurrentFont();
|
setCurrentFont();
|
||||||
|
|
||||||
|
64
src/Row.cpp
64
src/Row.cpp
@ -415,6 +415,70 @@ bool Row::setExtraWidth(int w)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pair<pos_type, bool> Row::x2pos(int & x) const
|
||||||
|
{
|
||||||
|
pos_type retpos = pos();
|
||||||
|
bool boundary = false;
|
||||||
|
if (empty())
|
||||||
|
x = left_margin;
|
||||||
|
else if (x <= left_margin) {
|
||||||
|
retpos = front().left_pos();
|
||||||
|
x = left_margin;
|
||||||
|
} else if (x >= width()) {
|
||||||
|
retpos = back().right_pos();
|
||||||
|
x = width();
|
||||||
|
} else {
|
||||||
|
double w = left_margin;
|
||||||
|
const_iterator cit = begin();
|
||||||
|
const_iterator cend = end();
|
||||||
|
for ( ; cit != cend; ++cit) {
|
||||||
|
if (w <= x && w + cit->full_width() > x) {
|
||||||
|
int x_offset = int(x - w);
|
||||||
|
retpos = cit->x2pos(x_offset);
|
||||||
|
x = int(x_offset + w);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
w += cit->full_width();
|
||||||
|
}
|
||||||
|
if (cit == end()) {
|
||||||
|
retpos = back().right_pos();
|
||||||
|
x = width();
|
||||||
|
}
|
||||||
|
/** This tests for the case where the cursor is placed
|
||||||
|
* just before a font direction change. See comment on
|
||||||
|
* the boundary_ member in DocIterator.h to understand
|
||||||
|
* how boundary helps here.
|
||||||
|
*/
|
||||||
|
else if (retpos == cit->endpos
|
||||||
|
&& ((!cit->isRTL() && cit + 1 != end()
|
||||||
|
&& (cit + 1)->isRTL())
|
||||||
|
|| (cit->isRTL() && cit != begin()
|
||||||
|
&& !(cit - 1)->isRTL())))
|
||||||
|
boundary = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty())
|
||||||
|
boundary = end_boundary();
|
||||||
|
/** This tests for the case where the cursor is set at the end
|
||||||
|
* of a row which has been broken due something else than a
|
||||||
|
* separator (a display inset or a forced breaking of the
|
||||||
|
* row). We know that there is a separator when the end of the
|
||||||
|
* row is larger than the end of its last element.
|
||||||
|
*/
|
||||||
|
else if (retpos == back().endpos && back().endpos == endpos()) {
|
||||||
|
// FIXME: need a row flag here to say that cursor cannot be at the end
|
||||||
|
Inset const * inset = back().inset;
|
||||||
|
if (inset && (inset->lyxCode() == NEWLINE_CODE
|
||||||
|
|| inset->lyxCode() == SEPARATOR_CODE))
|
||||||
|
retpos = back().pos;
|
||||||
|
else
|
||||||
|
boundary = end_boundary();
|
||||||
|
}
|
||||||
|
|
||||||
|
return make_pair(retpos, boundary);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Row::sameString(Font const & f, Change const & ch) const
|
bool Row::sameString(Font const & f, Change const & ch) const
|
||||||
{
|
{
|
||||||
if (elements_.empty())
|
if (elements_.empty())
|
||||||
|
14
src/Row.h
14
src/Row.h
@ -91,14 +91,14 @@ public:
|
|||||||
* \param i in the row element.
|
* \param i in the row element.
|
||||||
*/
|
*/
|
||||||
double pos2x(pos_type const i) const;
|
double pos2x(pos_type const i) const;
|
||||||
/** Return character position that is the closest to
|
/** Return character position that is the closest to pixel
|
||||||
* pixel position \param x. The value \param x is
|
* position \param x. The value \param x is adjusted to the
|
||||||
* adjusted to the actual pixel position.
|
* actual pixel position.
|
||||||
*/
|
*/
|
||||||
pos_type x2pos(int &x) const;
|
pos_type x2pos(int &x) const;
|
||||||
/** Break the element in two if possible, so that its width is less
|
/** Break the element in two if possible, so that its width is less
|
||||||
* than the required values.
|
* than the required values.
|
||||||
* \return true if something has been done ; false if this is
|
* \return true if something has been done; false if this is
|
||||||
* not needed or not possible.
|
* not needed or not possible.
|
||||||
* \param width: maximum width of the row.
|
* \param width: maximum width of the row.
|
||||||
* \param next_width: available width on next rows.
|
* \param next_width: available width on next rows.
|
||||||
@ -252,6 +252,12 @@ public:
|
|||||||
// distributed among expanders. \return false if the justification fails.
|
// distributed among expanders. \return false if the justification fails.
|
||||||
bool setExtraWidth(int w);
|
bool setExtraWidth(int w);
|
||||||
|
|
||||||
|
/** Return character position and boundary value that are the
|
||||||
|
* closest to pixel position \param x. The value \param x is
|
||||||
|
* adjusted to the actual pixel position.
|
||||||
|
*/
|
||||||
|
std::pair<pos_type, bool> x2pos(int & x) const;
|
||||||
|
|
||||||
///
|
///
|
||||||
void add(pos_type pos, Inset const * ins, Dimension const & dim,
|
void add(pos_type pos, Inset const * ins, Dimension const & dim,
|
||||||
Font const & f, Change const & ch);
|
Font const & f, Change const & ch);
|
||||||
|
@ -1432,8 +1432,7 @@ void TextMetrics::setRowHeight(Row & row) const
|
|||||||
// x is an absolute screen coord
|
// x is an absolute screen coord
|
||||||
// returns the column near the specified x-coordinate of the row
|
// returns the column near the specified x-coordinate of the row
|
||||||
// x is set to the real beginning of this column
|
// x is set to the real beginning of this column
|
||||||
pos_type TextMetrics::getPosNearX(Row const & row, int & x,
|
pair<pos_type, bool> TextMetrics::getPosNearX(Row const & row, int & x) const
|
||||||
bool & boundary) const
|
|
||||||
{
|
{
|
||||||
//LYXERR0("getPosNearX(" << x << ") row=" << row);
|
//LYXERR0("getPosNearX(" << x << ") row=" << row);
|
||||||
/// For the main Text, it is possible that this pit is not
|
/// For the main Text, it is possible that this pit is not
|
||||||
@ -1446,82 +1445,12 @@ pos_type TextMetrics::getPosNearX(Row const & row, int & x,
|
|||||||
int const offset = bv_->horizScrollOffset(text_, row.pit(), row.pos());
|
int const offset = bv_->horizScrollOffset(text_, row.pit(), row.pos());
|
||||||
x += offset;
|
x += offset;
|
||||||
|
|
||||||
pos_type pos = row.pos();
|
auto [pos, boundary] = row.x2pos(x);
|
||||||
boundary = false;
|
|
||||||
if (row.empty())
|
|
||||||
x = row.left_margin;
|
|
||||||
else if (x <= row.left_margin) {
|
|
||||||
pos = row.front().left_pos();
|
|
||||||
x = row.left_margin;
|
|
||||||
} else if (x >= row.width()) {
|
|
||||||
pos = row.back().right_pos();
|
|
||||||
x = row.width();
|
|
||||||
} else {
|
|
||||||
double w = row.left_margin;
|
|
||||||
Row::const_iterator cit = row.begin();
|
|
||||||
Row::const_iterator cend = row.end();
|
|
||||||
for ( ; cit != cend; ++cit) {
|
|
||||||
if (w <= x && w + cit->full_width() > x) {
|
|
||||||
int x_offset = int(x - w);
|
|
||||||
pos = cit->x2pos(x_offset);
|
|
||||||
x = int(x_offset + w);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
w += cit->full_width();
|
|
||||||
}
|
|
||||||
if (cit == row.end()) {
|
|
||||||
pos = row.back().right_pos();
|
|
||||||
x = row.width();
|
|
||||||
}
|
|
||||||
/** This tests for the case where the cursor is placed
|
|
||||||
* just before a font direction change. See comment on
|
|
||||||
* the boundary_ member in DocIterator.h to understand
|
|
||||||
* how boundary helps here.
|
|
||||||
*/
|
|
||||||
else if (pos == cit->endpos
|
|
||||||
&& ((!cit->isRTL() && cit + 1 != row.end()
|
|
||||||
&& (cit + 1)->isRTL())
|
|
||||||
|| (cit->isRTL() && cit != row.begin()
|
|
||||||
&& !(cit - 1)->isRTL())))
|
|
||||||
boundary = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (row.empty())
|
|
||||||
boundary = row.end_boundary();
|
|
||||||
/** This tests for the case where the cursor is set at the end
|
|
||||||
* of a row which has been broken due something else than a
|
|
||||||
* separator (a display inset or a forced breaking of the
|
|
||||||
* row). We know that there is a separator when the end of the
|
|
||||||
* row is larger than the end of its last element.
|
|
||||||
*/
|
|
||||||
else if (pos == row.back().endpos && row.back().endpos == row.endpos()) {
|
|
||||||
Inset const * inset = row.back().inset;
|
|
||||||
if (inset && (inset->lyxCode() == NEWLINE_CODE
|
|
||||||
|| inset->lyxCode() == SEPARATOR_CODE))
|
|
||||||
pos = row.back().pos;
|
|
||||||
else
|
|
||||||
boundary = row.end_boundary();
|
|
||||||
}
|
|
||||||
|
|
||||||
x += xo - offset;
|
x += xo - offset;
|
||||||
//LYXERR0("getPosNearX ==> pos=" << pos << ", boundary=" << boundary);
|
//LYXERR0("getPosNearX ==> pos=" << pos << ", boundary=" << boundary);
|
||||||
|
|
||||||
return pos;
|
return make_pair(pos, boundary);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pos_type TextMetrics::x2pos(pit_type pit, int row, int x) const
|
|
||||||
{
|
|
||||||
// We play safe and use parMetrics(pit) to make sure the
|
|
||||||
// ParagraphMetrics will be redone and OK to use if needed.
|
|
||||||
// Otherwise we would use an empty ParagraphMetrics in
|
|
||||||
// upDownInText() while in selection mode.
|
|
||||||
ParagraphMetrics const & pm = parMetrics(pit);
|
|
||||||
|
|
||||||
LBUFERR(row < int(pm.rows().size()));
|
|
||||||
bool bound = false;
|
|
||||||
Row const & r = pm.rows()[row];
|
|
||||||
return getPosNearX(r, x, bound);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1645,8 +1574,8 @@ Inset * TextMetrics::editXY(Cursor & cur, int x, int y,
|
|||||||
|
|
||||||
if (!e) {
|
if (!e) {
|
||||||
// No inset, set position in the text
|
// No inset, set position in the text
|
||||||
bool bound = false; // is modified by getPosNearX
|
auto [pos, bound] = getPosNearX(row, x);
|
||||||
cur.pos() = getPosNearX(row, x, bound);
|
cur.pos() = pos;
|
||||||
cur.boundary(bound);
|
cur.boundary(bound);
|
||||||
cur.setCurrentFont();
|
cur.setCurrentFont();
|
||||||
cur.setTargetX(x);
|
cur.setTargetX(x);
|
||||||
@ -1668,8 +1597,9 @@ Inset * TextMetrics::editXY(Cursor & cur, int x, int y,
|
|||||||
if (cur.text() == text_ && cur.pos() == e->pos) {
|
if (cur.text() == text_ && cur.pos() == e->pos) {
|
||||||
// non-editable inset, set cursor after the inset if x is
|
// non-editable inset, set cursor after the inset if x is
|
||||||
// nearer to that position (bug 9628)
|
// nearer to that position (bug 9628)
|
||||||
bool bound = false; // is modified by getPosNearX
|
// No inset, set position in the text
|
||||||
cur.pos() = getPosNearX(row, x, bound);
|
auto [pos, bound] = getPosNearX(row, x);
|
||||||
|
cur.pos() = pos;
|
||||||
cur.boundary(bound);
|
cur.boundary(bound);
|
||||||
cur.setCurrentFont();
|
cur.setCurrentFont();
|
||||||
cur.setTargetX(x);
|
cur.setTargetX(x);
|
||||||
@ -1681,13 +1611,13 @@ Inset * TextMetrics::editXY(Cursor & cur, int x, int y,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TextMetrics::setCursorFromCoordinates(Cursor & cur, int const x, int const y)
|
void TextMetrics::setCursorFromCoordinates(Cursor & cur, int x, int const y)
|
||||||
{
|
{
|
||||||
LASSERT(text_ == cur.text(), return);
|
LASSERT(text_ == cur.text(), return);
|
||||||
pit_type const pit = getPitNearY(y);
|
pit_type const pit = getPitNearY(y);
|
||||||
LASSERT(pit != -1, return);
|
LASSERT(pit != -1, return);
|
||||||
|
|
||||||
ParagraphMetrics const & pm = par_metrics_[pit];
|
ParagraphMetrics const & pm = parMetrics(pit);
|
||||||
|
|
||||||
int yy = pm.position() - pm.rows().front().ascent();
|
int yy = pm.position() - pm.rows().front().ascent();
|
||||||
LYXERR(Debug::PAINTING, "x: " << x << " y: " << y <<
|
LYXERR(Debug::PAINTING, "x: " << x << " y: " << y <<
|
||||||
@ -1706,9 +1636,7 @@ void TextMetrics::setCursorFromCoordinates(Cursor & cur, int const x, int const
|
|||||||
|
|
||||||
LYXERR(Debug::PAINTING, "row " << r << " from pos: " << row.pos());
|
LYXERR(Debug::PAINTING, "row " << r << " from pos: " << row.pos());
|
||||||
|
|
||||||
bool bound = false;
|
auto [pos, bound] = getPosNearX(row, x);
|
||||||
int xx = x;
|
|
||||||
pos_type const pos = getPosNearX(row, xx, bound);
|
|
||||||
|
|
||||||
LYXERR(Debug::PAINTING, "setting cursor pit: " << pit << " pos: " << pos);
|
LYXERR(Debug::PAINTING, "setting cursor pit: " << pit << " pos: " << pos);
|
||||||
|
|
||||||
|
@ -189,13 +189,7 @@ public:
|
|||||||
/// returns the position near the specified x-coordinate of the row.
|
/// returns the position near the specified x-coordinate of the row.
|
||||||
/// x is an absolute screen coord, it is set to the real beginning
|
/// x is an absolute screen coord, it is set to the real beginning
|
||||||
/// of this column. This takes in account horizontal cursor row scrolling.
|
/// of this column. This takes in account horizontal cursor row scrolling.
|
||||||
pos_type getPosNearX(Row const & row, int & x, bool & boundary) const;
|
std::pair<pos_type, bool> getPosNearX(Row const & row, int & x) const;
|
||||||
|
|
||||||
/// returns pos in given par at given x coord.
|
|
||||||
pos_type x2pos(pit_type pit, int row, int x) const;
|
|
||||||
|
|
||||||
// FIXME: is there a need for this?
|
|
||||||
//int pos2x(pit_type pit, pos_type pos) const;
|
|
||||||
|
|
||||||
/// returns the row near the specified y-coordinate in a given paragraph
|
/// returns the row near the specified y-coordinate in a given paragraph
|
||||||
/// (relative to the screen). If assert_in_view is true, it is made sure
|
/// (relative to the screen). If assert_in_view is true, it is made sure
|
||||||
|
@ -973,7 +973,7 @@ void GuiWorkArea::generateSyntheticMouseEvent()
|
|||||||
Text * text = cur.text();
|
Text * text = cur.text();
|
||||||
if (!text)
|
if (!text)
|
||||||
return;
|
return;
|
||||||
TextMetrics const & tm = d->buffer_view_->textMetrics(text);
|
TextMetrics & tm = d->buffer_view_->textMetrics(text);
|
||||||
|
|
||||||
// Quit gracefully if there are no metrics, since otherwise next
|
// Quit gracefully if there are no metrics, since otherwise next
|
||||||
// line would crash (bug #10324).
|
// line would crash (bug #10324).
|
||||||
@ -981,34 +981,8 @@ void GuiWorkArea::generateSyntheticMouseEvent()
|
|||||||
if (tm.empty())
|
if (tm.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pair<pit_type, const ParagraphMetrics *> pp = up ? tm.first() : tm.last();
|
const int y = up ? 0 : wh - defaultRowHeight();
|
||||||
ParagraphMetrics const & pm = *pp.second;
|
tm.setCursorFromCoordinates(cur, d->synthetic_mouse_event_.cmd.x(), y);
|
||||||
pit_type const pit = pp.first;
|
|
||||||
|
|
||||||
if (pm.rows().empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Find the row at which we set the cursor.
|
|
||||||
RowList::const_iterator rit = pm.rows().begin();
|
|
||||||
RowList::const_iterator rlast = pm.rows().end();
|
|
||||||
int yy = pm.top();
|
|
||||||
for (--rlast; rit != rlast; ++rit) {
|
|
||||||
int h = rit->height();
|
|
||||||
if ((up && yy + h > 0)
|
|
||||||
|| (!up && yy + h > wh - defaultRowHeight()))
|
|
||||||
break;
|
|
||||||
yy += h;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the position of the cursor
|
|
||||||
bool bound;
|
|
||||||
int x = d->synthetic_mouse_event_.cmd.x();
|
|
||||||
pos_type const pos = tm.getPosNearX(*rit, x, bound);
|
|
||||||
|
|
||||||
// Set the cursor
|
|
||||||
cur.pit() = pit;
|
|
||||||
cur.pos() = pos;
|
|
||||||
cur.boundary(bound);
|
|
||||||
|
|
||||||
d->buffer_view_->buffer().changed(false);
|
d->buffer_view_->buffer().changed(false);
|
||||||
}
|
}
|
||||||
|
@ -5292,15 +5292,15 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
|
|||||||
// setting also the right targetX.
|
// setting also the right targetX.
|
||||||
cur.selHandle(act == LFUN_DOWN_SELECT);
|
cur.selHandle(act == LFUN_DOWN_SELECT);
|
||||||
if (tabular.cellRow(cur.idx()) != tabular.nrows() - 1) {
|
if (tabular.cellRow(cur.idx()) != tabular.nrows() - 1) {
|
||||||
int const xtarget = cur.targetX();
|
int xtarget = cur.targetX();
|
||||||
// WARNING: Once cur.idx() has been reset, the cursor is in
|
// WARNING: Once cur.idx() has been reset, the cursor is in
|
||||||
// an inconsistent state until pos() has been set. Be careful
|
// an inconsistent state until pos() has been set. Be careful
|
||||||
// what you do with it!
|
// what you do with it!
|
||||||
cur.idx() = tabular.cellBelow(cur.idx());
|
cur.idx() = tabular.cellBelow(cur.idx());
|
||||||
cur.pit() = 0;
|
cur.pit() = 0;
|
||||||
TextMetrics const & tm =
|
TextMetrics const & tm = cur.bv().textMetrics(cell(cur.idx())->getText(0));
|
||||||
cur.bv().textMetrics(cell(cur.idx())->getText(0));
|
ParagraphMetrics const & pm = tm.parMetrics(cur.pit());
|
||||||
cur.pos() = tm.x2pos(cur.pit(), 0, xtarget);
|
cur.pos() = tm.getPosNearX(pm.rows().front(), xtarget).first;
|
||||||
cur.setCurrentFont();
|
cur.setCurrentFont();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5331,7 +5331,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
|
|||||||
// setting also the right targetX.
|
// setting also the right targetX.
|
||||||
cur.selHandle(act == LFUN_UP_SELECT);
|
cur.selHandle(act == LFUN_UP_SELECT);
|
||||||
if (tabular.cellRow(cur.idx()) != 0) {
|
if (tabular.cellRow(cur.idx()) != 0) {
|
||||||
int const xtarget = cur.targetX();
|
int xtarget = cur.targetX();
|
||||||
// WARNING: Once cur.idx() has been reset, the cursor is in
|
// WARNING: Once cur.idx() has been reset, the cursor is in
|
||||||
// an inconsistent state until pos() has been set. Be careful
|
// an inconsistent state until pos() has been set. Be careful
|
||||||
// what you do with it!
|
// what you do with it!
|
||||||
@ -5339,9 +5339,8 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
|
|||||||
cur.pit() = cur.lastpit();
|
cur.pit() = cur.lastpit();
|
||||||
Text const * text = cell(cur.idx())->getText(0);
|
Text const * text = cell(cur.idx())->getText(0);
|
||||||
TextMetrics const & tm = cur.bv().textMetrics(text);
|
TextMetrics const & tm = cur.bv().textMetrics(text);
|
||||||
ParagraphMetrics const & pm =
|
ParagraphMetrics const & pm = tm.parMetrics(cur.lastpit());
|
||||||
tm.parMetrics(cur.lastpit());
|
cur.pos() = tm.getPosNearX(pm.rows().back(), xtarget).first;
|
||||||
cur.pos() = tm.x2pos(cur.pit(), pm.rows().size()-1, xtarget);
|
|
||||||
cur.setCurrentFont();
|
cur.setCurrentFont();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user