Windows2003-3790/windows/richedit/lssrc/enumcore.c
2020-09-30 16:53:55 +02:00

169 lines
3.9 KiB
C

#include "enumcore.h"
#include "lsc.h"
#include "lssubl.h"
#include "heights.h"
#include "lsdnode.h"
#include "dninfo.h"
#include "lstfset.h"
static LSERR EnumerateDnode(PLSC plsc, PLSDNODE pdn, POINTUV pt, BOOL fReverse,
BOOL fGeometry, const POINT* pptOrg);
// %%Function: EnumSublineCore
// %%Contact: victork
//
/*
* Enumerates subline calling enumeration callback for pens, methods for objects.
* Provides geometry information if needed (Prepdisp should be done already in this case.)
* Notice that auto-decimal tab is enumerated as a tab before Prepdisp and as a pen after.
*/
LSERR EnumSublineCore(PLSSUBL plssubl, BOOL fReverse, BOOL fGeometry,
const POINT* pptOrg, long upLeftIndent)
{
LSERR lserr;
LSCP cpLim = plssubl->cpLimDisplay;
PLSC plsc = plssubl->plsc;
PLSDNODE pdn;
POINTUV pt = {0,0}; // init'ed to get rid of assert.
if (plssubl->plsdnFirst == NULL)
{
return lserrNone; // early exit for empty sublines
}
Assert(!fGeometry || plssubl->fDupInvalid == fFalse);
if (fReverse)
{
pdn = plssubl->plsdnFirst;
if (fGeometry)
{
pt.u = upLeftIndent;
pt.v = 0;
while (FDnodeBeforeCpLim(pdn, cpLim))
{
if (pdn->klsdn == klsdnReal)
{
pt.u += pdn->u.real.dup;
}
else
{
pt.u += pdn->u.pen.dup;
pt.v += pdn->u.pen.dvp;
}
pdn = pdn->plsdnNext;
}
}
pdn = plssubl->plsdnLastDisplay;
while (pdn != NULL)
{
if (fGeometry)
{
// pt is now after pdn, downdate it to point before
if (pdn->klsdn == klsdnReal)
{
pt.u -= pdn->u.real.dup;
}
else
{
pt.u -= pdn->u.pen.dup;
pt.v -= pdn->u.pen.dvp;
}
}
lserr = EnumerateDnode(plsc, pdn, pt, fReverse, fGeometry, pptOrg);
if (lserr != lserrNone) return lserr;
pdn = pdn->plsdnPrev;
}
}
else
{
pdn = plssubl->plsdnFirst;
pt.u = upLeftIndent;
pt.v = 0;
while (FDnodeBeforeCpLim(pdn, cpLim))
{
lserr = EnumerateDnode(plsc, pdn, pt, fReverse, fGeometry, pptOrg);
if (lserr != lserrNone) return lserr;
if (fGeometry)
{
if (pdn->klsdn == klsdnReal)
{
pt.u += pdn->u.real.dup;
}
else
{
pt.u += pdn->u.pen.dup;
pt.v += pdn->u.pen.dvp;
}
}
pdn = pdn->plsdnNext;
}
}
return lserrNone;
}
// %%Function: EnumerateDnode
// %%Contact: victork
//
static LSERR EnumerateDnode(PLSC plsc, PLSDNODE pdn, POINTUV pt, BOOL fReverse,
BOOL fGeometry, const POINT* pptOrg)
{
POINTUV ptRaised;
POINT ptXY;
LSTFLOW lstflow = pdn->plssubl->lstflow;
if (pdn->klsdn == klsdnReal)
{
if (pdn->u.real.pdobj == NULL)
{
// How could it happen:
// we substitute autodecimal tab by a pen at PrepareLineForDisplay time.
// Pens don't require plsrun, so we are fine at display.
// If Client doesn't ask for geometry, the substitution might not happen
Assert (!fGeometry);
Assert (pdn->fTab);
Assert(pdn->cpFirst < 0);
Assert(plsc->lsadjustcontext.fAutodecimalTabPresent);
return plsc->lscbk.pfnEnumPen(plsc->pols, fFalse, lstflow,
fReverse, fFalse, &ptXY, 0, 0);
}
else
{
if (fGeometry)
{
ptRaised = pt;
ptRaised.v += pdn->u.real.lschp.dvpPos;
LsPointXYFromPointUV(pptOrg, lstflow, &ptRaised, &(ptXY));
}
return (*plsc->lsiobjcontext.rgobj[pdn->u.real.lschp.idObj].lsim.pfnEnum)
(pdn->u.real.pdobj, pdn->u.real.plsrun, &(pdn->u.real.lschp), pdn->cpFirst, pdn->dcp,
lstflow, fReverse, fGeometry, &ptXY, &pdn->u.real.objdim.heightsPres, pdn->u.real.dup);
}
}
else
{
return plsc->lscbk.pfnEnumPen(plsc->pols, pdn->fBorderNode, lstflow,
fReverse, fGeometry, &ptXY, pdn->u.pen.dup, pdn->u.pen.dvp);
}
}