/* SampleView.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 "SampleView.h"
#include "Memory.h"
#include "SampleStorageDisplay.h"


struct SampleViewRec
	{
		SampleStorageDisplayRec*	Storage;
		WinType*									ScreenID;
		OrdType										XLoc;
		OrdType										YLoc;
		OrdType										Width;
		OrdType										Height;
		double										XScale;
		long											HorizontalIndex;
		long											SelectionStart;
		long											SelectionEnd;
	};


/* create a new sample view that will display the specified storage object. */
SampleViewRec*			NewSampleView(WinType* Screen, OrdType XLoc, OrdType YLoc,
											OrdType Width, OrdType Height, SampleStorageDisplayRec* TheRawData)
	{
		SampleViewRec*		View;

		View = (SampleViewRec*)AllocPtrCanFail(sizeof(SampleViewRec),"SampleViewRec");
		if (View != NIL)
			{
				View->Storage = TheRawData;
				View->ScreenID = Screen;
				View->XLoc = XLoc;
				View->YLoc = YLoc;
				View->Width = Width;
				View->Height = Height;
				View->XScale = 1;
				View->HorizontalIndex = 0;
				View->SelectionStart = 0;
				View->SelectionEnd = 0;
			}
		return View;
	}


/* dispose of the sample view.  the raw data object is also disposed. */
void								DisposeSampleView(SampleViewRec* View)
	{
		CheckPtrExistence(View);
		DisposeSampleStorageDisplay(View->Storage);
		ReleasePtr((char*)View);
	}


