-- TSGlue.mesa
-- Definitions pertaining to glue
-- Michael Plass,  June 17, 1982 8:26 pm

DIRECTORY
    TSTypes;

TSGlue: DEFINITIONS IMPORTS TSTypes =
BEGIN OPEN TSTypes;

-- Your basic glue
Glue: TYPE = RECORD [space: Dimn, stretch: Dimn, shrink: Dimn];
zeroGlue: Glue = [zeroDimn, zeroDimn, zeroDimn];

-- Constants for making infinite glue
fil: Dimn = [texPts: 1.0E+5];
fill: Dimn = [texPts: 1.0E+10];
filll: Dimn = [texPts: 1.0E+15];

-- Glue sums have a special representation to allow cancellation of infinite glue items without undue loss of precision.
Flex: TYPE = ARRAY [0..3] OF Dimn;
zeroFlex: Flex = [zeroDimn, zeroDimn, zeroDimn, zeroDimn];
GlueSum: TYPE = RECORD [space: Dimn, stretch: Flex, shrink: Flex];
zeroGlueSum: GlueSum = [zeroDimn, zeroFlex, zeroFlex];

AddGlue: PROCEDURE [t: GlueSum, g: Glue] RETURNS [s: GlueSum] = INLINE {
	s ← t;
	s.space.texPts ← s.space.texPts + g.space.texPts;
	SELECT ABS[g.stretch.texPts] FROM
		< fil.texPts => s.stretch[0].texPts ← s.stretch[0].texPts + g.stretch.texPts;
		< fill.texPts => s.stretch[1].texPts ← s.stretch[1].texPts + g.stretch.texPts;
		< filll.texPts => s.stretch[2].texPts ← s.stretch[2].texPts + g.stretch.texPts;
		ENDCASE => s.stretch[3].texPts ← s.stretch[3].texPts + g.stretch.texPts;
	SELECT ABS[g.shrink.texPts] FROM
		< fil.texPts => s.shrink[0].texPts ← s.shrink[0].texPts + g.shrink.texPts;
		< fill.texPts => s.shrink[1].texPts ← s.shrink[1].texPts + g.shrink.texPts;
		< filll.texPts => s.shrink[2].texPts ← s.shrink[2].texPts + g.shrink.texPts;
		ENDCASE => s.shrink[3].texPts ← s.shrink[3].texPts + g.shrink.texPts;
	};

GlueFromSum: PROCEDURE [s: GlueSum] RETURNS [Glue] = INLINE {
	RETURN[[space: s.space,
		stretch: [s.stretch[0].texPts + s.stretch[1].texPts + s.stretch[2].texPts + s.stretch[3].texPts],
		shrink: [s.shrink[0].texPts + s.shrink[1].texPts + s.shrink[2].texPts + s.shrink[3].texPts]]]
	};

GlueSet: TYPE = RECORD[value: REAL];
zeroGlueSet: GlueSet = [value: 0];
overfullGlueSet: GlueSet = [value: -1.0625];

SetGlue: PROCEDURE [desired: Dimn, g: Glue] RETURNS [GlueSet];

GlueBadness: PROCEDURE [GlueSet] RETURNS [Badness];

FixGlue: PROCEDURE [glue: Glue, set: GlueSet] RETURNS [d: Dimn] = INLINE {
	d ← IF set.value<0 THEN AddDimn[glue.space, RealDimn[set.value, glue.shrink]]
		ELSE AddDimn[glue.space, RealDimn[set.value, glue.stretch]]
	};

END.