windows-nt/Source/XPSP1/NT/windows/richedit/lssrc/sobjhelp.c
2020-09-26 16:20:57 +08:00

250 lines
6.5 KiB
C

/*
* sobjhelp.c
*
* This file contains implementations of methods that help
* common simple objects handle breaking and queries. All objects
* that use these routines must as the first entry in their dobj
* structure define an SObjCommon entry which these routines
* will cast dobj's to.
*
*/
#include "lsdefs.h"
#include "lsidefs.h"
#include "plocchnk.h"
#include "pposichn.h"
#include "posichnk.h"
#include "locchnk.h"
#include "brkcond.h"
#include "pbrko.h"
#include "brko.h"
#include "lsqout.h"
#include "lsqin.h"
#include "objhelp.h"
#include "sobjhelp.h"
#include "memory.h"
#include "lsmem.h"
#include "brkkind.h"
#define GET_DUR(pdobj) (((PSOBJHELP)pdobj)->objdimAll.dur)
#define GET_OBJDIM(pdobj) (((PSOBJHELP)pdobj)->objdimAll)
#define GET_DCP(pdobj) (((PSOBJHELP)pdobj)->dcp)
#define GET_MODAFTER(pdobj) (((PSOBJHELP)pdobj)->durModAfter)
/* F I L L B R E A K O U T */
/*----------------------------------------------------------------------------
%%Function: FillBreakOut
%%Contact: ricksa
Fill break output record.
----------------------------------------------------------------------------*/
static void FillBreakOut(
PDOBJ pdobj, /* (IN): DOBJ for object */
DWORD ichnk, /* (IN): index in chunk */
PBRKOUT pbrkout) /* (OUT): break output record */
{
pbrkout->posichnk.ichnk = ichnk;
pbrkout->fSuccessful = fTrue;
pbrkout->posichnk.dcp = GET_DCP(pdobj);
pbrkout->objdim = GET_OBJDIM(pdobj);
pbrkout->objdim.dur -= GET_MODAFTER(pdobj);
}
/* S O B J T R U N C A T E C H U N K */
/*----------------------------------------------------------------------------
%%Function: SobjTruncateChunk
%%Contact: ricksa
.
----------------------------------------------------------------------------*/
LSERR WINAPI SobjTruncateChunk(
PCLOCCHNK plocchnk, /* (IN): locchnk to truncate */
PPOSICHNK posichnk) /* (OUT): truncation point */
{
long urColumnMax = plocchnk->lsfgi.urColumnMax;
long ur = plocchnk->ppointUvLoc[0].u;
PDOBJ pdobj = NULL;
DWORD i = 0;
AssertSz(plocchnk->ppointUvLoc[0].u <= urColumnMax,
"SobjTruncateChunk - pen greater than column max");
while (ur <= urColumnMax)
{
AssertSz((i < plocchnk->clschnk), "SobjTruncateChunk exceeded group of chunks");
AssertSz(plocchnk->ppointUvLoc[i].u <= urColumnMax,
"SobjTruncateChunk starting pen exceeds col max");
pdobj = plocchnk->plschnk[i].pdobj;
ur = plocchnk->ppointUvLoc[i].u + GET_DUR(pdobj);
i++;
}
/* LS does not allow the truncation point to be at the beginning of the object */
AssertSz(pdobj != NULL, "SobjTruncateChunk - pdobj NULL!");
posichnk->ichnk = i - 1;
posichnk->dcp = GET_DCP(pdobj);
return lserrNone;
}
/* S O B J F I N D P R E V B R E A K C H U N K */
/*----------------------------------------------------------------------------
%%Function: SobjFindPrevBreakChunk
%%Contact: ricksa
.
----------------------------------------------------------------------------*/
LSERR WINAPI SobjFindPrevBreakChunk(
PCLOCCHNK pclocchnk, /* (IN): locchnk to break */
PCPOSICHNK pcpoischnk, /* (IN): place to start looking for break */
BRKCOND brkcond, /* (IN): recommmendation about the break after chunk */
PBRKOUT pbrkout) /* (OUT): results of breaking */
{
PDOBJ pdobj;
DWORD ichnk = pcpoischnk->ichnk;
AssertSz((int) brkcondPlease == 0,
"SobjFindPrevBreakChunk - brcondPlease != 0");
ZeroMemory(pbrkout, sizeof(*pbrkout));
if (ichnk == ichnkOutside)
{
ichnk = pclocchnk->clschnk - 1;
pbrkout->posichnk.ichnk = ichnk;
pdobj = pclocchnk->plschnk[ichnk].pdobj;
if (GET_DUR(pdobj) - GET_MODAFTER(pdobj)
+ pclocchnk->ppointUvLoc[ichnk].u
> pclocchnk->lsfgi.urColumnMax)
{
/* Are we at beginning of chunk? */
if (ichnk > 0)
{
/* No - use the prior object in chunk */
ichnk--;
pdobj = pclocchnk->plschnk[ichnk].pdobj;
}
else
{
/* Yes. We need the break to happen before us. */
pbrkout->posichnk.ichnk = ichnk;
return lserrNone;
}
}
if (brkcond != brkcondNever)
{
/* Break at end of chunk. */
FillBreakOut(pdobj, ichnk, pbrkout);
return lserrNone;
}
/* Else break at the beginning of last part of chunk */
}
if (ichnk >= 1)
{
/* Break before the current object */
FillBreakOut(pclocchnk->plschnk[ichnk - 1].pdobj, ichnk - 1, pbrkout);
}
return lserrNone;
}
/* S O B J F I N D N E X T B R E A K C H U N K */
/*----------------------------------------------------------------------------
%%Function: SobjFindNextBreakChunk
%%Contact: ricksa
.
----------------------------------------------------------------------------*/
LSERR WINAPI SobjFindNextBreakChunk(
PCLOCCHNK pclocchnk, /* (IN): locchnk to break */
PCPOSICHNK pcpoischnk, /* (IN): place to start looking for break */
BRKCOND brkcond, /* (IN): recommmendation about the break before chunk */
PBRKOUT pbrkout) /* (OUT): results of breaking */
{
DWORD ichnk = pcpoischnk->ichnk;
AssertSz((int) brkcondPlease == 0,
"SobjFindNextBreakChunk - brcondPlease != 0");
ZeroMemory(pbrkout, sizeof(*pbrkout));
if (ichnkOutside == ichnk)
{
if (brkcondNever != brkcond)
{
pbrkout->fSuccessful = fTrue;
return lserrNone;
}
/* can't break before so break after first item in chunk */
ichnk = 0;
}
/* If not outside, we break at end of current dobj */
FillBreakOut(pclocchnk->plschnk[ichnk].pdobj, ichnk, pbrkout);
if (pclocchnk->clschnk - 1 == ichnk)
{
/* At the end of chunk. We can't say success for sure */
pbrkout->fSuccessful = fFalse;
}
return lserrNone;
}
/* S O B J F O R C E B R E A K C H U N K */
/*----------------------------------------------------------------------------
%%Function: SobjForceBreak
%%Contact: ricksa
Force Break
.
----------------------------------------------------------------------------*/
LSERR WINAPI SobjForceBreakChunk(
PCLOCCHNK pclocchnk, /* (IN): locchnk to break */
PCPOSICHNK pcposichnk, /* (IN): place to start looking for break */
PBRKOUT pbrkout) /* (OUT): results of breaking */
{
DWORD ichnk = pcposichnk->ichnk;
ZeroMemory(pbrkout, sizeof(*pbrkout));
pbrkout->posichnk.ichnk = ichnk;
if (pclocchnk->lsfgi.fFirstOnLine && (0 == ichnk))
{
FillBreakOut(pclocchnk->plschnk[ichnk].pdobj, ichnk, pbrkout);
}
else if (ichnk == ichnkOutside)
{
/* Breaking after first object */
FillBreakOut(pclocchnk->plschnk[0].pdobj, 0, pbrkout);
}
else if (ichnk != 0)
{
FillBreakOut(pclocchnk->plschnk[ichnk-1].pdobj, ichnk-1, pbrkout);
}
else /* Nothing, breaking before object */;
pbrkout->fSuccessful = fTrue; /* Force break is always successful! */
return lserrNone;
}