/* redraw one displayed sample line, at the specified X coordinate */
void								RedrawSampleViewOneLine(SampleViewRec* View, OrdType XPixel)
	{
		long							NumSampleFrames;

		CheckPtrExistence(View);
		SetClipRect(View->ScreenID,View->XLoc,View->YLoc,View->Width,View->Height);
		NumSampleFrames = GetSampleStorageDisplayNumFrames(View->Storage);
		DrawLine(View->ScreenID,eBlack,View->XLoc + XPixel,View->YLoc,0,0);
		DrawLine(View->ScreenID,eBlack,View->XLoc + XPixel,View->YLoc + View->Height,0,0);
		if (GetSampleStorageDisplayNumChannels(View->Storage) == eSampleStereo)
			{
				OrdType				LeftStart;
				OrdType				LeftEnd;
				OrdType				RightStart;
				OrdType				RightEnd;
				long					Index;
				Patterns			DotColor;
				Patterns			BackgroundColor;

				/* stereo sample has two panes */
				LeftStart = View->YLoc + 1;
				RightEnd = View->YLoc + View->Height - 1;
				LeftEnd = View->YLoc + (View->Height / 2 - 1);
				RightStart = LeftEnd + 1;
				DrawLine(View->ScreenID,eBlack,View->XLoc + XPixel,LeftEnd,0,0);
				Index = ((XPixel - 1) * View->XScale) + View->HorizontalIndex;
				if ((Index >= View->SelectionStart) && (Index < View->SelectionEnd))
					{
						DotColor = eWhite;
						BackgroundColor = eBlack;
					}
				else if ((View->SelectionStart == View->SelectionEnd)
					&& (Index == View->SelectionStart))
					{
						DotColor = eBlack;
						BackgroundColor = eMediumGrey;
					}
				else
					{
						DotColor = eBlack;
						BackgroundColor = eWhite;
					}
				if ((Index >= 0) && (Index < NumSampleFrames))
					{
						double					Value;
						OrdType					Position;

						/* draw for left channel */
						DrawLine(View->ScreenID,BackgroundColor,(XPixel - 1) + View->XLoc + 1,
							LeftStart,0,LeftEnd - LeftStart - 1);
						Value = largefixed2double(GetSampleStorageDisplayValue(View->Storage,Index,
							eLeftChannel));
						Position = ((1 - Value) / 2) * (LeftEnd - LeftStart - 1);
						if (Position == (LeftEnd - LeftStart - 1) / 2)
							{
								/* zero point:  displace very nearly zero points away from the */
								/* origin line so you can see they aren't zero */
								if (Value < 0)
									{
										Position += 1;
									}
								else if (Value > 0)
									{
										Position -= 1;
									}
							}
						DrawLine(View->ScreenID,DotColor,(XPixel - 1) + View->XLoc + 1,
							LeftStart + Position,0,0);
						/* draw for right channel */
						DrawLine(View->ScreenID,BackgroundColor,(XPixel - 1) + View->XLoc + 1,
							RightStart,0,RightEnd - RightStart - 1);
						Value = largefixed2double(GetSampleStorageDisplayValue(View->Storage,Index,
							eRightChannel));
						Position = ((1 - Value) / 2) * (RightEnd - RightStart - 1);
						if (Position == (RightEnd - RightStart - 1) / 2)
							{
								/* zero point:  displace very nearly zero points away from the */
								/* origin line so you can see they aren't zero */
								if (Value < 0)
									{
										Position += 1;
									}
								else if (Value > 0)
									{
										Position -= 1;
									}
							}
						DrawLine(View->ScreenID,DotColor,(XPixel - 1) + View->XLoc + 1,
							RightStart + Position,0,0);
					}
				 else
					{
						DrawLine(View->ScreenID,eLightGrey,(XPixel - 1) + View->XLoc + 1,
							LeftStart,0,LeftEnd - LeftStart - 1);
						DrawLine(View->ScreenID,eLightGrey,(XPixel - 1) + View->XLoc + 1,
							RightStart,0,RightEnd - RightStart - 1);
					}
			}
		 else
			{
				OrdType				Start;
				OrdType				End;
				long					Index;
				Patterns			DotColor;
				Patterns			BackgroundColor;

				/* mono sample has one pane */
				Start = View->YLoc + 1;
				End = View->YLoc + View->Height - 1;
				Index = ((XPixel - 1) * View->XScale) + View->HorizontalIndex;
				if ((Index >= View->SelectionStart) && (Index < View->SelectionEnd))
					{
						DotColor = eWhite;
						BackgroundColor = eBlack;
					}
				else if ((View->SelectionStart == View->SelectionEnd)
					&& (Index == View->SelectionStart))
					{
						DotColor = eBlack;
						BackgroundColor = eMediumGrey;
					}
				else
					{
						DotColor = eBlack;
						BackgroundColor = eWhite;
					}
				if ((Index >= 0) && (Index < NumSampleFrames))
					{
						double					Value;
						OrdType					Position;

						DrawLine(View->ScreenID,BackgroundColor,(XPixel - 1) + View->XLoc + 1,
							Start,0,End - Start - 1);
						Value = largefixed2double(GetSampleStorageDisplayValue(View->Storage,Index,
							eMonoChannel));
						Position = ((1 - Value) / 2) * (End - Start - 1);
						if (Position == (End - Start - 1) / 2)
							{
								/* zero point:  displace very nearly zero points away from the */
								/* origin line so you can see they aren't zero */
								if (Value < 0)
									{
										Position += 1;
									}
								else if (Value > 0)
									{
										Position -= 1;
									}
							}
						DrawLine(View->ScreenID,DotColor,(XPixel - 1) + View->XLoc + 1,
							Start + Position,0,0);
					}
				 else
					{
						DrawLine(View->ScreenID,eLightGrey,(XPixel - 1) + View->XLoc + 1,
							Start,0,End - Start - 1);
					}
			}
	}


