--Author: John Maxwell --last modified: December 18, 1981 8:45 AM DIRECTORY BcplFontFileDefs USING [OpenSDFontFile, CloseSDFontFile, SplineCommandPtr,SplineDataPtr,GetSplineCommands], Beam USING [AddBeam,AddChord,AddNote,GetHeapIndex,Remove], Chord USING [GetHeapIndex,RemoveNote], Cubic USING [Bezier,BezierToCoeffs,Coeffs], Device USING [Free, Handle, Object], Graphics USING [DisplayContext, DisplayChar, DisplayString, DrawArea, DrawTo, EnterCubic, EnterPoint, FontId, FreeContext, GetPosition, Map, MoveTo, NewBoundary, NewContext, RelMoveTo, Scale, SetFont, SetLineWidth, SetColor, StartAreaPath, Texture, Translate, UserToScreen, Vec], IODefs USING [WriteLine,WriteNumber,WriteString], Memory USING [NewZone], MusicDefs, Note USING [GetBackTie], OpaqueDevice, Piece USING [Length,RemoveSync], PressDefs USING [PressFileDescriptor,PutText,SetFont], PressDevice USING [NewPressDevice], PressDeviceImpl USING [DataRef], Real USING [FixC], Score USING [], Sync USING [GetScoreIndex, Octava, RemoveNote], SystemDefs USING [AllocateHeapNode,AllocateSegment,FreeHeapNode,FreeSegment], StringDefs USING [AppendLongNumber], Utility USING [FreeBeam, FreeChord, FreeSync, SetFont]; UtilityImpl: PROGRAM IMPORTS BcplFontFileDefs, Beam, Chord, Cubic, Device, Graphics, IODefs, Memory, MusicDefs, Note, Piece, PressDefs, PressDevice, PressDeviceImpl, Real, StringDefs, Sync, SystemDefs, Utility EXPORTS MusicDefs, OpaqueDevice, Score, Utility SHARES PressDeviceImpl = BEGIN OPEN Graphics,MusicDefs; --**************************************************************************** --graphics procedures --**************************************************************************** context:PUBLIC DisplayContext; text,music:PUBLIC FontId; light:PUBLIC Graphics.Texture _ 102041B; DrawLine: PUBLIC PROCEDURE[x1,y1,x2,y2:INTEGER] = BEGIN MoveTo[context,[x1,y1]]; DrawTo[context,[x2,y2]]; END; DrawCubic:PUBLIC PROC[x1,y1,x2,y2,height:INTEGER] = BEGIN c:Cubic.Coeffs; b1,b2:Cubic.Bezier; StartAreaPath[context]; EnterPoint[context,[x1,y1]]; b1 _ [[x1,y1],[(4*x1+x2)/5,height+y1],[(x1+4*x2)/5,height+y1],[x2,y2]]; c _ Cubic.BezierToCoeffs[b1]; EnterCubic[context,@c]; EnterPoint[context,[x2,y2-width1]]; b2 _ [[x2,y2-width1],[(x1+4*x2)/5,height-width2+y1], [(4*x1+x2)/5,height-width2+y1],[x1,y1-width1]]; c _ Cubic.BezierToCoeffs[b2]; EnterCubic[context,@c]; DrawArea[context]; END; width1:INTEGER _ 0; width2:INTEGER _ 3; SetFont:PUBLIC PROCEDURE[dc:DisplayContext,font:FontId,size:INTEGER]= BEGIN OPEN PressDeviceImpl; l:REAL_1; Graphics.SetFont[dc,font,size]; IF NOT print THEN {Graphics.SetFont[dc,font,size]; RETURN}; IF printChar THEN BEGIN fontname:STRING_[16]; ph:POINTER TO PressDefs.PressFileDescriptor; ptsize,face,rotation:CARDINAL_0; ph_LOOPHOLE[device.data,PressDeviceImpl.DataRef].pressHandle; IF font=music THEN fontname_"MOCKINGBIRD" ELSE fontname_"TIMESROMAN"; ptsize _ IF font=music THEN LOOPHOLE[-24] ELSE 8; face _ 0; --PressDefs.EncodeFace['n,'n,'n] PressDefs.SetFont[ph,fontname,ptsize,face,rotation]; END ELSE BEGIN BcplFontFileDefs.CloseSDFontFile[]; IF font=music THEN BcplFontFileDefs.OpenSDFontFile["music8.sd"] ELSE BcplFontFileDefs.OpenSDFontFile["timesroman.sd"]; IF font=text THEN Scale[context,[12,12]] ELSE Scale[context,[l/12,l/12]]; END; END; DrawString:PUBLIC PROCEDURE[dc:DisplayContext,s:STRING] = BEGIN screen,pos:Vec_GetPosition[context]; IF NOT print THEN {DisplayString[dc,s]; RETURN}; IF printChar THEN { ph:POINTER TO PressDefs.PressFileDescriptor; ph_LOOPHOLE[device.data,PressDeviceImpl.DataRef].pressHandle; screen _ UserToScreen[context,pos]; IF screen.x<0 OR screen.y<0 THEN RETURN; PressDefs.PutText[ph,s,Real.FixC[screen.x],Real.FixC[screen.y]]} ELSE { FOR i:CARDINAL IN [0..s.length) DO DrawChar[dc,s[i]]; RelMoveTo[dc,[5,0]]; ENDLOOP}; END; DrawChar:PUBLIC PROCEDURE[dc:Graphics.DisplayContext,c:CHARACTER]= BEGIN screen,pos:Vec_GetPosition[context]; Move: PROC[v: POINTER TO Vec] = { NewBoundary[dc]; EnterPoint[dc,v^] }; Draw: PROC[v: POINTER TO Vec] = { EnterPoint[dc,v^] }; ECubic: PROC[c: POINTER TO Cubic.Coeffs] = { EnterCubic[dc,c] }; IF NOT print THEN BEGIN DisplayChar[dc,c]; RETURN; END; IF printChar THEN BEGIN s:STRING_[1]; ph:POINTER TO PressDefs.PressFileDescriptor; ph_LOOPHOLE[device.data,PressDeviceImpl.DataRef].pressHandle; s.length_1; s[0]_c; screen _ UserToScreen[context,pos]; IF screen.x<0 OR screen.y<0 THEN RETURN; PressDefs.PutText[ph,s,Real.FixC[screen.x],Real.FixC[screen.y]]; END ELSE BEGIN Translate[context,pos]; StartAreaPath[context,IF c='P OR c='X THEN FALSE ELSE TRUE]; DoSDChar[c,Move,Draw,ECubic]; DrawArea[context]; Translate[context,[-pos.x,-pos.y]]; END; END; ndp:BcplFontFileDefs.SplineDataPtr_NIL; ncp:BcplFontFileDefs.SplineCommandPtr_NIL; DoSDChar: PROCEDURE[char: CHARACTER, Move: PROC[v: POINTER TO Vec], Draw: PROC[v: POINTER TO Vec], DCubic: PROC[c: POINTER TO Cubic.Coeffs]] = BEGIN pos: Vec_[0,0]; tscp,scp:BcplFontFileDefs.SplineCommandPtr; sdp:BcplFontFileDefs.SplineDataPtr; IF char=154C AND ndp#NIL THEN {sdp_ndp; scp_ncp} ELSE [sdp,scp]_BcplFontFileDefs.GetSplineCommands[char, SystemDefs.AllocateHeapNode]; IF char=154C AND ndp=NIL THEN {ndp_sdp; ncp_scp}; tscp_scp; UNTIL scp=NIL DO WITH scp SELECT FROM MoveTo => {pos_[x,y]; Move[@pos]}; DrawTo => {pos_[x,y]; Draw[@pos]}; DrawCurve => { c: Cubic.Coeffs_[c3:[x2,y2],c2:[x1,y1],c1:[x0,y0],c0:pos]; DCubic[@c]; pos_[pos.x+x0+x1+x2, pos.y+y0+y1+y2]; }; NewObject => NULL; EndDefinition => EXIT; ENDCASE; scp_scp.next; ENDLOOP; IF char#154C THEN UNTIL (scp_tscp)=NIL DO tscp_scp.next; SystemDefs.FreeHeapNode[scp]; ENDLOOP; END; PointSize:PROCEDURE[n:INTEGER] RETURNS[INTEGER] = INLINE BEGIN SELECT scale FROM 1 => RETURN[n]; 2 => RETURN[2*n/3]; 4 => RETURN[n/4]; ENDCASE; RETURN[n]; END; --********************************************************** --printing the score --********************************************************** print:PUBLIC BOOLEAN_FALSE; olddc:Graphics.DisplayContext; printChar:BOOLEAN_FALSE; DeviceObject: PUBLIC TYPE = Device.Object; -- exported to OpaqueDevice device:Device.Handle; OpenPressDevice:PUBLIC PROCEDURE[splines:BOOLEAN] RETURNS[Device.Handle] = BEGIN l:REAL_1; pos:Graphics.Vec; printChar _ ~splines AND scale=2; print_TRUE; olddc_context; device_PressDevice.NewPressDevice["music.press"]; context_Graphics.NewContext[device]; pos _ Graphics.Map[olddc,context,[0,0]]; pos.x _ pos.x+8; pos.y _ pos.y+28; Graphics.Translate[context,pos]; Graphics.SetLineWidth[context,1]; IF scale=2 THEN Scale[context,[(2*l)/3,(2*l)/3]] ELSE Scale[context,[l/scale,l/scale]]; SetColor[context,[0,0,0]]; IF NOT printChar THEN { Graphics.Scale[context,[12,12]]; -- to offset bug in something BcplFontFileDefs.OpenSDFontFile["music8.sd"]; [ndp,ncp]_BcplFontFileDefs.GetSplineCommands[0154C,SystemDefs.AllocateHeapNode]}; Utility.SetFont[context,music,8]; RETURN[device]; END; ClosePressDevice:PUBLIC PROCEDURE[device:POINTER TO Device.Handle]= BEGIN tncp:BcplFontFileDefs.SplineCommandPtr; Graphics.FreeContext[@context]; Device.Free[device]; IF NOT printChar THEN BEGIN BcplFontFileDefs.CloseSDFontFile[]; UNTIL ncp=NIL DO tncp_ncp.next; SystemDefs.FreeHeapNode[ncp]; ncp _ tncp; ENDLOOP; END; context _ olddc; print_FALSE; END; --**************************************************************************** --Basic Allocation Procedures --**************************************************************************** zone:UNCOUNTED ZONE = Memory.NewZone["musicZone"]; chordHeap:PUBLIC POINTER TO ARRAY [0..maxChordHeapLength) OF ChordPTR_NIL; chordHeapLength:PUBLIC CARDINAL; beamHeap:PUBLIC POINTER TO ARRAY [0..maxBeamHeapLength) OF BeamPTR_NIL; beamHeapLength:PUBLIC CARDINAL; InitStorage:PUBLIC PROCEDURE = BEGIN i,j:CARDINAL; IF beamHeap#NIL THEN FOR i IN [0..beamHeapLength) DO IF beamHeap[i]#NIL THEN zone.FREE[@beamHeap[i]]; ENDLOOP; IF beamHeap=NIL THEN BEGIN beamHeap_ SystemDefs.AllocateSegment[maxBeamHeapLength*SIZE[BeamPTR]]; beamHeap^ _ ALL[NIL]; END; beamHeapLength _ 0; IF chordHeap#NIL THEN FOR i IN [0..chordHeapLength) DO IF chordHeap[i]#NIL THEN zone.FREE[@chordHeap[i]]; ENDLOOP; IF chordHeap=NIL THEN BEGIN chordHeap_ SystemDefs.AllocateSegment[maxChordHeapLength*SIZE[ChordPTR]]; chordHeap^ _ ALL[NIL]; END; chordHeapLength _ 0; IF score#NIL THEN FOR i IN [0..scoreLength) DO FOR j IN [0..syncLength) DO IF score[i].event[j]=NIL THEN EXIT; zone.FREE[@score[i].event[j]]; ENDLOOP; zone.FREE[@score[i]]; ENDLOOP; IF score=NIL THEN score _ NewPiece[maxScoreLength]; scoreLength _ 0; selectionLength _ 0; selection _ ALL[NIL]; END; NewPiece:PUBLIC PROCEDURE[length:CARDINAL] RETURNS[p:PiecePTR] = BEGIN p _ LOOPHOLE[SystemDefs.AllocateSegment[length*SIZE[SyncPTR]]]; FOR i:CARDINAL IN [0..length) DO p[i] _ NIL; ENDLOOP; END; FreePiece:PUBLIC PROCEDURE[p:POINTER TO PiecePTR] = BEGIN FOR i:CARDINAL DECREASING IN [0..Piece.Length[p^]) DO IF p[i]=NIL THEN LOOP; IF p[i].type=notes THEN FOR j:CARDINAL IN [0..syncLength) DO IF p[i].event[j]=NIL THEN EXIT; p[i].event[j].sync _ NIL; -- so FreeNote doesn't free p[i] p[i].event[j].tied _ FALSE; FreeNote[@p[i].event[j],p^]; ENDLOOP; FreeSync[@p[i]]; ENDLOOP; SystemDefs.FreeSegment[p^]; p^ _ NIL; END; NewSync:PUBLIC PROCEDURE RETURNS[p:SyncPTR] = BEGIN p _ zone.NEW[SyncRec]; p^ _ []; --defaults to the values listed in MusicDefs RETURN; END; FreeSync:PUBLIC PROCEDURE[s:LONG POINTER TO SyncPTR] = BEGIN IF s^.type=notes THEN FOR i:CARDINAL IN [0..syncLength) DO IF s^.event[i]=NIL THEN EXIT; IF s^.event[i]#NIL THEN ERROR; ENDLOOP; zone.FREE[s]; END; NewChord:PUBLIC PROCEDURE RETURNS[p:ChordPTR] = BEGIN p _ zone.NEW[ChordRec]; p^ _ [,0,ALL[NIL]]; chordHeap[chordHeapLength] _ p; chordHeapLength _ chordHeapLength + 1; RETURN; END; FreeChord:PUBLIC PROCEDURE[c:LONG POINTER TO ChordPTR] = BEGIN IF c.note[1]#NIL THEN {zone.FREE[c]; RETURN}; -- don't need to carefully dismantle IF c.note[0]#NIL THEN { c.note[0].chord _ NIL; IF c.note[0].beam#NIL THEN FOR i:CARDINAL IN [0..beamLength) DO IF c.note[0].beam.chord[i]#[chord[c^]] THEN LOOP; c.note[0].beam.chord[i] _ [note[c.note[0]]]; EXIT; ENDLOOP}; chordHeapLength _ chordHeapLength - 1; chordHeap[Chord.GetHeapIndex[c^]]_chordHeap[chordHeapLength]; chordHeap[chordHeapLength] _ NIL; zone.FREE[c]; END; NewBeam:PUBLIC PROCEDURE RETURNS[p:BeamPTR] = BEGIN IF beamHeapLength=maxBeamHeapLength THEN ERROR; p _ zone.NEW[BeamRec]; p^ _ [0,TRUE,0,0,NIL,NIL,NIL,0,FALSE,0,1,ALL[endOfBeam]]; beamHeap[beamHeapLength] _ p; beamHeapLength _ beamHeapLength + 1; END; FreeBeam:PUBLIC PROCEDURE[b:LONG POINTER TO BeamPTR] = BEGIN IF b.chord[1]#endOfBeam THEN {zone.FREE[b]; RETURN}; -- don't need to carefully dismantle IF b.chord[0]#endOfBeam THEN WITH ev:b.chord[0] SELECT FROM note => {ev.n.beam _ NIL; IF b.beam#NIL THEN Beam.AddNote[b.beam,ev.n]}; chord=> {FOR j:CARDINAL IN [0..chordLength) DO IF ev.c.note[j]=NIL THEN EXIT; ev.c.note[j].beam _ NIL; ENDLOOP; IF b.beam#NIL THEN Beam.AddChord[b.beam,ev.c]}; beam => {ev.b.beam _ NIL; IF b.beam#NIL THEN Beam.AddBeam[b.beam,ev.b]}; ENDCASE; IF b^.beam#NIL THEN Beam.Remove[b^.beam,NIL,NIL,b^]; beamHeapLength _ beamHeapLength -1; beamHeap[Beam.GetHeapIndex[b^]]_beamHeap[beamHeapLength]; beamHeap[beamHeapLength] _ NIL; zone.FREE[b]; END; NewNote:PUBLIC PROCEDURE RETURNS[p:NotePTR] = BEGIN p _ zone.NEW[NoteRec]; p^ _ []; --defaults to the values listed in MusicDefs RETURN; END; FreeNote:PUBLIC PROCEDURE[n:LONG POINTER TO NotePTR,p:PiecePTR] = BEGIN s:SyncPTR _ n.sync; IF n^.tied THEN Note.GetBackTie[n^].tie_NIL; IF n^.tie#NIL THEN n^.tie.tied_FALSE; IF n^.chord#NIL THEN Chord.RemoveNote[n^.chord,n^]; IF n^.beam#NIL THEN Beam.Remove[n^.beam,n^,NIL,NIL]; IF n^.sync#NIL THEN Sync.RemoveNote[n^.sync,n^]; IF s#NIL AND s.event[0]=NIL THEN { Piece.RemoveSync[p,s]; FreeSync[@s]}; zone.FREE[n]; END; --**************************************************************************** --filestats, consistency checking --**************************************************************************** FileStats:PUBLIC PROCEDURE = BEGIN OPEN IODefs, Utility; i,j:CARDINAL; memory:LONG INTEGER; highWater,notes:INTEGER _ 0; number:STRING _ [20]; WriteLine[""]; memory _ 2*maxBeamHeapLength+2*maxChordHeapLength+ 2*maxScoreLength; memory _memory+ LONG[scoreLength]*SIZE[SyncRec]; WriteString["scoreLength= "]; WriteNumber[scoreLength,[10,FALSE,TRUE,4]]; FOR i IN [0..scoreLength) DO FOR j IN [0..syncLength) DO IF score[i].event[j] =NIL THEN BEGIN highWater _ MAX[highWater,j]; EXIT; END ELSE notes _ notes + 1; ENDLOOP; ENDLOOP; memory _ memory + LONG[notes]*SIZE[NoteRec]; WriteString["; #notes= "]; WriteNumber[notes,[10,FALSE,TRUE,5]]; WriteString["; maxUsageOfSyncs= "]; WriteNumber[highWater,[10,FALSE,TRUE,2]]; WriteLine[""]; highWater _ 0; WriteString[" #chords="]; WriteNumber[chordHeapLength,[10,FALSE,TRUE,3]]; FOR i IN [0..chordHeapLength) DO FOR j IN [0..chordLength) DO IF chordHeap[i].note[j] #NIL THEN LOOP; highWater _ MAX[highWater,j]; EXIT; ENDLOOP; ENDLOOP; WriteString["; maxUsageOfChords= "]; WriteNumber[highWater,[10,FALSE,TRUE,2]]; memory _ memory + LONG[chordHeapLength]*SIZE[ChordRec]; memory _ memory + LONG[beamHeapLength]*SIZE[BeamRec]; WriteLine[""]; highWater _ 0; WriteString[" #beams ="]; WriteNumber[beamHeapLength,[10,FALSE,TRUE,3]]; FOR i IN [0..beamHeapLength) DO FOR j IN [0..beamLength) DO IF beamHeap[i].chord[j] #endOfBeam THEN LOOP; highWater _ MAX[highWater,j]; EXIT; ENDLOOP; ENDLOOP; WriteString["; maxUsageOfBeams= "]; WriteNumber[highWater,[10,FALSE,TRUE,2]]; WriteLine[""]; WriteString["sync="]; WriteNumber[SIZE[SyncRec],[10,FALSE,TRUE,2]]; WriteString["; note="]; WriteNumber[SIZE[NoteRec],[10,FALSE,TRUE,2]]; WriteString["; chord="]; WriteNumber[SIZE[ChordRec],[10,FALSE,TRUE,2]]; WriteString["; beam="]; WriteNumber[SIZE[BeamRec],[10,FALSE,TRUE,2]]; WriteString["; memory="]; StringDefs.AppendLongNumber[number,memory,10]; WriteString[number]; WriteLine[""]; END; Test:PUBLIC PROCEDURE RETURNS[BOOLEAN] = BEGIN i,j,k:CARDINAL; n:NotePTR; s:SyncPTR; lastBeam:BeamPTR_NIL; nilFound,beamFound:BOOLEAN; sync1,sync2:BOOLEAN; dataError _ FALSE; FOR i IN [0..maxScoreLength) DO IF score[i]#NIL AND i>=scoreLength THEN WriteError[sync,i,-1,"beyond scoreLength"]; IF score[i]=NIL AND iscore[i].time THEN -- WriteError[sync,i,-1,"out of place"]; IF score[i].type IN [octava1..octava2] AND Sync.Octava[Sync.Octava[score[i]]]#score[i] THEN WriteError[sync,i,-1,"=octava with no matching end."]; IF score[i].type#notes AND score[i].event[0]#NIL THEN WriteError[sync,i,-1,"measure with note attached!"]; IF score[i].type#notes THEN LOOP; IF score[i].type=notes AND score[i].event[0]=NIL THEN WriteError[sync,i,-1,"empty"]; nilFound _ FALSE; FOR j IN [0..syncLength) DO n _ score[i].event[j]; IF n#NIL AND nilFound THEN WriteError[sync,i,j,"not compact"]; IF n=NIL THEN BEGIN nilFound_TRUE; LOOP; END; IF n.sync#score[i] THEN WriteError[sync,i,j,"n.sync#score[i]"]; IF n.beam=NIL THEN LOOP; IF n.beam=lastBeam THEN LOOP; beamFound _ FALSE; FOR k IN [0..beamHeapLength) DO IF beamHeap[k]#n.beam THEN LOOP; beamFound _ TRUE; lastBeam_n.beam; EXIT; ENDLOOP; IF NOT beamFound THEN WriteError[sync,i,j,"non-existant beam"]; ENDLOOP; ENDLOOP; FOR i IN [0..maxChordHeapLength) DO IF chordHeap[i]#NIL AND i>=chordHeapLength THEN WriteError[chord,i,-1,"beyond chordHeapLength"]; IF chordHeap[i]=NIL AND i=beamHeapLength THEN WriteError[beam,i,-1,"beyond beamHeapLength"]; IF beamHeap[i]=NIL AND i BEGIN IF ev.n.beam#pointer THEN WriteError[beam,i,j,"wrong beam"]; IF ev.n.sync=pointer.sync1 THEN sync1_TRUE; IF ev.n.sync=pointer.sync2 THEN sync2_TRUE; END; chord=> BEGIN IF ev.c.note[0].sync=pointer.sync1 THEN sync1_TRUE; IF ev.c.note[0].sync=pointer.sync2 THEN sync2_TRUE; FOR k IN [0..chordLength) DO IF ev.c.note[k]=NIL THEN LOOP; IF ev.c.note[k].beam#pointer THEN WriteError[beam,i,j,"wrong beam"]; ENDLOOP; END; beam => BEGIN IF ev.b.beam#pointer THEN WriteError[beam,i,j,"wrong beam"]; IF ev.b.sync1=pointer.sync1 THEN sync1_TRUE; IF ev.b.sync2=pointer.sync2 THEN sync2_TRUE; END; ENDCASE; ENDLOOP; IF NOT sync1 THEN WriteError[beam,i,-1,"bad sync1"]; IF NOT sync2 THEN WriteError[beam,i,-1,"bad sync2"]; END; WriteError:PROCEDURE[t:Type,i,j:INTEGER,s:STRING] = BEGIN OPEN IODefs; SELECT t FROM sync => BEGIN WriteString["sync"]; WriteNumber[i,[10,FALSE,TRUE,4]]; IF j>-1 THEN BEGIN WriteString[",event"]; WriteNumber[j,[10,FALSE,TRUE,2]]; END; END; chord=> BEGIN WriteString["chord"]; WriteNumber[i,[10,FALSE,TRUE,4]]; IF j>-1 THEN BEGIN WriteString[",note"]; WriteNumber[j,[10,FALSE,TRUE,2]]; END; END; beam => BEGIN WriteString["beam"]; WriteNumber[i,[10,FALSE,TRUE,4]]; IF j>-1 THEN BEGIN WriteString[",chord"]; WriteNumber[j,[10,FALSE,TRUE,2]]; END; END; ENDCASE; dataError _ TRUE; WriteString[": "]; WriteLine[s]; END; Type:TYPE = {sync,chord,beam,none}; dataError:BOOLEAN; CleanUp:PROCEDURE = BEGIN i,j,k:CARDINAL; n:NotePTR; s:SyncPTR; nilFound,beamFound:BOOLEAN; sync1,sync2:BOOLEAN; FOR i IN [0..maxScoreLength) DO IF score[i]#NIL AND i>=scoreLength THEN WriteError[sync,i,-1,"beyond scoreLength"]; IF score[i]=NIL AND iscore[i].time THEN WriteError[sync,i,-1,"out of place"]; IF score[i].type#notes AND score[i].event[0]#NIL THEN WriteError[sync,i,-1,"measure with note attached!"]; IF score[i].type#notes THEN LOOP; IF score[i].type=notes AND score[i].event[0]=NIL THEN WriteError[sync,i,-1,"empty"]; nilFound _ FALSE; FOR j IN [0..syncLength) DO n _ score[i].event[j]; IF n#NIL AND nilFound THEN WriteError[sync,i,j,"not compact"]; IF n=NIL THEN BEGIN nilFound_TRUE; LOOP; END; IF n.sync#score[i] THEN n.sync _ score[i]; IF n.beam=NIL THEN LOOP; beamFound _ FALSE; FOR k IN [0..beamHeapLength) DO IF beamHeap[k]#n.beam THEN LOOP; beamFound _ TRUE; EXIT; ENDLOOP; IF NOT beamFound THEN score[i].event[j].beam _ NIL; ENDLOOP; ENDLOOP; FOR i IN [0..maxChordHeapLength) DO IF chordHeap[i]#NIL AND i>=chordHeapLength THEN WriteError[chord,i,-1,"beyond chordHeapLength"]; IF chordHeap[i]=NIL AND i=beamHeapLength THEN WriteError[beam,i,-1,"beyond beamHeapLength"]; IF beamHeap[i]=NIL AND i IF ev.n.beam#pointer THEN ev.n.beam _ pointer; chord=> FOR k IN [0..chordLength) DO IF ev.c.note[k]=NIL THEN LOOP; IF ev.c.note[k].beam#pointer THEN ev.c.note[k].beam _ pointer; ENDLOOP; ENDCASE; ENDLOOP; END; CleanUpSheets:PROCEDURE = BEGIN sheet:Staves; FOR i:CARDINAL DECREASING IN [0..scoreLength) DO IF score[i].type NOT IN SheetSwitch THEN LOOP; sheet _ LOOPHOLE[score[i].event]; FOR j:CARDINAL IN [0..sheet.sl] DO IF sheet.staff[j].pitch#0 THEN LOOP; Utility.FreeSync[@score[i]]; EXIT; ENDLOOP; ENDLOOP; END; END.. (0,3648)(1,4288)\1708b8B24b4B1b5B16b5B37b8B104b9B529b7B874b10B524b8B2080i19I63b5B173b15B774b16B593b9B66b15B19b8B64b14B19b11B918b8B186b10B431b7B80i42I14b9B205b8B175b9B523b7B247b8B735b7B79i42I15b8B497i31I81b9B1995b4B8093f3 1f0