Jesper Skov wrote:
> open abiword
> enter "1234"
> cursor left twice
> break page (control-return)
>
> **** (1) Assert ****
> **** (1) FP_RUN_NOT != containsOffset(iOffset) at fp_Run.cpp:1222 ****
> **** (1) Continue ? (y/n) [y] : n
This is one of the files I've done some local surgery on, and I notice
that my local copy don't behave like this. I've been planning to try to
clean up that code, but if you beat me to it (since I'm at the moment
completely engulfed in cursor stuff) I won't complain. :-)
> Basically, I just crashed on the sources and there are a gazillion
> things I don't understand,
Then we're at least two that are confused about this.
To either add to the confusion, or hopefully shed some light over this
(if my understanding of it is correct that is):
The bEOL tells us if the cursor (insert point) is at EOL. AFAIK the only
two ways we can get to EOL is to either click the mouse at the EOL
position or press the (possibly qualified) <end> key. In that case, we
really want the first fp_Run from the _next_ line, since IP is physically
(displaying) at EOL line 1, but when it inserts you insert into the
beginning of line 2, therefore we should return x&y for the first fp_Run
at line 2. I hope this makes sense and is correct.
As for the loops except the first one I can (almost) only guess. Can it
be that it doesn't trust that the runs have their internal notion about
size/position correct, and lookupProperties() "updates" the runs internal
data about it? A quick look at fp_TextRun seems to imply so.
I attach my (apparently working, at least at my site) version of
fl_BlockLayout::findPointCoords for comparison.
++Luck;
/Mike
fp_Run* fl_BlockLayout::findPointCoords(PT_DocPosition iPos,
UT_Bool bEOL,
UT_sint32& x,
UT_sint32& y,
UT_sint32& height)
{
// find the run which has this position inside it.
PT_DocPosition dPos = getPosition();
UT_ASSERT(iPos >= dPos);
if (!m_pFirstLine || !m_pFirstRun)
{
// when we have no formatting information, can't find anything
return NULL;
}
const UT_uint32 iRelOffset = iPos - dPos;
fp_Run* pRun = m_pFirstRun;
while (pRun)
{
UT_uint32 iWhere = pRun->containsOffset(iRelOffset);
if (FP_RUN_JUSTAFTER == iWhere)
{
fp_Run* pNextRun = pRun->getNext();
if (bEOL)
{
const fp_Line* pNextLine = pNextRun ?
pNextRun->getLine() : 0;
if (pNextLine != pRun->getLine())
{
pRun->findPointCoords(iRelOffset, x, y,
height);
return pRun;
}
if (pNextRun)
{
pRun->findPointCoords(iRelOffset, x, y,
height);
return pNextRun;
}
}
if (pNextRun &&
pNextRun->containsOffset(iRelOffset) == FP_RUN_INSIDE)
{
pNextRun->findPointCoords(iRelOffset, x, y, height);
return pNextRun;
}
}
if (FP_RUN_INSIDE == iWhere)
{
pRun->findPointCoords(iRelOffset, x, y, height);
return pRun;
}
pRun = pRun->getNext();
}
pRun = m_pFirstRun;
while (pRun)
{
UT_uint32 iWhere = pRun->containsOffset(iRelOffset);
if ((FP_RUN_JUSTAFTER == iWhere))
{
fp_Run* nextRun = pRun->getNext();
if (nextRun)
{
nextRun->lookupProperties();
nextRun->findPointCoords(iRelOffset, x, y, height);
}
else
{
pRun->findPointCoords(iRelOffset, x, y, height);
}
return pRun;
}
if (!pRun->getNext())
{
// this is the last run, we're not going to get another
chance, so try harder
if (iRelOffset > (pRun->getBlockOffset() + pRun->getLength()))
{
pRun->findPointCoords(iRelOffset, x, y, height);
return pRun;
}
}
pRun = pRun->getNext();
}
if (iRelOffset < m_pFirstRun->getBlockOffset())
{
m_pFirstRun->findPointCoords(iRelOffset, x, y, height);
return m_pFirstRun;
}
pRun = m_pFirstRun;
while (pRun)
{
if (pRun->canContainPoint())
{
fp_Run* nextRun = pRun->getNext();
if (nextRun)
{
nextRun->findPointCoords(iRelOffset, x, y, height);
}
else
{
pRun->findPointCoords(iRelOffset, x, y, height);
}
return pRun;
}
pRun = pRun->getNext();
}
UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
return NULL;
}