1567 lines
42 KiB
C
1567 lines
42 KiB
C
#include "lsmem.h"
|
|
#include "limits.h"
|
|
#include "lscbk.h"
|
|
#include "lsdevres.h"
|
|
#include "pdobj.h"
|
|
#include "objdim.h"
|
|
#include "plssubl.h"
|
|
#include "plsdnode.h"
|
|
#include "pilsobj.h"
|
|
#include "lscrsubl.h"
|
|
#include "lssubset.h"
|
|
#include "lsdnset.h"
|
|
#include "lsdocinf.h"
|
|
#include "lsidefs.h"
|
|
#include "fmti.h"
|
|
#include "posichnk.h"
|
|
#include "locchnk.h"
|
|
#include "lsdnfin.h"
|
|
#include "brko.h"
|
|
#include "lspap.h"
|
|
#include "plspap.h"
|
|
#include "lsqsubl.h"
|
|
#include "dispi.h"
|
|
#include "lsdssubl.h"
|
|
#include "lsems.h"
|
|
#include "lstfset.h"
|
|
#include "plnobj.h"
|
|
#include "plocchnk.h"
|
|
#include "lsimeth.h"
|
|
#include "robj.h"
|
|
#include "lsidefs.h"
|
|
#include "brkpos.h"
|
|
#include "objhelp.h"
|
|
|
|
#include "lssubset.h"
|
|
|
|
typedef enum breaksublinetype
|
|
{
|
|
breakSublineAfter,
|
|
breakSublineInside
|
|
|
|
} BREAKSUBLINETYPE;
|
|
|
|
struct ilsobj
|
|
{
|
|
POLS pols;
|
|
LSCBK lscbk;
|
|
PLSC plsc;
|
|
DWORD idobj;
|
|
LSESC lsesc;
|
|
PFNREVERSEGETINFO pfnReverseGetInfo;
|
|
PFNREVERSEENUM pfnReverseEnum;
|
|
};
|
|
|
|
|
|
typedef struct rbreakrec
|
|
{
|
|
BOOL fValid; /* Is this break record contains valid info? */
|
|
BREAKSUBLINETYPE breakSublineType; /* After / Inside */
|
|
LSCP cpBreak; /* CpLim of the break */
|
|
|
|
} RBREAKREC;
|
|
|
|
|
|
struct dobj
|
|
{
|
|
PILSOBJ pilsobj; /* ILS object */
|
|
LSTFLOW lstflowL; /* flow of line input */
|
|
LSTFLOW lstflowO; /* flow of this object */
|
|
BOOL fDoNotBreakAround; /* Break around robj as "can" */
|
|
BOOL fSuppressTrailingSpaces;
|
|
/* Kill trailing space when robj is
|
|
alone on the line & broken */
|
|
BOOL fFirstOnLine; /* If first on line -- required for
|
|
fSuppressTrailingSpaces */
|
|
PLSDNODE plsdnTop; /* Parent dnode */
|
|
LSCP cpStart; /* Starting LS cp for object */
|
|
LSCP cpStartObj; /* cp for start of object can be different
|
|
than cpStart if object is broken. */
|
|
LSCP cpFirstSubline; /* cpFirst of the subline; will be
|
|
equal to cpStart when object is broken and
|
|
equal to cpStart+1 when it isnot broken */
|
|
LSDCP dcpSubline; /* Number of characters in the subline */
|
|
|
|
LSDCP dcp; /* Number of characters in object */
|
|
PLSSUBL plssubl; /* Subline formatted RTL */
|
|
OBJDIM objdimAll; /* Objdim for entire object */
|
|
long dup; /* dup of object */
|
|
|
|
RBREAKREC breakRecord [NBreaksToSave];
|
|
|
|
/* Last 3 break records for each break */
|
|
};
|
|
|
|
static LSTFLOW rlstflowReverse[8] =
|
|
{
|
|
lstflowWS, /* Reverse lstflowES */
|
|
lstflowWN, /* Reverse lstflowEN */
|
|
lstflowNE, /* Reverse lstflowSE */
|
|
lstflowNW, /* Reverse lstflowSW */
|
|
lstflowES, /* Reverse lstflowWS */
|
|
lstflowEN, /* Reverse lstflowWN */
|
|
lstflowSE, /* Reverse lstflowNE */
|
|
lstflowSW /* Reverse lstflowNW */
|
|
};
|
|
|
|
|
|
/* R E V E R S E S A V E B R E A K R E C O R D */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: RobjSaveBreakRecord
|
|
%%Contact: antons
|
|
|
|
Save break record in DOBJ.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
static void ReverseSaveBreakRecord (
|
|
PDOBJ pdobj,
|
|
BRKKIND brkkindWhatBreak,
|
|
BREAKSUBLINETYPE breakSublineType,
|
|
LSCP cpBreak)
|
|
{
|
|
DWORD ind = GetBreakRecordIndex (brkkindWhatBreak);
|
|
|
|
pdobj->breakRecord [ind].fValid = TRUE;
|
|
pdobj->breakRecord [ind].breakSublineType = breakSublineType;
|
|
pdobj->breakRecord [ind].cpBreak = cpBreak;
|
|
}
|
|
|
|
/* R E V E R S E G E T B R E A K R E C O R D */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseGetBreakRecord
|
|
%%Contact: antons
|
|
|
|
Read break record from DOBJ.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
static void ReverseGetBreakRecord (
|
|
PDOBJ pdobj,
|
|
BRKKIND brkkindWhatBreak,
|
|
BREAKSUBLINETYPE *breakSublineType,
|
|
LSCP * pcpBreak )
|
|
{
|
|
DWORD ind = GetBreakRecordIndex (brkkindWhatBreak);
|
|
|
|
Assert (pdobj->breakRecord [ind].fValid);
|
|
|
|
*breakSublineType = pdobj->breakRecord [ind].breakSublineType;
|
|
*pcpBreak = pdobj->breakRecord [ind].cpBreak;
|
|
}
|
|
|
|
|
|
/* F R E E D O B J */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseFreeDobj
|
|
%%Contact: antons
|
|
|
|
Free all resources associated with this Reverse dobj.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
static LSERR ReverseFreeDobj(PDOBJ pdobj)
|
|
{
|
|
LSERR lserr = lserrNone;
|
|
|
|
PILSOBJ pilsobj = pdobj->pilsobj;
|
|
|
|
if (pdobj->plssubl != NULL)
|
|
{
|
|
lserr = LsDestroySubline(pdobj->plssubl);
|
|
}
|
|
|
|
pilsobj->lscbk.pfnDisposePtr(pilsobj->pols, pdobj);
|
|
|
|
return lserr;
|
|
}
|
|
|
|
/* R E V E R S E F M T F A I L E D */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseFmtFailed
|
|
%%Contact: antons
|
|
|
|
Could not create Reverse DOBJ due to error.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
static LSERR ReverseFmtFailed (PDOBJ pdobj, LSERR lserr)
|
|
{
|
|
if (pdobj != NULL) ReverseFreeDobj (pdobj); /* Works with parially-filled DOBJ */
|
|
|
|
return lserr;
|
|
}
|
|
|
|
/* T R A N S L A T E C P L I M S U B L I N E T O D C P E X T E R N A L
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: TranslateCpLimSublineToDcpExternal
|
|
%%Contact: antons
|
|
|
|
Translates position (CpLim) in the subline to dcp of
|
|
the reverse object.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
/* REVIEW (antons): Is old name OK for new behavior? */
|
|
|
|
LSDCP TranslateCpLimSublineToDcpExternal (PDOBJ pdobj, LSCP cpLim)
|
|
{
|
|
Unreferenced (pdobj);
|
|
|
|
Assert (cpLim <= pdobj->cpStart + (long) pdobj->dcp);
|
|
Assert (cpLim >= pdobj->cpStart);
|
|
|
|
Assert (pdobj->cpStart <= pdobj->cpFirstSubline);
|
|
Assert (pdobj->cpStart + pdobj->dcp >= pdobj->cpFirstSubline + pdobj->dcpSubline);
|
|
|
|
return cpLim - pdobj->cpStart;
|
|
}
|
|
|
|
/* T R A N S L A T E D C P E X T E R N A L T O C P L I M S U B L I N E
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: TranslateCpLimInternalToExternal
|
|
%%Contact: antons
|
|
|
|
Translates position (dcp) in reverse object to cpLim of
|
|
the subline.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
LSCP TranslateDcpExternalToCpLimSubline (PDOBJ pdobj, LSDCP dcp)
|
|
{
|
|
Unreferenced (pdobj);
|
|
|
|
Assert (dcp <= pdobj->dcp);
|
|
|
|
Assert (pdobj->cpStart <= pdobj->cpFirstSubline);
|
|
Assert (pdobj->cpStart + pdobj->dcp >= pdobj->cpFirstSubline + pdobj->dcpSubline);
|
|
|
|
return pdobj->cpStart + dcp;
|
|
}
|
|
|
|
|
|
/* F I N I S H B R E A K R E G U L A R */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: FinishBreakRegular
|
|
%%Contact: antons
|
|
|
|
Set up breaking information for proposed break point.
|
|
|
|
Caller must save break record by hiself!
|
|
|
|
----------------------------------------------------------------------------*/
|
|
static LSERR FinishBreakRegular (
|
|
|
|
DWORD ichnk, /* (IN): chunk id */
|
|
PDOBJ pdobj, /* (IN): object for break */
|
|
LSCP cpBreak, /* (IN): cp - break to report outside */
|
|
POBJDIM pobjdimSubline, /* (IN): objdim for subline at proposed break */
|
|
PBRKOUT pbrkout) /* (OUT): break info for Line Services */
|
|
{
|
|
Assert (ichnk != ichnkOutside);
|
|
|
|
pbrkout->fSuccessful = fTrue;
|
|
pbrkout->posichnk.dcp = TranslateCpLimSublineToDcpExternal (pdobj, cpBreak);
|
|
pbrkout->posichnk.ichnk = ichnk;
|
|
|
|
pbrkout->objdim = *pobjdimSubline;
|
|
|
|
return lserrNone;
|
|
}
|
|
|
|
/* P U T B R E A K A T E N D O F O B J E C T */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: PutBreakAtEndOfObject
|
|
%%Contact: antons
|
|
|
|
Fill in break output record for the end of the object.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
static void PutBreakAtEndOfObject (
|
|
|
|
DWORD ichnk, /* (IN): index in chunk */
|
|
PCLOCCHNK pclocchnk, /* (IN): locchnk to find break */
|
|
PBRKOUT pbrkout) /* (OUT): results of breaking */
|
|
{
|
|
PDOBJ pdobj = pclocchnk->plschnk[ichnk].pdobj;
|
|
|
|
Assert (ichnk != ichnkOutside);
|
|
|
|
pbrkout->fSuccessful = fTrue;
|
|
pbrkout->posichnk.dcp = pdobj->dcp;
|
|
pbrkout->posichnk.ichnk = ichnk;
|
|
pbrkout->objdim = pdobj->objdimAll;
|
|
}
|
|
|
|
|
|
/* P U T B R E A K B E F O R E O B J E C T */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: PutBreakBeforeObject
|
|
%%Contact: antons
|
|
|
|
Fill in break output record for break before object.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
static void PutBreakBeforeObject (
|
|
|
|
DWORD ichnk, /* (IN): index in chunk */
|
|
PCLOCCHNK pclocchnk, /* (IN): locchnk to find break */
|
|
PBRKOUT pbrkout) /* (OUT): results of breaking */
|
|
{
|
|
Unreferenced (pclocchnk);
|
|
|
|
Assert (ichnk != ichnkOutside);
|
|
|
|
pbrkout->fSuccessful = fTrue;
|
|
pbrkout->posichnk.dcp = 0;
|
|
pbrkout->posichnk.ichnk = ichnk;
|
|
|
|
ZeroMemory (&pbrkout->objdim, sizeof(pbrkout->objdim));
|
|
}
|
|
|
|
|
|
/* P U T B R E A K U N S U C C E S S F U L */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: PutBreakUnsuccessful
|
|
%%Contact: antons
|
|
|
|
Fill in break output record for unsuccessful break of ROBJ
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
static void PutBreakUnsuccessful (PDOBJ pdobj, PBRKOUT pbrkout)
|
|
{
|
|
pbrkout->fSuccessful = FALSE;
|
|
|
|
if (pdobj->fDoNotBreakAround) pbrkout->brkcond = brkcondCan;
|
|
else
|
|
pbrkout->brkcond = brkcondPlease;
|
|
|
|
}
|
|
|
|
|
|
/* I N I T D O B J */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: InitDobj
|
|
%%Contact: ricksa
|
|
|
|
Allocate and initialize DOBJ with basic information.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
static LSERR InitDobj(
|
|
PILSOBJ pilsobj, /* (IN): ilsobj */
|
|
PCFMTIN pcfmtin, /* (IN): formatting input */
|
|
PDOBJ *ppdobj) /* (OUT): initialized dobj */
|
|
{
|
|
/* Assume failure */
|
|
LSERR lserr;
|
|
|
|
PDOBJ pdobj = (PDOBJ)
|
|
pilsobj->lscbk.pfnNewPtr(pilsobj->pols, sizeof(*pdobj));
|
|
|
|
if (pdobj != NULL)
|
|
{
|
|
int iBreakRec;
|
|
|
|
ZeroMemory(pdobj, sizeof(*pdobj));
|
|
|
|
pdobj->pilsobj = pilsobj;
|
|
pdobj->cpStart = pcfmtin->lsfgi.cpFirst;
|
|
pdobj->lstflowL = pcfmtin->lsfgi.lstflow;
|
|
pdobj->lstflowO = rlstflowReverse[(int) pcfmtin->lsfgi.lstflow];
|
|
pdobj->cpStartObj = pcfmtin->lsfgi.cpFirst;
|
|
|
|
for (iBreakRec = 0; iBreakRec < NBreaksToSave; iBreakRec++)
|
|
{
|
|
pdobj->breakRecord [iBreakRec].fValid = FALSE;
|
|
};
|
|
|
|
*ppdobj = pdobj;
|
|
|
|
lserr = lserrNone;
|
|
}
|
|
else
|
|
{
|
|
lserr = lserrOutOfMemory;
|
|
}
|
|
|
|
return lserr;
|
|
}
|
|
|
|
/* F I N I S H F M T */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: FinishFmt
|
|
%%Contact: ricksa
|
|
|
|
Helper for ReverseFmt & ReverseFmtResume that completes work
|
|
for formatting.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
static LSERR FinishFmt(
|
|
PDOBJ pdobj, /* (IN): dobj for reverse */
|
|
PILSOBJ pilsobj, /* (IN): ILS object for Reverse */
|
|
PCFMTIN pcfmtin, /* (IN): formatting input */
|
|
LSCP cpFirstMain, /* (IN): cp first of reverse subline */
|
|
LSCP cpLast, /* (IN): cp output from formatting subline */
|
|
FMTRES fmtres) /* (IN): final format state */
|
|
{
|
|
LSERR lserr;
|
|
|
|
/* Set cpFirst and cpLim for reverse subline */
|
|
|
|
pdobj->cpFirstSubline = cpFirstMain;
|
|
pdobj->dcpSubline = cpLast - pdobj->cpFirstSubline;
|
|
|
|
/* Set dcp for whole object */
|
|
|
|
pdobj->dcp = cpLast - pdobj->cpStart;
|
|
|
|
if (fmtres != fmtrExceededMargin)
|
|
{
|
|
/* Note: +1 for the escape character at the end of the object. */
|
|
pdobj->dcp++;
|
|
}
|
|
|
|
lserr = LsdnSubmitSublines(pilsobj->plsc, pcfmtin->plsdnTop, 1,
|
|
&pdobj->plssubl, TRUE, FALSE, TRUE, TRUE, FALSE);
|
|
|
|
if (lserr != lserrNone) return ReverseFmtFailed (pdobj, lserr);
|
|
|
|
return LsdnFinishRegular(pilsobj->plsc, pdobj->dcp,
|
|
pcfmtin->lsfrun.plsrun, pcfmtin->lsfrun.plschp, pdobj,
|
|
&pdobj->objdimAll);
|
|
}
|
|
|
|
/* R E V E R S E C R E A T E I L S O B J */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseCreateILSObj
|
|
%%Contact: ricksa
|
|
|
|
CreateILSObj
|
|
|
|
Create the ILS object for all Reverse objects.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
LSERR WINAPI ReverseCreateILSObj(
|
|
POLS pols, /* (IN): client application context */
|
|
PLSC plsc, /* (IN): LS context */
|
|
PCLSCBK pclscbk, /* (IN): callbacks to client application */
|
|
DWORD idObj, /* (IN): id of the object */
|
|
PILSOBJ *ppilsobj) /* (OUT): object ilsobj */
|
|
{
|
|
PILSOBJ pilsobj;
|
|
REVERSEINIT reverseinit;
|
|
LSERR lserr;
|
|
|
|
*ppilsobj = NULL; /* in case of error */
|
|
|
|
/* Get initialization data */
|
|
reverseinit.dwVersion = REVERSE_VERSION;
|
|
lserr = pclscbk->pfnGetObjectHandlerInfo(pols, idObj, &reverseinit);
|
|
|
|
if (lserr != lserrNone) return lserr;
|
|
|
|
pilsobj = (PILSOBJ) pclscbk->pfnNewPtr(pols, sizeof(*pilsobj));
|
|
|
|
if (NULL == pilsobj) return lserrOutOfMemory;
|
|
|
|
pilsobj->pols = pols;
|
|
pilsobj->lscbk = *pclscbk;
|
|
pilsobj->plsc = plsc;
|
|
pilsobj->idobj = idObj;
|
|
pilsobj->lsesc.wchFirst = reverseinit.wchEndReverse;
|
|
pilsobj->lsesc.wchLast = reverseinit.wchEndReverse;
|
|
pilsobj->pfnReverseEnum = reverseinit.pfnEnum;
|
|
pilsobj->pfnReverseGetInfo = reverseinit.pfnGetRobjInfo;
|
|
|
|
*ppilsobj = pilsobj;
|
|
|
|
return lserrNone;
|
|
}
|
|
|
|
/* R E V E R S E D E S T R O Y I L S O B J */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseDestroyILSObj
|
|
%%Contact: ricksa
|
|
|
|
DestroyILSObj
|
|
|
|
Free all resources assocaiated with Reverse ILS object.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
LSERR WINAPI ReverseDestroyILSObj(
|
|
PILSOBJ pilsobj) /* (IN): object ilsobj */
|
|
{
|
|
pilsobj->lscbk.pfnDisposePtr(pilsobj->pols, pilsobj);
|
|
return lserrNone;
|
|
}
|
|
|
|
/* R E V E R S E S E T D O C */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseSetDoc
|
|
%%Contact: ricksa
|
|
|
|
SetDoc
|
|
|
|
Keep track of device information for scaling purposes.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
LSERR WINAPI ReverseSetDoc(
|
|
PILSOBJ pilsobj, /* (IN): object ilsobj */
|
|
PCLSDOCINF pclsdocinf) /* (IN): initialization data of the document level */
|
|
{
|
|
Unreferenced(pilsobj);
|
|
Unreferenced(pclsdocinf);
|
|
|
|
return lserrNone;
|
|
}
|
|
|
|
|
|
/* R E V E R S E C R E A T E L N O B J */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseCreateLNObj
|
|
%%Contact: ricksa
|
|
|
|
CreateLNObj
|
|
|
|
Create the Line Object for the Reverse. No real need for a line
|
|
object so don't allocated it.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
LSERR WINAPI ReverseCreateLNObj(
|
|
PCILSOBJ pcilsobj, /* (IN): object ilsobj */
|
|
PLNOBJ *pplnobj) /* (OUT): object lnobj */
|
|
{
|
|
*pplnobj = (PLNOBJ) pcilsobj;
|
|
|
|
return lserrNone;
|
|
}
|
|
|
|
/* R E V E R S E D E S T R O Y L N O B J */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseDestroyLNObj
|
|
%%Contact: ricksa
|
|
|
|
DestroyLNObj
|
|
|
|
Frees resources associated with the Reverse line object. Since
|
|
there isn't any this is a no-op.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
LSERR WINAPI ReverseDestroyLNObj(
|
|
PLNOBJ plnobj) /* (OUT): object lnobj */
|
|
|
|
{
|
|
Unreferenced(plnobj);
|
|
|
|
return lserrNone;
|
|
}
|
|
|
|
/* R E V E R S E F M T */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseFmt
|
|
%%Contact: ricksa
|
|
|
|
Fmt
|
|
|
|
Format the Reverse object.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
LSERR WINAPI ReverseFmt(
|
|
PLNOBJ plnobj, /* (IN): object lnobj */
|
|
PCFMTIN pcfmtin, /* (IN): formatting input */
|
|
FMTRES *pfmtres) /* (OUT): formatting result */
|
|
{
|
|
PDOBJ pdobj;
|
|
LSERR lserr;
|
|
PILSOBJ pilsobj = (PILSOBJ) plnobj;
|
|
LSCP cpStartMain = pcfmtin->lsfgi.cpFirst + 1;
|
|
LSCP cpOut;
|
|
|
|
lserr = InitDobj(pilsobj, pcfmtin, &pdobj);
|
|
|
|
// Assert (pilsobj->pfnReverseGetInfo != NULL);
|
|
|
|
if (pilsobj->pfnReverseGetInfo != NULL)
|
|
{
|
|
lserr = pilsobj->pfnReverseGetInfo (pilsobj->pols,
|
|
pcfmtin->lsfgi.cpFirst,
|
|
pcfmtin->lsfrun.plsrun,
|
|
&pdobj->fDoNotBreakAround,
|
|
&pdobj->fSuppressTrailingSpaces);
|
|
|
|
if (lserr != lserrNone) return ReverseFmtFailed (pdobj, lserr);
|
|
|
|
};
|
|
|
|
if (lserr != lserrNone) return lserrNone;
|
|
|
|
pdobj->fFirstOnLine = pcfmtin->lsfgi.fFirstOnLine;
|
|
pdobj->plsdnTop = pcfmtin->plsdnTop;
|
|
|
|
// Format the text to the maximum remaining in the column
|
|
lserr = FormatLine(pilsobj->plsc, cpStartMain,
|
|
pcfmtin->lsfgi.urColumnMax - pcfmtin->lsfgi.urPen,
|
|
pdobj->lstflowO, &pdobj->plssubl, 1, &pilsobj->lsesc,
|
|
&pdobj->objdimAll, &cpOut, NULL, NULL, pfmtres);
|
|
|
|
if (lserr != lserrNone) return ReverseFmtFailed (pdobj, lserr);
|
|
|
|
return FinishFmt(pdobj, pilsobj, pcfmtin, cpStartMain, cpOut, *pfmtres);
|
|
}
|
|
|
|
/* R E V E R S E F M T R E S U M E */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseFmtResume
|
|
%%Contact: ricksa
|
|
|
|
Fmt
|
|
|
|
Format a broken Reverse object.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
LSERR WINAPI ReverseFmtResume(
|
|
PLNOBJ plnobj, /* (IN): object lnobj */
|
|
const BREAKREC *rgBreakRecord, /* (IN): array of break records */
|
|
DWORD nBreakRecord, /* (IN): size of the break records array */
|
|
PCFMTIN pcfmtin, /* (IN): formatting input */
|
|
FMTRES *pfmtres) /* (OUT): formatting result */
|
|
{
|
|
PDOBJ pdobj;
|
|
LSERR lserr;
|
|
PILSOBJ pilsobj = (PILSOBJ) plnobj;
|
|
LSCP cpStartMain = pcfmtin->lsfgi.cpFirst;
|
|
LSCP cpOut;
|
|
|
|
lserr = InitDobj(pilsobj, pcfmtin, &pdobj);
|
|
|
|
if (lserr != lserrNone) return lserr;
|
|
|
|
/* InitDobj sets cpStartObj to start of text. Because we are resuming,
|
|
we need to set this to the real start of the object. */
|
|
|
|
pdobj->cpStartObj = rgBreakRecord->cpFirst;
|
|
|
|
// Assert (pilsobj->pfnReverseGetInfo != NULL);
|
|
|
|
if (pilsobj->pfnReverseGetInfo != NULL)
|
|
{
|
|
lserr = pilsobj->pfnReverseGetInfo (pilsobj->pols, pcfmtin->lsfgi.cpFirst,
|
|
pcfmtin->lsfrun.plsrun,
|
|
&pdobj->fDoNotBreakAround,
|
|
&pdobj->fSuppressTrailingSpaces);
|
|
|
|
if (lserr != lserrNone) return ReverseFmtFailed (pdobj, lserr);
|
|
};
|
|
|
|
pdobj->fFirstOnLine = pcfmtin->lsfgi.fFirstOnLine;
|
|
pdobj->plsdnTop = pcfmtin->plsdnTop;
|
|
|
|
/* Format the text to the maximum remaining in the column */
|
|
|
|
lserr = FormatResumedLine(pilsobj->plsc, cpStartMain,
|
|
pcfmtin->lsfgi.urColumnMax - pcfmtin->lsfgi.urPen,
|
|
pdobj->lstflowO, &pdobj->plssubl, 1, &pilsobj->lsesc,
|
|
&pdobj->objdimAll, &cpOut, NULL, NULL, pfmtres,
|
|
&rgBreakRecord[1], nBreakRecord - 1);
|
|
|
|
if (lserr != lserrNone) return ReverseFmtFailed (pdobj, lserr);
|
|
|
|
return FinishFmt(pdobj, pilsobj, pcfmtin, cpStartMain, cpOut, *pfmtres);
|
|
}
|
|
|
|
|
|
|
|
/* R E V E R S E T R U N C A T E C H U N K */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseTruncateChunk
|
|
%%Contact: ricksa
|
|
|
|
|
|
----------------------------------------------------------------------------*/
|
|
LSERR WINAPI ReverseTruncateChunk(
|
|
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;
|
|
LSCP cp;
|
|
LSERR lserr;
|
|
|
|
AssertSz(plocchnk->ppointUvLoc[0].u <= urColumnMax,
|
|
"ReverseTruncateChunk - pen greater than column max");
|
|
|
|
/* Look for chunk to truncate */
|
|
for (i = 0; ur <= urColumnMax; i++)
|
|
{
|
|
AssertSz((i < plocchnk->clschnk), "ReverseTruncateChunk exceeded group of chunks");
|
|
|
|
ur = plocchnk->ppointUvLoc[i].u;
|
|
|
|
AssertSz(ur <= urColumnMax,
|
|
"ReverseTruncateChunk - pen pos past column max");
|
|
|
|
pdobj = plocchnk->plschnk[i].pdobj;
|
|
|
|
ur += pdobj->objdimAll.dur;
|
|
}
|
|
|
|
/* Found the object where truncation is to occur */
|
|
AssertSz(pdobj != NULL, "ReverseTruncateChunk - pdobj is NULL");
|
|
|
|
/* Get the truncation point from the subline */
|
|
lserr = LsTruncateSubline(pdobj->plssubl,
|
|
urColumnMax - (ur - pdobj->objdimAll.dur), &cp);
|
|
|
|
if (lserr != lserrNone) return lserr;
|
|
|
|
/* Format return result */
|
|
|
|
posichnk->ichnk = i - 1;
|
|
|
|
posichnk->dcp = TranslateCpLimSublineToDcpExternal (pdobj, cp + 1);
|
|
|
|
return lserrNone;
|
|
}
|
|
|
|
|
|
/* R E V E R S E F I N D P R E V B R E A K C O R E*/
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseFindPrevBreakCore
|
|
%%Contact: antons
|
|
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
LSERR ReverseFindPrevBreakCore (
|
|
|
|
PCLOCCHNK pclocchnk, /* (IN): locchnk to break */
|
|
DWORD ichnk, /* (IN): object to start looking for break */
|
|
BOOL fDcpOutside, /* (IN): when true, start looking from outside */
|
|
LSDCP dcp, /* (IN): starting dcp; valid only when fDcpOutside=False */
|
|
BRKCOND brkcond, /* (IN): recommmendation about the break before ichnk */
|
|
PBRKOUT pbrkout) /* (OUT): result of breaking */
|
|
{
|
|
LSERR lserr;
|
|
PDOBJ pdobj = pclocchnk->plschnk[ichnk].pdobj;
|
|
|
|
if (fDcpOutside)
|
|
{
|
|
if ( brkcond != brkcondNever &&
|
|
! (pdobj->fDoNotBreakAround && brkcond == brkcondCan) )
|
|
{
|
|
/* Can break after ichnk */
|
|
|
|
PutBreakAtEndOfObject(ichnk, pclocchnk, pbrkout);
|
|
ReverseSaveBreakRecord (pdobj, brkkindPrev, breakSublineAfter, pdobj->cpStart + pdobj->dcp);
|
|
return lserrNone;
|
|
}
|
|
else
|
|
{
|
|
/* Try to break ichnk */
|
|
|
|
return ReverseFindPrevBreakCore ( pclocchnk,
|
|
ichnk,
|
|
fFalse,
|
|
pclocchnk->plschnk[ichnk].dcp - 1,
|
|
brkcond,
|
|
pbrkout );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
LSCP cpTruncateSubline = TranslateDcpExternalToCpLimSubline (pdobj, dcp - 1);
|
|
BOOL fSuccessful;
|
|
LSCP cpBreak;
|
|
OBJDIM objdimSubline;
|
|
BRKPOS brkpos;
|
|
|
|
Assert (dcp >= 1 && dcp <= pdobj->dcp);
|
|
|
|
/* REVIEW (antons): I do not think that passing pclocchnk->lsfgi.urColumnMax is correct... */
|
|
/* need to be confirmed with IgorZv */
|
|
|
|
lserr = LsFindPrevBreakSubline (
|
|
pdobj->plssubl,
|
|
pclocchnk->lsfgi.fFirstOnLine,
|
|
cpTruncateSubline,
|
|
pclocchnk->lsfgi.urColumnMax,
|
|
&fSuccessful,
|
|
&cpBreak,
|
|
&objdimSubline,
|
|
&brkpos);
|
|
|
|
if (lserr != lserrNone) return lserr;
|
|
|
|
/* 1. Unsuccessful or break before first DNode */
|
|
|
|
if (!fSuccessful || (fSuccessful && brkpos == brkposBeforeFirstDnode))
|
|
{
|
|
if (ichnk == 0)
|
|
{
|
|
/* First in the chunk => return UnSuccessful */
|
|
|
|
PutBreakUnsuccessful (pdobj, pbrkout);
|
|
return lserrNone;
|
|
}
|
|
|
|
else
|
|
{
|
|
/* Break between objects */
|
|
|
|
if (pdobj->fDoNotBreakAround)
|
|
{
|
|
return ReverseFindPrevBreakCore ( pclocchnk,
|
|
ichnk - 1,
|
|
fTrue,
|
|
0,
|
|
brkcondCan,
|
|
pbrkout );
|
|
}
|
|
else
|
|
{
|
|
pdobj = pclocchnk->plschnk[ichnk-1].pdobj;
|
|
|
|
PutBreakAtEndOfObject(ichnk - 1, pclocchnk, pbrkout);
|
|
ReverseSaveBreakRecord (
|
|
pclocchnk->plschnk[ichnk-1].pdobj,
|
|
brkkindPrev,
|
|
breakSublineAfter, pdobj->cpStart + pdobj->dcp);
|
|
return lserrNone;
|
|
};
|
|
|
|
};
|
|
}
|
|
|
|
/* 2. Successful break after last DNode */
|
|
|
|
else if (brkpos == brkposAfterLastDnode)
|
|
{
|
|
if (brkcond == brkcondNever) /* Can not reset dcp */
|
|
{
|
|
|
|
/* We are not allowed to break "after", */
|
|
/* so we are trying another previous break if possible */
|
|
|
|
return ReverseFindPrevBreakCore ( pclocchnk,
|
|
ichnk,
|
|
fFalse,
|
|
dcp-1,
|
|
brkcondCan,
|
|
pbrkout );
|
|
}
|
|
|
|
else /* Can reset dcp */
|
|
{
|
|
|
|
/* We reset dcp of the break so it happends after object but in break
|
|
record we remember that we should call SetBreakSubline with brkkindPrev */
|
|
|
|
ReverseSaveBreakRecord ( pdobj, brkkindPrev, breakSublineInside,
|
|
pdobj->cpStart + pdobj->dcp );
|
|
|
|
return FinishBreakRegular ( ichnk,
|
|
pdobj,
|
|
pdobj->cpStart + pdobj->dcp,
|
|
& objdimSubline,
|
|
pbrkout );
|
|
} ;
|
|
}
|
|
else
|
|
{
|
|
/* 3. Successful break inside subline */
|
|
|
|
ReverseSaveBreakRecord (pdobj, brkkindPrev, breakSublineInside,
|
|
cpBreak );
|
|
|
|
return FinishBreakRegular ( ichnk,
|
|
pdobj,
|
|
cpBreak,
|
|
&objdimSubline,
|
|
pbrkout );
|
|
};
|
|
};
|
|
|
|
}
|
|
|
|
|
|
/* R E V E R S E F I N D P R E V B R E A K C H U N K */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseFindPrevBreakChunk
|
|
%%Contact: antons
|
|
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
LSERR WINAPI ReverseFindPrevBreakChunk (
|
|
|
|
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 */
|
|
{
|
|
|
|
if (pcpoischnk->ichnk == ichnkOutside)
|
|
{
|
|
return ReverseFindPrevBreakCore ( pclocchnk,
|
|
pclocchnk->clschnk - 1,
|
|
fTrue,
|
|
0,
|
|
brkcond,
|
|
pbrkout );
|
|
}
|
|
else
|
|
{
|
|
return ReverseFindPrevBreakCore ( pclocchnk,
|
|
pcpoischnk->ichnk,
|
|
fFalse,
|
|
pcpoischnk->dcp,
|
|
brkcondPlease,
|
|
pbrkout );
|
|
};
|
|
}
|
|
|
|
|
|
/* R E V E R S E F I N D N E X T B R E A K C O R E*/
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseFindNextBreakCore
|
|
%%Contact: antons
|
|
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
LSERR ReverseFindNextBreakCore (
|
|
|
|
PCLOCCHNK pclocchnk, /* (IN): locchnk to break */
|
|
DWORD ichnk, /* (IN): object to start looking for break */
|
|
BOOL fDcpOutside, /* (IN): when true, start looking from outside */
|
|
LSDCP dcp, /* (IN): starting dcp; valid only when fDcpOutside=False */
|
|
BRKCOND brkcond, /* (IN): recommmendation about the break before ichnk */
|
|
PBRKOUT pbrkout ) /* (OUT): result of breaking */
|
|
{
|
|
LSERR lserr;
|
|
PDOBJ pdobj = pclocchnk->plschnk[ichnk].pdobj;
|
|
|
|
if (fDcpOutside)
|
|
{
|
|
if ( brkcond != brkcondNever &&
|
|
! (pdobj->fDoNotBreakAround && brkcond == brkcondCan) )
|
|
{
|
|
/* Can break before ichnk */
|
|
|
|
PutBreakBeforeObject (ichnk, pclocchnk, pbrkout);
|
|
return lserrNone;
|
|
}
|
|
else
|
|
{
|
|
/* Try to break ichnk */
|
|
|
|
return ReverseFindNextBreakCore (pclocchnk, ichnk, fFalse, 1, brkcond, pbrkout );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Dcp is inside ichnk */
|
|
|
|
LSCP cpTruncateSubline = TranslateDcpExternalToCpLimSubline (pdobj, dcp - 1);
|
|
BOOL fSuccessful;
|
|
LSCP cpBreak;
|
|
OBJDIM objdimSubline;
|
|
BRKPOS brkpos;
|
|
|
|
Assert (dcp >= 1 && dcp <= pdobj->dcp);
|
|
|
|
|
|
/* REVIEW (antons): I do not think that passing pclocchnk->lsfgi.urColumnMax is correct... */
|
|
/* need to be confirmed with IgorZv */
|
|
|
|
lserr = LsFindNextBreakSubline (
|
|
pdobj->plssubl,
|
|
pclocchnk->lsfgi.fFirstOnLine,
|
|
cpTruncateSubline,
|
|
pclocchnk->lsfgi.urColumnMax,
|
|
&fSuccessful,
|
|
&cpBreak,
|
|
&objdimSubline,
|
|
&brkpos);
|
|
|
|
if (lserr != lserrNone) return lserr;
|
|
|
|
if (!fSuccessful)
|
|
{
|
|
/* Unsuccessful break */
|
|
|
|
if (ichnk == pclocchnk->clschnk-1) /* Last object in chunk */
|
|
{
|
|
/* Review (AntonS): Better would be take objdimSubline */
|
|
|
|
pbrkout->objdim = pclocchnk->plschnk[ichnk].pdobj->objdimAll;
|
|
|
|
PutBreakUnsuccessful (pdobj, pbrkout);
|
|
|
|
/* Break condition is not next => have to store break record */
|
|
ReverseSaveBreakRecord ( pdobj,
|
|
brkkindNext,
|
|
breakSublineAfter, pdobj->cpStart + pdobj->dcp );
|
|
return lserrNone;
|
|
}
|
|
else if (pdobj->fDoNotBreakAround)
|
|
{
|
|
/* Try to break next object */
|
|
|
|
return ReverseFindNextBreakCore (
|
|
pclocchnk,
|
|
ichnk+1,
|
|
fTrue,
|
|
0,
|
|
brkcondCan,
|
|
pbrkout );
|
|
}
|
|
else
|
|
{
|
|
/* Break after ichnk */
|
|
|
|
PutBreakAtEndOfObject(ichnk, pclocchnk, pbrkout);
|
|
|
|
ReverseSaveBreakRecord ( pclocchnk->plschnk[ichnk].pdobj,
|
|
brkkindNext,
|
|
breakSublineAfter,
|
|
pclocchnk->plschnk[ichnk].pdobj->cpStart +
|
|
pclocchnk->plschnk[ichnk].pdobj->dcp );
|
|
return lserrNone;
|
|
};
|
|
}
|
|
|
|
else if (brkpos == brkposAfterLastDnode)
|
|
{
|
|
/* Break after last dnode => reset dcp and break afetr ichnk */
|
|
|
|
ReverseSaveBreakRecord (pdobj, brkkindNext, breakSublineInside, pdobj->cpStart + pdobj->dcp);
|
|
|
|
return FinishBreakRegular ( ichnk,
|
|
pdobj,
|
|
pdobj->cpStart + pdobj->dcp,
|
|
& objdimSubline,
|
|
pbrkout );
|
|
}
|
|
|
|
else
|
|
{
|
|
/* 3. Successful break inside subline */
|
|
|
|
ReverseSaveBreakRecord (pdobj, brkkindNext, breakSublineInside, cpBreak);
|
|
|
|
return FinishBreakRegular ( ichnk,
|
|
pdobj,
|
|
cpBreak,
|
|
& objdimSubline,
|
|
pbrkout);
|
|
};
|
|
}
|
|
|
|
} /* End of ReverseFindNextBreakCore */
|
|
|
|
|
|
/* R E V E R S E F I N D N E X T B R E A K C H U N K */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseFindNextBreakChunk
|
|
%%Contact: antons
|
|
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
LSERR WINAPI ReverseFindNextBreakChunk (
|
|
|
|
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 */
|
|
{
|
|
LSERR lserr;
|
|
|
|
if (pcpoischnk->ichnk == ichnkOutside)
|
|
{
|
|
lserr = ReverseFindNextBreakCore ( pclocchnk,
|
|
0,
|
|
fTrue,
|
|
0,
|
|
brkcond,
|
|
pbrkout );
|
|
|
|
}
|
|
else
|
|
{
|
|
lserr = ReverseFindNextBreakCore ( pclocchnk,
|
|
pcpoischnk->ichnk,
|
|
fFalse,
|
|
pcpoischnk->dcp,
|
|
brkcondPlease,
|
|
pbrkout );
|
|
};
|
|
|
|
return lserr;
|
|
}
|
|
|
|
|
|
/* R E V E R S E F O R C E B R E A K C H U N K */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseForceBreak
|
|
%%Contact: antons
|
|
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
LSERR WINAPI ReverseForceBreakChunk (
|
|
|
|
PCLOCCHNK pclocchnk, /* (IN): locchnk to break */
|
|
PCPOSICHNK pcposichnkIn, /* (IN): place to start looking for break */
|
|
PBRKOUT pbrkout) /* (OUT): results of breaking */
|
|
{
|
|
|
|
POSICHNK posichnk = * pcposichnkIn;
|
|
|
|
LSERR lserr;
|
|
LSCP cpTruncateSubline;
|
|
LSCP cpBreak;
|
|
OBJDIM objdimSubline;
|
|
PDOBJ pdobj;
|
|
|
|
BRKPOS brkpos;
|
|
|
|
if (posichnk.ichnk == ichnkOutside)
|
|
{
|
|
/* When left indent is bigger then Right Margin */
|
|
posichnk.ichnk = 0;
|
|
posichnk.dcp = 1;
|
|
};
|
|
|
|
Assert (posichnk.ichnk != ichnkOutside);
|
|
|
|
pdobj = pclocchnk->plschnk[posichnk.ichnk].pdobj;
|
|
|
|
if (pclocchnk->lsfgi.fFirstOnLine && (posichnk.ichnk == 0))
|
|
{
|
|
|
|
/* Object is the first on line (can not break before) */
|
|
|
|
LSDCP dcp = posichnk.dcp;
|
|
BOOL fEmpty;
|
|
|
|
Assert (dcp >= 1 && dcp <= pdobj->dcp);
|
|
|
|
lserr = LssbFIsSublineEmpty (pdobj->plssubl, &fEmpty);
|
|
|
|
if (lserr != lserrNone) return lserr;
|
|
|
|
if (fEmpty)
|
|
{
|
|
/* Can not ForceBreak empty subline */
|
|
|
|
Assert (posichnk.ichnk == 0);
|
|
|
|
PutBreakAtEndOfObject(0, pclocchnk, pbrkout);
|
|
|
|
ReverseSaveBreakRecord ( pclocchnk->plschnk[0].pdobj,
|
|
brkkindForce,
|
|
breakSublineAfter,
|
|
pclocchnk->plschnk[0].pdobj->cpStart +
|
|
pclocchnk->plschnk[0].pdobj->dcp );
|
|
|
|
return lserrNone;
|
|
};
|
|
|
|
/* Subline is not empty => do force break */
|
|
|
|
/* REVIEW (antons): The same as in Prev & Next Break */
|
|
cpTruncateSubline = TranslateDcpExternalToCpLimSubline (pdobj, dcp - 1);
|
|
|
|
lserr = LsForceBreakSubline (
|
|
pdobj->plssubl,
|
|
pclocchnk->lsfgi.fFirstOnLine,
|
|
cpTruncateSubline,
|
|
pclocchnk->lsfgi.urColumnMax,
|
|
&cpBreak,
|
|
&objdimSubline,
|
|
&brkpos );
|
|
|
|
if (lserr != lserrNone) return lserr;
|
|
|
|
/* REVIEW (antons): Check with IgorZv that Assert is correct ;-) */
|
|
|
|
Assert (brkpos != brkposBeforeFirstDnode);
|
|
|
|
if (brkpos == brkposAfterLastDnode)
|
|
{
|
|
/* We reset dcp so that closing brace stays on the same line */
|
|
|
|
ReverseSaveBreakRecord (pdobj, brkkindForce, breakSublineInside, pdobj->cpStart + pdobj->dcp);
|
|
|
|
return FinishBreakRegular ( posichnk.ichnk,
|
|
pdobj,
|
|
pdobj->cpStart + pdobj->dcp,
|
|
&objdimSubline,
|
|
pbrkout );
|
|
}
|
|
else
|
|
{
|
|
/* "Regular" ;-) ForceBreak inside subline */
|
|
|
|
ReverseSaveBreakRecord (pdobj, brkkindForce, breakSublineInside, cpBreak);
|
|
|
|
return FinishBreakRegular ( posichnk.ichnk,
|
|
pdobj,
|
|
cpBreak,
|
|
&objdimSubline,
|
|
pbrkout );
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
/* Can break before ichnk */
|
|
|
|
PutBreakBeforeObject (posichnk.ichnk, pclocchnk, pbrkout);
|
|
|
|
/* Do not need to save break record when break "before", because it will be
|
|
translated by manager to SetBreak (previous_dnode, ImposeAfter) */
|
|
|
|
/* REVIEW (antons): It is strange that I have difference between break "before"
|
|
not-first ichnk element and break "after" not-last. And only
|
|
in the second case I remember break record */
|
|
|
|
return lserrNone;
|
|
|
|
};
|
|
|
|
} /* ReverseForceBreakChunk */
|
|
|
|
|
|
/* R E V E R S E S E T B R E A K */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseSetBreak
|
|
%%Contact: antons
|
|
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
LSERR WINAPI ReverseSetBreak(
|
|
PDOBJ pdobj, /* (IN): dobj which is broken */
|
|
BRKKIND brkkind, /* (IN): Prev / Next / Force / Impose After */
|
|
DWORD cBreakRecord, /* (IN): size of array */
|
|
BREAKREC *rgBreakRecord, /* (IN): array of break records */
|
|
DWORD *pcActualBreakRecord) /* (IN): actual number of used elements in array */
|
|
{
|
|
LSERR lserr = lserrNone;
|
|
|
|
if (cBreakRecord < 1) return lserrInsufficientBreakRecBuffer;
|
|
|
|
if (pdobj->fSuppressTrailingSpaces && pdobj->fFirstOnLine)
|
|
{
|
|
/* Robj is alone on the line => submit for trailing spaces */
|
|
|
|
if (brkkind != brkkindImposedAfter)
|
|
{
|
|
BREAKSUBLINETYPE breakSublineType;
|
|
LSCP cpBreak;
|
|
ReverseGetBreakRecord (pdobj, brkkind, &breakSublineType, &cpBreak);
|
|
|
|
if (cpBreak < (LSCP) (pdobj->cpStart + pdobj->dcp))
|
|
{
|
|
lserr = LsdnSubmitSublines(pdobj->pilsobj->plsc, pdobj->plsdnTop, 1,
|
|
&pdobj->plssubl, TRUE, TRUE, TRUE, TRUE, TRUE);
|
|
|
|
if (lserr != lserrNone) return lserr;
|
|
};
|
|
};
|
|
};
|
|
|
|
if (brkkind == brkkindImposedAfter)
|
|
{
|
|
/* Break is imposed ater DNODE */
|
|
|
|
lserr = LsSetBreakSubline ( pdobj->plssubl,
|
|
brkkindImposedAfter,
|
|
cBreakRecord-1,
|
|
& rgBreakRecord [1],
|
|
pcActualBreakRecord );
|
|
if (lserr != lserrNone) return lserr;
|
|
|
|
Assert (*pcActualBreakRecord == 0);
|
|
return lserrNone;
|
|
}
|
|
|
|
else
|
|
{
|
|
BREAKSUBLINETYPE breakSublineType;
|
|
LSCP cpBreak;
|
|
|
|
/* Result of previous Prev / Next or Force - used stored break record */
|
|
|
|
ReverseGetBreakRecord (pdobj, brkkind, &breakSublineType, &cpBreak);
|
|
|
|
Assert (breakSublineType == breakSublineAfter || breakSublineType == breakSublineInside);
|
|
|
|
if (breakSublineType == breakSublineAfter)
|
|
{
|
|
/* type = breakSublineAfter */
|
|
|
|
lserr = LsSetBreakSubline ( pdobj->plssubl,
|
|
brkkindImposedAfter,
|
|
cBreakRecord-1,
|
|
& rgBreakRecord [1],
|
|
pcActualBreakRecord );
|
|
if (lserr != lserrNone) return lserr;
|
|
|
|
Assert (*pcActualBreakRecord == 0);
|
|
return lserrNone;
|
|
}
|
|
|
|
else
|
|
{
|
|
/* type = breakSublineInside */
|
|
|
|
lserr = LsSetBreakSubline ( pdobj->plssubl,
|
|
brkkind,
|
|
cBreakRecord-1,
|
|
& rgBreakRecord [1],
|
|
pcActualBreakRecord );
|
|
if (lserr != lserrNone) return lserr;
|
|
|
|
/* Still possible to have break after object */
|
|
|
|
|
|
if (cpBreak == (LSCP) (pdobj->cpStart + pdobj->dcp))
|
|
{
|
|
Assert (*pcActualBreakRecord == 0);
|
|
return lserrNone;
|
|
}
|
|
else
|
|
{
|
|
(*pcActualBreakRecord) += 1;
|
|
|
|
rgBreakRecord[0].idobj = pdobj->pilsobj->idobj;
|
|
rgBreakRecord[0].cpFirst = pdobj->cpStartObj;
|
|
|
|
return lserrNone;
|
|
}
|
|
};
|
|
|
|
};
|
|
}
|
|
|
|
/* R E V E R S E G E T S P E C I A L E F F E C T S I N S I D E */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseGetSpecialEffectsInside
|
|
%%Contact: ricksa
|
|
|
|
GetSpecialEffectsInside
|
|
|
|
.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
LSERR WINAPI ReverseGetSpecialEffectsInside(
|
|
PDOBJ pdobj, /* (IN): dobj */
|
|
UINT *pEffectsFlags) /* (OUT): Special effects for this object */
|
|
{
|
|
return LsGetSpecialEffectsSubline(pdobj->plssubl, pEffectsFlags);
|
|
}
|
|
|
|
/* R E V E R S E C A L C P R E S E N T A T I O N */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseCalcPresentation
|
|
%%Contact: ricksa
|
|
|
|
CalcPresentation
|
|
|
|
----------------------------------------------------------------------------*/
|
|
LSERR WINAPI ReverseCalcPresentation(
|
|
PDOBJ pdobj, /* (IN): dobj */
|
|
long dup, /* (IN): dup of dobj */
|
|
LSKJUST lskjust, /* (IN): Justification type */
|
|
BOOL fLastVisibleOnLine ) /* (IN): Is this object last visible on line? */
|
|
{
|
|
LSERR lserr;
|
|
BOOL fDone;
|
|
|
|
Unreferenced (lskjust);
|
|
Unreferenced (fLastVisibleOnLine);
|
|
|
|
pdobj->dup = dup;
|
|
|
|
/* Make sure that justification line has been made ready for presentation */
|
|
lserr = LssbFDonePresSubline(pdobj->plssubl, &fDone);
|
|
|
|
if ((lserrNone == lserr) && !fDone)
|
|
{
|
|
lserr = LsMatchPresSubline(pdobj->plssubl);
|
|
}
|
|
|
|
return lserr;
|
|
}
|
|
|
|
/* R E V E R S E Q U E R Y P O I N T P C P */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseQueryPointPcp
|
|
%%Contact: ricksa
|
|
|
|
Map dup to dcp
|
|
|
|
----------------------------------------------------------------------------*/
|
|
LSERR WINAPI ReverseQueryPointPcp(
|
|
PDOBJ pdobj, /*(IN): dobj to query */
|
|
PCPOINTUV ppointuvQuery, /*(IN): query point (uQuery,vQuery) */
|
|
PCLSQIN plsqin, /*(IN): query input */
|
|
PLSQOUT plsqout) /*(OUT): query output */
|
|
{
|
|
Unreferenced(ppointuvQuery);
|
|
|
|
return CreateQueryResult(pdobj->plssubl, pdobj->dup - 1, 0, plsqin, plsqout);
|
|
}
|
|
|
|
/* R E V E R S E Q U E R Y C P P P O I N T */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseQueryCpPpoint
|
|
%%Contact: ricksa
|
|
|
|
Map dcp to dup
|
|
|
|
----------------------------------------------------------------------------*/
|
|
LSERR WINAPI ReverseQueryCpPpoint(
|
|
PDOBJ pdobj, /*(IN): dobj to query, */
|
|
LSDCP dcp, /*(IN): dcp for the query */
|
|
PCLSQIN plsqin, /*(IN): query input */
|
|
PLSQOUT plsqout) /*(OUT): query output */
|
|
{
|
|
Unreferenced(dcp);
|
|
|
|
return CreateQueryResult(pdobj->plssubl, pdobj->dup - 1, 0, plsqin, plsqout);
|
|
}
|
|
|
|
|
|
/* R E V E R S E D I S P L A Y */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseDisplay
|
|
%%Contact: ricksa
|
|
|
|
Display
|
|
|
|
This calculates the positions of the various lines for the
|
|
display and then displays them.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
LSERR WINAPI ReverseDisplay(
|
|
PDOBJ pdobj,
|
|
PCDISPIN pcdispin)
|
|
{
|
|
POINTUV pointuv;
|
|
POINT pt;
|
|
BOOL fDisplayed;
|
|
LSERR lserr = LssbFDoneDisplay(pdobj->plssubl, &fDisplayed);
|
|
|
|
if (lserr != lserrNone)
|
|
{
|
|
return lserr;
|
|
}
|
|
|
|
if (fDisplayed)
|
|
{
|
|
return lserrNone;
|
|
}
|
|
|
|
/* Calculate point to start displaying the subline. */
|
|
pointuv.u = pdobj->dup - 1;
|
|
pointuv.v = 0;
|
|
|
|
LsPointXYFromPointUV(&pcdispin->ptPen, pdobj->lstflowL, &pointuv, &pt);
|
|
|
|
/* display the Reverse line */
|
|
|
|
return LsDisplaySubline(pdobj->plssubl, &pt, pcdispin->kDispMode, pcdispin->prcClip);
|
|
|
|
}
|
|
|
|
/* R E V E R S E D E S T R O Y D O B J */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseDestroyDobj
|
|
%%Contact: ricksa
|
|
|
|
DestroyDobj
|
|
|
|
Free all resources connected with the input dobj.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
LSERR WINAPI ReverseDestroyDobj(
|
|
PDOBJ pdobj)
|
|
{
|
|
return ReverseFreeDobj(pdobj);
|
|
}
|
|
|
|
/* R E V E R S E E N U M */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: ReverseEnum
|
|
%%Contact: ricksa
|
|
|
|
Enum
|
|
|
|
Enumeration callback - passed to client.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
LSERR WINAPI ReverseEnum(
|
|
PDOBJ pdobj, /*(IN): dobj to enumerate */
|
|
PLSRUN plsrun, /*(IN): from DNODE */
|
|
PCLSCHP plschp, /*(IN): from DNODE */
|
|
LSCP cp, /*(IN): from DNODE */
|
|
LSDCP dcp, /*(IN): from DNODE */
|
|
LSTFLOW lstflow, /*(IN): text flow*/
|
|
BOOL fReverse, /*(IN): enumerate in reverse order */
|
|
BOOL fGeometryNeeded, /*(IN): */
|
|
const POINT *pt, /*(IN): starting position (top left), iff fGeometryNeeded */
|
|
PCHEIGHTS pcheights, /*(IN): from DNODE, relevant iff fGeometryNeeded */
|
|
long dupRun) /*(IN): from DNODE, relevant iff fGeometryNeeded */
|
|
{
|
|
return pdobj->pilsobj->pfnReverseEnum(pdobj->pilsobj->pols, plsrun, plschp,
|
|
cp, dcp, lstflow, fReverse, fGeometryNeeded, pt, pcheights, dupRun,
|
|
pdobj->lstflowO, pdobj->plssubl);
|
|
}
|
|
|
|
/* L S G E T R E V E R S E L S I M E T H O D S */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: LsGetReverseLsimethods
|
|
%%Contact: ricksa
|
|
|
|
Initialize object handler for client.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
LSERR WINAPI LsGetReverseLsimethods(
|
|
LSIMETHODS *plsim)
|
|
{
|
|
plsim->pfnCreateILSObj = ReverseCreateILSObj;
|
|
plsim->pfnDestroyILSObj = ReverseDestroyILSObj;
|
|
plsim->pfnSetDoc = ReverseSetDoc;
|
|
plsim->pfnCreateLNObj = ReverseCreateLNObj;
|
|
plsim->pfnDestroyLNObj = ReverseDestroyLNObj;
|
|
plsim->pfnFmt = ReverseFmt;
|
|
plsim->pfnFmtResume = ReverseFmtResume;
|
|
plsim->pfnGetModWidthPrecedingChar = ObjHelpGetModWidthChar;
|
|
plsim->pfnGetModWidthFollowingChar = ObjHelpGetModWidthChar;
|
|
plsim->pfnTruncateChunk = ReverseTruncateChunk;
|
|
plsim->pfnFindPrevBreakChunk = ReverseFindPrevBreakChunk;
|
|
plsim->pfnFindNextBreakChunk = ReverseFindNextBreakChunk;
|
|
plsim->pfnForceBreakChunk = ReverseForceBreakChunk;
|
|
plsim->pfnSetBreak = ReverseSetBreak;
|
|
plsim->pfnGetSpecialEffectsInside = ReverseGetSpecialEffectsInside;
|
|
plsim->pfnFExpandWithPrecedingChar = ObjHelpFExpandWithPrecedingChar;
|
|
plsim->pfnFExpandWithFollowingChar = ObjHelpFExpandWithFollowingChar;
|
|
plsim->pfnCalcPresentation = ReverseCalcPresentation;
|
|
plsim->pfnQueryPointPcp = ReverseQueryPointPcp;
|
|
plsim->pfnQueryCpPpoint = ReverseQueryCpPpoint;
|
|
plsim->pfnDisplay = ReverseDisplay;
|
|
plsim->pfnDestroyDObj = ReverseDestroyDobj;
|
|
plsim->pfnEnum = ReverseEnum;
|
|
return lserrNone;
|
|
}
|