/* redraw the entire sample view area */
void								RedrawSampleView(SampleViewRec* View)
	{
		long						NumSampleFrames;

		CheckPtrExistence(View);
		SetClipRect(View->ScreenID,View->XLoc,View->YLoc,View->Width,View->Height);
		DrawBoxFrame(View->ScreenID,eBlack,View->XLoc,View->YLoc,View->Width,View->Height);
		NumSampleFrames = GetSampleStorageDisplayNumFrames(View->Storage);
		if (GetSampleStorageDisplayNumChannels(View->Storage) == eSampleStereo)
			{
				OrdType				LeftStart;
				OrdType				LeftEnd;
				OrdType				RightStart;
				OrdType				RightEnd;
				OrdType				Scan;

				/* stereo sample has two panes */
				LeftStart = View->YLoc + 1;
				RightEnd = View->YLoc + View->Height - 1;
				LeftEnd = View->YLoc + (View->Height / 2 - 1);
				RightStart = LeftEnd + 1;
				DrawLine(View->ScreenID,eBlack,View->XLoc,LeftEnd,View->Width,0);
				for (Scan = 0; Scan < View->Width - 2; Scan += 1)
					{
						long								Index;
						Patterns						DotColor;
						Patterns						BackgroundColor;

						Index = (Scan * View->XScale) + View->HorizontalIndex;
						if ((Index >= View->SelectionStart) && (Index < View->SelectionEnd))
							{
								DotColor = eWhite;
								BackgroundColor = eBlack;
							}
						else if ((View->SelectionStart == View->SelectionEnd)
							&& (Index == View->SelectionStart))
							{
								DotColor = eBlack;
								BackgroundColor = eMediumGrey;
							}
						else
							{
								DotColor = eBlack;
								BackgroundColor = eWhite;
							}
						if ((Index >= 0) && (Index < NumSampleFrames))
							{
								double					Value;
								OrdType					Position;

								/* draw left line */
								DrawLine(View->ScreenID,BackgroundColor,Scan + View->XLoc + 1,
									LeftStart,0,LeftEnd - LeftStart - 1);
								Value = largefixed2double(GetSampleStorageDisplayValue(View->Storage,
									Index,eLeftChannel));
								Position = ((1 - Value) / 2) * (LeftEnd - LeftStart - 1);
								if (Position == (LeftEnd - LeftStart - 1) / 2)
									{
										/* zero point:  displace very nearly zero points away from the */
										/* origin line so you can see they aren't zero */
										if (Value < 0)
											{
												Position += 1;
											}
										else if (Value > 0)
											{
												Position -= 1;
											}
									}
								DrawLine(View->ScreenID,DotColor,Scan + View->XLoc + 1,
									LeftStart + Position,0,0);
								/* draw right line */
								DrawLine(View->ScreenID,BackgroundColor,Scan + View->XLoc + 1,
									RightStart,0,RightEnd - RightStart - 1);
								Value = largefixed2double(GetSampleStorageDisplayValue(View->Storage,
									Index,eRightChannel));
								Position = ((1 - Value) / 2) * (RightEnd - RightStart - 1);
								if (Position == (RightEnd - RightStart - 1) / 2)
									{
										/* zero point:  displace very nearly zero points away from the */
										/* origin line so you can see they aren't zero */
										if (Value < 0)
											{
												Position += 1;
											}
										else if (Value > 0)
											{
												Position -= 1;
											}
									}
								DrawLine(View->ScreenID,DotColor,Scan + View->XLoc + 1,
									RightStart + Position,0,0);
							}
						 else
							{
								DrawLine(View->ScreenID,eLightGrey,Scan + View->XLoc + 1,LeftStart,
									0,LeftEnd - LeftStart - 1);
								DrawLine(View->ScreenID,eLightGrey,Scan + View->XLoc + 1,RightStart,
									0,RightEnd - RightStart - 1);
							}
					}
			}
		 else
			{
				OrdType				Start;
				OrdType				End;
				OrdType				Scan;

				/* mono sample has one pane */
				Start = View->YLoc + 1;
				End = View->YLoc + View->Height - 1;
				for (Scan = 0; Scan < View->Width - 2; Scan += 1)
					{
						long								Index;
						Patterns						DotColor;
						Patterns						BackgroundColor;

						Index = (Scan * View->XScale) + View->HorizontalIndex;
						if ((Index >= View->SelectionStart) && (Index < View->SelectionEnd))
							{
								DotColor = eWhite;
								BackgroundColor = eBlack;
							}
						else if ((View->SelectionStart == View->SelectionEnd)
							&& (Index == View->SelectionStart))
							{
								DotColor = eBlack;
								BackgroundColor = eMediumGrey;
							}
						else
							{
								DotColor = eBlack;
								BackgroundColor = eWhite;
							}
						if ((Index >= 0) && (Index < NumSampleFrames))
							{
								double					Value;
								OrdType					Position;

								/* mono */
								DrawLine(View->ScreenID,BackgroundColor,Scan + View->XLoc + 1,
									Start,0,End - Start - 1);
								Value = largefixed2double(GetSampleStorageDisplayValue(View->Storage,
									Index,eMonoChannel));
								Position = ((1 - Value) / 2) * (End - Start - 1);
								if (Position == (End - Start - 1) / 2)
									{
										/* zero point:  displace very nearly zero points away from the */
										/* origin line so you can see they aren't zero */
										if (Value < 0)
											{
												Position += 1;
											}
										else if (Value > 0)
											{
												Position -= 1;
											}
									}
								DrawLine(View->ScreenID,DotColor,Scan + View->XLoc + 1,
									Start + Position,0,0);
							}
						 else
							{
								DrawLine(View->ScreenID,eLightGrey,Scan + View->XLoc + 1,
									Start,0,End - Start - 1);
							}
					}
			}
	}


