#include "lsdnset.h" #include "lsc.h" #include "lsdnode.h" #include "dnutils.h" #include "iobj.h" #include "ntiman.h" #include "tabutils.h" #include "getfmtst.h" #include "setfmtst.h" #include "lstext.h" #include "dninfo.h" #include "chnutils.h" #include "lssubl.h" #include "sublutil.h" #include "lscfmtfl.h" #include "iobjln.h" #include "lsmem.h" /* memset() */ #define FColinearTflows(t1, t2) \ (((t1) & fUVertical) == ((t2) & fUVertical)) /* L S D N Q U E R Y O B J D I M R A N G E */ /*---------------------------------------------------------------------------- %%Function: LsdnQueryObjDimRange %%Contact: igorzv Parameters: plsc - (IN) ptr to line services context plsdnFirst - (IN) first dnode in the range plsdnLast - (IN) last dnode in the range pobjdim - (OUT) geometry of the range ----------------------------------------------------------------------------*/ LSERR WINAPI LsdnQueryObjDimRange(PLSC plsc, PLSDNODE plsdnFirst, PLSDNODE plsdnLast, POBJDIM pobjdim) { PLSDNODE plsdn; LSERR lserr; if (pobjdim == NULL) return lserrNullOutputParameter; if (!FIsLSC(plsc)) return lserrInvalidContext; /* if client call us with empty range return right away */ if (plsdnFirst == NULL) { if (plsdnLast != NULL) return lserrInvalidDnode; memset(pobjdim, 0, sizeof(OBJDIM)); return lserrNone; } if (!FIsLSDNODE(plsdnFirst)) return lserrInvalidDnode; if (!FIsLSDNODE(plsdnLast)) return lserrInvalidDnode; if (plsdnFirst->plssubl != plsdnLast->plssubl) return lserrInvalidDnode; /* we should call NominalToIdeal if we are in formating stage and range intersects last chunk and this chunk is chunk of text*/ plsdn = plsdnLast; /* to find chunk where we are we should skip back borders */ while (plsdn != NULL && FIsDnodeBorder(plsdn)) { plsdn = plsdn->plsdnPrev; } if ((plsc->lsstate == LsStateFormatting) && FNominalToIdealEncounted(plsc) && (plsdn != NULL) && FIsDnodeReal(plsdn) && (IdObjFromDnode(plsdn) == IobjTextFromLsc(&plsc->lsiobjcontext)) ) { for(; !FIsChunkBoundary(plsdn->plsdnNext, IobjTextFromLsc(&plsc->lsiobjcontext), plsdnLast->cpFirst); plsdn=plsdn->plsdnNext); if (plsdn->plsdnNext == NULL) { lserr = ApplyNominalToIdeal(PlschunkcontextFromSubline(plsdnFirst->plssubl), &plsc->lsiobjcontext, plsc->grpfManager, plsc->lsadjustcontext.lskj, FIsSubLineMain(SublineFromDnode(plsdn)), FLineContainsAutoNumber(plsc), plsdn); if (lserr != lserrNone) return lserr; } } return FindListDims(plsdnFirst, plsdnLast, pobjdim); } /* L S D N G E T C U R T A B I N F O */ /*---------------------------------------------------------------------------- %%Function: LsdnGetCurTabInfo %%Contact: igorzv Parameters: plsc - (IN) ptr to line services context plsktab - (OUT) type of current tab Finds tab stop nearest to the current pen position and returns type of such tab stop. ----------------------------------------------------------------------------*/ LSERR WINAPI LsdnGetCurTabInfo(PLSC plsc, LSKTAB* plsktab) { PLSDNODE plsdnTab; LSTABSCONTEXT* plstabscontext; BOOL fBreakThroughTab; LSERR lserr; long urNewMargin; if (!FIsLSC(plsc)) return lserrInvalidParameter; if (!FFormattingAllowed(plsc)) return lserrFormattingFunctionDisabled; if (plsktab == NULL) return lserrInvalidParameter; plsdnTab = GetCurrentDnode(plsc); plstabscontext = &(plsc->lstabscontext); Assert(FIsLSDNODE(plsdnTab)); if (!plsdnTab->fTab) return lserrCurrentDnodeIsNotTab; Assert(FIsDnodeReal(plsdnTab)); if (plstabscontext->plsdnPendingTab != NULL) return lserrPendingTabIsNotResolved; lserr = GetCurTabInfoCore(&plsc->lstabscontext, plsdnTab, GetCurrentUr(plsc), fFalse, plsktab, &fBreakThroughTab); if (lserr != lserrNone) return lserr; TurnOnTabEncounted(plsc); if (*plsktab != lsktLeft) TurnOnNonLeftTabEncounted(plsc); /* move current pen position */ AdvanceCurrentUr(plsc, DurFromDnode(plsdnTab)); if (fBreakThroughTab) { lserr = GetMarginAfterBreakThroughTab(&plsc->lstabscontext, plsdnTab, &urNewMargin); if (lserr != lserrNone) return lserr; SetBreakthroughLine(plsc, urNewMargin); } return lserrNone; } /* L S D N R E S O L V E P R E V T A B */ /*---------------------------------------------------------------------------- %%Function: LsdnResolvePrevTab %%Contact: igorzv Parameters: plsc - (IN) ptr to line services context ----------------------------------------------------------------------------*/ LSERR WINAPI LsdnResolvePrevTab(PLSC plsc) { long dur; LSERR lserr; if (!FIsLSC(plsc)) return lserrInvalidParameter; if (!FFormattingAllowed(plsc)) return lserrFormattingFunctionDisabled; lserr = ResolvePrevTabCore(&plsc->lstabscontext, GetCurrentDnode(plsc), GetCurrentUr(plsc), &dur); if (lserr != lserrNone) return lserr; AdvanceCurrentUr(plsc, dur); return lserrNone; } /* L S D N S K I P C U R T A B */ /*---------------------------------------------------------------------------- %%Function: LsdnSkipCurTab %%Contact: igorzv Parameters: plsc - (IN) ptr to line services context ----------------------------------------------------------------------------*/ LSERR WINAPI LsdnSkipCurTab(PLSC plsc) /* IN: Pointer to LS Context */ { PLSDNODE plsdnTab; LSTABSCONTEXT* plstabscontext; if (!FIsLSC(plsc)) return lserrInvalidParameter; if (!FFormattingAllowed(plsc)) return lserrFormattingFunctionDisabled; plsdnTab = GetCurrentDnode(plsc); plstabscontext = &(plsc->lstabscontext); Assert(FIsLSDNODE(plsdnTab)); if (!plsdnTab->fTab) return lserrCurrentDnodeIsNotTab; Assert(FIsDnodeReal(plsdnTab)); if (plstabscontext->plsdnPendingTab != NULL) { CancelPendingTab(&plsc->lstabscontext); } else { AdvanceCurrentUr(plsc, - plsdnTab->u.real.objdim.dur); SetDnodeDurFmt(plsdnTab, 0); } return lserrNone; } /* L S D N S E T R I G I D D U P */ /*---------------------------------------------------------------------------- %%Function: LsdnSetRigidDup %%Contact: igorzv Parameters: plsc - (IN) ptr to line services context plsdn - (IN) dnode to be modified dup - (IN) dup to put in the dnode ----------------------------------------------------------------------------*/ LSERR WINAPI LsdnSetRigidDup(PLSC plsc, PLSDNODE plsdn, long dup) { if (!FIsLSC(plsc)) return lserrInvalidParameter; if (!FIsLSDNODE(plsdn)) return lserrInvalidParameter; if (!FFormattingAllowed(plsc)) return lserrFormattingFunctionDisabled; plsdn->fRigidDup = fTrue; if (plsdn->klsdn == klsdnReal) { plsdn->u.real.dup = dup; } else { plsdn->u.pen.dup = dup; } return lserrNone; } /* L S D N G E T D U P */ /*---------------------------------------------------------------------------- %%Function: LsdnGetDup %%Contact: igorzv Parameters: plsc - (IN) ptr to line services context plsdn - (IN) dnode queried dup - (OUT) dup of this dnode ----------------------------------------------------------------------------*/ LSERR WINAPI LsdnGetDup(PLSC plsc, PLSDNODE plsdn, long* pdup) { if (!FIsLSC(plsc)) return lserrInvalidParameter; if (!FIsLSDNODE(plsdn)) return lserrInvalidParameter; /* check that dup in dnode is valid */ if (plsdn->plssubl->fDupInvalid && !plsdn->fRigidDup) return lserrDupInvalid; *pdup = DupFromDnode(plsdn); return lserrNone; } /* L S D N R E S E T O B J D I M */ /*---------------------------------------------------------------------------- %%Function: LsdnResetObjDim %%Contact: igorzv Parameters: plsc - (IN) ptr to line services context plsdn - (IN) dnode to be modified pobjdimNew - (IN) new dimensions of the dnode ----------------------------------------------------------------------------*/ LSERR WINAPI LsdnResetObjDim(PLSC plsc, PLSDNODE plsdn, PCOBJDIM pobjdimNew) { long durOld; if (!FIsLSC(plsc)) return lserrInvalidParameter; if (!FIsLSDNODE(plsdn)) return lserrInvalidParameter; if (!FIsDnodeReal(plsdn)) return lserrInvalidParameter; /* we should be in the stage of formatting or breaking */ if (!FFormattingAllowed(plsc) && !FBreakingAllowed(plsc)) return lserrFormattingFunctionDisabled; durOld = plsdn->u.real.objdim.dur; SetDnodeObjdimFmt(plsdn, *pobjdimNew); /* update current pen position */ AdvanceCurrentUrSubl(plsdn->plssubl, (plsdn->u.real.objdim.dur - durOld)); return lserrNone; } /* L S D N R E S E T P E N N O D E */ /*---------------------------------------------------------------------------- %%Function: LsdnResetPenNode %%Contact: igorzv Parameters: plsc - (IN) ptr to line services context plsdnPen - (IN) dnode to be modified dvpPen - (IN) new dvp of the dnode durPen - (IN) new dur of the dnode dvrPen - (IN) new dvr of the dnode ----------------------------------------------------------------------------*/ LSERR WINAPI LsdnResetPenNode(PLSC plsc, PLSDNODE plsdnPen, long dvpPen, long durPen, long dvrPen) { long durOld; long dvrOld; if (!FIsLSC(plsc)) return lserrInvalidParameter; if (!FIsLSDNODE(plsdnPen)) return lserrInvalidParameter; if (!FIsDnodePen(plsdnPen)) return lserrInvalidParameter; /* we should be in the stage of formatting */ if (!FFormattingAllowed(plsc)) return lserrFormattingFunctionDisabled; if (GetDnodeToFinish(plsc) == NULL) return lserrFormattingFunctionDisabled; if (!FIsDnodeReal(GetDnodeToFinish(plsc)) ) return lserrFormattingFunctionDisabled; if (plsdnPen->plssubl != GetCurrentSubline(plsc)) return lserrInvalidParameter; durOld = plsdnPen->u.pen.dur; dvrOld = plsdnPen->u.pen.dvr; plsdnPen->u.pen.dvp = dvpPen; SetPenBorderDurFmt(plsdnPen, durPen); plsdnPen->u.pen.dvr = dvrPen; /* update current pen position */ AdvanceCurrentUr(plsc, plsdnPen->u.pen.dur - durOld); AdvanceCurrentVr(plsc, plsdnPen->u.pen.dvr - dvrOld); return lserrNone; } /* L S D N Q U E R Y N O D E */ /*---------------------------------------------------------------------------- %%Function: LsdnQueryPenNode %%Contact: igorzv Parameters: plsc - (IN) ptr to line services context plsdnPen - (IN) dnode quried pdvpPen - (OUT) dvp of the dnode pdurPen - (OUT) dur of the dnode pdvrPen - (OUT) dvr of the dnode ----------------------------------------------------------------------------*/ LSERR WINAPI LsdnQueryPenNode(PLSC plsc, PLSDNODE plsdnPen, long* pdvpPen, long* pdurPen, long* pdvrPen) { if (!FIsLSC(plsc)) return lserrInvalidParameter; if (!FIsLSDNODE(plsdnPen)) return lserrInvalidParameter; if (!FIsDnodePen(plsdnPen)) return lserrInvalidParameter; *pdvpPen = plsdnPen->u.pen.dvp; *pdurPen = plsdnPen->u.pen.dur; *pdvrPen = plsdnPen->u.pen.dvr; return lserrNone; } /* L S D N S E T A B S B A S E L I N E */ /*---------------------------------------------------------------------------- %%Function: LsdnSetAbsBaseLine %%Contact: igorzv Parameters: plsc - (IN) ptr to line services context vaAdvanceNew - (IN) new vaBase ----------------------------------------------------------------------------*/ LSERR WINAPI LsdnSetAbsBaseLine(PLSC plsc, long vaAdvanceNew) { if (!FIsLSC(plsc)) return lserrInvalidParameter; /* we should be in the stage of formatting*/ if (!FFormattingAllowed(plsc)) return lserrFormattingFunctionDisabled; plsc->plslineCur->lslinfo.fAdvanced = fTrue; plsc->plslineCur->lslinfo.vaAdvance = vaAdvanceNew; return lserrNone; } #define PlnobjFromLsc(plsc,iobj) ((Assert(FIsLSC(plsc)), PlnobjFromLsline((plsc)->plslineCur,iobj))) /* L S D N M O D I F Y P A R A E N D I N G*/ /*---------------------------------------------------------------------------- %%Function: LsdnModifyParaEnding %%Contact: igorzv Parameters: plsc - (IN) ptr to line services context lskeop - (IN) Kind of line ending ----------------------------------------------------------------------------*/ LSERR WINAPI LsdnModifyParaEnding(PLSC plsc, LSKEOP lskeop) { LSERR lserr; DWORD iobjText; PLNOBJ plnobjText; if (!FIsLSC(plsc)) return lserrInvalidParameter; /* we should be in the stage of formatting*/ if (!FFormattingAllowed(plsc)) return lserrFormattingFunctionDisabled; iobjText = IobjTextFromLsc(&plsc->lsiobjcontext); plnobjText = PlnobjFromLsc(plsc, iobjText); lserr = ModifyTextLineEnding(plnobjText, lskeop); return lserr; } /* L S D N D I S T R I B U T E */ /*---------------------------------------------------------------------------- %%Function: LsdnDistribute %%Contact: igorzv Parameters: plsc - (IN) ptr to line services context plsdnFirst - (IN) first dnode in the range plsdnFirst - (IN) last dnode in the range durToDistribute - (IN) amount to distribute between dnodes ----------------------------------------------------------------------------*/ LSERR WINAPI LsdnDistribute(PLSC plsc, PLSDNODE plsdnFirst, PLSDNODE plsdnLast, long durToDistribute) { GRCHUNKEXT grchunkext; LSERR lserr; long durToNonText; if (!FIsLSC(plsc)) return lserrInvalidParameter; if (!FIsLSDNODE(plsdnFirst)) return lserrInvalidParameter; if (!FIsLSDNODE(plsdnLast)) return lserrInvalidParameter; /* we should be in the stage of formatting or breaking*/ if (!FFormattingAllowed(plsc) && !FBreakingAllowed(plsc)) return lserrFormattingFunctionDisabled; InitGroupChunkExt(PlschunkcontextFromSubline(plsdnFirst->plssubl), IobjTextFromLsc(&plsc->lsiobjcontext), &grchunkext); /* skip first pen dnodes */ while (FIsDnodePen(plsdnFirst) && (plsdnFirst != plsdnLast)) { plsdnFirst = plsdnFirst->plsdnNext; if (plsdnFirst == NULL) /* plsdnFirst and plksdnLast are not in the same level */ return lserrInvalidParameter; } if (FIsDnodePen(plsdnFirst)) /* only pens are in the list so there is no business for us */ return lserrNone; while (FIsDnodePen(plsdnLast) && (plsdnLast != plsdnFirst)) { plsdnLast = plsdnLast->plsdnPrev; if (plsdnLast == NULL) /* plsdnFirst and plksdnLast are not in the same level */ return lserrInvalidParameter; } Assert(!FIsDnodePen(plsdnLast)); lserr = CollectTextGroupChunk(plsdnFirst, plsdnLast->cpFirst + plsdnLast->dcp, CollectSublinesNone, &grchunkext); if (lserr != lserrNone) return lserr; /* Because of rigid dup it doesn't make sense to change dur of non text objects We inforce text to distrubute everything among text by setting amount of non text to 0 */ return DistributeInText(&(grchunkext.lsgrchnk), LstflowFromSubline(SublineFromDnode(plsdnFirst)), 0, durToDistribute, &durToNonText); } /* L S D N S U B M I T S U B L I N E S */ /*---------------------------------------------------------------------------- %%Function: LsdnSubmitSublines %%Contact: igorzv Parameters: plsc - (IN) ptr to line services context plsdnode - (IN) dnode cSubline - (IN) amount of submitted sublines rgpsubl - (IN) array of submitted sublines fUseForJustification - (IN) to use for justification fUseForCompression - (IN) to use for compression fUseForDisplay - (IN) to use for display fUseForDecimalTab - (IN) to use for decimal tab fUseForTrailingArea - (IN) to use for calculating trailing area ----------------------------------------------------------------------------*/ LSERR WINAPI LsdnSubmitSublines(PLSC plsc, PLSDNODE plsdnode, DWORD cSubline, PLSSUBL* rgpsubl, BOOL fUseForJustification, BOOL fUseForCompression, BOOL fUseForDisplay, BOOL fUseForDecimalTab, BOOL fUseForTrailingArea) { DWORD i; BOOL fEmpty = fFalse; BOOL fEmptyWork; BOOL fTabOrPen = fFalse; BOOL fNotColinearTflow = fFalse; BOOL fNotSameTflow = fFalse; LSERR lserr; if (!FIsLSC(plsc)) return lserrInvalidParameter; if (!FIsLSDNODE(plsdnode)) return lserrInvalidParameter; if (!FIsDnodeReal(plsdnode)) return lserrInvalidParameter; /* we should be in the stage of formatting or breaking*/ if (!FFormattingAllowed(plsc) && !FBreakingAllowed(plsc)) return lserrFormattingFunctionDisabled; /* this procedure can be called many times for the same dnode, so we should dispose memory allocated in previous call */ if (plsdnode->u.real.pinfosubl != NULL) { if (plsdnode->u.real.pinfosubl->rgpsubl != NULL) { plsc->lscbk.pfnDisposePtr(plsc->pols, plsdnode->u.real.pinfosubl->rgpsubl); } plsc->lscbk.pfnDisposePtr(plsc->pols, plsdnode->u.real.pinfosubl); plsdnode->u.real.pinfosubl = NULL; } /* if nothing submitted return right away */ if (cSubline == 0) return lserrNone; TurnOnSubmittedSublineEncounted(plsc); /* calculate some properties of sublines to decide accept or not */ for (i = 0; i < cSubline; i++) { if (rgpsubl[i] == NULL) return lserrInvalidParameter; if (!FIsLSSUBL(rgpsubl[i])) return lserrInvalidParameter; lserr = FIsSublineEmpty(rgpsubl[i], &fEmptyWork); if (lserr != lserrNone) return lserr; if (fEmptyWork) fEmpty = fTrue; if (FAreTabsPensInSubline(rgpsubl[i])) fTabOrPen = fTrue; if (LstflowFromSubline(SublineFromDnode(plsdnode)) != LstflowFromSubline(rgpsubl[i])) fNotSameTflow = fTrue; if (!FColinearTflows(LstflowFromSubline(SublineFromDnode(plsdnode)), LstflowFromSubline(rgpsubl[i]))) fNotColinearTflow = fTrue; } plsdnode->u.real.pinfosubl = plsc->lscbk.pfnNewPtr(plsc->pols, sizeof(*(plsdnode->u.real.pinfosubl))); if (plsdnode->u.real.pinfosubl == NULL) return lserrOutOfMemory; plsdnode->u.real.pinfosubl->cSubline = cSubline; plsdnode->u.real.pinfosubl->rgpsubl = plsc->lscbk.pfnNewPtr(plsc->pols, sizeof(PLSSUBL) * cSubline); if (plsdnode->u.real.pinfosubl->rgpsubl == NULL) return lserrOutOfMemory; /* copy array of sublines */ for (i = 0; i < cSubline; i++) { plsdnode->u.real.pinfosubl->rgpsubl[i] = rgpsubl[i]; } /* set flags */ plsdnode->u.real.pinfosubl->fUseForJustification = fUseForJustification && !fEmpty && !fTabOrPen && !fNotColinearTflow ; plsdnode->u.real.pinfosubl->fUseForCompression = fUseForCompression && plsdnode->u.real.pinfosubl->fUseForJustification; /* if subline is submitted for compression it should also submitted for justification */ plsdnode->u.real.pinfosubl->fUseForTrailingArea = fUseForTrailingArea && plsdnode->u.real.pinfosubl->fUseForCompression; /* if subline is submitted for trailing area it should also be submitted for compression which implies submitting for justification */ plsdnode->u.real.pinfosubl->fUseForDisplay = fUseForDisplay && !fEmpty && !(plsc->grpfManager & fFmiDrawInCharCodes); plsdnode->u.real.pinfosubl->fUseForDecimalTab = fUseForDecimalTab && !fEmpty && !fTabOrPen; return lserrNone; } /* L S D N G E T F O R M A T D E P T H */ /*---------------------------------------------------------------------------- %%Function: LsdnGetFormatDepth %%Contact: igorzv Parameters: plsc - (IN) ptr to line services context pnDepthFormatLineMax - (OUT) maximum depth of sublines ----------------------------------------------------------------------------*/ LSERR WINAPI LsdnGetFormatDepth( PLSC plsc, /* IN: Pointer to LS Context */ DWORD* pnDepthFormatLineMax) /* OUT: nDepthFormatLineMax */ { if (!FIsLSC(plsc)) return lserrInvalidParameter; /* we should be in the stage of formatting or breaking*/ if (!FFormattingAllowed(plsc) && !FBreakingAllowed(plsc)) return lserrFormattingFunctionDisabled; Assert(FWorkWithCurrentLine(plsc)); *pnDepthFormatLineMax = plsc->plslineCur->lslinfo.nDepthFormatLineMax; return lserrNone; }