<> <> <> <> <> DIRECTORY Beam USING [AddBeam, AddChord, AddNote, Remove, SetStems], Chord USING [AddNote, RemoveNote, SetDefaultStem, Sort], Graphics USING [DisplayChar, MoveTo], Heuristic USING [MakeNTuplets], MusicDefs, Note USING [FindChord, GetBackTie], Piece USING [AddSync, CleanUpSyncs, Delete], Real USING [FixI], Selection USING [Clear, Draw, MakeBeam, MakeBeamOfBeams, RemoveNote], Sheet USING [Height, HiLite, Map, MapNote, NextStaff], Sync USING [AddNote], Utility USING [FreeBeam, FreeNote, NewBeam, NewChord, NewSync]; SelectionImpl: CEDAR PROGRAM IMPORTS Beam, Chord, Graphics, Heuristic, MusicDefs, Note, Piece, Real, Selection, Sheet, Sync, Utility EXPORTS Selection, MusicDefs = BEGIN OPEN Graphics, MusicDefs; lineSelect: PUBLIC BOOL; select1, greySelect1: PUBLIC Time _ 1; greySelect2, select2: PUBLIC Time _ 0; selection: PUBLIC ARRAY [0..maxSelectionLength) OF NotePTR; selectionLength: PUBLIC CARDINAL _ 0; min, max: PUBLIC Time _ 1; command: PUBLIC BOOL _ FALSE; flash: PUBLIC BOOL _ FALSE; Includes: PUBLIC PROC[n: NotePTR] RETURNS[BOOL] = { IF voice AND n.voice#selectedVoice THEN RETURN[FALSE]; IF lineSelect THEN RETURN[n.sync.time IN [select1..select2)] ELSE FOR i: CARDINAL IN [0..selectionLength) DO IF selection[i]=n THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE] }; <<***************************************************************************>> <> <<***************************************************************************>> Clear: PUBLIC PROC = { Selection.Draw[]; greySelect1 _ select1 _ 1; greySelect2 _ select2 _ 0; selectionLength _ 0; }; AddNote: PUBLIC PROC[n: NotePTR] = { i: CARDINAL; x, y: INTEGER; IF lineSelect THEN Clear[]; IF n=NIL THEN RETURN; IF voice AND n.voice#selectedVoice THEN RETURN; IF selectionLength=maxSelectionLength THEN RETURN; FOR i IN [0..selectionLength) DO IF selection[i]=n THEN RETURN; ENDLOOP; selection[selectionLength] _ n; selectionLength _ selectionLength+1; lineSelect _ FALSE; [x, y] _ Sheet.MapNote[n]; Graphics.MoveTo[context,[x, y]]; SetBrush[black, invert]; Graphics.DisplayChar[context, 170C]; }; RemoveNote: PUBLIC PROC[n: NotePTR] = { x, y: INTEGER; IF n=NIL THEN RETURN; SetBrush[black, invert]; FOR i: CARDINAL IN [0..selectionLength) DO IF selection[i]#n THEN LOOP; selection[i] _ NIL; FOR j: CARDINAL DECREASING IN [0..selectionLength) DO IF selection[j]#NIL THEN EXIT; selectionLength _ j; ENDLOOP; [x, y] _ Sheet.MapNote[n]; Graphics.MoveTo[context,[x, y]]; Graphics.DisplayChar[context, 170C]; RETURN; ENDLOOP; }; AddLine: PUBLIC PROC[time1, time2: Time] = { IF lineSelect THEN Sheet.HiLite[black, select1, select2] ELSE Selection.Clear[]; Sheet.HiLite[black, time1, time2]; select1 _ time1; select2 _ time2; lineSelect _ TRUE; }; AddGreyLine: PUBLIC PROC[time1, time2: Time] = { IF lineSelect THEN Sheet.HiLite[grey, greySelect1, greySelect2] ELSE Selection.Clear[]; Sheet.HiLite[grey, time1, time2]; greySelect1 _ time1; greySelect2 _ time2; lineSelect _ TRUE; }; Draw: PUBLIC PROC = { x, y: INTEGER; IF lineSelect THEN { Sheet.HiLite[black, select1, select2]; Sheet.HiLite[grey, greySelect1, greySelect2]; RETURN}; SetBrush[black, invert]; FOR i: CARDINAL IN [0..selectionLength) DO IF selection[i]=NIL THEN LOOP; IF voice AND selection[i].voice#selectedVoice THEN LOOP; [x, y] _ Sheet.MapNote[selection[i]]; Graphics.MoveTo[context,[x, y]]; Graphics.DisplayChar[context, 170C]; ENDLOOP; }; <<****************************************************************************>> <> <<****************************************************************************>> SetNoteValue: PUBLIC PROC[v: NoteValue, dots: INTEGER] = { i, j: CARDINAL; n: NotePTR; IF lineSelect THEN FOR i IN [0..scoreLength) DO IF score[i]=NIL THEN LOOP; IF score[i].time < select1 OR score[i].time > select2 THEN LOOP; FOR j IN [0..syncLength) DO IF (n _ score[i].event[j])=NIL THEN EXIT; IF voice AND n.voice#selectedVoice THEN LOOP; n.value_ v; IF dots>1 THEN n.doubleDotted _ TRUE ELSE n.doubleDotted _ FALSE; IF dots MOD 2=1 THEN n.dotted _ TRUE ELSE n.dotted _ FALSE; IF v>quarter OR n.beam=NIL OR NOT n.beam.beamed THEN LOOP; Beam.Remove[n.beam, n, Note.FindChord[n], NIL]; ENDLOOP; ENDLOOP ELSE FOR i IN [0..selectionLength) DO IF (n _ selection[i])=NIL THEN LOOP; IF voice AND n.voice#selectedVoice THEN LOOP; SetDirty[n.sync.time, n.sync.time]; n.value_ v; IF dots>1 THEN n.doubleDotted _ TRUE ELSE n.doubleDotted _ FALSE; IF dots MOD 2=1 THEN n.dotted _ TRUE ELSE n.dotted _ FALSE; IF v>quarter OR n.beam=NIL OR NOT n.beam.beamed THEN LOOP; Beam.Remove[n.beam, n, Note.FindChord[n], NIL]; ENDLOOP; IF lineSelect THEN SetDirty[select1, select2]; }; SetRest: PUBLIC PROC[rest: BOOL] = { i, j: CARDINAL; n: NotePTR; IF lineSelect THEN FOR i IN [0..scoreLength) DO IF score[i]=NIL THEN LOOP; IF score[i].time < select1 OR score[i].time > select2 THEN LOOP; FOR j IN [0..syncLength) DO IF (n _ score[i].event[j])=NIL THEN EXIT; IF voice AND n.voice#selectedVoice THEN LOOP; n.rest _ rest; ENDLOOP; ENDLOOP ELSE FOR i IN [0..selectionLength) DO IF (n _ selection[i])=NIL THEN LOOP; IF voice AND n.voice#selectedVoice THEN LOOP; SetDirty[n.sync.time, n.sync.time]; n.rest_ rest; ENDLOOP; IF lineSelect THEN SetDirty[select1, select2]; }; SetStaff: PUBLIC PROC[staff: CARDINAL] = { n: NotePTR; Count: PROC[s: CARDINAL, t: Time] RETURNS[j: CARDINAL] = { j _ 0; FOR i: CARDINAL IN [0..s) DO j _ Sheet.NextStaff[j, t]; ENDLOOP}; IF staff=0 THEN {flash _ TRUE; RETURN} ELSE staff _ staff-1; IF lineSelect THEN FOR i: CARDINAL IN [0..scoreLength) DO IF score[i]=NIL THEN LOOP; IF score[i].time < select1 OR score[i].time > select2 THEN LOOP; FOR j: CARDINAL IN [0..syncLength) DO IF (n _ score[i].event[j])=NIL THEN EXIT; IF voice AND n.voice#selectedVoice THEN LOOP; n.staff _ Count[staff, n.sync.time]; IF n.beam#NIL THEN Beam.SetStems[n.beam]; ENDLOOP; ENDLOOP ELSE FOR i: CARDINAL IN [0..selectionLength) DO IF (n _ selection[i])=NIL THEN LOOP; IF voice AND n.voice#selectedVoice THEN LOOP; SetDirty[n.sync.time, n.sync.time]; n.staff _ Count[staff, n.sync.time]; IF n.beam#NIL THEN Beam.SetStems[n.beam]; ENDLOOP; IF lineSelect THEN SetDirty[select1, select2]; }; SetStem: PUBLIC PROC[stemUp: BOOL] = { i, j: CARDINAL; x, y, xb, yb: INTEGER; d: INTEGER; n: NotePTR; c: ChordPTR; b: BeamPTR; IF lineSelect THEN FOR i IN [0..scoreLength) DO IF score[i]=NIL THEN LOOP; IF score[i].time < select1 OR score[i].time > select2 THEN LOOP; FOR j IN [0..syncLength) DO IF (n _ score[i].event[j])=NIL THEN EXIT; IF voice AND n.voice#selectedVoice THEN LOOP; n.stemUp _ stemUp; c _ Note.FindChord[n]; IF c#NIL THEN c.stemUp _ stemUp; IF (b _ n.beam)=NIL OR NOT n.beam.beamed THEN LOOP; [x, y] _ Sheet.Map[n.sync.time, n.pitch, n.staff]; [xb, yb] _ Sheet.Map[b.sync1.time,, b.staff]; yb _ yb+b.height; d _ Real.FixI[yb+b.tilt*(x-xb)-y]; b.height _ b.height-(IF stemUp THEN MIN[0, d-28] ELSE MAX[0, d+28]); ENDLOOP; ENDLOOP ELSE FOR i IN [0..selectionLength) DO IF (n _ selection[i])=NIL THEN LOOP; IF voice AND n.voice#selectedVoice THEN LOOP; SetDirty[n.sync.time, n.sync.time]; n.stemUp _ stemUp; c _ Note.FindChord[n]; IF c#NIL THEN c.stemUp _ stemUp; IF (b _ n.beam)=NIL OR NOT n.beam.beamed THEN LOOP; [x, y] _ Sheet.Map[n.sync.time, n.pitch, n.staff]; [xb, yb] _ Sheet.Map[b.sync1.time,, b.staff]; yb _ yb+b.height; d _ Real.FixI[yb+n.beam.tilt*(x-xb)-y]; b.height _ b.height-(IF stemUp THEN MIN[0, d-28] ELSE MAX[0, d+28]); ENDLOOP; IF lineSelect THEN SetDirty[select1, select2]; }; SetGrace: PUBLIC PROC[grace: BOOL] = { i, j: CARDINAL; n: NotePTR; IF lineSelect THEN FOR i IN [0..scoreLength) DO IF score[i]=NIL THEN LOOP; IF score[i].time < select1 OR score[i].time > select2 THEN LOOP; FOR j IN [0..syncLength) DO IF (n _ score[i].event[j])=NIL THEN EXIT; IF voice AND n.voice#selectedVoice THEN LOOP; n.grace _ grace; ENDLOOP; ENDLOOP ELSE FOR i IN [0..selectionLength) DO IF (n _ selection[i])=NIL THEN LOOP; IF voice AND n.voice#selectedVoice THEN LOOP; SetDirty[n.sync.time, n.sync.time]; n.grace_ grace; ENDLOOP; IF lineSelect THEN SetDirty[select1, select2]; }; Transpose: PUBLIC PROC[halfsteps: INTEGER] = { i, j: CARDINAL; n: NotePTR; IF lineSelect THEN FOR i IN [0..scoreLength) DO IF score[i]=NIL THEN LOOP; IF score[i].time < select1 OR score[i].time > select2 THEN LOOP; FOR j IN [0..syncLength) DO IF (n _ score[i].event[j])=NIL THEN EXIT; IF voice AND n.voice#selectedVoice THEN LOOP; n.pitch _ n.pitch+halfsteps; IF (halfsteps MOD 12)#0 THEN {n.spelled _ inKey; n.show _ FALSE}; ENDLOOP; ENDLOOP ELSE FOR i IN [0..selectionLength) DO IF (n _ selection[i])=NIL THEN LOOP; IF voice AND n.voice#selectedVoice THEN LOOP; SetDirty[n.sync.time, n.sync.time]; n.pitch _ n.pitch+halfsteps; IF (halfsteps MOD 12)#0 THEN {n.spelled _ inKey; n.show _ FALSE}; ENDLOOP; IF lineSelect THEN SetDirty[select1, select2]; }; <<**************************************************************************>> <> <<**************************************************************************>> MakeSync: PUBLIC PROC = { sync: SyncPTR _ NIL; c: ChordPTR; n: NotePTR; i, j: CARDINAL; begin, end: Time; begin _ EndOfScore[]; end _ -1; FOR i IN [0..selectionLength) DO IF (n _ selection[i])=NIL THEN LOOP; begin _ MIN[begin, n.sync.time]; end _ MAX[end, n.sync.time]; ENDLOOP; IF ABS[end-begin]>20 THEN {flash _ TRUE; RETURN}; FOR i IN [0..selectionLength) DO IF (n _ selection[i])=NIL THEN LOOP; IF voice AND n.voice#selectedVoice THEN LOOP; SetDirty[n.sync.time, n.sync.time]; IF sync=NIL THEN { sync _ n.sync; LOOP; }; c _ Note.FindChord[n]; FOR j IN [0..chordLength) DO IF c=NIL AND j#0 THEN EXIT; IF c#NIL THEN n _ c.note[j]; IF n=NIL THEN EXIT; Sync.AddNote[sync, n]; ENDLOOP; ENDLOOP; Piece.CleanUpSyncs[score]; }; ClearSync: PUBLIC PROC = { n: NotePTR; sync: SyncPTR; i, j: CARDINAL; first: BOOL _ TRUE; IF lineSelect THEN FOR i IN [0..scoreLength) DO IF score[i].timeselect2 THEN LOOP; FOR j DECREASING IN [0..syncLength) DO IF score[i].event[j]=NIL THEN EXIT; sync _ Utility.NewSync[]; sync.time _ score[i].time; Piece.AddSync[score, sync]; Sync.AddNote[sync, score[i].event[j]]; ENDLOOP; ENDLOOP; IF NOT lineSelect THEN FOR i IN [0..selectionLength) DO IF (n _ selection[i])=NIL THEN LOOP; IF voice AND n.voice#selectedVoice THEN LOOP; SetDirty[n.sync.time, n.sync.time]; sync _ Utility.NewSync[]; sync.time _ n.sync.time; Piece.AddSync[score, sync]; Sync.AddNote[sync, n]; ENDLOOP; Piece.CleanUpSyncs[score]; IF lineSelect THEN SetDirty[select1, select2]; }; MakeTie: PUBLIC PROC = { n: NotePTR; ties: ARRAY [0..10) OF RECORD[n1, n2: NotePTR]; ties _ ALL[[NIL, NIL]]; <> FOR i: CARDINAL IN [0..selectionLength) DO IF selection[i]=NIL THEN LOOP; FOR j: CARDINAL IN [0..10) DO IF ties[j].n1=NIL THEN {ties[j].n1 _ selection[i]; EXIT}; IF ties[j].n1.pitch#selection[i].pitch THEN LOOP; IF ties[j].n1.sync=selection[i].sync THEN {flash _ TRUE; RETURN}; IF ties[j].n2#NIL THEN {flash _ TRUE; RETURN}; ties[j].n2 _ selection[i]; EXIT; ENDLOOP; ENDLOOP; IF ties[0].n1=NIL THEN {flash _ TRUE; RETURN}; <> IF ties[0].n2=NIL AND ties[1].n2=NIL AND ties[2].n1=NIL THEN { ties[0].n2 _ ties[1].n1; ties[1].n1 _ NIL}; <> FOR i: CARDINAL IN [0..10) DO IF ties[i].n1=NIL THEN EXIT; IF ties[i].n2=NIL THEN {flash _ TRUE; RETURN}; ENDLOOP; <> FOR i: CARDINAL IN [0..10) DO IF ties[i].n1=NIL THEN EXIT; IF ties[i].n1.sync.time>ties[i].n2.sync.time THEN {n _ ties[i].n1; ties[i].n1 _ ties[i].n2; ties[i].n2 _ n}; IF ties[i].n1.tied THEN { (n _ Note.GetBackTie[ties[i].n1]).tie _ NIL; SetDirty[n.sync.time, n.sync.time]}; IF (n _ ties[i].n2.tie)#NIL THEN { n.tied _ FALSE; SetDirty[n.sync.time, n.sync.time]}; ties[i].n2.tie _ ties[i].n1; ties[i].n1.tied _ TRUE; ties[i].n2.tieHeight _ -10; SetDirty[ties[i].n1.sync.time, ties[i].n2.sync.time]; ENDLOOP; }; ClearTie: PUBLIC PROC = { n: NotePTR; i, j: CARDINAL; IF lineSelect THEN FOR i IN [0..scoreLength) DO IF score[i].timeselect2 THEN EXIT; FOR j IN [0..syncLength) DO IF (n _ score[i].event[j])=NIL THEN EXIT; IF n.tie=NIL THEN LOOP; n.tie.tied _ FALSE; n.tie _ NIL; ENDLOOP; ENDLOOP ELSE FOR i IN [0..selectionLength) DO IF (n _ selection[i])=NIL THEN LOOP; IF n.tie=NIL THEN LOOP; SetDirty[n.sync.time, n.sync.time]; SetDirty[n.tie.sync.time, n.tie.sync.time]; n.tie.tied _ FALSE; n.tie _ NIL; ENDLOOP; IF lineSelect THEN SetDirty[select1, select2]; }; <<******************************************************************>> <> <<******************************************************************>> MakeChord: PUBLIC PROC = { n: NotePTR; begin, end: Time; chord: ChordPTR; beam: BeamPTR _ NIL; sync: SyncPTR _ NIL; count: CARDINAL _ 0; <> begin _ EndOfScore[]; end _ -1; FOR i: CARDINAL IN [0..selectionLength) DO IF (n _ selection[i])=NIL THEN LOOP; IF voice AND n.voice#selectedVoice THEN LOOP; begin _ MIN[begin, n.sync.time]; end _ MAX[end, n.sync.time]; count _ count+1; ENDLOOP; IF ABS[end-begin]>20 OR count<2 THEN {flash _ TRUE; RETURN}; <> chord _ Utility.NewChord[]; FOR i: CARDINAL IN [0..selectionLength) DO IF (n _ selection[i])=NIL THEN LOOP; IF voice AND n.voice#selectedVoice THEN LOOP; SetDirty[n.sync.time, n.sync.time]; Chord.AddNote[chord, n]; ENDLOOP; Chord.SetDefaultStem[chord]; Piece.CleanUpSyncs[score]; }; ClearChord: PUBLIC PROC = { n: NotePTR; c: ChordPTR; i, j: CARDINAL; IF lineSelect THEN { FOR i DECREASING IN [0..scoreLength) DO IF score[i].time < select1 OR score[i].time > select2 THEN LOOP; FOR j IN [0..syncLength) DO IF (n _ score[i].event[j])=NIL THEN EXIT; IF voice AND n.voice#selectedVoice THEN LOOP; c _ Note.FindChord[n]; IF c#NIL THEN Chord.RemoveNote[c, n]; -- NIL's n.beam ENDLOOP; ENDLOOP}; IF NOT lineSelect THEN { FOR i IN [0..selectionLength) DO IF (n _ selection[i])=NIL THEN LOOP; IF voice AND n.voice#selectedVoice THEN LOOP; SetDirty[n.sync.time, n.sync.time]; c _ Note.FindChord[n]; IF c#NIL THEN Chord.RemoveNote[c, n]; -- NIL's n.beam ENDLOOP}; IF lineSelect THEN SetDirty[select1, select2]; }; <<****************************************************************************>> <> <<****************************************************************************>> MakeBeam: PUBLIC PROC[beamed: BOOL] = { b: BeamPTR _ Utility.NewBeam[]; c: ChordPTR; n, tmp: NotePTR; i: CARDINAL; height, stem: INTEGER; stemUp, first: BOOL _ TRUE; FOR i IN [0..selectionLength) DO IF (n _ selection[i])=NIL THEN LOOP; IF voice AND n.voice#selectedVoice THEN LOOP; <> IF beamed AND n.valueSheet.Height[tmp.sync.time, tmp.pitch, tmp.staff] THEN height _ Sheet.Height[tmp.sync.time, tmp.pitch, tmp.staff]; }; IF c=NIL THEN { Beam.AddNote[b, n]; IF first THEN { stemUp_ n.stemUp; first _ FALSE; height _ (IF stemUp THEN -1000 ELSE 1000); b.staff _ n.staff; }; IF beamed THEN n.stemUp _ stemUp; IF n.stemUp AND heightSheet.Height[n.sync.time, n.pitch, n.staff] THEN height _ Sheet.Height[n.sync.time, n.pitch, n.staff]; }; ENDLOOP; IF beamed THEN stem _ 34 ELSE stem _ 28; b.height _ height-Sheet.Height[0,, b.staff]+(IF stemUp THEN stem ELSE -stem); IF b.chord[1]=endOfBeam THEN {Utility.FreeBeam[@b]; RETURN}; SetDirty[b.sync1.time, b.sync2.time]; }; MakeBeamOfBeams: PUBLIC PROC[beamed: BOOL] = { <> n: NotePTR; c: ChordPTR; oldBeam: BeamPTR; b: BeamPTR _ Utility.NewBeam[]; FOR i: CARDINAL IN [0..selectionLength) DO IF (n _ selection[i])=NIL THEN LOOP; IF n.beam=NIL THEN LOOP; IF NOT n.beam.beamed THEN {flash _ TRUE; RETURN}; IF n.beam.beam#NIL THEN {flash _ TRUE; RETURN}; ENDLOOP; FOR i: CARDINAL IN [0..selectionLength) DO IF (n _ selection[i])=NIL THEN LOOP; IF voice AND n.voice#selectedVoice THEN LOOP; oldBeam _ n.beam; IF oldBeam=b THEN LOOP; IF oldBeam#NIL THEN { Beam.AddBeam[b, oldBeam]; b.staff _ oldBeam.staff; b.height _ oldBeam.height; LOOP; }; IF beamed AND n.value { ev.b.height _ b.height; ev.b.staff _ b.staff; ev.b.tilt _ 0; }; ENDCASE; ENDLOOP; b.tilt _ 0; SetDirty[b.sync1.time, b.sync2.time]; }; ClearBeam: PUBLIC PROC = { c: ChordPTR; b: BeamPTR; n: NotePTR; i, j: CARDINAL; IF lineSelect THEN { SetDirty[select1, select2]; FOR i IN [0..scoreLength) DO IF score[i].time < select1 OR score[i].time > select2 THEN LOOP; FOR j IN [0..syncLength) DO IF (n _ score[i].event[j])=NIL THEN EXIT; IF voice AND n.voice#selectedVoice THEN EXIT; c _Note.FindChord[n]; b _ n.beam; IF b#NIL THEN Beam.Remove[b, n, c, NIL]; ENDLOOP; ENDLOOP}; IF NOT lineSelect THEN { FOR i IN [0..selectionLength) DO IF (n _ selection[i])=NIL THEN LOOP; IF voice AND n.voice#selectedVoice THEN LOOP; SetDirty[n.sync.time, n.sync.time]; c _Note.FindChord[n]; b _ n.beam; IF b=NIL THEN LOOP; Beam.Remove[b, n, c, NIL]; ENDLOOP}; }; MakeNTuplet: PUBLIC PROC[n, a: INTEGER] = { i: CARDINAL; b: BeamPTR _ NIL; newBeam: BOOL _ FALSE; IF lineSelect THEN {Heuristic.MakeNTuplets[a, n, select1, select2]; RETURN}; FOR i IN [0..selectionLength) DO IF selection[i]=NIL THEN LOOP; IF voice AND selection[i].voice#selectedVoice THEN LOOP; IF b=NIL THEN b _ selection[i].beam; IF b=NIL OR selection[i].beam#b THEN newBeam _ TRUE; ENDLOOP; IF newBeam THEN { Selection.MakeBeam[FALSE]; FOR i IN [0..selectionLength) DO IF selection[i]=NIL THEN LOOP; IF voice AND selection[i].voice#selectedVoice THEN LOOP; b _ selection[i].beam; EXIT; ENDLOOP; IF b#NIL THEN b.beamed _ FALSE}; IF b=NIL THEN RETURN; b.against _ n; b.ntuple _ a; b.invisible _ FALSE; SetDirty[b.sync1.time, b.sync2.time]; }; HideNTuplets: PUBLIC PROC[invisible: BOOL] = { b: BeamPTR; n: NotePTR; i, j: CARDINAL; IF lineSelect THEN FOR i IN [0..scoreLength) DO IF score[i]=NIL THEN LOOP; IF score[i].time < select1 OR score[i].time > select2 THEN LOOP; FOR j IN [0..syncLength) DO IF (n _ score[i].event[j])=NIL THEN EXIT; IF voice AND n.voice#selectedVoice THEN LOOP; FOR b _ n.beam, b.beam WHILE b#NIL DO IF b.ntuple=0 THEN LOOP; b.invisible _ invisible; ENDLOOP; ENDLOOP; ENDLOOP ELSE FOR i IN [0..selectionLength) DO IF (n _ selection[i])=NIL THEN LOOP; IF voice AND n.voice#selectedVoice THEN LOOP; SetDirty[n.sync.time, n.sync.time]; FOR b _ n.beam, b.beam WHILE b#NIL DO IF b.ntuple=0 THEN LOOP; b.invisible _ invisible; ENDLOOP; ENDLOOP; IF lineSelect THEN SetDirty[select1, select2]; }; MakeNTupletOfBeams: PUBLIC PROC[n, a: INTEGER] = { t: NotePTR; i: CARDINAL; b: BeamPTR _ NIL; newBeam: BOOL _ FALSE; TopBeam: PROC[b: BeamPTR] RETURNS[BeamPTR] = {IF b#NIL AND b.beam#NIL THEN RETURN[b.beam] ELSE RETURN[b]}; FOR i IN [0..selectionLength) DO IF (t _ selection[i])=NIL THEN LOOP; IF voice AND t.voice#selectedVoice THEN LOOP; IF b=NIL THEN b _ TopBeam[t.beam]; IF b=NIL OR TopBeam[t.beam]#b THEN newBeam _ TRUE; ENDLOOP; IF newBeam THEN { Selection.MakeBeamOfBeams[FALSE]; FOR i IN [0..selectionLength) DO IF selection[i]=NIL THEN LOOP; IF selection[i].beam=NIL THEN LOOP; IF voice AND selection[i].voice#selectedVoice THEN LOOP; b _ TopBeam[selection[i].beam]; EXIT; ENDLOOP; IF b#NIL THEN b.beamed _ FALSE}; IF b=NIL THEN RETURN; b.against _ n; b.ntuple _ a; b.invisible _ FALSE; SetDirty[b.sync1.time, b.sync2.time]; }; Delete: PUBLIC PROC = { n: NotePTR; IF lineSelect THEN Piece.Delete[select1, select2] ELSE FOR i: CARDINAL IN [0..selectionLength) DO IF (n _ selection[i])=NIL THEN LOOP; IF voice AND n.voice#selectedVoice THEN LOOP; SetDirty[n.sync.time, n.sync.time]; Selection.RemoveNote[n]; Utility.FreeNote[@n]; ENDLOOP; }; END.