/* return the number of bits that the sample storage object has */
NumBitsType					GetSampleViewNumBits(SampleViewRec* View)
	{
		CheckPtrExistence(View);
		return GetSampleStorageDisplayNumBits(View->Storage);
	}


/* return the number of channels that the sample has */
NumChannelsType			GetSampleViewNumChannels(SampleViewRec* View)
	{
		CheckPtrExistence(View);
		return GetSampleStorageDisplayNumChannels(View->Storage);
	}


/* return the number of sample frames in the sample */
long								GetSampleViewNumFrames(SampleViewRec* View)
	{
		CheckPtrExistence(View);
		return GetSampleStorageDisplayNumFrames(View->Storage);
	}


/* return one point from the sample array.  for mono samples, WhichChannel must be */
/* eMonoChannel.  for stereo samples, it must either be eRightChannel or eLeftChannel */
largefixedsigned		GetSampleViewValue(SampleViewRec* View, long Index,
											ChannelType WhichChannel)
	{
		CheckPtrExistence(View);
		return GetSampleStorageDisplayValue(View->Storage,Index,WhichChannel);
	}


/* change the number of bits the sample is stored as */
MyBoolean						SetSampleViewNumBits(SampleViewRec* View,
											NumBitsType NewNumBits)
	{
		CheckPtrExistence(View);
		SetSampleStorageDisplayNumBits(View->Storage,NewNumBits);
		RedrawSampleView(View);
		return True;
	}


/* change the number of channels the sample has */
MyBoolean						SetSampleViewNumChannels(SampleViewRec* View,
											NumChannelsType NewNumChannels)
	{
		MyBoolean					Result;

		CheckPtrExistence(View);
		Result = SetSampleStorageDisplayNumChannels(View->Storage,NewNumChannels);
		RedrawSampleView(View);
		return Result;
	}


void								SetSampleViewValue(SampleViewRec* View, long Index,
											ChannelType WhichChannel, largefixedsigned NewValue)
	{
		CheckPtrExistence(View);
		SetSampleStorageDisplayValue(View->Storage,Index,WhichChannel,NewValue);
		/* don't redraw! */
	}


/* insert a zero area into the sample.  returns True if successful. */
MyBoolean						InsertSampleViewArea(SampleViewRec* View, long Index,
											long NumFramesToInsert)
	{
		MyBoolean					ReturnValue;

		CheckPtrExistence(View);
		ReturnValue = InsertSampleStorageDisplayArea(View->Storage,Index,NumFramesToInsert);
		if (ReturnValue)
			{
				View->SelectionStart = Index;
				View->SelectionEnd = Index + NumFramesToInsert;
				RedrawSampleView(View);
			}
		return ReturnValue;
	}


/* delete an area from the sample.  returns True if successful. */
MyBoolean						DeleteSampleViewArea(SampleViewRec* View, long Index,
											long NumFramesToDelete)
	{
		MyBoolean					ReturnValue;

		CheckPtrExistence(View);
		ReturnValue = DeleteSampleStorageDisplayArea(View->Storage,Index,NumFramesToDelete);
		if (ReturnValue)
			{
				View->SelectionStart = Index;
				View->SelectionEnd = Index;
				RedrawSampleView(View);
			}
		SampleViewValidateSelection(View); /* make sure selection is still valid */
		return ReturnValue;
	}


/* return the index of the leftmost displayed sample frame */
long								GetSampleViewXOffset(SampleViewRec* View)
	{
		CheckPtrExistence(View);
		return View->HorizontalIndex;
	}


void								SetSampleViewXOffset(SampleViewRec* View, long NewXOffset)
	{
		CheckPtrExistence(View);
		if (NewXOffset > GetSampleViewNumFrames(View) - GetSampleViewNumVisibleFrames(View))
			{
				NewXOffset = GetSampleViewNumFrames(View) - GetSampleViewNumVisibleFrames(View);
			}
		if (NewXOffset < 0)
			{
				NewXOffset = 0;
			}
		View->HorizontalIndex = NewXOffset;
		RedrawSampleView(View);
	}


/* return the scaling factor (zoom in/out).  large numbers are compress more. */
double							GetSampleViewHorizontalScale(SampleViewRec* View)
	{
		CheckPtrExistence(View);
		return View->XScale;
	}


