#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; }