-- Author: John Maxwell
-- Last Edited by: Maxwell, November 18, 1983 1:33 pm

DIRECTORY
	MusicDefs: FROM "MusicDefs", 
	Real USING [FixI], 
	Sheet USING [Height];

Beam: DEFINITIONS IMPORTS MusicDefs, Real, Sheet = 
BEGIN
OPEN MusicDefs;

Draw: PROCEDURE[score: ScorePTR, b: BeamPTR] RETURNS[INTEGER, INTEGER];
Drawn: PROCEDURE[score: ScorePTR, b: BeamPTR] RETURNS[BOOLEAN];

AddItem: PROCEDURE[score: ScorePTR, beam: BeamPTR, item: VariousPTR] 
	RETURNS[new: BeamPTR]; -- may need to create a new beam
RemoveItem: PROCEDURE[score: ScorePTR, beam: BeamPTR, item: VariousPTR, 
	free: BOOLEAN ← TRUE];
-- removes item from beam.  
-- If beam.length < 2 and free = TRUE, then beam is freed.

New: PROC[score: ScorePTR, length: CARDINAL, old: BeamPTR ← NIL] 
	RETURNS[beam: BeamPTR]; -- copies from old and then frees it
Free: PROC[score: ScorePTR, b: BeamPTR];
-- removes beam from anything that points to it, then frees it.

Grace: PROCEDURE[b: BeamPTR] RETURNS[BOOLEAN];
InVoice: PROCEDURE[b: BeamPTR, voice: CARDINAL] RETURNS[BOOLEAN];
SetStems: PROCEDURE[sheet: SheetPTR, b: BeamPTR];
SetSyncs: PROCEDURE[b: BeamPTR];
GetSyncs: PROCEDURE[b: BeamPTR] RETURNS[sync1, sync2: SyncPTR];
-- returns the first and last sync in the beam (may recurse down nested beams)
Sort: PROCEDURE[b: BeamPTR];

-- inline procedures

GetHeapIndex: PUBLIC PROC[heap: BeamHeapPTR, p: BeamPTR] RETURNS[CARDINAL] = INLINE 
   {FOR i: CARDINAL IN [0..heap.length) DO 
        IF heap.beam[i] = p THEN RETURN[i]; 
        ENDLOOP; 
    RETURN[heap.length]}; 

Height: PROCEDURE[sheet: SheetPTR, b: BeamPTR, time: Time] RETURNS[h: INTEGER] = INLINE
   {sync1: SyncPTR ← GetSyncs[b].sync1;
    h ← b.height+Sheet.Height[sheet, sync1.time, , b.staff];
    IF time # sync1.time THEN h ← h + Real.FixI[(time-sync1.time)*b.tilt]};

Length: PROC[b: BeamPTR] RETURNS[CARDINAL] = INLINE {RETURN[b.length]};

time: PUBLIC PROCEDURE[chord: VariousPTR] RETURNS[Time] = INLINE
   {WITH ev: chord SELECT FROM
	note   => RETURN[ev.n.sync.time];
	chord  => RETURN[ev.c.note[0].sync.time];
	beam   => {sync1: SyncPTR ← GetSyncs[ev.b].sync1; 
		RETURN[IF sync1 # NIL THEN sync1.time ELSE 0]};
	ENDCASE => ERROR};

END..