void								SetSampleViewHorizontalScale(SampleViewRec* View,
											double NewHorizontalScale)
	{
		double						ZoomFactor;
		long							HalfVisibleFrames;

		CheckPtrExistence(View);
		if (NewHorizontalScale < MINIMUMHORIZSCALE)
			{
				NewHorizontalScale = MINIMUMHORIZSCALE;
			}
		/* if we zoom in or out, try to center it */
		/* if we zoom in a factor of 2, then we lose 1/4 off each side, thus */
		/* adjust Xposition by 1/4 of visible frames */
		/* if we zoom in a factor of 4, then we lose 6/8 of image, or 3/8 off each side */
		/* if we zoom by 0.5, we gain on each side. */
		HalfVisibleFrames = GetSampleViewNumVisibleFrames(View) / 2;
		ZoomFactor = View->XScale / NewHorizontalScale; /* >1 = zoom in, <1 = zoom out */
		View->HorizontalIndex += HalfVisibleFrames - (HalfVisibleFrames / ZoomFactor);
		if (View->HorizontalIndex < 0)
			{
				View->HorizontalIndex = 0;
			}
		View->XScale = NewHorizontalScale;
		RedrawSampleView(View);
	}


/* extract a section of the sample & return a new sample object containing it. */
SampleStorageDisplayRec*	ExtractSampleViewSection(SampleViewRec* View, long Index,
											long NumFramesToExtract)
	{
		CheckPtrExistence(View);
		return ExtractSampleStorageDisplaySection(View->Storage,Index,NumFramesToExtract);
	}


/* insert a sample into our sample at a specified point.  returns True if successful */
MyBoolean						InsertSampleViewSection(SampleViewRec* View, long Index,
											SampleStorageDisplayRec* DataToInsert)
	{
		MyBoolean					ReturnValue;

		CheckPtrExistence(View);
		ReturnValue = InsertSampleStorageDisplaySection(View->Storage,Index,DataToInsert);
		if (ReturnValue)
			{
				View->SelectionStart = Index;
				View->SelectionEnd = Index + GetSampleStorageDisplayNumFrames(DataToInsert);
				RedrawSampleView(View);
			}
		return ReturnValue;
	}


/* get the start point of the selection */
long								GetSampleViewSelectStart(SampleViewRec* View)
	{
		CheckPtrExistence(View);
		return View->SelectionStart;
	}


/* get the end point of the selection */
long								GetSampleViewSelectEnd(SampleViewRec* View)
	{
		CheckPtrExistence(View);
		return View->SelectionEnd;
	}


/* set a selection.  if the selection is invalid, it will be corrected. */
void								SetSampleViewSelection(SampleViewRec* View, long Start, long End)
	{
		CheckPtrExistence(View);
		View->SelectionStart = Start;
		View->SelectionEnd = End;
		SampleViewValidateSelection(View);
		RedrawSampleView(View);
	}


/* make sure the selection is correct (i.e. not out of range) */
void								SampleViewValidateSelection(SampleViewRec* View)
	{
		MyBoolean					SomethingChanged = False;

		CheckPtrExistence(View);
		if (View->SelectionStart < 0)
			{
				SomethingChanged = True;
				View->SelectionStart = 0;
			}
		if (View->SelectionEnd > GetSampleStorageDisplayNumFrames(View->Storage))
			{
				SomethingChanged = True;
				View->SelectionEnd = GetSampleStorageDisplayNumFrames(View->Storage);
			}
		if (View->SelectionStart > View->SelectionEnd)
			{
				SomethingChanged = True;
				View->SelectionStart = View->SelectionEnd;
			}
		if (SomethingChanged)
			{
				RedrawSampleView(View);
			}
	}


/* return the left edge of the sample view area */
OrdType							GetSampleViewXLoc(SampleViewRec* View)
	{
		CheckPtrExistence(View);
		return View->XLoc;
	}


/* return the top edge of the sample view area */
OrdType							GetSampleViewYLoc(SampleViewRec* View)
	{
		CheckPtrExistence(View);
		return View->YLoc;
	}


/* return the width of the sample view area */
OrdType							GetSampleViewWidth(SampleViewRec* View)
	{
		CheckPtrExistence(View);
		return View->Width;
	}


/* return the height of the sample view area */
OrdType							GetSampleViewHeight(SampleViewRec* View)
	{
		CheckPtrExistence(View);
		return View->Height;
	}


/* move the sample view to a new location */
void								SetSampleViewLocation(SampleViewRec* View, OrdType XLoc,
											OrdType YLoc, OrdType Width, OrdType Height)
	{
		CheckPtrExistence(View);
		View->XLoc = XLoc;
		View->YLoc = YLoc;
		View->Width = Width;
		View->Height = Height;
		RedrawSampleView(View);
	}


