-- TexGlue.Mesa -- implementation of procedures in TexGlueDefs -- last written by Doug Wyatt, December 5, 1979 6:30 PM DIRECTORY TexDefs: FROM "TexDefs", TexGlueDefs: FROM "TexGlueDefs", TexMemDefs: FROM "TexMemDefs", InlineDefs: FROM "InlineDefs"; TexGlue: PROGRAM IMPORTS TexMemDefs, InlineDefs EXPORTS TexGlueDefs = BEGIN OPEN TexDefs, TexGlueDefs; -- eventually, some of these procedures should be made INLINE -- and moved to TexGlueDefs ClearFlexSums: PUBLIC PROCEDURE[sums: FlexSumsPtr] = BEGIN sums^_[[0,0,0],[0,0,0]]; END; SumFlex: PUBLIC PROCEDURE[glue: GluePtr, sums: FlexSumsPtr] = BEGIN dir: FlexDir; vec: FlexVecPtr; flex: Flex; FOR dir IN FlexDir DO vec_@sums[dir]; flex_glue.flex[dir]; vec[flex.order]_vec[flex.order]+flex.val; ENDLOOP; END; DominantFlex: PUBLIC PROCEDURE[vec: FlexVecPtr] RETURNS[Flex] = BEGIN ord: FlexOrder; FOR ord DECREASING IN FlexOrder DO IF vec[ord]#0 THEN RETURN[[order: ord, val: vec[ord]]]; ENDLOOP; RETURN[zeroFlex]; END; nullGlueSpec: GlueSpec = [refs: 0, space: 0, flex: [zeroFlex,zeroFlex]]; MakeGlue: PUBLIC PROCEDURE RETURNS[GluePtr] = BEGIN p: GluePtr_TexMemDefs.AllocMem[SIZE[GlueSpec]]; p^_nullGlueSpec; RETURN[p]; END; AddGlueLink: PUBLIC PROCEDURE[p: GluePtr] = BEGIN IF p.refs#infRefs THEN p.refs_p.refs+1; END; DelGlueLink: PUBLIC PROCEDURE[p: GluePtr] = BEGIN SELECT p.refs FROM 1 => TexMemDefs.FreeMem[p,SIZE[GlueSpec]]; -- deallocate if only 1 ref infRefs => NULL; -- glue with infinite ref count is permanent ENDCASE => p.refs_p.refs-1; -- just decrement ref count END; CommonGlueArray: TYPE = ARRAY CommonGlueType OF GlueSpec; commonGlue: POINTER TO CommonGlueArray_NIL; GlueInit: PROCEDURE = BEGIN g: CommonGlueType; p: GluePtr; fillFlex: Flex=[fill,1]; lowerfillFlex: Flex=[lowerfill,1]; filFlex: Flex=lowerfillFlex; filnegFlex: Flex=[filFlex.order,-filFlex.val]; commonGlue_TexMemDefs.AllocMem[SIZE[CommonGlueArray]]; FOR g IN CommonGlueType DO p_@commonGlue[g]; p.refs_infRefs; p.space_0 ENDLOOP; commonGlue[zero].flex_[zeroFlex,zeroFlex]; commonGlue[fill].flex_[fillFlex,zeroFlex]; commonGlue[fil].flex_[filFlex,zeroFlex]; commonGlue[filneg].flex_[filnegFlex,zeroFlex]; commonGlue[lowerfill].flex_[lowerfillFlex,lowerfillFlex]; END; CommonGlue: PUBLIC PROCEDURE[g: CommonGlueType] RETURNS[GluePtr] = BEGIN RETURN[@commonGlue[g]] END; Overfull: PUBLIC SIGNAL[excess: Dimn] = CODE; SetGlue: PUBLIC PROCEDURE[dir: FlexDir, delta: Dimn, sums: FlexSumsPtr] RETURNS[GlueSet] = BEGIN flex: Flex_DominantFlex[@sums[dir]]; v: FlexVal_flex.val; fuzz: Dimn=4; -- about a tenth of a point IF dir=shr AND flex.order=regular AND delta>v+fuzz THEN BEGIN -- overfull box SIGNAL Overfull[delta-v]; v_delta; -- so num/den=1 END; IF v=0 THEN RETURN[zeroGlueSet] ELSE RETURN[[dir: dir, order: flex.order, num: delta, den: v]]; END; FixGlue: PUBLIC PROCEDURE[glue: GluePtr, set: GlueSet] RETURNS[Dimn] = BEGIN s: Dimn_glue.space; flex: Flex_glue.flex[set.dir]; IF flex.order=set.order --AND set.num#0-- THEN BEGIN -- s_s+(set.num*flex.val)/set.den; v: FlexVal; t: LONG INTEGER; v_flex.val; IF set.dir=shr THEN v_-v; t_v; t_(t*set.num)/set.den; s_s+InlineDefs.LowHalf[t]; -- *** worry about rounding and overflow? *** END; RETURN[s]; END; GluePenalty: PUBLIC PROCEDURE[set: GlueSet] RETURNS[Penalty] = BEGIN OPEN set; t: LONG INTEGER; -- no penalty for stretching/shrinking fill glue IF order#regular THEN RETURN[0]; -- can't do anything if not flex -- and can't shrink more than shrinkability IF (dir=shr AND num>den) OR den<=0 THEN RETURN[maxPenalty]; -- for regular glue, penalty is 100*(num/den)^3 t_1000; THROUGH [1..3] DO IF t>maxPenalty THEN t_maxPenalty; t_(t*num)/den; ENDLOOP; t_(t+5)/10; IF t>maxPenalty THEN t_maxPenalty; RETURN[InlineDefs.LowHalf[t]]; END; -- initialization GlueInit; END.