Transfer getColumnNearX from LyXText to TextMetrics.

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@16454 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Abdelrazak Younes 2007-01-01 10:33:37 +00:00
parent e58397400c
commit f1d90e17d8
5 changed files with 154 additions and 157 deletions

View File

@ -30,6 +30,7 @@
#include "FontIterator.h"
#include "LColor.h"
#include "lyxlength.h"
#include "lyxrc.h"
#include "lyxtext.h"
#include "metricsinfo.h"
#include "ParagraphParameters.h"
@ -775,6 +776,149 @@ void TextMetrics::setHeightOfRow(pit_type const pit,
}
// 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 TextMetrics::getColumnNearX(pit_type const pit,
Row const & row, int & x, bool & boundary) const
{
Buffer const & buffer = *bv_->buffer();
/// For the main LyXText, it is possible that this pit is not
/// yet in the CoordCache when moving cursor up.
/// x Paragraph coordinate is always 0 for main text anyway.
int const xo = main_text_? 0 : bv_->coordCache().get(text_, pit).x_;
x -= xo;
RowMetrics const r = computeRowMetrics(pit, row);
Paragraph const & par = text_->getPar(pit);
pos_type vc = row.pos();
pos_type end = row.endpos();
pos_type c = 0;
LyXLayout_ptr const & layout = par.layout();
bool left_side = false;
pos_type body_pos = par.beginOfBody();
double tmpx = r.x;
double last_tmpx = tmpx;
if (body_pos > 0 &&
(body_pos > end || !par.isLineSeparator(body_pos - 1)))
body_pos = 0;
// check for empty row
if (vc == end) {
x = int(tmpx) + xo;
return 0;
}
frontend::FontMetrics const & fm
= theFontMetrics(text_->getLabelFont(buffer, par));
while (vc < end && tmpx <= x) {
c = text_->bidi.vis2log(vc);
last_tmpx = tmpx;
if (body_pos > 0 && c == body_pos - 1) {
// FIXME UNICODE
docstring const lsep = from_utf8(layout->labelsep);
tmpx += r.label_hfill + fm.width(lsep);
if (par.isLineSeparator(body_pos - 1))
tmpx -= text_->singleWidth(buffer, par, body_pos - 1);
}
if (par.hfillExpansion(row, c)) {
tmpx += text_->singleWidth(buffer, par, c);
if (c >= body_pos)
tmpx += r.hfill;
else
tmpx += r.label_hfill;
} else if (par.isSeparator(c)) {
tmpx += text_->singleWidth(buffer, par, c);
if (c >= body_pos)
tmpx += r.separator;
} else {
tmpx += text_->singleWidth(buffer, par, c);
}
++vc;
}
if ((tmpx + last_tmpx) / 2 > x) {
tmpx = last_tmpx;
left_side = true;
}
BOOST_ASSERT(vc <= end); // This shouldn't happen.
boundary = false;
// This (rtl_support test) is not needed, but gives
// some speedup if rtl_support == false
bool const lastrow = lyxrc.rtl_support && row.endpos() == par.size();
// If lastrow is false, we don't need to compute
// the value of rtl.
bool const rtl = lastrow ? text_->isRTL(buffer, par) : false;
if (lastrow &&
((rtl && left_side && vc == row.pos() && x < tmpx - 5) ||
(!rtl && !left_side && vc == end && x > tmpx + 5)))
c = end;
else if (vc == row.pos()) {
c = text_->bidi.vis2log(vc);
if (text_->bidi.level(c) % 2 == 1)
++c;
} else {
c = text_->bidi.vis2log(vc - 1);
bool const rtl = (text_->bidi.level(c) % 2 == 1);
if (left_side == rtl) {
++c;
boundary = text_->bidi.isBoundary(buffer, par, c);
}
}
// I believe this code is not needed anymore (Jug 20050717)
#if 0
// The following code is necessary because the cursor position past
// the last char in a row is logically equivalent to that before
// the first char in the next row. That's why insets causing row
// divisions -- Newline and display-style insets -- must be treated
// specially, so cursor up/down doesn't get stuck in an air gap -- MV
// Newline inset, air gap below:
if (row.pos() < end && c >= end && par.isNewline(end - 1)) {
if (text_->bidi.level(end -1) % 2 == 0)
tmpx -= text_->singleWidth(buffer, par, end - 1);
else
tmpx += text_->singleWidth(buffer, par, end - 1);
c = end - 1;
}
// Air gap above display inset:
if (row.pos() < end && c >= end && end < par.size()
&& par.isInset(end) && par.getInset(end)->display()) {
c = end - 1;
}
// Air gap below display inset:
if (row.pos() < end && c >= end && par.isInset(end - 1)
&& par.getInset(end - 1)->display()) {
c = end - 1;
}
#endif
x = int(tmpx) + xo;
pos_type const col = c - row.pos();
if (!c || end == par.size())
return col;
if (c==end && !par.isLineSeparator(c-1) && !par.isNewline(c-1)) {
boundary = true;
return col;
}
return min(col, end - 1 - row.pos());
}
int defaultRowHeight()
{
return int(theFontMetrics(LyXFont(LyXFont::ALL_SANE)).maxHeight() * 1.2);

View File

@ -90,6 +90,12 @@ private:
/// Calculate and set the height of the row
void setHeightOfRow(pit_type, Row & row);
/// returns the column near the specified x-coordinate of the row.
/// x is an absolute screen coord, it is set to the real beginning
/// of this column.
pos_type getColumnNearX(pit_type pit, Row const & row, int & x,
bool & boundary) const;
/// The BufferView owner.
BufferView * bv_;

View File

@ -149,13 +149,6 @@ public:
/// FIXME: move to TextMetrics.
pit_type getPitNearY(BufferView & bv, int y);
/** returns the column near the specified x-coordinate of the row
x is set to the real beginning of this column
*/
/// FIXME: move to TextMetrics.
pos_type getColumnNearX(BufferView const & bv, int right_margin,
pit_type pit, Row const & row, int & x, bool & boundary) const;
/** Find the word under \c from in the relative location
* defined by \c word_location.
* @param from return here the start of the word

View File

@ -1687,7 +1687,7 @@ pos_type LyXText::x2pos(BufferView const & bv, pit_type pit, int row,
BOOST_ASSERT(row < int(pm.rows().size()));
bool bound = false;
Row const & r = pm.rows()[row];
return r.pos() + getColumnNearX(bv, tm.rightMargin(pm), pit, r, x, bound);
return r.pos() + tm.getColumnNearX(pit, r, x, bound);
}
@ -1736,8 +1736,8 @@ void LyXText::setCursorFromCoordinates(LCursor & cur, int const x, int const y)
bool bound = false;
int xx = x;
int right_margin = tm.rightMargin(pm);
pos_type const pos = row.pos() + getColumnNearX(cur.bv(), right_margin,
pit, row, xx, bound);
pos_type const pos = row.pos()
+ tm.getColumnNearX(pit, row, xx, bound);
lyxerr[Debug::DEBUG]
<< BOOST_CURRENT_FUNCTION

View File

@ -748,152 +748,6 @@ void LyXText::setCurrentFont(LCursor & cur)
}
}
// 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(BufferView const & bv, int right_margin,
pit_type const pit, Row const & row, int & x, bool & boundary) const
{
Buffer const & buffer = *bv.buffer();
TextMetrics const & tm = bv.textMetrics(this);
/// For the main LyXText, it is possible that this pit is not
/// yet in the CoordCache when moving cursor up.
/// x Paragraph coordinate is always 0 for main text anyway.
int const xo = isMainText(*bv.buffer())?
0 : bv.coordCache().get(this, pit).x_;
x -= xo;
RowMetrics const r = tm.computeRowMetrics(pit, row);
Paragraph const & par = pars_[pit];
pos_type vc = row.pos();
pos_type end = row.endpos();
pos_type c = 0;
LyXLayout_ptr const & layout = par.layout();
bool left_side = false;
pos_type body_pos = par.beginOfBody();
double tmpx = r.x;
double last_tmpx = tmpx;
if (body_pos > 0 &&
(body_pos > end || !par.isLineSeparator(body_pos - 1)))
body_pos = 0;
// check for empty row
if (vc == end) {
x = int(tmpx) + xo;
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) {
// FIXME UNICODE
docstring const lsep = from_utf8(layout->labelsep);
tmpx += r.label_hfill + fm.width(lsep);
if (par.isLineSeparator(body_pos - 1))
tmpx -= singleWidth(buffer, par, body_pos - 1);
}
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(buffer, par, c);
if (c >= body_pos)
tmpx += r.separator;
} else {
tmpx += singleWidth(buffer, par, c);
}
++vc;
}
if ((tmpx + last_tmpx) / 2 > x) {
tmpx = last_tmpx;
left_side = true;
}
BOOST_ASSERT(vc <= end); // This shouldn't happen.
boundary = false;
// This (rtl_support test) is not needed, but gives
// some speedup if rtl_support == false
bool const lastrow = lyxrc.rtl_support && row.endpos() == par.size();
// If lastrow is false, we don't need to compute
// the value of rtl.
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)))
c = end;
else if (vc == row.pos()) {
c = bidi.vis2log(vc);
if (bidi.level(c) % 2 == 1)
++c;
} else {
c = bidi.vis2log(vc - 1);
bool const rtl = (bidi.level(c) % 2 == 1);
if (left_side == rtl) {
++c;
boundary = bidi.isBoundary(buffer, par, c);
}
}
// I believe this code is not needed anymore (Jug 20050717)
#if 0
// The following code is necessary because the cursor position past
// the last char in a row is logically equivalent to that before
// the first char in the next row. That's why insets causing row
// divisions -- Newline and display-style insets -- must be treated
// specially, so cursor up/down doesn't get stuck in an air gap -- MV
// Newline inset, air gap below:
if (row.pos() < end && c >= end && par.isNewline(end - 1)) {
if (bidi.level(end -1) % 2 == 0)
tmpx -= singleWidth(buffer, par, end - 1);
else
tmpx += singleWidth(buffer, par, end - 1);
c = end - 1;
}
// Air gap above display inset:
if (row.pos() < end && c >= end && end < par.size()
&& par.isInset(end) && par.getInset(end)->display()) {
c = end - 1;
}
// Air gap below display inset:
if (row.pos() < end && c >= end && par.isInset(end - 1)
&& par.getInset(end - 1)->display()) {
c = end - 1;
}
#endif
x = int(tmpx) + xo;
pos_type const col = c - row.pos();
if (!c || end == par.size())
return col;
if (c==end && !par.isLineSeparator(c-1) && !par.isNewline(c-1)) {
boundary = true;
return col;
}
return min(col, end - 1 - row.pos());
}
// y is screen coordinate
pit_type LyXText::getPitNearY(BufferView & bv, int y)
{
@ -1007,7 +861,7 @@ InsetBase * LyXText::editXY(LCursor & cur, int x, int y)
int right_margin = tm.rightMargin(pm);
int xx = x; // is modified by getColumnNearX
pos_type const pos = row.pos()
+ getColumnNearX(cur.bv(), right_margin, pit, row, xx, bound);
+ tm.getColumnNearX(pit, row, xx, bound);
cur.pit() = pit;
cur.pos() = pos;
cur.boundary(bound);