/* return the number of frames that are currently displayed. */
long								GetSampleViewNumVisibleFrames(SampleViewRec* View)
	{
		CheckPtrExistence(View);
		return (View->Width - 2) * View->XScale - 1;
	}


/* return True if the data has been modified since the last time it was saved */
MyBoolean						DoesSampleViewNeedToBeSaved(SampleViewRec* View)
	{
		CheckPtrExistence(View);
		return DoesSampleStorageDisplayNeedToBeSaved(View->Storage);
	}


/* clear the not-saved flag.  this is called when the file is saved */
void								SampleViewHasBeenSaved(SampleViewRec* View)
	{
		CheckPtrExistence(View);
		SampleStorageDisplayHasBeenSaved(View->Storage);
	}


/* make a copy of the data in NewData & store it in the current sample.  NewData is */
/* not disposed. */
MyBoolean						SampleViewSetContents(SampleViewRec* View,
											SampleStorageDisplayRec* NewData)
	{
		MyBoolean					ReturnValue;

		CheckPtrExistence(View);
		ReturnValue = SampleStorageDisplaySetContents(View->Storage,NewData);
		if (ReturnValue)
			{
				View->SelectionStart = 0;
				View->SelectionEnd = 0;
				RedrawSampleView(View);
			}
		return ReturnValue;
	}


/* returns True if there is a selection or False if there is an insertion point. */
MyBoolean						SampleViewIsThereValidSelection(SampleViewRec* View)
	{
		CheckPtrExistence(View);
		return View->SelectionStart < View->SelectionEnd;
	}


/* get a copy of the specified channel as an array of fixedpoint numbers */
largefixedsigned*		SampleViewGetChannelFixed(SampleViewRec* View,
											ChannelType WhichChannel)
	{
		CheckPtrExistence(View);
		return SampleStorageDisplayGetChannelFixed(View->Storage,WhichChannel);
	}


/* store a new array of data into the sample (replacing old contents).  returns */
/* True if successful.  this can only be used for mono samples. */
MyBoolean						SampleViewPutMonoFixed(SampleViewRec* View, largefixedsigned* Data)
	{
		MyBoolean					Result;

		CheckPtrExistence(View);
		Result = SampleStorageDisplayPutMonoFixed(View->Storage,Data);
		SetSampleViewSelection(View,View->SelectionStart,View->SelectionEnd);
		return Result;
	}


/* store new arrays of data into the sample (replacing old contents).  returns True */
/* if successful.  this can only be used for stereo samples. */
MyBoolean						SampleViewPutStereoFixed(SampleViewRec* View, largefixedsigned* Left,
											largefixedsigned* Right)
	{
		MyBoolean					Result;

		CheckPtrExistence(View);
		Result = SampleStorageDisplayPutStereoFixed(View->Storage,Left,Right);
		SetSampleViewSelection(View,View->SelectionStart,View->SelectionEnd);
		return Result;
	}


/* flush undo information. */
void								SampleViewFlushUndo(SampleViewRec* View)
	{
		CheckPtrExistence(View);
		SampleStorageDisplayFlushUndo(View->Storage);
	}


/* save the current sample configuration into the undo information. */
MyBoolean						SampleViewSetupForUndo(SampleViewRec* View)
	{
		MyBoolean					Result;

		CheckPtrExistence(View);
		Result = SampleStorageDisplaySetupForUndo(View->Storage);
		RedrawSampleView(View);
		return Result;
	}


/* find out if it is possible to restore state to the last SampleViewSetupForUndo() */
MyBoolean						SampleViewUndoAvailable(SampleViewRec* View)
	{
		CheckPtrExistence(View);
		return SampleStorageDisplayUndoAvailable(View->Storage);
	}


/* attempt to undo.  returns True if successful.  this call swaps the current sample */
/* state with that saved from the last call to SampleViewSetupForUndo(). */
MyBoolean						SampleViewUndo(SampleViewRec* View)
	{
		MyBoolean					Result;

		CheckPtrExistence(View);
		Result = SampleStorageDisplayUndo(View->Storage);
		RedrawSampleView(View);
		return Result;
	}


/* get the actual raw sample data */
largefixedsigned*		SampleViewGetActualRawData(SampleViewRec* View)
	{
		CheckPtrExistence(View);
		return SampleStorageDisplayGetActualData(View->Storage);
	}
