home *** CD-ROM | disk | FTP | other *** search
- /* TrackView.c */
- /*****************************************************************************/
- /* */
- /* Out Of Phase: Digital Music Synthesis on General Purpose Computers */
- /* Copyright (C) 1994 Thomas R. Lawrence */
- /* */
- /* This program is free software; you can redistribute it and/or modify */
- /* it under the terms of the GNU General Public License as published by */
- /* the Free Software Foundation; either version 2 of the License, or */
- /* (at your option) any later version. */
- /* */
- /* This program is distributed in the hope that it will be useful, */
- /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
- /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
- /* GNU General Public License for more details. */
- /* */
- /* You should have received a copy of the GNU General Public License */
- /* along with this program; if not, write to the Free Software */
- /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
- /* */
- /* Thomas R. Lawrence can be reached at tomlaw@world.std.com. */
- /* */
- /*****************************************************************************/
-
- #include "MiscInfo.h"
- #include "Audit.h"
- #include "Debug.h"
- #include "Definitions.h"
-
- #include "TrackView.h"
- #include "TrackObject.h"
- #include "Memory.h"
- #include "FrameObject.h"
- #include "Frequency.h"
- #include "EditImages.h"
- #include "StaffCalibration.h"
- #include "TrackDisplayScheduling.h"
- #include "Array.h"
- #include "EditCommandParameters.h"
- #include "Numbers.h"
- #include "TieTrackPixel.h"
- #include "Scrap.h"
- #include "Files.h"
- #include "BufferedFileInput.h"
- #include "BufferedFileOutput.h"
- #include "DataMunging.h"
- #include "MainWindowStuff.h"
- #include "LoadSaveNoteVectors.h"
- #include "Alert.h"
-
-
- /* so that tips of notes can be seen above last staff line */
- #define EDGESPACER (48)
-
- /* so that you have space to add new notes */
- #define HORIZONTALEXTENTION (200)
-
- /* width of the insertion point */
- #define INSERTIONPOINTWIDTH (2)
-
- /* tie endpoint positioning correction values */
- #define TIESTARTXCORRECTION (11)
- #define TIESTARTYCORRECTION (9)
- #define TIEENDXCORRECTION (4)
- #define TIEENDYCORRECTION (9)
-
- /* tie curve drawing parameters */
- #define NUMTIELINEINTERVALS (10)
- #define MAXTIEDEPTH (15)
-
- /* the width of the box drawn for range selection */
- #define RANGESELECTTHICKNESS (3)
-
-
- #define MAGICSCRAPSTRING ("\xff\x00\x1f\xfe NoteRangeScrap")
-
-
- typedef enum
- {
- eTrackViewNoSelection EXECUTE(= -99),
- eTrackViewSingleNoteSelection,
- eTrackViewSingleCommandSelection,
- eTrackViewRangeSelection
- } SelectionModes;
-
- typedef enum
- {
- eTrackViewNoUndo EXECUTE(= -5134),
- eTrackViewUndoNoteInsertion,
- eTrackViewUndoRangeInsertion,
- eTrackViewUndoFromFile
- } UndoChoices;
-
- struct TrackViewRec
- {
- WinType* Window;
- OrdType XLoc;
- OrdType YLoc;
- OrdType Width;
- OrdType Height;
- TrackObjectRec* TrackObj;
- MyBoolean CursorBarIsVisible;
- OrdType CursorBarLoc;
- long PixelIndent;
- long VerticalOffset;
-
- SelectionModes SelectionMode;
- long InsertionPointIndex; /* valid only for eTrackViewNoSelection */
- NoteObjectRec* SelectedNote; /* valid only for single selection */
- long SelectedNoteFrame; /* valid only for single selection */
- long RangeSelectStart; /* valid only for eTrackViewRangeSelection */
- long RangeSelectEnd; /* valid only for eTrackViewRangeSelection */
-
- UndoChoices UndoState;
- long UndoNoteInsertionFrameIndex; /* valid only for eTrackViewUndoNoteInsertion */
- long UndoNoteInsertionNoteIndex; /* valid only for eTrackViewUndoNoteInsertion */
- long UndoRangeStartIndex; /* valid only for eTrackViewUndoRangeInsertion */
- long UndoRangeElemCount; /* valid only for eTrackViewUndoRangeInsertion */
- FileSpec* UndoTempFileLoc; /* valid only for eTrackViewUndoFromFile */
- FileType* UndoTempFileDesc; /* valid only for eTrackViewUndoFromFile */
-
- TrackDispScheduleRec* Schedule;
- };
-
-
- static long StaffRefCount = 0;
- static short* MinorStaffList = NIL;
-
-
- /* create a new track view object */
- TrackViewRec* NewTrackView(struct TrackObjectRec* TrackObj, WinType* Window,
- OrdType X, OrdType Y, OrdType Width, OrdType Height)
- {
- TrackViewRec* View;
- ArrayRec* BackgroundList;
- long Limit;
- long Scan;
-
- View = (TrackViewRec*)AllocPtrCanFail(sizeof(TrackViewRec),"TrackViewRec");
- if (View == NIL)
- {
- FailurePoint1:
- return NIL;
- }
- View->Schedule = NewTrackDisplaySchedule(TrackObj);
- if (View->Schedule == NIL)
- {
- FailurePoint3:
- ReleasePtr((char*)View);
- goto FailurePoint1;
- }
- BackgroundList = TrackObjectGetBackgroundList(TrackObj);
- Limit = ArrayGetLength(BackgroundList);
- for (Scan = 0; Scan < Limit; Scan += 1)
- {
- if (!AddTrackToDisplaySchedule(View->Schedule,
- (TrackObjectRec*)ArrayGetElement(BackgroundList,Scan)))
- {
- FailurePoint4:
- goto FailurePoint3;
- }
- }
- if (!TrackObjectAddDependentView(TrackObj,View))
- {
- FailurePoint5:
- goto FailurePoint4;
- }
- for (Scan = 0; Scan < Limit; Scan += 1)
- {
- if (!TrackObjectAddDependentView((TrackObjectRec*)ArrayGetElement(
- BackgroundList,Scan),View))
- {
- FailurePoint6:
- /* WARNING: Scan must be valid from this loop */
- while (Scan > 0)
- {
- Scan -= 1;
- TrackObjectRemoveDependentView((TrackObjectRec*)ArrayGetElement(
- BackgroundList,Scan),View);
- }
- TrackObjectRemoveDependentView(TrackObj,View);
- goto FailurePoint5;
- }
- }
- if (StaffRefCount == 0)
- {
- MinorStaffList = GetMinorStaffList();
- if (MinorStaffList == NIL)
- {
- goto FailurePoint6;
- }
- }
- StaffRefCount += 1;
- View->Window = Window;
- View->XLoc = X;
- View->YLoc = Y;
- View->Width = Width;
- View->Height = Height;
- View->TrackObj = TrackObj;
- View->PixelIndent = 0;
- View->CursorBarIsVisible = False;
- View->SelectionMode = eTrackViewNoSelection;
- View->InsertionPointIndex = 0;
- View->VerticalOffset = (MaxVerticalSize() - Height) / 2;
- if (View->VerticalOffset < -EDGESPACER)
- {
- View->VerticalOffset = -EDGESPACER;
- }
- View->VerticalOffset = (View->VerticalOffset / 4) * 4;
- View->UndoState = eTrackViewNoUndo;
- return View;
- }
-
-
- /* dispose of the track view object */
- void DisposeTrackView(TrackViewRec* View)
- {
- ArrayRec* BackgroundList;
- long Limit;
- long Scan;
-
- CheckPtrExistence(View);
- TrackViewFlushUndoInfo(View);
- BackgroundList = TrackObjectGetBackgroundList(View->TrackObj);
- Limit = ArrayGetLength(BackgroundList);
- for (Scan = 0; Scan < Limit; Scan += 1)
- {
- TrackObjectRemoveDependentView((TrackObjectRec*)ArrayGetElement(
- BackgroundList,Scan),View);
- }
- TrackObjectRemoveDependentView(View->TrackObj,View);
- DisposeTrackDisplaySchedule(View->Schedule);
- StaffRefCount -= 1;
- if (StaffRefCount == 0)
- {
- ReleasePtr((char*)MinorStaffList);
- }
- ReleasePtr((char*)View);
- }
-
-
- /* get the left edge of the track view area */
- OrdType GetTrackViewXLoc(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- return View->XLoc;
- }
-
-
- /* get the top edge of the track view area */
- OrdType GetTrackViewYLoc(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- return View->YLoc;
- }
-
-
- /* get the width of the track view area */
- OrdType GetTrackViewWidth(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- return View->Width;
- }
-
-
- /* get the height of the track view area */
- OrdType GetTrackViewHeight(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- return View->Height;
- }
-
-
- /* change the location of the track view area */
- void SetTrackViewPosition(TrackViewRec* View, OrdType X, OrdType Y,
- OrdType Width, OrdType Height)
- {
- CheckPtrExistence(View);
- View->VerticalOffset += (View->Height - Height) / 2;
- if (View->VerticalOffset < -EDGESPACER)
- {
- View->VerticalOffset = -EDGESPACER;
- }
- View->VerticalOffset = (View->VerticalOffset / 4) * 4;
- View->XLoc = X;
- View->YLoc = Y;
- View->Width = Width;
- View->Height = Height;
- TrackViewRedrawAll(View);
- }
-
-
- /* redraw the track view staff bars. it assumes clipping rectangle has been */
- /* properly set up */
- void TrackViewRedrawStaff(TrackViewRec* View, OrdType XStart,
- OrdType Width)
- {
- long Scan;
- short* MajorStaffList;
-
- CheckPtrExistence(View);
- /* draw staff bars around C */
- MajorStaffList = GetMajorStaffList();
- for (Scan = GetMajorStaffListLength(); Scan >= 0; Scan -= 1)
- {
- DrawLine(View->Window,eBlack,XStart,ConvertPitchToPixel(MajorStaffList[Scan],0)
- - View->VerticalOffset + View->YLoc,Width,0);
- }
- /* draw other staff bars */
- for (Scan = PtrSize((char*)MinorStaffList) / sizeof(short) - 1; Scan >= 0; Scan -= 1)
- {
- DrawLine(View->Window,eMediumGrey,XStart,ConvertPitchToPixel(
- MinorStaffList[Scan],0) - View->VerticalOffset + View->YLoc,Width,0);
- }
- /* draw all C lines */
- for (Scan = 0; Scan <= (NUMNOTES - 1) / 2; Scan += 12)
- {
- DrawLine(View->Window,eLightGrey,XStart,ConvertPitchToPixel(CENTERNOTE - Scan,0)
- - View->VerticalOffset + View->YLoc,Width,0);
- DrawLine(View->Window,eLightGrey,XStart,ConvertPitchToPixel(CENTERNOTE + Scan,0)
- - View->VerticalOffset + View->YLoc,Width,0);
- }
- }
-
-
- /* get the number of vertical degrees of freedom, for setting the vertical scroll bar */
- long TrackViewGetVerticalDegreesOfFreedom(TrackViewRec* View)
- {
- long ReturnValue;
-
- CheckPtrExistence(View);
- ReturnValue = MaxVerticalSize() - View->Height + (2 * EDGESPACER);
- if (ReturnValue < 0)
- {
- ReturnValue = 0;
- }
- return ReturnValue;
- }
-
-
- /* get the vertical offset for setting vertical scroll bar. 0 is top of score area. */
- long TrackViewGetVerticalOffset(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- /* they want all positive numbers, so we add in EDGESPACER */
- return View->VerticalOffset + EDGESPACER;
- }
-
-
- /* hit test to see if the coordinates are within the track view area */
- MyBoolean TrackViewHitTest(TrackViewRec* View, OrdType X, OrdType Y)
- {
- CheckPtrExistence(View);
- return (X >= View->XLoc) && (Y >= View->YLoc) && (X < View->XLoc + View->Width)
- && (Y < View->YLoc + View->Height);
- }
-
-
- /* change the vertical offset and redraw the track view area */
- void TrackViewSetNewVerticalOffset(TrackViewRec* View, long Offset)
- {
- long Delta;
-
- CheckPtrExistence(View);
- TrackViewUndrawCursorBar(View);
- /* do some bounds checking. we don't use EDGESPACER since they are dealing */
- /* in positive numbers, and so does TrackViewGetVerticalDegreesOfFreedom. */
- if (Offset < 0)
- {
- Offset = 0;
- }
- if (Offset > TrackViewGetVerticalDegreesOfFreedom(View) - 1)
- {
- Offset = TrackViewGetVerticalDegreesOfFreedom(View) - 1;
- }
- /* they use positive numbers, but we need one with proper origin */
- Offset -= EDGESPACER;
- /* since we use patterns aligned to 2 and 4 pixels, keep things even so */
- /* the patterns don't look weird */
- Offset = (Offset / 4) * 4;
- /* figure out how much to scroll by */
- Delta = View->VerticalOffset - Offset;
- if (Delta < ORDTYPEMIN)
- {
- Delta = ORDTYPEMIN;
- }
- else if (Delta > ORDTYPEMAX)
- {
- Delta = ORDTYPEMAX;
- }
- SetClipRect(View->Window,View->XLoc,View->YLoc,View->Width,View->Height);
- ScrollArea(View->Window,View->XLoc,View->YLoc,View->Width,View->Height,0,Delta);
- if (Delta < 0)
- {
- /* current offset < new offset, scroll up & open hole at bottom */
- AddClipRect(View->Window,View->XLoc,View->YLoc + View->Height + Delta
- - RANGESELECTTHICKNESS,View->Width,-Delta + RANGESELECTTHICKNESS);
- }
- else
- {
- /* current offset > new offset, scroll down & open hole at top */
- AddClipRect(View->Window,View->XLoc,View->YLoc,View->Width,Delta
- + RANGESELECTTHICKNESS);
- }
- View->VerticalOffset = Offset;
- TrackViewRedrawDontSetClip(View,View->XLoc,View->Width);
- }
-
-
- /* redraw the entire track view, including properly setting the clipping region. */
- void TrackViewRedrawAll(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- SetClipRect(View->Window,View->XLoc,View->YLoc,View->Width,View->Height);
- TrackViewRedrawDontSetClip(View,View->XLoc,View->Width);
- }
-
-
- /* update the cursor and optionally draw the vertical (pitch) positioning bar */
- void TrackViewUpdateMouseCursor(TrackViewRec* View,
- OrdType X, OrdType Y, MyBoolean DrawFunnyBarThing)
- {
- MyBoolean OnAFrameFlag;
- long Dummy;
- OrdType NewCursorBar;
-
- CheckPtrExistence(View);
- X -= View->XLoc;
- Y -= View->YLoc;
- if (!TrackDisplayPixelToIndex(View->Schedule,View->TrackObj,X + View->PixelIndent,
- &OnAFrameFlag,&Dummy))
- {
- return;
- }
- if (DrawFunnyBarThing)
- {
- NewCursorBar = ConvertPitchToPixel(ConvertPixelToPitch(Y + View->VerticalOffset),0);
- if ((NewCursorBar != View->CursorBarLoc) || !View->CursorBarIsVisible)
- {
- TrackViewUndrawCursorBar(View);
- View->CursorBarLoc = NewCursorBar;
- TrackViewDrawCursorBar(View);
- }
- }
- if (OnAFrameFlag)
- {
- SetScoreOverlayCursor();
- }
- else
- {
- SetScoreIntersticeCursor();
- }
- }
-
-
- /* the track data has been modified, so set some flags */
- void TrackViewTrackObjectModified(TrackViewRec* View,
- TrackObjectRec* TrackObj, long Index)
- {
- CheckPtrExistence(View);
- CheckPtrExistence(TrackObj);
- TrackDisplayScheduleMarkChanged(View->Schedule,View->TrackObj,Index);
- }
-
-
- /* another track has been deleted, so remove it from the background list */
- void TrackViewObjectTrackDying(TrackViewRec* View,
- TrackObjectRec* TrackObj)
- {
- CheckPtrExistence(View);
- CheckPtrExistence(TrackObj);
- DeleteTrackFromDisplaySchedule(View->Schedule,TrackObj);
- }
-
-
- /* insert a note at the specified mouse coordinate with the attributes */
- void TrackViewAddNote(TrackViewRec* View,
- OrdType X, OrdType Y, unsigned long NoteAttributes)
- {
- MyBoolean AddToFrame;
- long Index;
- NoteObjectRec* Note;
- unsigned long NoteSharpFlatTemp;
- short NotePitchTemp;
-
- CheckPtrExistence(View);
- ERROR((NoteAttributes & eCommandFlag) != 0,PRERR(ForceAbort,
- "TrackViewAddNote being used to insert command into score"));
- TrackViewFlushUndoInfo(View);
- X -= View->XLoc;
- Y -= View->YLoc;
- /* figure out where we are supposed to put this note. */
- if (!TrackDisplayPixelToIndex(View->Schedule,View->TrackObj,X + View->PixelIndent,
- &AddToFrame,&Index))
- {
- return;
- }
- /* construct the note to be added */
- Note = NewNote();
- if (Note == NIL)
- {
- return;
- }
- SetUpNoteInfo(&NotePitchTemp,&NoteSharpFlatTemp,(NoteAttributes & eSharpModifier)
- != 0,(NoteAttributes & eFlatModifier) != 0,Y + View->VerticalOffset);
- PutNotePitch(Note,NotePitchTemp);
- PutNoteDuration(Note,NoteAttributes & eDurationMask);
- PutNoteDurationDivision(Note,NoteAttributes & eDivisionMask);
- PutNoteDotStatus(Note,(NoteAttributes & eDotModifier) != 0);
- PutNoteFlatOrSharpStatus(Note,NoteSharpFlatTemp);
- PutNoteIsItARest(Note,(NoteAttributes & eRestModifier) != 0);
- ERROR((NoteAttributes & ~(eSharpModifier | eFlatModifier | eDurationMask
- | eDivisionMask | eDotModifier | eRestModifier)) != 0,PRERR(AllowResume,
- "TrackViewAddNote: some unknown bits in the note attributes word are set"));
- /* add note to the appropriate place */
- if (AddToFrame)
- {
- FrameObjectRec* Frame;
-
- /* add to existing frame */
- Frame = TrackObjectGetFrame(View->TrackObj,Index);
- if (IsThisACommandFrame(Frame))
- {
- /* if it's a command frame, then insert note after it */
- Index += 1;
- goto InsertionPoint;
- }
- if (!AppendNoteToFrame(Frame,Note))
- {
- AppendFailurePoint1:
- DisposeNote(Note);
- return;
- }
- TrackObjectAltered(View->TrackObj,Index);
- /* remember the undo information */
- ERROR(View->UndoState != eTrackViewNoUndo,PRERR(ForceAbort,
- "TrackViewAddNote: undo info should have been purged"));
- View->UndoState = eTrackViewUndoNoteInsertion;
- View->UndoNoteInsertionFrameIndex = Index;
- View->UndoNoteInsertionNoteIndex = NumNotesInFrame(Frame) - 1;
- }
- else
- {
- FrameObjectRec* Frame;
-
- /* create a new frame */
- InsertionPoint:
- /* we hafta create a new frame */
- Frame = NewFrame();
- if (Frame == NIL)
- {
- InsertionFailurePoint1:
- goto AppendFailurePoint1;
- }
- if (!AppendNoteToFrame(Frame,Note))
- {
- InsertionFailurePoint2:
- DisposeFrameAndContents(Frame);
- goto InsertionFailurePoint1;
- }
- if (!TrackObjectInsertFrame(View->TrackObj,Index,Frame))
- {
- InsertionFailurePoint3:
- goto InsertionFailurePoint2;
- }
- /* remember the undo information */
- ERROR(View->UndoState != eTrackViewNoUndo,PRERR(ForceAbort,
- "TrackViewAddNote: undo info should have been purged"));
- View->UndoState = eTrackViewUndoNoteInsertion;
- View->UndoNoteInsertionFrameIndex = Index;
- View->UndoNoteInsertionNoteIndex = 0;
- /* we don't have to notify track of change because it knows already. */
- }
- /* adjust the insertion point */
- View->SelectionMode = eTrackViewSingleNoteSelection;
- View->SelectedNote = Note;
- View->SelectedNoteFrame = Index;
- /* redraw what needs to be redrawn. this definitely needs to be fixed */
- /* up since it's unnecessary to redraw the whole staff just to add a note. */
- TrackViewRedrawAll(View);
- View->CursorBarIsVisible = False; /* temporary */
- }
-
-
- /* add a command at the specified mouse coordinates. */
- void TrackViewAddCommand(TrackViewRec* View,
- OrdType X, OrdType Y, NoteCommands CommandOpcode)
- {
- MyBoolean AddToFrame;
- long Index;
- NoteObjectRec* Command;
- FrameObjectRec* Frame;
-
- CheckPtrExistence(View);
- TrackViewFlushUndoInfo(View);
- X -= View->XLoc;
- Y -= View->YLoc;
- /* figure out where we are supposed to put this note. */
- if (!TrackDisplayPixelToIndex(View->Schedule,View->TrackObj,X + View->PixelIndent,
- &AddToFrame,&Index))
- {
- return;
- }
- /* AddToFrame is ignored for adding commands */
- /* construct the command to be added */
- Command = NewCommand();
- if (Command == NIL)
- {
- return;
- }
- PutCommandOpcode(Command,CommandOpcode);
- /* add command to the appropriate place */
- /* create a new frame */
- Frame = NewFrame();
- if (Frame == NIL)
- {
- InsertionFailurePoint1:
- DisposeNote(Command);
- return;
- }
- if (!AppendNoteToFrame(Frame,Command))
- {
- InsertionFailurePoint2:
- DisposeFrameAndContents(Frame);
- goto InsertionFailurePoint1;
- }
- if (!TrackObjectInsertFrame(View->TrackObj,Index,Frame))
- {
- InsertionFailurePoint3:
- goto InsertionFailurePoint2;
- }
- /* remember the undo information */
- ERROR(View->UndoState != eTrackViewNoUndo,PRERR(ForceAbort,
- "TrackViewAddCommand: undo info should have been purged"));
- View->UndoState = eTrackViewUndoNoteInsertion;
- View->UndoNoteInsertionFrameIndex = Index;
- View->UndoNoteInsertionNoteIndex = 0;
- /* we don't have to notify track of change because it knows already. */
- /* adjust the insertion point */
- View->SelectionMode = eTrackViewSingleCommandSelection;
- View->SelectedNote = Command;
- View->SelectedNoteFrame = Index;
- /* redraw what needs to be redrawn. this definitely needs to be fixed */
- /* up since it's unnecessary to redraw the whole staff just to add a command. */
- TrackViewRedrawAll(View);
- View->CursorBarIsVisible = False; /* temporary */
- }
-
-
- /* erase the vertical (pitch) positioning bar */
- void TrackViewUndrawCursorBar(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- if (View->CursorBarIsVisible)
- {
- SetClipRect(View->Window,View->XLoc,View->YLoc,View->Width,View->Height);
- AddClipRect(View->Window,View->XLoc,View->YLoc - View->VerticalOffset
- + View->CursorBarLoc - 1,View->Width,3);
- DrawBoxErase(View->Window,View->XLoc,View->YLoc - View->VerticalOffset
- + View->CursorBarLoc - 1,View->Width,3);
- TrackViewRedrawDontSetClip(View,View->XLoc,View->Width);
- }
- View->CursorBarIsVisible = False;
- }
-
-
- /* draw the vertical (pitch) positioning bar. this assumes that it has been */
- /* previously undrawn (i.e. it doesn't erase any existing bars) */
- void TrackViewDrawCursorBar(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- View->CursorBarIsVisible = True;
- SetClipRect(View->Window,View->XLoc,View->YLoc,View->Width,View->Height);
- DrawBoxPaint(View->Window,eMediumGrey,View->XLoc,View->YLoc - View->VerticalOffset
- + View->CursorBarLoc - 1,View->Width,3);
- }
-
-
- /* draw a cute little paraboloid thing */
- static void DrawTieLine(WinType* ScreenID, Patterns Pattern,
- OrdType StartX, OrdType StartY, OrdType Width, OrdType Height)
- {
- long Index;
- OrdType PixelXLoc[NUMTIELINEINTERVALS];
- OrdType PixelYLoc[NUMTIELINEINTERVALS];
-
- /* generate coordinates */
- for (Index = 0; Index < NUMTIELINEINTERVALS; Index += 1)
- {
- double FuncX;
-
- FuncX = 2 * ((double)Index / (NUMTIELINEINTERVALS - 1)) - 1;
- PixelXLoc[Index] = Width * ((double)Index / (NUMTIELINEINTERVALS - 1));
- PixelYLoc[Index] = Height * ((double)Index / (NUMTIELINEINTERVALS - 1))
- + ((1 - FuncX * FuncX) * MAXTIEDEPTH);
- }
- /* draw the lines */
- for (Index = 0; Index < NUMTIELINEINTERVALS - 1; Index += 1)
- {
- OrdType PosX = StartX + PixelXLoc[Index];
- OrdType PosY = StartY + PixelYLoc[Index];
-
- DrawLine(ScreenID,Pattern,PosX,PosY,(StartX + PixelXLoc[Index + 1]) - PosX,
- (StartY + PixelYLoc[Index + 1]) - PosY);
- }
- }
-
-
- /* redraw the whole track view, but don't mess with the clipping region. XStart is */
- /* is in window coordinates, not local coordinates */
- void TrackViewRedrawDontSetClip(TrackViewRec* View, OrdType XStart,
- OrdType Width)
- {
- long NumTracks;
- long TrackScan;
- long CenterNotePixel;
- FontType Font;
- OrdType FontHeight;
-
- CheckPtrExistence(View);
- /* erase the drawing area */
- DrawBoxErase(View->Window,XStart,View->YLoc,Width,View->Height);
- /* draw the staff */
- TrackViewRedrawStaff(View,XStart,Width);
- /* now we have to draw the notes */
- CenterNotePixel = View->YLoc - View->VerticalOffset + GetCenterNotePixel();
- Font = GetScreenFont();
- FontHeight = GetFontHeight(Font,9);
-
- /* draw ties first, so they are under the notes */
- {
- TieIntersectListRec* TieList;
-
- TieList = TrackDisplayGetTieIntervalList(View->Schedule,View->PixelIndent,Width);
- if (TieList != NIL)
- {
- long TieLimit;
- long TieScan;
-
- TieLimit = GetTieTrackIntersectListLength(TieList);
- for (TieScan = 0; TieScan < TieLimit; TieScan += 1)
- {
- long StartX;
- long StartY;
- long EndX;
- long EndY;
-
- GetTieTrackIntersectElement(TieList,TieScan,&StartX,&StartY,&EndX,&EndY);
- DrawTieLine(View->Window,eBlack,(StartX + TIESTARTXCORRECTION)
- - View->PixelIndent + View->XLoc,(StartY + TIESTARTYCORRECTION)
- + View->YLoc - View->VerticalOffset,(EndX + TIEENDXCORRECTION)
- - (StartX + TIESTARTXCORRECTION),(EndY + TIEENDYCORRECTION)
- - (StartY + TIESTARTYCORRECTION));
- }
- DisposeTieTrackIntersectList(TieList);
- }
- }
-
- /* draw the notes */
- NumTracks = TrackDisplayGetNumTracks(View->Schedule);
- /* note the less than or EQUAL to NumTracks in the loop... */
- /* see note inside loop about why */
- for (TrackScan = 0; TrackScan <= NumTracks; TrackScan += 1)
- {
- TrackObjectRec* TrackObj;
- long ActualTrackIndex;
-
- /* we want to draw our track, but we want to draw it last. to do this, */
- /* we won't draw it when it comes around normally, but we'll loop one extra */
- /* (fake) time, during which we won't do the normal get track but instead, */
- /* we'll just use our own track. not especially elegant, but it works */
- if (TrackScan < NumTracks)
- {
- TrackObj = TrackDisplayGetParticularTrack(View->Schedule,TrackScan);
- }
- else
- {
- TrackObj = View->TrackObj;
- }
- ActualTrackIndex = TrackDisplayGetTrackIndex(View->Schedule,TrackObj);
- if ((TrackObj != View->TrackObj) || (TrackScan == NumTracks))
- {
- MyBoolean Idiot;
- long Position;
-
- if (TrackDisplayPixelToIndex(View->Schedule,TrackObj,XStart
- + View->PixelIndent,&Idiot,&Position))
- {
- long Limit;
- long Scan;
-
- /* find out how much to draw. this definitely needs to be */
- /* fixed since there is no reason to draw frames until the */
- /* end of the entire track */
- Limit = TrackObjectGetNumFrames(TrackObj);
-
- if (Position > 0)
- {
- /* this draws the note just off the left edge of the */
- /* screen to fix some update region alignment problems. */
- Position -= 1;
- }
-
- /* draw the insertion point, if there is one */
- if ((TrackObj == View->TrackObj) && (View->SelectionMode
- == eTrackViewNoSelection))
- {
- long TotalNumFrames;
-
- TotalNumFrames = TrackObjectGetNumFrames(TrackObj);
- if (View->InsertionPointIndex < TotalNumFrames)
- {
- long InsertionPixel;
-
- /* draw the selection before it's corresponding frame */
- if (TrackDisplayIndexToPixel(View->Schedule,0/*first track*/,
- View->InsertionPointIndex,&InsertionPixel))
- {
- DrawBoxPaint(View->Window,eBlack,View->XLoc
- - INSERTIONPOINTWIDTH / 2 + InsertionPixel
- - View->PixelIndent,View->YLoc,INSERTIONPOINTWIDTH,
- View->Height);
- }
- }
- else if (TotalNumFrames > 0)
- {
- long InsertionPixel;
-
- /* oops, no frame, so draw it after the last frame */
- if (TrackDisplayIndexToPixel(View->Schedule,0/*first track*/,
- TrackObjectGetNumFrames(TrackObj) - 1,&InsertionPixel))
- {
- InsertionPixel += WidthOfFrameAndDraw(View->Window,
- 0,0,0,0,0,TrackObjectGetFrame(TrackObj,TotalNumFrames - 1),
- False/*don't draw*/,False);
- DrawBoxPaint(View->Window,eBlack,View->XLoc
- - INSERTIONPOINTWIDTH / 2 + InsertionPixel
- + EXTERNALSEPARATION - View->PixelIndent,View->YLoc,
- INSERTIONPOINTWIDTH,View->Height);
- }
- }
- else
- {
- /* oops, no frames at all, so just draw it at the beginning */
- /* oh, well, it doesn't get drawn... should fix. (not that */
- /* there's any doubt where an insertion would occur...) */
- }
- }
-
- /* draw all of the frames */
- for (Scan = Position; Scan < Limit; Scan += 1)
- {
- long PixelIndex;
- OrdType TheFrameWidth EXECUTE(= -8181);
-
- /* see if we can draw. if TrackDisplayIndexToPixel returns false, */
- /* then it just won't be drawn. if TrackDisplayShouldWeDrawIt */
- /* returns False, then don't draw because it isn't scheduled. */
- if (TrackDisplayIndexToPixel(View->Schedule,ActualTrackIndex,Scan,
- &PixelIndex) && TrackDisplayShouldWeDrawIt(View->Schedule,
- ActualTrackIndex,Scan))
- {
- FrameObjectRec* Frame;
-
- /* escape if we have gone past the end of the window */
- if (PixelIndex - (View->PixelIndent - View->XLoc)
- - LEFTNOTEEDGEINSET >= XStart + Width)
- {
- goto DonePoint;
- }
-
- /* get the frame to draw */
- Frame = TrackObjectGetFrame(TrackObj,Scan);
-
- /* this section is for stuff that only works in */
- /* the current track */
- if (TrackObj == View->TrackObj)
- {
- long MeasureBarIndex;
-
- /* if we should draw a measure bar, then do so. this */
- /* is done before drawing the notes so that the notes */
- /* will appear on top of the measure bar numbers if */
- /* there is an overwrite */
-
- /* draw the measure bar */
- MeasureBarIndex = TrackDisplayMeasureBarIndex(
- View->Schedule,Scan);
- if (MeasureBarIndex != -1)
- {
- char* IndexText;
- Patterns HowToDraw;
-
- if (TrackDisplayShouldMeasureBarBeGreyed(
- View->Schedule,Scan))
- {
- HowToDraw = eMediumGrey;
- }
- else
- {
- HowToDraw = eBlack;
- }
- /* actually something to be drawn */
- DrawLine(View->Window,HowToDraw,PixelIndex - 4/*!*/
- - View->PixelIndent + View->XLoc,View->YLoc
- - View->VerticalOffset,0,MaxVerticalSize());
- IndexText = IntegerToString(MeasureBarIndex);
- if (IndexText != NIL)
- {
- DrawTextLine(View->Window,GetScreenFont(),9,
- IndexText,PtrSize(IndexText),PixelIndex - 4/*!*/
- - View->PixelIndent + View->XLoc - (LengthOfText(
- GetScreenFont(),9,IndexText,PtrSize(IndexText),
- ePlain) / 2),CenterNotePixel - (GetFontHeight(
- GetScreenFont(),9) / 2),ePlain);
- ReleasePtr(IndexText);
- }
- }
- }
-
- /* draw the notes */
- TheFrameWidth = WidthOfFrameAndDraw(View->Window,PixelIndex
- - View->PixelIndent + View->XLoc,CenterNotePixel,Font,9,
- FontHeight,Frame,True/*draw*/,
- (TrackObj != View->TrackObj)/*greyed*/);
-
- /* draw any hilighting for selected items */
- switch (View->SelectionMode)
- {
- default:
- EXECUTE(PRERR(ForceAbort,
- "TrackViewRedrawDontSetClip: bad selection mode"));
- break;
- case eTrackViewNoSelection:
- break;
- case eTrackViewSingleNoteSelection:
- {
- long FrameEnd;
- long Scan;
-
- FrameEnd = NumNotesInFrame(Frame);
- Scan = 0;
- while (Scan < FrameEnd)
- {
- if (GetNoteFromFrame(Frame,Scan)
- == View->SelectedNote)
- {
- DrawBoxFrame(View->Window,eMediumGrey,
- PixelIndex - View->PixelIndent + View->XLoc
- + (Scan * INTERNALSEPARATION),View->YLoc
- - View->VerticalOffset,ICONWIDTH,
- MaxVerticalSize());
- DrawBoxFrame(View->Window,eMediumGrey,
- PixelIndex - View->PixelIndent + View->XLoc
- + (Scan * INTERNALSEPARATION) + 1,View->YLoc
- - View->VerticalOffset + 1,ICONWIDTH - 2,
- MaxVerticalSize() - 2);
- goto SingleNoteSelectDonePoint;
- }
- Scan += 1;
- }
- }
- SingleNoteSelectDonePoint:
- break;
- case eTrackViewSingleCommandSelection:
- if (IsThisACommandFrame(Frame))
- {
- if (View->SelectedNote == GetNoteFromFrame(Frame,0))
- {
- DrawBoxFrame(View->Window,eMediumGrey,PixelIndex
- - View->PixelIndent + View->XLoc,View->YLoc
- - View->VerticalOffset,TheFrameWidth,
- MaxVerticalSize());
- DrawBoxFrame(View->Window,eMediumGrey,PixelIndex
- - View->PixelIndent + View->XLoc + 1,View->YLoc
- - View->VerticalOffset + 1,TheFrameWidth - 2,
- MaxVerticalSize() - 2);
- }
- }
- break;
- case eTrackViewRangeSelection:
- break;
- }
- }
- } /* end of frame scan */
- /* jump here when end of visible note series is reached */
- DonePoint:
- ;
- }
- }
- } /* end of track scan */
-
- /* draw selection box */
- if (View->SelectionMode == eTrackViewRangeSelection)
- {
- long StartPixelIndex;
- long EndPixelIndex;
- long OurTrackIndex;
-
- OurTrackIndex = TrackDisplayGetTrackIndex(View->Schedule,View->TrackObj);
- ERROR(View->RangeSelectStart >= View->RangeSelectEnd,
- PRERR(ForceAbort,"TrackViewRedrawDontSetClip: "
- "range selection boundaries are invalid"));
-
- if (!TrackDisplayIndexToPixel(View->Schedule,OurTrackIndex,
- View->RangeSelectStart,&StartPixelIndex))
- {
- return;
- }
- StartPixelIndex += (View->XLoc - View->PixelIndent); /* normalize to screen */
- if (StartPixelIndex < ORDTYPEMIN / 2)
- {
- StartPixelIndex = ORDTYPEMIN / 2;
- }
- if (StartPixelIndex > ORDTYPEMAX / 2)
- {
- StartPixelIndex = ORDTYPEMAX / 2;
- }
-
- if (!TrackDisplayIndexToPixel(View->Schedule,OurTrackIndex,
- View->RangeSelectEnd - 1,&EndPixelIndex))
- {
- return;
- }
- EndPixelIndex += WidthOfFrameAndDraw(View->Window,0,0,0,0,0,
- TrackObjectGetFrame(View->TrackObj,View->RangeSelectEnd - 1),
- False/*nodraw*/,False);
- EndPixelIndex += (View->XLoc - View->PixelIndent); /* normalize to screen */
- if (EndPixelIndex < ORDTYPEMIN / 2)
- {
- EndPixelIndex = ORDTYPEMIN / 2;
- }
- if (EndPixelIndex > ORDTYPEMAX / 2)
- {
- EndPixelIndex = ORDTYPEMAX / 2;
- }
-
- /* draw upper and lower edges of bounding box */
- DrawBoxPaint(View->Window,eBlack,StartPixelIndex,View->YLoc,EndPixelIndex
- - StartPixelIndex + EXTERNALSEPARATION,RANGESELECTTHICKNESS);
- DrawBoxPaint(View->Window,eBlack,StartPixelIndex,View->YLoc + View->Height
- - RANGESELECTTHICKNESS,EndPixelIndex - StartPixelIndex + EXTERNALSEPARATION,
- RANGESELECTTHICKNESS);
-
- /* draw left edge of bounding box */
- DrawBoxPaint(View->Window,eBlack,StartPixelIndex,View->YLoc,
- RANGESELECTTHICKNESS,View->Height);
-
- /* draw right edge of bounding box */
- DrawBoxPaint(View->Window,eBlack,EndPixelIndex + EXTERNALSEPARATION,
- View->YLoc,RANGESELECTTHICKNESS,View->Height);
- }
- }
-
-
- /* get the horizontal offset from the start of the track, in pixels */
- long TrackViewGetHorizontalOffset(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- return View->PixelIndent;
- }
-
-
- /* get the horizontal extent of the track (in pixels) for setting the scroll bar */
- long TrackViewGetHorizontalDegreesOfFreedom(TrackViewRec* View)
- {
- long Temp;
-
- CheckPtrExistence(View);
- if (!TrackDisplayGetTotalLength(View->Schedule,&Temp))
- {
- return 0;
- }
- Temp = Temp - View->Width + HORIZONTALEXTENTION;
- if (Temp < 0)
- {
- Temp = 0;
- }
- return Temp;
- }
-
-
- /* change the horizontal position of the track display and redraw */
- void TrackViewSetNewHorizontalOffset(TrackViewRec* View, long Offset)
- {
- long Delta;
-
- CheckPtrExistence(View);
- TrackViewUndrawCursorBar(View);
- /* do some bounds checking. */
- if (Offset < 0)
- {
- Offset = 0;
- }
- if (Offset > TrackViewGetHorizontalDegreesOfFreedom(View) - 1)
- {
- Offset = TrackViewGetHorizontalDegreesOfFreedom(View) - 1;
- }
- /* since we use patterns aligned to 2 and 4 pixels, keep things even so */
- /* the patterns don't look weird */
- Offset = (Offset / 4) * 4;
- /* figure out how much to shift by */
- Delta = View->PixelIndent - Offset;
- if (Delta < ORDTYPEMIN)
- {
- Delta = ORDTYPEMIN;
- }
- else if (Delta > ORDTYPEMAX)
- {
- Delta = ORDTYPEMAX;
- }
- SetClipRect(View->Window,View->XLoc,View->YLoc,View->Width,View->Height);
- ScrollArea(View->Window,View->XLoc,View->YLoc,View->Width,View->Height,Delta,0);
- if (Delta < 0)
- {
- /* current offset < new offset, scroll left & open hole at right */
- AddClipRect(View->Window,View->XLoc + View->Width + Delta,View->YLoc,
- -Delta,View->Height);
- }
- else
- {
- /* current offset > new offset, scroll right & open hole at left */
- AddClipRect(View->Window,View->XLoc,View->YLoc,Delta,View->Height);
- }
- View->PixelIndent = Offset;
- TrackViewRedrawDontSetClip(View,View->XLoc,View->Width);
- }
-
-
- /* try to select a single note, if there is one, at the specified mouse location */
- void TrackViewTrySingleNoteSelection(TrackViewRec* View,
- OrdType X, OrdType Y)
- {
- NoteObjectRec* Note;
- MyBoolean CommandFlag;
- long FrameIndex;
-
- CheckPtrExistence(View);
- X -= View->XLoc;
- Y -= View->YLoc;
- Note = TrackDisplayGetUnderlyingNote(View->Schedule,TrackDisplayGetTrackIndex(
- View->Schedule,View->TrackObj),&CommandFlag,X + View->PixelIndent,&FrameIndex);
- if (Note != NIL)
- {
- if (CommandFlag)
- {
- View->SelectionMode = eTrackViewSingleCommandSelection;
- }
- else
- {
- View->SelectionMode = eTrackViewSingleNoteSelection;
- }
- View->SelectedNote = Note;
- View->SelectedNoteFrame = FrameIndex;
- }
- else
- {
- View->SelectionMode = eTrackViewNoSelection;
- View->InsertionPointIndex = FrameIndex;
- ERROR(View->InsertionPointIndex > TrackObjectGetNumFrames(View->TrackObj),
- PRERR(ForceAbort,"TrackViewTrySingleNoteSelection: insertion point beyond end of track"));
- }
- TrackViewUndrawCursorBar(View);
- TrackViewRedrawAll(View);
- }
-
-
- /* is the current selection a single note? */
- MyBoolean TrackViewIsASingleNoteSelected(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- return (View->SelectionMode == eTrackViewSingleNoteSelection);
- }
-
-
- /* is the current selection a single command? */
- MyBoolean TrackViewIsASingleCommandSelected(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- return (View->SelectionMode == eTrackViewSingleCommandSelection);
- }
-
-
- /* is a range of frames selected? */
- MyBoolean TrackViewIsARangeSelected(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- return (View->SelectionMode == eTrackViewRangeSelection);
- }
-
-
- /* is nothing selected, and thus there is an insertion point? */
- MyBoolean TrackViewIsThereInsertionPoint(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- return (View->SelectionMode == eTrackViewNoSelection);
- }
-
-
- /* get the frame index of the insertion point. it is an error if there is no */
- /* valid insertion point */
- long TrackViewGetInsertionPointIndex(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- ERROR(View->SelectionMode != eTrackViewNoSelection,PRERR(ForceAbort,
- "TrackViewGetInsertionPointIndex: there is no valid insertion point"));
- ERROR(View->InsertionPointIndex > TrackObjectGetNumFrames(View->TrackObj),
- PRERR(ForceAbort,"TrackViewGetInsertionPointIndex: insertion point beyond end of track"));
- return View->InsertionPointIndex;
- }
-
-
- /* get the beginning of a selection range. it is an error if a range is not selected */
- long TrackViewGetRangeStart(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- ERROR(View->SelectionMode != eTrackViewRangeSelection,PRERR(ForceAbort,
- "TrackViewGetRangeStart: there is no valid range selection"));
- return View->RangeSelectStart;
- }
-
-
- /* get the frame after the end of a selection range. it is an error if there is */
- /* no selected range. */
- long TrackViewGetRangeEndPlusOne(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- ERROR(View->SelectionMode != eTrackViewRangeSelection,PRERR(ForceAbort,
- "TrackViewGetRangeEndPlusOne: there is no valid range selection"));
- return View->RangeSelectEnd;
- }
-
-
- /* get the frame number of a single note or command selection */
- long TrackViewGetSingleNoteSelectionFrameNumber(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- ERROR(!TrackViewIsASingleNoteSelected(View)
- && !TrackViewIsASingleCommandSelected(View),PRERR(ForceAbort,
- "TrackViewGetSingleNoteSelectionFrameNumber: no single note/command selection"));
- return View->SelectedNoteFrame;
- }
-
-
- /* delete the selected single note or command. it is an error if no single note */
- /* or command is selected */
- void TrackViewDeleteSingleNoteOrCommand(TrackViewRec* View)
- {
- FrameObjectRec* Frame;
- long Limit;
- long Scan;
-
- CheckPtrExistence(View);
- TrackViewFlushUndoInfo(View);
- ERROR((View->SelectionMode != eTrackViewSingleNoteSelection)
- && (View->SelectionMode != eTrackViewSingleCommandSelection),PRERR(ForceAbort,
- "TrackViewDeleteSingleNote: no single note is selected"));
- if (!TrackViewBuildFullUndoBackingStore(View))
- {
- switch (AskYesNoCancel("There is not enough disk space available to preserve "
- "undo information. Continue?",NIL,"Continue","Cancel",NIL))
- {
- default:
- EXECUTE(PRERR(ForceAbort,
- "TrackViewDeleteSingleNoteOrCommand: bad value from AskYesNoCancel"));
- break;
- case eYes:
- break;
- case eNo:
- return; /* abort now */
- }
- }
- Frame = TrackObjectGetFrame(View->TrackObj,View->SelectedNoteFrame);
- CheckPtrExistence(Frame);
- Limit = NumNotesInFrame(Frame);
- for (Scan = 0; Scan < Limit; Scan += 1)
- {
- if (View->SelectedNote == GetNoteFromFrame(Frame,Scan))
- {
- /* we found the note to delete */
- /* zap ties to this note */
- TrackObjectNullifyTies(View->TrackObj,View->SelectedNote);
- /* indicate that stuff needs to be redrawn */
- TrackObjectAltered(View->TrackObj,View->SelectedNoteFrame);
- /* now do the actual deletion */
- if (NumNotesInFrame(Frame) == 1)
- {
- /* since this is the only note in the frame, we'll just delete the */
- /* whole frame. */
- TrackObjectDeleteFrameRun(View->TrackObj,View->SelectedNoteFrame,1);
- }
- else
- {
- /* there are other notes in the frame, so just delete this one note */
- if (!DeleteNoteFromFrame(Frame,Scan))
- {
- /* failed */
- return;
- }
- DisposeNote(View->SelectedNote);
- }
- View->SelectionMode = eTrackViewNoSelection;
- View->InsertionPointIndex = View->SelectedNoteFrame;
- ERROR(View->InsertionPointIndex > TrackObjectGetNumFrames(View->TrackObj),
- PRERR(ForceAbort,"TrackViewDeleteSingleNote: insertion point beyond end of track"));
- EXECUTE(View->SelectedNote = (NoteObjectRec*)0x81818181;)
- EXECUTE(View->SelectedNoteFrame = -1;)
- /* redrawing everything is overkill and should be fixed */
- TrackViewRedrawAll(View);
- return;
- }
- }
- EXECUTE(PRERR(AllowResume,"TrackViewDeleteSingleNote: couldn't find the note"));
- }
-
-
- /* add a track to the greyed-out background display */
- MyBoolean TrackViewAddBackgroundTrack(TrackViewRec* View,
- struct TrackObjectRec* TrackObj)
- {
- MyBoolean Result;
- long FrameIndex;
- MyBoolean OnAFrameFlag;
-
- CheckPtrExistence(View);
- CheckPtrExistence(TrackObj);
- (void)TrackDisplayPixelToIndex(View->Schedule,View->TrackObj,View->PixelIndent,
- &OnAFrameFlag,&FrameIndex);
- Result = AddTrackToDisplaySchedule(View->Schedule,TrackObj);
- if (FrameIndex < TrackObjectGetNumFrames(View->TrackObj))
- {
- (void)TrackDisplayIndexToPixel(View->Schedule,0,FrameIndex,&(View->PixelIndent));
- }
- else
- {
- View->PixelIndent = 0;
- }
- TrackViewRedrawAll(View);
- return Result;
- }
-
-
- /* remove a track from the greyed-out background display */
- void TrackViewRemoveBackgroundTrack(TrackViewRec* View,
- struct TrackObjectRec* TrackObj)
- {
- long FrameIndex;
- MyBoolean OnAFrameFlag;
-
- CheckPtrExistence(View);
- CheckPtrExistence(TrackObj);
- (void)TrackDisplayPixelToIndex(View->Schedule,View->TrackObj,View->PixelIndent,
- &OnAFrameFlag,&FrameIndex);
- DeleteTrackFromDisplaySchedule(View->Schedule,TrackObj);
- if (FrameIndex < TrackObjectGetNumFrames(View->TrackObj))
- {
- (void)TrackDisplayIndexToPixel(View->Schedule,0,FrameIndex,&(View->PixelIndent));
- }
- else
- {
- View->PixelIndent = 0;
- }
- TrackViewRedrawAll(View);
- }
-
-
- /* present a dialog box for editing the selected object's attributes. it is an */
- /* error if there is no single note or command selected. */
- void TrackViewEditSingleSelectionAttributes(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- TrackViewFlushUndoInfo(View);
- ERROR(!TrackViewIsASingleNoteSelected(View)
- && !TrackViewIsASingleCommandSelected(View),PRERR(ForceAbort,
- "TrackViewEditSingleSelectionAttributes: no singly select object"));
- EditNoteOrCommandAttributes(View->SelectedNote,View->TrackObj);
- }
-
-
- /* set a tie from the currently selected note to the note at the specified position. */
- /* it is an error if there is no single note selected. */
- void TrackViewSetTieOnNote(TrackViewRec* View, OrdType X, OrdType Y)
- {
- MyBoolean ActuallyOnAFrame;
- long Index;
- long DestinationFrameIndex;
- NoteObjectRec* DestinationNote;
- MyBoolean CommandFlag;
-
- CheckPtrExistence(View);
- TrackViewFlushUndoInfo(View);
- ERROR(View->SelectionMode != eTrackViewSingleNoteSelection,PRERR(ForceAbort,
- "TrackViewSetTieOnNote: single note selection is false."));
- X -= View->XLoc;
- Y -= View->YLoc;
- /* figure out where we are supposed to put this note. */
- if (!TrackDisplayPixelToIndex(View->Schedule,View->TrackObj,X + View->PixelIndent,
- &ActuallyOnAFrame,&Index))
- {
- return;
- }
-
- /* if they didn't click on anything, then cancel the tie */
- if (!ActuallyOnAFrame)
- {
- goto DeleteTheTiePoint;
- }
-
- /* get the destination note */
- DestinationNote = TrackDisplayGetUnderlyingNote(View->Schedule,
- TrackDisplayGetTrackIndex(View->Schedule,View->TrackObj),&CommandFlag,
- X + View->PixelIndent,&DestinationFrameIndex);
-
- /* change the data */
- if ((DestinationFrameIndex <= View->SelectedNoteFrame) || (DestinationNote == NIL))
- {
- /* delete the tie */
- DeleteTheTiePoint:
- PutNoteTieTarget(View->SelectedNote,NIL);
- TrackObjectAltered(View->TrackObj,View->SelectedNoteFrame);
- }
- else
- {
- /* create the tie */
- /* patch the tie flag thing */
- PutNoteTieTarget(View->SelectedNote,DestinationNote);
- TrackObjectAltered(View->TrackObj,View->SelectedNoteFrame);
- /* change selection */
- View->SelectedNote = DestinationNote;
- View->SelectedNoteFrame = DestinationFrameIndex;
- }
-
- /* redraw */
- TrackViewRedrawAll(View);
- View->CursorBarIsVisible = False; /* temporary */
- }
-
-
- /* select a range of frames. */
- void TrackViewSetRangeSelection(TrackViewRec* View, long StartFrame,
- long EndFramePlusOne)
- {
- CheckPtrExistence(View);
- ERROR(StartFrame >= EndFramePlusOne,PRERR(ForceAbort,
- "TrackViewSetRangeSelection: frame boundaries are invalid"));
- ERROR(StartFrame < 0,PRERR(ForceAbort,
- "TrackViewSetRangeSelection: start frame is before beginning of track"));
- ERROR(EndFramePlusOne > TrackObjectGetNumFrames(View->TrackObj),PRERR(ForceAbort,
- "TrackViewSetRangeSelection: end frame is after end of track"));
- View->SelectionMode = eTrackViewRangeSelection;
- View->RangeSelectStart = StartFrame;
- View->RangeSelectEnd = EndFramePlusOne;
- /* redraw with the selection changes */
- TrackViewRedrawAll(View);
- View->CursorBarIsVisible = False; /* temporary */
- }
-
-
- /* set an insertion point at the specified frame index */
- void TrackViewSetInsertionPoint(TrackViewRec* View, long FrameIndex)
- {
- CheckPtrExistence(View);
- ERROR((FrameIndex < 0) || (FrameIndex > TrackObjectGetNumFrames(View->TrackObj)),
- PRERR(ForceAbort,"TrackViewSetInsertionPoint: index is out of range"));
- View->SelectionMode = eTrackViewNoSelection;
- View->InsertionPointIndex = FrameIndex;
- /* redraw with the selection changes */
- TrackViewRedrawAll(View);
- View->CursorBarIsVisible = False; /* temporary */
- }
-
-
- /* do a mouse down, which may select things. ExtendSelection is true for shift-key */
- /* type selection extending */
- void TrackViewDoMouseDown(TrackViewRec* View, OrdType XLoc,
- OrdType YLoc, MyBoolean ExtendSelection,
- void (*ScrollCallback)(void* Refcon), void* Refcon)
- {
- MyBoolean LandedOnAFrame;
- long ClickFrameIndex;
- long BaseSelectStart;
- long BaseSelectEnd;
- long PreviousSelectStart;
- long PreviousSelectEnd;
-
- CheckPtrExistence(View);
-
- /* if we are NOT extending the selection, then we need to set the insertion */
- /* point to the specified location */
- if (!ExtendSelection || ((View->SelectionMode != eTrackViewNoSelection)
- && (View->SelectionMode != eTrackViewRangeSelection)))
- {
- if (!TrackDisplayPixelToIndex(View->Schedule,View->TrackObj,
- XLoc - View->XLoc + View->PixelIndent,&LandedOnAFrame,&ClickFrameIndex))
- {
- return;
- }
- ERROR((ClickFrameIndex < 0) || (ClickFrameIndex
- > TrackObjectGetNumFrames(View->TrackObj)),PRERR(ForceAbort,
- "TrackViewDoMouseDown: click frame index is beyond the bounds of the track"));
- View->SelectionMode = eTrackViewNoSelection;
- View->InsertionPointIndex = ClickFrameIndex;
- ERROR(View->InsertionPointIndex > TrackObjectGetNumFrames(View->TrackObj),
- PRERR(ForceAbort,"TrackViewDoMouseDown: insertion point beyond end of track"));
- }
- ERROR((View->SelectionMode != eTrackViewNoSelection) && (View->SelectionMode
- != eTrackViewRangeSelection),PRERR(ForceAbort,
- "TrackViewDoMouseDown: bad selection mode"));
-
- /* now figure out where the existing selection boundaries are */
- if (View->SelectionMode == eTrackViewRangeSelection)
- {
- BaseSelectStart = View->RangeSelectStart;
- BaseSelectEnd = View->RangeSelectEnd;
- }
- else
- {
- BaseSelectStart = View->InsertionPointIndex;
- BaseSelectEnd = View->InsertionPointIndex;
- }
- PreviousSelectStart = BaseSelectStart;
- PreviousSelectEnd = BaseSelectEnd;
- if (BaseSelectStart < BaseSelectEnd)
- {
- TrackViewSetRangeSelection(View,BaseSelectStart,BaseSelectEnd);
- }
- else
- {
- TrackViewSetInsertionPoint(View,BaseSelectStart);
- }
-
- /* enter the selection tracking loop */
- do
- {
- long NewSelectStart;
- long NewSelectEnd;
-
- /* scroll if necessary */
- if (XLoc - View->XLoc < 0)
- {
- /* scroll left */
- TrackViewSetNewHorizontalOffset(View,TrackViewGetHorizontalOffset(
- View) - (1 * GetTrackViewWidth(View)) / 8);
- ScrollCallback(Refcon);
- }
- if (XLoc - View->XLoc >= View->Width)
- {
- /* scroll right */
- TrackViewSetNewHorizontalOffset(View,TrackViewGetHorizontalOffset(
- View) + (1 * GetTrackViewWidth(View)) / 8);
- ScrollCallback(Refcon);
- }
- if (YLoc - View->YLoc < 0)
- {
- /* scroll up */
- TrackViewSetNewVerticalOffset(View,TrackViewGetVerticalOffset(
- View) - (1 * GetTrackViewHeight(View)) / 8);
- ScrollCallback(Refcon);
- }
- if (YLoc - View->YLoc >= View->Height)
- {
- /* scroll down */
- TrackViewSetNewVerticalOffset(View,TrackViewGetVerticalOffset(
- View) + (1 * GetTrackViewHeight(View)) / 8);
- ScrollCallback(Refcon);
- }
-
- /* figure out where the thang goes now */
- if (!TrackDisplayPixelToIndex(View->Schedule,View->TrackObj,
- XLoc - View->XLoc + View->PixelIndent,&LandedOnAFrame,&ClickFrameIndex))
- {
- return;
- }
- ERROR((ClickFrameIndex < 0) || (ClickFrameIndex
- > TrackObjectGetNumFrames(View->TrackObj)),PRERR(ForceAbort,
- "TrackViewDoMouseDown: click frame index is beyond the bounds of the track"));
- NewSelectStart = BaseSelectStart;
- NewSelectEnd = BaseSelectEnd;
- if (ClickFrameIndex < NewSelectStart)
- {
- NewSelectStart = ClickFrameIndex;
- }
- if (ClickFrameIndex > NewSelectEnd)
- {
- NewSelectEnd = ClickFrameIndex;
- }
- if ((NewSelectStart != PreviousSelectStart)
- || (NewSelectEnd != PreviousSelectEnd))
- {
- PreviousSelectStart = NewSelectStart;
- PreviousSelectEnd = NewSelectEnd;
- if (NewSelectStart < NewSelectEnd)
- {
- TrackViewSetRangeSelection(View,NewSelectStart,NewSelectEnd);
- }
- else
- {
- TrackViewSetInsertionPoint(View,NewSelectStart);
- }
- }
- } while (eMouseUp != GetAnEvent(&XLoc,&YLoc,NIL,NIL,NIL,NIL));
- }
-
-
- /* set the range selection to the entire track */
- void TrackViewSelectAll(TrackViewRec* View)
- {
- long NumFrames;
-
- CheckPtrExistence(View);
- NumFrames = TrackObjectGetNumFrames(View->TrackObj);
- if (NumFrames > 0)
- {
- View->SelectionMode = eTrackViewRangeSelection;
- View->RangeSelectStart = 0;
- View->RangeSelectEnd = NumFrames;
- }
- else
- {
- View->SelectionMode = eTrackViewNoSelection;
- View->InsertionPointIndex = 0;
- }
- /* redraw with the selection changes */
- TrackViewRedrawAll(View);
- View->CursorBarIsVisible = False; /* temporary */
- }
-
-
- /* delete the selected range. it is an error if there is no selected range. it */
- /* returns False if it fails. undo information is automatically maintained */
- MyBoolean TrackViewDeleteRangeSelection(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- ERROR(View->SelectionMode != eTrackViewRangeSelection,PRERR(ForceAbort,
- "TrackViewDeleteRangeSelection: called with no range selected"));
- TrackViewFlushUndoInfo(View);
- if (!TrackViewBuildFullUndoBackingStore(View))
- {
- switch (AskYesNoCancel("There is not enough disk space available to preserve "
- "undo information. Continue?",NIL,"Continue","Cancel",NIL))
- {
- default:
- EXECUTE(PRERR(ForceAbort,
- "TrackViewDeleteSingleNoteOrCommand: bad value from AskYesNoCancel"));
- break;
- case eYes:
- break;
- case eNo:
- return False; /* abort now */
- }
- }
-
- /* delete the stuff */
- TrackObjectDeleteFrameRun(View->TrackObj,View->RangeSelectStart,
- View->RangeSelectEnd - View->RangeSelectStart);
- View->SelectionMode = eTrackViewNoSelection;
- View->InsertionPointIndex = View->RangeSelectStart;
- ERROR(View->InsertionPointIndex > TrackObjectGetNumFrames(View->TrackObj),
- PRERR(ForceAbort,"TrackViewDeleteRangeSelection: insertion point beyond end of track"));
-
- /* redraw with changes */
- TrackViewRedrawAll(View);
- View->CursorBarIsVisible = False; /* temporary */
- TrackViewShowSelection(View);
-
- return True;
- }
-
-
- /* attempt to paste notes into the track. returns False if it fails. undo */
- /* information is automatically maintained. */
- MyBoolean TrackViewAttemptPaste(TrackViewRec* View)
- {
- char* Scrap;
- MyBoolean TotalSuccessFlag = False;
-
- CheckPtrExistence(View);
- TrackViewFlushUndoInfo(View);
- if (View->SelectionMode == eTrackViewRangeSelection)
- {
- if (!TrackViewDeleteRangeSelection(View))
- {
- return False;
- }
- }
- ERROR(View->SelectionMode != eTrackViewNoSelection,PRERR(ForceAbort,
- "TrackViewAttemptPaste: no insertion point"));
- Scrap = GetCopyOfScrap();
- if (Scrap != NIL)
- {
- if ((PtrSize(Scrap) >= sizeof(MAGICSCRAPSTRING))
- && MemEqu(MAGICSCRAPSTRING,Scrap,sizeof(MAGICSCRAPSTRING)))
- {
- FileSpec* TempFileLoc;
-
- TempFileLoc = NewTempFileSpec(CODE4BYTES('\?','\?','\?','\?'),
- CODE4BYTES('\?','\?','\?','\?'));
- if (TempFileLoc != NIL)
- {
- FileType* FileDesc;
-
- if (OpenFile(TempFileLoc,&FileDesc,eReadAndWrite))
- {
- if (0 == WriteToFile(FileDesc,Scrap + sizeof(MAGICSCRAPSTRING),
- PtrSize(Scrap) - sizeof(MAGICSCRAPSTRING)))
- {
- if (SetFilePosition(FileDesc,0))
- {
- BufferedInputRec* BuffFile;
-
- BuffFile = NewBufferedInput(FileDesc);
- if (BuffFile != NIL)
- {
- ArrayRec* FrameArray EXECUTE(= (ArrayRec*)0x81818181);
-
- if (eFileLoadNoError == ReadNoteVector(&FrameArray,BuffFile))
- {
- long Scan;
-
- CheckPtrExistence(FrameArray);
- Scan = 0;
- while (ArrayGetLength(FrameArray) > 0)
- {
- FrameObjectRec* Thing;
-
- Thing = (FrameObjectRec*)ArrayGetElement(
- FrameArray,0);
- if (!TrackObjectInsertFrame(View->TrackObj,
- Scan + View->InsertionPointIndex,Thing))
- {
- long Limit;
-
- /* delete all the ones we added */
- TrackObjectDeleteFrameRun(View->TrackObj,
- View->InsertionPointIndex,Scan);
- /* delete the ones we didn't add */
- Limit = ArrayGetLength(FrameArray);
- for (Scan = 0; Scan < Limit; Scan += 1)
- {
- DisposeFrameAndContents(
- (FrameObjectRec*)ArrayGetElement(
- FrameArray,Scan));
- }
- goto ExitPoint;
- }
- ArrayDeleteElement(FrameArray,0);
- Scan += 1;
- }
- /* remember undo information */
- View->UndoState = eTrackViewUndoRangeInsertion;
- View->UndoRangeStartIndex = View->InsertionPointIndex;
- View->UndoRangeElemCount = Scan;
- /* update display parameters */
- View->InsertionPointIndex += Scan;
- ERROR(View->InsertionPointIndex
- > TrackObjectGetNumFrames(View->TrackObj),
- PRERR(ForceAbort,"TrackViewAttemptPaste: "
- "insertion point beyond end of track"));
- TotalSuccessFlag = True;
- TrackViewRedrawAll(View);
- View->CursorBarIsVisible = False; /* temporary */
- TrackViewShowSelection(View);
- /* jump here when something bad happens */
- ExitPoint:
- DisposeArray(FrameArray);
- }
- EndBufferedInput(BuffFile);
- }
- }
- }
- CloseFile(FileDesc);
- }
- DeleteFile(TempFileLoc);
- DisposeFileSpec(TempFileLoc);
- }
- }
- ReleasePtr(Scrap);
- }
- return TotalSuccessFlag;
- }
-
-
- /* copy the selected range to the clipboard. it is an error if there is no selected */
- /* range. it returns True if successful. */
- MyBoolean TrackViewCopyRangeSelection(TrackViewRec* View)
- {
- MyBoolean TotalSuccessFlag;
- ArrayRec* CopyOfSelection;
-
- CheckPtrExistence(View);
- ERROR(View->SelectionMode != eTrackViewRangeSelection,PRERR(ForceAbort,
- "TrackViewDeleteRangeSelection: called with no range selected"));
- TrackViewFlushUndoInfo(View);
- CopyOfSelection = TrackObjectCopyFrameRun(View->TrackObj,View->RangeSelectStart,
- View->RangeSelectEnd - View->RangeSelectStart);
- if (CopyOfSelection != NIL)
- {
- long Limit;
- long Scan;
- FileSpec* TempFileLoc;
-
- TempFileLoc = NewTempFileSpec(CODE4BYTES('\?','\?','\?','\?'),
- CODE4BYTES('\?','\?','\?','\?'));
- if (TempFileLoc != NIL)
- {
- FileType* FileDesc;
-
- if (OpenFile(TempFileLoc,&FileDesc,eReadAndWrite))
- {
- BufferedOutputRec* BuffOut;
-
- BuffOut = NewBufferedOutput(FileDesc);
- if (BuffOut != NIL)
- {
- MyBoolean WriteSucceeded = False;
-
- if (WriteBufferedOutput(BuffOut,sizeof(MAGICSCRAPSTRING),
- MAGICSCRAPSTRING))
- {
- if (eFileLoadNoError == WriteNoteVector(CopyOfSelection,BuffOut))
- {
- WriteSucceeded = True;
- }
- }
- if (EndBufferedOutput(BuffOut) && WriteSucceeded)
- {
- if (SetFilePosition(FileDesc,0))
- {
- char* Scrap;
-
- Scrap = AllocPtrCanFail(GetFileLength(FileDesc),
- "TrackViewCopyRangeSelection: scrap temp");
- if (Scrap != NIL)
- {
- if (0 == ReadFromFile(FileDesc,Scrap,PtrSize(Scrap)))
- {
- if (SetScrapToThis(Scrap))
- {
- TotalSuccessFlag = True;
- }
- }
- ReleasePtr(Scrap);
- }
- }
- }
- }
- CloseFile(FileDesc);
- }
- DeleteFile(TempFileLoc);
- DisposeFileSpec(TempFileLoc);
- }
- Limit = ArrayGetLength(CopyOfSelection);
- for (Scan = 0; Scan < Limit; Scan += 1)
- {
- DisposeFrameAndContents((FrameObjectRec*)ArrayGetElement(
- CopyOfSelection,Scan));
- }
- DisposeArray(CopyOfSelection);
- }
- return TotalSuccessFlag;
- }
-
-
- /* cut the range selection (copy to clipboard, then delete). returns True if */
- /* successful. it is an error if there is no range selected. automatically */
- /* updates undo information. */
- MyBoolean TrackViewCutRangeSelection(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- TrackViewFlushUndoInfo(View);
- if (TrackViewCopyRangeSelection(View))
- {
- if (TrackViewDeleteRangeSelection(View))
- {
- return True;
- }
- }
- return False;
- }
-
-
- /* show the selection or insertion point by scrolling the view area */
- void TrackViewShowSelection(TrackViewRec* View)
- {
- long CenteringIndex;
- long PixelIndex;
-
- CheckPtrExistence(View);
- switch (View->SelectionMode)
- {
- default:
- EXECUTE(PRERR(ForceAbort,"TrackViewShowSelection: illegal selection mode"));
- break;
- case eTrackViewNoSelection:
- CenteringIndex = View->InsertionPointIndex;
- break;
- case eTrackViewSingleNoteSelection:
- case eTrackViewSingleCommandSelection:
- CenteringIndex = View->SelectedNoteFrame;
- break;
- case eTrackViewRangeSelection:
- CenteringIndex = View->RangeSelectStart;
- break;
- }
- if (CenteringIndex < TrackObjectGetNumFrames(View->TrackObj))
- {
- if (!TrackDisplayIndexToPixel(View->Schedule,0/*first track*/,
- CenteringIndex,&PixelIndex))
- {
- return;
- }
- }
- else if (TrackObjectGetNumFrames(View->TrackObj) > 0)
- {
- if (!TrackDisplayIndexToPixel(View->Schedule,0/*first track*/,
- CenteringIndex - 1,&PixelIndex))
- {
- return;
- }
- }
- else
- {
- /* no frames at all. */
- PixelIndex = 0;
- }
- PixelIndex -= View->Width / 2;
- if (PixelIndex < 0)
- {
- PixelIndex = 0;
- }
- TrackViewSetNewHorizontalOffset(View,PixelIndex);
- }
-
-
- /* find out if we can undo the last operation */
- MyBoolean TrackViewCanWeUndo(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- return (eTrackViewNoUndo != View->UndoState);
- }
-
-
- /* dispose of all undo information. */
- void TrackViewFlushUndoInfo(TrackViewRec* View)
- {
- CheckPtrExistence(View);
- switch (View->UndoState)
- {
- default:
- EXECUTE(PRERR(ForceAbort,"TrackViewFlushUndoInfo: bad undo state"));
- break;
- case eTrackViewNoUndo:
- case eTrackViewUndoNoteInsertion:
- case eTrackViewUndoRangeInsertion:
- break;
- case eTrackViewUndoFromFile:
- CloseFile(View->UndoTempFileDesc);
- DeleteFile(View->UndoTempFileLoc);
- DisposeFileSpec(View->UndoTempFileLoc);
- break;
- }
- View->UndoState = eTrackViewNoUndo;
- }
-
-
- /* save the undo information for the track. returns False if it fails. */
- MyBoolean TrackViewBuildFullUndoBackingStore(TrackViewRec* View)
- {
- BufferedOutputRec* Output;
-
- CheckPtrExistence(View);
- TrackViewFlushUndoInfo(View);
- ERROR(View->UndoState != eTrackViewNoUndo,PRERR(ForceAbort,
- "TrackViewBuildFullUndoBackingStore: expected undo information to be purged"));
- /* make backups (see, even my programs do it!) */
- View->UndoTempFileLoc = NewTempFileSpec(CODE4BYTES('\?','\?','\?','\?'),
- CODE4BYTES('\?','\?','\?','\?'));
- if (View->UndoTempFileLoc == NIL)
- {
- FailurePoint1:
- return False;
- }
- if (!OpenFile(View->UndoTempFileLoc,&(View->UndoTempFileDesc),eReadAndWrite))
- {
- FailurePoint2:
- DeleteFile(View->UndoTempFileLoc);
- DisposeFileSpec(View->UndoTempFileLoc);
- goto FailurePoint1;
- }
- Output = NewBufferedOutput(View->UndoTempFileDesc);
- if (Output == NIL)
- {
- FailurePoint3:
- CloseFile(View->UndoTempFileDesc);
- goto FailurePoint2;
- }
- if (!TrackObjectWriteNotesOutToFile(View->TrackObj,Output))
- {
- FailurePoint3a:
- EndBufferedOutput(Output);
- goto FailurePoint3;
- }
- if (!EndBufferedOutput(Output))
- {
- FailurePoint4:
- goto FailurePoint3;
- }
- View->UndoState = eTrackViewUndoFromFile;
- return True;
- }
-
-
- /* undo the last operation. if it fails, well... */
- void TrackViewUndo(TrackViewRec* View)
- {
- UndoChoices LocalUndoState;
- long LocalUndoNoteInsertionFrameIndex;
- long LocalUndoNoteInsertionNoteIndex;
- long LocalUndoRangeStartIndex;
- long LocalUndoRangeElemCount;
- FileSpec* LocalUndoTempFileLoc;
- FileType* LocalUndoTempFileDesc;
-
- CheckPtrExistence(View);
- /* first, make a backup of the undo information, so we can undo the undo */
- LocalUndoState = View->UndoState;
- LocalUndoNoteInsertionFrameIndex = View->UndoNoteInsertionFrameIndex;
- LocalUndoNoteInsertionNoteIndex = View->UndoNoteInsertionNoteIndex;
- LocalUndoRangeStartIndex = View->UndoRangeStartIndex;
- LocalUndoRangeElemCount = View->UndoRangeElemCount;
- LocalUndoTempFileLoc = View->UndoTempFileLoc;
- LocalUndoTempFileDesc = View->UndoTempFileDesc;
- /* reset the undo state */
- View->UndoState = eTrackViewNoUndo;
- /* build backup for our undo */
- if (!TrackViewBuildFullUndoBackingStore(View))
- {
- switch (AskYesNoCancel("There is not enough disk space available to preserve "
- "undo information. Continue?",NIL,"Continue","Cancel",NIL))
- {
- default:
- EXECUTE(PRERR(ForceAbort,
- "TrackViewDeleteSingleNoteOrCommand: bad value from AskYesNoCancel"));
- break;
- case eYes:
- /* continue */
- break;
- case eNo:
- /* abort now -- restore the undo information */
- View->UndoState = LocalUndoState;
- View->UndoNoteInsertionFrameIndex = LocalUndoNoteInsertionFrameIndex;
- View->UndoNoteInsertionNoteIndex = LocalUndoNoteInsertionNoteIndex;
- View->UndoRangeStartIndex = LocalUndoRangeStartIndex;
- View->UndoRangeElemCount = LocalUndoRangeElemCount;
- View->UndoTempFileLoc = LocalUndoTempFileLoc;
- View->UndoTempFileDesc = LocalUndoTempFileDesc;
- return;
- }
- }
- /* do the undoing */
- switch (LocalUndoState)
- {
- default:
- EXECUTE(PRERR(ForceAbort,"TrackViewUndo: bad undo state"));
- break;
- case eTrackViewUndoNoteInsertion:
- /* delete the note */
- {
- FrameObjectRec* Frame;
-
- Frame = TrackObjectGetFrame(View->TrackObj,LocalUndoNoteInsertionFrameIndex);
- if (NumNotesInFrame(Frame) == 1)
- {
- /* delete whole frame */
- TrackObjectDeleteFrameRun(View->TrackObj,
- LocalUndoNoteInsertionFrameIndex,1);
- }
- else
- {
- NoteObjectRec* Note;
-
- /* just delete a note from the frame */
- Note = GetNoteFromFrame(Frame,LocalUndoNoteInsertionNoteIndex);
- if (!IsItACommand(Note))
- {
- TrackObjectNullifyTies(View->TrackObj,Note);
- }
- DeleteNoteFromFrame(Frame,LocalUndoNoteInsertionNoteIndex);
- }
- }
- break;
- case eTrackViewUndoRangeInsertion:
- TrackObjectDeleteFrameRun(View->TrackObj,LocalUndoRangeStartIndex,
- LocalUndoRangeElemCount);
- break;
- case eTrackViewUndoFromFile:
- /* recover all the notes from the file */
- if (SetFilePosition(LocalUndoTempFileDesc,0))
- {
- BufferedInputRec* Input;
-
- Input = NewBufferedInput(LocalUndoTempFileDesc);
- if (Input != NIL)
- {
- if (TrackObjectRecoverNotesFromFile(View->TrackObj,Input))
- {
- /* successful */
- }
- EndBufferedInput(Input);
- }
- }
- CloseFile(LocalUndoTempFileDesc);
- DeleteFile(LocalUndoTempFileLoc);
- DisposeFileSpec(LocalUndoTempFileLoc);
- break;
- }
- TrackViewRedrawAll(View);
- View->CursorBarIsVisible = False; /* temporary */
- }
-
-
- /* transpose the selection by adding AddHalfSteps to the pitch of each selected note */
- /* AddHalfSteps can be negative. it is an error if there is no single note selection */
- /* or no range selection */
- void TrackViewTransposeSelection(TrackViewRec* View, long AddHalfSteps)
- {
- CheckPtrExistence(View);
- TrackViewFlushUndoInfo(View);
- if (TrackViewIsASingleNoteSelected(View))
- {
- long NewPitch;
-
- NewPitch = GetNotePitch(View->SelectedNote) + AddHalfSteps;
- if (NewPitch < 0)
- {
- NewPitch = 0;
- }
- else if (NewPitch > NUMNOTES - 1)
- {
- NewPitch = NUMNOTES - 1;
- }
- PutNotePitch(View->SelectedNote,NewPitch);
- switch (NewPitch % 12)
- {
- case 0: /* C */
- case 2: /* D */
- case 4: /* E */
- case 5: /* F */
- case 7: /* G */
- case 9: /* A */
- case 11: /* B */
- PutNoteFlatOrSharpStatus(View->SelectedNote,0);
- break;
- case 1: /* C# / Db */
- case 3: /* D# / Eb */
- case 6: /* F# / Gb */
- case 8: /* G# / Ab */
- case 10: /* A# / Bb */
- if (AddHalfSteps >= 0)
- {
- if (GetNoteFlatOrSharpStatus(View->SelectedNote) == eFlatModifier)
- {
- PutNoteFlatOrSharpStatus(View->SelectedNote,eFlatModifier);
- }
- else
- {
- PutNoteFlatOrSharpStatus(View->SelectedNote,eSharpModifier);
- }
- }
- else
- {
- if (GetNoteFlatOrSharpStatus(View->SelectedNote) == eSharpModifier)
- {
- PutNoteFlatOrSharpStatus(View->SelectedNote,eSharpModifier);
- }
- else
- {
- PutNoteFlatOrSharpStatus(View->SelectedNote,eFlatModifier);
- }
- }
- break;
- }
- }
- else if (TrackViewIsARangeSelected(View))
- {
- long FrameScan;
-
- for (FrameScan = View->RangeSelectStart; FrameScan < View->RangeSelectEnd;
- FrameScan += 1)
- {
- FrameObjectRec* Frame;
-
- Frame = TrackObjectGetFrame(View->TrackObj,FrameScan);
- CheckPtrExistence(Frame);
- if (!IsThisACommandFrame(Frame))
- {
- long NoteScan;
- long NoteLimit;
-
- NoteLimit = NumNotesInFrame(Frame);
- for (NoteScan = 0; NoteScan < NoteLimit; NoteScan += 1)
- {
- NoteObjectRec* Note;
- long NewPitch;
-
- Note = GetNoteFromFrame(Frame,NoteScan);
- CheckPtrExistence(Note);
- NewPitch = GetNotePitch(Note) + AddHalfSteps;
- if (NewPitch < 0)
- {
- NewPitch = 0;
- }
- else if (NewPitch > NUMNOTES - 1)
- {
- NewPitch = NUMNOTES - 1;
- }
- PutNotePitch(Note,NewPitch);
- switch (NewPitch % 12)
- {
- case 0: /* C */
- case 2: /* D */
- case 4: /* E */
- case 5: /* F */
- case 7: /* G */
- case 9: /* A */
- case 11: /* B */
- PutNoteFlatOrSharpStatus(Note,0);
- break;
- case 1: /* C# / Db */
- case 3: /* D# / Eb */
- case 6: /* F# / Gb */
- case 8: /* G# / Ab */
- case 10: /* A# / Bb */
- if (AddHalfSteps >= 0)
- {
- if (GetNoteFlatOrSharpStatus(Note) == eFlatModifier)
- {
- PutNoteFlatOrSharpStatus(Note,eFlatModifier);
- }
- else
- {
- PutNoteFlatOrSharpStatus(Note,eSharpModifier);
- }
- }
- else
- {
- if (GetNoteFlatOrSharpStatus(Note) == eSharpModifier)
- {
- PutNoteFlatOrSharpStatus(Note,eSharpModifier);
- }
- else
- {
- PutNoteFlatOrSharpStatus(Note,eFlatModifier);
- }
- }
- break;
- }
- }
- }
- }
- }
- else
- {
- EXECUTE(PRERR(ForceAbort,"TrackViewTransposeSelection: improper selection"));
- }
- TrackViewRedrawAll(View);
- View->CursorBarIsVisible = False; /* temporary */
- }
-
-
- /* scroll to the specified measure. invalid measure numbers may be specified. */
- void TrackViewShowMeasure(TrackViewRec* View, long MeasureNumber)
- {
- long FrameIndex;
-
- CheckPtrExistence(View);
- if (!TrackDisplayMeasureIndexToFrame(View->Schedule,MeasureNumber,&FrameIndex))
- {
- ErrorBeep();
- }
- else
- {
- long PixelIndex;
-
- if (FrameIndex < TrackObjectGetNumFrames(View->TrackObj))
- {
- if (!TrackDisplayIndexToPixel(View->Schedule,0/*first track*/,
- FrameIndex,&PixelIndex))
- {
- return;
- }
- }
- else if (TrackObjectGetNumFrames(View->TrackObj) > 0)
- {
- if (!TrackDisplayIndexToPixel(View->Schedule,0/*first track*/,
- FrameIndex - 1,&PixelIndex))
- {
- return;
- }
- }
- else
- {
- /* no frames at all. */
- PixelIndex = 0;
- }
- PixelIndex -= (View->Width / 3);
- if (PixelIndex < 0)
- {
- PixelIndex = 0;
- }
- TrackViewSetNewHorizontalOffset(View,PixelIndex);
- }
- }
-