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

634 lines
17 KiB
C

#include "lsmem.h"
#include "limits.h"
#include "tatenak.h"
#include "objhelp.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 "zqfromza.h"
#include "sobjhelp.h"
#include "lsdocinf.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 "dispmisc.h"
#include "lstfset.h"
#include "sobjhelp.h"
#define TATENAKAYOKO_ESC_CNT 1
struct ilsobj
{
POLS pols;
LSCBK lscbk;
PLSC plsc;
LSDEVRES lsdevres;
LSESC lsescTatenakayoko;
TATENAKAYOKOCBK tcbk; /* Callbacks to client application */
};
typedef struct SUBLINEDNODES
{
PLSDNODE plsdnStart;
PLSDNODE plsdnEnd;
} SUBLINEDNODES, *PSUBLINEDNODES;
struct dobj
{
SOBJHELP sobjhelp; /* common simple object area */
PILSOBJ pilsobj; /* ILS object */
LSCP cpStart; /* Starting LS cp for object */
LSTFLOW lstflowParent; /* text flow of the parent subline */
LSTFLOW lstflowSubline; /* text flow in Tatenakayoko Subline
(must be Rotate90 [lstflowParent] */
PLSSUBL plssubl; /* Handle to subline for Tatenakayoko */
long dvpDescentReserved; /* Part of descent reserved for client */
OBJDIM objdimT; /* Objdim of the Tatenakayoko */
/* (dupSubline, duvSubline) is vector from starting point of Tatenakayoko to */
/* the starting point of its subline in coordinate system of parent subline */
long dupSubline;
long dvpSubline;
};
static const POINTUV pointuvOrigin00 = { 0, 0 };
static const POINT pointOrigin00 = { 0, 0 };
/* F R E E D O B J */
/*----------------------------------------------------------------------------
%%Function: TatenakayokoFreeDobj
%%Contact: antons
Free all resources associated with this Tatenakayoko dobj.
----------------------------------------------------------------------------*/
static LSERR TatenakayokoFreeDobj(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;
}
/* T A T E N A K A Y O K O C R E A T E I L S O B J */
/*----------------------------------------------------------------------------
%%Function: TatenakayokoCreateILSObj
%%Contact: ricksa
CreateILSObj
Create the ILS object for all Tatenakayoko objects.
----------------------------------------------------------------------------*/
LSERR WINAPI TatenakayokoCreateILSObj(
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;
LSERR lserr;
TATENAKAYOKOINIT tatenakayokoinit;
tatenakayokoinit.dwVersion = TATENAKAYOKO_VERSION;
/* Get initialization data */
lserr = pclscbk->pfnGetObjectHandlerInfo(pols, idObj, &tatenakayokoinit);
if (lserr != lserrNone)
{
*ppilsobj = NULL;
return lserr;
}
pilsobj = pclscbk->pfnNewPtr(pols, sizeof(*pilsobj));
if (pilsobj == NULL)
{
*ppilsobj = NULL;
return lserrOutOfMemory;
}
pilsobj->pols = pols;
pilsobj->lscbk = *pclscbk;
pilsobj->plsc = plsc;
pilsobj->lsescTatenakayoko.wchFirst = tatenakayokoinit.wchEndTatenakayoko;
pilsobj->lsescTatenakayoko.wchLast = tatenakayokoinit.wchEndTatenakayoko;
pilsobj->tcbk = tatenakayokoinit.tatenakayokocbk;
*ppilsobj = pilsobj;
return lserrNone;
}
/* T A T E N A K A Y O K O D E S T R O Y I L S O B J */
/*----------------------------------------------------------------------------
%%Function: TatenakayokoDestroyILSObj
%%Contact: ricksa
DestroyILSObj
Free all resources assocaiated with Tatenakayoko ILS object.
----------------------------------------------------------------------------*/
LSERR WINAPI TatenakayokoDestroyILSObj(
PILSOBJ pilsobj) /* (IN): object ilsobj */
{
pilsobj->lscbk.pfnDisposePtr(pilsobj->pols, pilsobj);
return lserrNone;
}
/* T A T E N A K A Y O K O S E T D O C */
/*----------------------------------------------------------------------------
%%Function: TatenakayokoSetDoc
%%Contact: ricksa
SetDoc
Keep track of device information for scaling purposes.
----------------------------------------------------------------------------*/
LSERR WINAPI TatenakayokoSetDoc(
PILSOBJ pilsobj, /* (IN): object ilsobj */
PCLSDOCINF pclsdocinf) /* (IN): initialization data of the document level */
{
pilsobj->lsdevres = pclsdocinf->lsdevres;
return lserrNone;
}
/* T A T E N A K A Y O K O C R E A T E L N O B J */
/*----------------------------------------------------------------------------
%%Function: TatenakayokoCreateLNObj
%%Contact: ricksa
CreateLNObj
Create the Line Object for the Tatenakayoko. No real need for a line
object so don't allocated it.
----------------------------------------------------------------------------*/
LSERR WINAPI TatenakayokoCreateLNObj(
PCILSOBJ pcilsobj, /* (IN): object ilsobj */
PLNOBJ *pplnobj) /* (OUT): object lnobj */
{
*pplnobj = (PLNOBJ) pcilsobj;
return lserrNone;
}
/* T A T E N A K A Y O K O D E S T R O Y L N O B J */
/*----------------------------------------------------------------------------
%%Function: TatenakayokoDestroyLNObj
%%Contact: ricksa
DestroyLNObj
Frees resources associated with the Tatenakayoko line object. Since
there isn't any this is a no-op.
----------------------------------------------------------------------------*/
LSERR WINAPI TatenakayokoDestroyLNObj(
PLNOBJ plnobj) /* (OUT): object lnobj */
{
Unreferenced(plnobj);
return lserrNone;
}
/* T A T E N A K A Y O K O F M T */
/*----------------------------------------------------------------------------
%%Function: TatenakayokoFmt
%%Contact: ricksa
Fmt
Format the Tatenakayoko object.
----------------------------------------------------------------------------*/
LSERR WINAPI TatenakayokoFmt(
PLNOBJ plnobj, /* (IN): object lnobj */
PCFMTIN pcfmtin, /* (IN): formatting input */
FMTRES *pfmtres) /* (OUT): formatting result */
{
static LSTFLOW lstflowRotate90[] =
{
lstflowNE, /* [ lstflowES ] */
lstflowNW, /* [ lstflowEN ] */
lstflowEN, /* [ lstflowSE ] */
lstflowES, /* [ lstflowSW ] */
lstflowSE, /* [ lstflowWS ] */
lstflowSW, /* [ lstflowWN ] */
lstflowWN, /* [ lstflowNE ] */
lstflowWS /* [ lstflowNW ] */
};
PDOBJ pdobj;
LSERR lserr;
PILSOBJ pilsobj = (PILSOBJ) plnobj;
POLS pols = pilsobj->pols;
LSCP cpStartMain = pcfmtin->lsfgi.cpFirst + 1;
LSCP cpOut;
LSTFLOW lstflow = pcfmtin->lsfgi.lstflow;
FMTRES fmtres;
FMTRES fmtr = fmtrCompletedRun;
/*
* Allocate the DOBJ
*/
pdobj = pilsobj->lscbk.pfnNewPtr(pols, sizeof(*pdobj));
if (NULL == pdobj)
{
return lserrOutOfMemory;
}
ZeroMemory(pdobj, sizeof(*pdobj));
pdobj->pilsobj = pilsobj;
pdobj->cpStart = pcfmtin->lsfgi.cpFirst;
pdobj->lstflowParent = lstflow;
pdobj->lstflowSubline = lstflowRotate90 [lstflow];
/*
* Build main line of text
*/
lserr = FormatLine(pilsobj->plsc, cpStartMain, LONG_MAX, pdobj->lstflowSubline,
&pdobj->plssubl, TATENAKAYOKO_ESC_CNT, &pilsobj->lsescTatenakayoko,
&pdobj->objdimT, &cpOut, NULL, NULL, &fmtres);
if (lserr != lserrNone)
{
TatenakayokoFreeDobj (pdobj);
return lserr;
}
Assert (fmtres != fmtrExceededMargin);
/*
* Calculate the object dimensions.
*/
lserr = pilsobj->tcbk.pfnGetTatenakayokoLinePosition(pols, pdobj->cpStart, pdobj->lstflowParent,
pcfmtin->lsfrun.plsrun, pdobj->objdimT.dur,
&pdobj->sobjhelp.objdimAll.heightsRef,
&pdobj->sobjhelp.objdimAll.heightsPres,
&pdobj->dvpDescentReserved);
if (lserr != lserrNone)
{
TatenakayokoFreeDobj (pdobj);
return lserr;
}
/* set width of Tatenakayoko relative to text flow of line that contains it. */
pdobj->sobjhelp.objdimAll.dur = pdobj->objdimT.heightsRef.dvAscent
+ pdobj->objdimT.heightsRef.dvDescent;
/*
* Note: the + 2 in the following is because cpStartMain is + 1 from the
* actual start of the object (it is the cpStartMain of the Tatenakayoko
* data) and additional + 1 for the escape character at the end of the
* tatenakayoko.
*/
pdobj->sobjhelp.dcp = cpOut - cpStartMain + 2;
lserr = LsdnFinishRegular(pilsobj->plsc, pdobj->sobjhelp.dcp,
pcfmtin->lsfrun.plsrun, pcfmtin->lsfrun.plschp, pdobj,
&pdobj->sobjhelp.objdimAll);
if (lserr != lserrNone)
{
TatenakayokoFreeDobj (pdobj);
return lserr;
}
lserr = LsdnSetRigidDup ( pilsobj->plsc, pcfmtin->plsdnTop,
pdobj->objdimT.heightsPres.dvAscent +
pdobj->objdimT.heightsPres.dvDescent );
if (lserr != lserrNone)
{
TatenakayokoFreeDobj (pdobj);
return lserr;
}
if (pcfmtin->lsfgi.urPen + pdobj->sobjhelp.objdimAll.dur > pcfmtin->lsfgi.urColumnMax)
{
fmtr = fmtrExceededMargin;
}
*pfmtres = fmtr;
return lserrNone;
}
/* T A T E N A K A Y O K O G E T S P E C I A L E F F E C T S I N S I D E */
/*----------------------------------------------------------------------------
%%Function: TatenakayokoGetSpecialEffectsInside
%%Contact: ricksa
GetSpecialEffectsInside
.
----------------------------------------------------------------------------*/
LSERR WINAPI TatenakayokoGetSpecialEffectsInside(
PDOBJ pdobj, /* (IN): dobj */
UINT *pEffectsFlags) /* (OUT): Special effects for this object */
{
return LsGetSpecialEffectsSubline(pdobj->plssubl, pEffectsFlags);
}
/* G E T U F R O M L S T F L O W */
/*----------------------------------------------------------------------------
%%Function: GetUFromLstflow
%%Contact: antons
GetUFromLstflow
Gets XY vector corresponding to U-direction of lstflow.
----------------------------------------------------------------------------*/
void GetUFromLstflow (LSTFLOW lstflow, POINT * ppoint)
{
POINTUV ptOneU = {1, 0};
LsPointXYFromPointUV (& pointOrigin00, lstflow, &ptOneU, ppoint);
}
/* G E T V F R O M L S T F L O W */
/*----------------------------------------------------------------------------
%%Function: GetVFromLstflow
%%Contact: antons
GetVFromLstflow
Gets XY vector corresponding to V-direction of lstflow.
----------------------------------------------------------------------------*/
void GetVFromLstflow (LSTFLOW lstflow, POINT * ppoint)
{
POINTUV ptOneV = {0, 1};
LsPointXYFromPointUV (& pointOrigin00, lstflow, &ptOneV, ppoint);
}
/* T A T E N A K A Y O K O C A L C P R E S E N T A T I O N */
/*----------------------------------------------------------------------------
%%Function: TatenakayokoCalcPresentation
%%Contact: antons
CalcPresentation
This just makes the line match the calculated presentation of the line.
----------------------------------------------------------------------------*/
LSERR WINAPI TatenakayokoCalcPresentation(
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? */
{
POINTUV ptTemp;
POINTUV pointuv;
POINT ptSublineV;
POINT ptParentU;
Unreferenced (fLastVisibleOnLine);
Unreferenced (lskjust);
pdobj->dupSubline = 0;
pdobj->dvpSubline = 0;
GetUFromLstflow (pdobj->lstflowParent, &ptParentU);
GetVFromLstflow (pdobj->lstflowSubline, &ptSublineV);
/* Assert that Main U is parallel to Subline V */
Assert (ptParentU.x * ptSublineV.y - ptParentU.y * ptSublineV.x == 0);
pointuv.u = - (pdobj->sobjhelp.objdimAll.heightsPres.dvDescent
- pdobj->dvpDescentReserved);
pointuv.v = 0;
LsPointUV2FromPointUV1 (pdobj->lstflowSubline, & pointuvOrigin00, & pointuv,
pdobj->lstflowParent, & ptTemp);
pdobj->dupSubline += ptTemp.u;
pdobj->dvpSubline += ptTemp.v;
if ((ptParentU.x == ptSublineV.x) && (ptParentU.y == ptSublineV.y))
{
pdobj->dupSubline += pdobj->objdimT.heightsPres.dvDescent;
}
else
{
pdobj->dupSubline += pdobj->objdimT.heightsPres.dvAscent;
}
Unreferenced(dup);
return LsMatchPresSubline(pdobj->plssubl);
}
/* T A T E N A K A Y O K O Q U E R Y P O I N T P C P */
/*----------------------------------------------------------------------------
%%Function: TatenakayokoQueryPointPcp
%%Contact: ricksa
Map dup to dcp
This just passes the offset of the subline to the helper function
which will format the output.
----------------------------------------------------------------------------*/
LSERR WINAPI TatenakayokoQueryPointPcp(
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->dupSubline, pdobj->dvpSubline, plsqin, plsqout);
}
/* T A T E N A K A Y O K O Q U E R Y C P P P O I N T */
/*----------------------------------------------------------------------------
%%Function: TatenakayokoQueryCpPpoint
%%Contact: ricksa
Map dcp to dup
This just passes the offset of the subline to the helper function
which will format the output.
----------------------------------------------------------------------------*/
LSERR WINAPI TatenakayokoQueryCpPpoint(
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->dupSubline, pdobj->dvpSubline, plsqin, plsqout);
}
/* T A T E N A K A Y O K O D I S P L A Y */
/*----------------------------------------------------------------------------
%%Function: TatenakayokoDisplay
%%Contact: ricksa
Display
This calculates the position of the subline for the
display and then displays it.
----------------------------------------------------------------------------*/
LSERR WINAPI TatenakayokoDisplay(
PDOBJ pdobj, /*(IN): dobj to display */
PCDISPIN pcdispin) /*(IN): info for display */
{
POINT ptLine;
POINTUV ptAdd;
ptAdd.u = pdobj->dupSubline;
ptAdd.v = pdobj->dvpSubline;
LsPointXYFromPointUV(&pcdispin->ptPen, pdobj->lstflowParent, &ptAdd, &ptLine);
/* display the Tatenakayoko line */
return LsDisplaySubline(pdobj->plssubl, &ptLine, pcdispin->kDispMode,
pcdispin->prcClip);
}
/* T A T E N A K A Y O K O D E S T R O Y D O B J */
/*----------------------------------------------------------------------------
%%Function: TatenakayokoDestroyDobj
%%Contact: ricksa
DestroyDobj
Free all resources connected with the input dobj.
----------------------------------------------------------------------------*/
LSERR WINAPI TatenakayokoDestroyDobj(
PDOBJ pdobj) /*(IN): dobj to destroy */
{
return TatenakayokoFreeDobj(pdobj);
}
/* T A T E N A K A Y O K O E N U M */
/*----------------------------------------------------------------------------
%%Function: TatenakayokoEnum
%%Contact: ricksa
Enum
Enumeration callback - passed to client.
----------------------------------------------------------------------------*/
LSERR WINAPI TatenakayokoEnum(
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->tcbk.pfnTatenakayokoEnum(pdobj->pilsobj->pols, plsrun,
plschp, cp, dcp, lstflow, fReverse, fGeometryNeeded, pt, pcheights,
dupRun, pdobj->lstflowParent, pdobj->plssubl);
}
/* T A T E N A K A Y O K O H A N D L E R I N I T */
/*----------------------------------------------------------------------------
%%Function: TatenakayokoHandlerInit
%%Contact: ricksa
Initialize global Tatenakayoko data and return LSIMETHODS.
----------------------------------------------------------------------------*/
LSERR WINAPI LsGetTatenakayokoLsimethods(
LSIMETHODS *plsim)
{
plsim->pfnCreateILSObj = TatenakayokoCreateILSObj;
plsim->pfnDestroyILSObj = TatenakayokoDestroyILSObj;
plsim->pfnSetDoc = TatenakayokoSetDoc;
plsim->pfnCreateLNObj = TatenakayokoCreateLNObj;
plsim->pfnDestroyLNObj = TatenakayokoDestroyLNObj;
plsim->pfnFmt = TatenakayokoFmt;
plsim->pfnFmtResume = ObjHelpFmtResume;
plsim->pfnGetModWidthPrecedingChar = ObjHelpGetModWidthChar;
plsim->pfnGetModWidthFollowingChar = ObjHelpGetModWidthChar;
plsim->pfnTruncateChunk = SobjTruncateChunk;
plsim->pfnFindPrevBreakChunk = SobjFindPrevBreakChunk;
plsim->pfnFindNextBreakChunk = SobjFindNextBreakChunk;
plsim->pfnForceBreakChunk = SobjForceBreakChunk;
plsim->pfnSetBreak = ObjHelpSetBreak;
plsim->pfnGetSpecialEffectsInside = TatenakayokoGetSpecialEffectsInside;
plsim->pfnFExpandWithPrecedingChar = ObjHelpFExpandWithPrecedingChar;
plsim->pfnFExpandWithFollowingChar = ObjHelpFExpandWithFollowingChar;
plsim->pfnCalcPresentation = TatenakayokoCalcPresentation;
plsim->pfnQueryPointPcp = TatenakayokoQueryPointPcp;
plsim->pfnQueryCpPpoint = TatenakayokoQueryCpPpoint;
plsim->pfnDisplay = TatenakayokoDisplay;
plsim->pfnDestroyDObj = TatenakayokoDestroyDobj;
plsim->pfnEnum = TatenakayokoEnum;
return lserrNone;
}