extern struct Border BorderCancel;
extern ULONG allocated[4],start[4];
extern ULONG startpos[4],end[4],length[4],startpos[4];
extern struct Window *RequestWindow;

struct NewWindow NewDisplayWindow = {
       55,19,530,172,0,1,
       CLOSEWINDOW|GADGETDOWN|GADGETUP,
       ACTIVATE,
       NULL,NULL,
       "Graphic Display: Track 1",
       NULL,NULL,
       640,200,640,200,
       WBENCHSCREEN };

#define STRPOSITION1 75
#define STRPOSITION2 90
#define EXIT 52
#define ONEONE 91
#define ALL 57
#define SAMPLE 58
#define BACKWARD1 59
#define FORWARD1 60
#define RIGHT 93
#define LEFT 92
#define POSITION1 50
#define POSITION2 51
#define ONE_TO_ONE TRUE
#define DIS_ALL FALSE

char BufferDisplay1[7] = "0";
char BufferDisplay2[7] = "0";
char BufferSample[4] = "0";

struct PropInfo PositionInfo[2];

struct StringInfo DisplayPositionInfo1 = { BufferDisplay1,0,0,7,0,0,3,2,10,27,0,0,0 };
struct StringInfo DisplayPositionInfo2 = { BufferDisplay2,0,0,7,0,0,3,2,10,27,0,0,0 };
struct StringInfo SampleInfo = { BufferSample,0,0,4,0,0,0,10,27,0,0,0 };

struct Image PositionImage[3];

struct IntuiText TextExit = {1,0,JAM2,3,2,NULL," EXIT ",NULL };
struct IntuiText TextOne_One = {1,0,JAM2,15,2,NULL,"1:1",NULL };
struct IntuiText TextAll = {1,0,JAM2,15,2,NULL,"ALL",NULL };

USHORT LinesPosition[] = { 0,0,63,0,63,10,0,10,0,0 };
USHORT LinesForward[] = { 0,0,25,0,25,10,0,10,0,0 };
USHORT LinesCursorLeft[] = { 2,3,15,3,15,1,23,5,23,6,15,9,15,7,2,7,2,3 };
USHORT LinesCursorRight[] = { 23,3,10,3,10,1,2,5,2,6,10,9,10,7,23,7,23,3 };
USHORT LinesSample[] = { 0,0,55,0,55,10,0,10,0,0 };

struct Border BorderPosition = { 2,-2,1,3,JAM1,5,&LinesPosition,NULL };
struct Border DrawCursorLeft = { 0,0,1,3,JAM1,9,&LinesCursorLeft,NULL };
struct Border DrawCursorRight = { 0,0,1,3,JAM1,9,&LinesCursorRight,NULL };
struct Border BorderBackward = { 0,0,1,3,JAM1,5,&LinesForward,&DrawCursorLeft };
struct Border BorderForward = { 0,0,1,3,JAM1,5,&LinesForward,&DrawCursorRight };
struct Border BorderSample = { 14,-2,1,3,JAM1,5,&LinesSample,NULL };

struct Gadget GGPosition1 = { NULL,5,145,274,11,GADGHCOMP,
                              RELVERIFY|GADGIMMEDIATE,PROPGADGET,
                              &PositionImage[0],0,NULL,0,&PositionInfo[0],POSITION1,0};
struct Gadget GGPosition2 = { &GGPosition1,5,158,274,11,GADGHCOMP,
                              RELVERIFY|GADGIMMEDIATE,PROPGADGET,
                              &PositionImage[1],0,NULL,0,&PositionInfo[1],POSITION2,0};
struct Gadget GGExit = { &GGPosition2,468,145,56,11,GADGHCOMP,GADGIMMEDIATE|RELVERIFY,
                         BOOLGADGET,&BorderCancel,0,&TextExit,0,0,EXIT,0};
struct Gadget GGOne_One = { &GGExit,408,158,56,11,GADGHCOMP,RELVERIFY,
                         BOOLGADGET,&BorderCancel,0,&TextOne_One,0,0,ONEONE,0};
struct Gadget GGAll = { &GGOne_One,468,158,56,11,GADGHCOMP,GADGIMMEDIATE|RELVERIFY,
                         BOOLGADGET,&BorderCancel,0,&TextAll,0,0,ALL,0};
struct Gadget GGSample = { &GGAll,394,147,64,11,GADGHCOMP,
                           RELVERIFY|STRINGRIGHT|LONGINT,STRGADGET,
                           &BorderSample,0,NULL,0,&SampleInfo,SAMPLE,0};
struct Gadget GGForward1 = { &GGSample,282,145,26,11,GADGHCOMP,GADGIMMEDIATE|RELVERIFY,
                         BOOLGADGET,&BorderForward,0,NULL,0,0,FORWARD1,0};
struct Gadget GGBackward1 = { &GGForward1,311,145,26,11,GADGHCOMP,GADGIMMEDIATE|RELVERIFY,
                         BOOLGADGET,&BorderBackward,0,NULL,0,0,BACKWARD1,0};
struct Gadget GGForward2 = { &GGBackward1,282,158,26,11,GADGHCOMP,GADGIMMEDIATE|RELVERIFY,
                         BOOLGADGET,&BorderForward,0,NULL,0,0,RIGHT,0};
struct Gadget GGBackward2 = { &GGForward2,311,158,26,11,GADGHCOMP,GADGIMMEDIATE|RELVERIFY,
                         BOOLGADGET,&BorderBackward,0,NULL,0,0,LEFT,0};
struct Gadget GGStringPosition1 = { &GGBackward2,338,147,64,11,GADGHCOMP,
                              RELVERIFY|STRINGRIGHT|LONGINT,STRGADGET,
                              &BorderPosition,0,NULL,0,&DisplayPositionInfo1,STRPOSITION1,0};
struct Gadget GGStringPosition2 = { &GGStringPosition1,338,160,64,11,GADGHCOMP,
                              RELVERIFY|STRINGRIGHT|LONGINT,STRGADGET,
                              &BorderPosition,0,NULL,0,&DisplayPositionInfo2,STRPOSITION2,0};

ULONG hipart,lopart,part,partition;
struct RastPort *DrawRast;
struct Window *DisplayWindow;
SHORT coordinates[1024];
BOOL DisplayModus,LineDrawed;
ULONG RangeStart,RangeEnd;

DisplayTrack(track)

 UBYTE track;

{
 struct IntuiMessage *DisplayMsg;
 struct Gadget *WhatGadget;
 ULONG position=0,Class;
 USHORT ID;
 BOOL exit=FALSE;
 ULONG Start,End,OldStart,OldEnd;

 PositionInfo[0].Flags=FREEHORIZ|AUTOKNOB;
 PositionInfo[1].Flags=FREEHORIZ|AUTOKNOB;
 PositionInfo[1].HorizBody=1;
 PositionInfo[0].HorizBody=1;
 PositionInfo[1].HorizPot=0;
 PositionInfo[0].HorizPot=0;
 partition=100*allocated[track]/256;
 DisplayModus=ONE_TO_ONE;

 NewDisplayWindow.Title[23]=track+49;
 NewDisplayWindow.FirstGadget=&GGStringPosition2;
 if (!(DisplayWindow=OpenWindow(&NewDisplayWindow)))
     {
      DisplayRequest("Not enough memory to open window!");
      return;
     }
 DrawRast=DisplayWindow->RPort;
 SetDrMd(DrawRast,JAM1);
 Start=RangeStart=startpos[track];
 DisplaySample(Start+start[track]);
 End=RangeEnd=end[track];
 NextPosition(Start,track);
 DrawIt();
 RefreshPosition(Start,&GGPosition1);
 RefreshPosition(End,&GGPosition2);
 Number_to_String(BufferDisplay1,Start,5);
 OnlyRefresh(&GGStringPosition1,DisplayWindow);
 Number_to_String(BufferDisplay2,End,5);
 OnlyRefresh(&GGStringPosition2,DisplayWindow);

 while(exit==FALSE)
 {
  WaitPort(DisplayWindow->UserPort);
  while (DisplayMsg=GetMsg(DisplayWindow->UserPort))
         {
          WhatGadget=DisplayMsg->IAddress;
          ID=WhatGadget->GadgetID;
          Class=DisplayMsg->Class;
          ReplyMsg(DisplayMsg);
          switch(Class)
                {
                 case GADGETDOWN:
                 switch(ID)
                    {
                     case POSITION1:
                     SoundOFF(track);
                     do {
                     OldStart=Start;
                     position=PositionInfo[0].HorizPot/256*partition;
                     position/=100;
                     if (position<End)
                         Start=position/2*2;
                     else Start=End-2;
                     if (OldStart!=Start && !DisplayModus)
                         {
                          DrawStart(OldStart);
                          DrawStart(Start);
                         }
                     DisplaySample(Start+start[track]);
                     Number_to_String(BufferDisplay1,Start,5);
                     OnlyRefresh(&GGStringPosition1,DisplayWindow);
                     } while(!(64 & *((UBYTE *)0xbfe001)));
                     SetStart(track,Start);
                     SetStatus(track);
                     if (DisplayModus)
                         {
                          NextPosition(Start,track);
                          DrawIt();
                         }
                     break;
                     case POSITION2:
                     SoundOFF(track);
                     do {
                     OldEnd=End;
                     position=PositionInfo[1].HorizPot/256*partition;
                     position/=100;
                     if (position>Start) End=position/2*2;
                     else End=Start+2;
                     if (OldEnd!=End && !DisplayModus)
                         {
                          DrawEnd(OldEnd);
                          DrawEnd(End);
                         }
                     Number_to_String(BufferDisplay2,End,5);
                     OnlyRefresh(&GGStringPosition2,DisplayWindow);
                     } while(!(64 & *((UBYTE *)0xbfe001)));
                     SetEnd(track,End);
                     SetStatus(track);
                     break;
                     case BACKWARD1:
                     SoundOFF(track);
                     if (!DisplayModus) DrawStart(Start);
                     do {
                     if (!(Start+2==End || Start>=allocated[track])) Start+=2;
                     DisplaySample(Start+start[track]);
                     Number_to_String(BufferDisplay1,Start,5);
                     OnlyRefresh(&GGStringPosition1,DisplayWindow);
                     } while(!(64 & *((UBYTE *)0xbfe001)));
                     if (DisplayModus)
                         {
                          NextPosition(Start,track);
                          DrawIt();
                         }
                     else DrawStart(Start);
                     SetStart(track,Start);
                     SetStatus(track);
                     RefreshPosition(Start,&GGPosition1);
                     break;
                     case FORWARD1:
                     SoundOFF(track);
                     if (!DisplayModus) DrawStart(Start);
                     do {
                     if (Start) Start-=2;
                     DisplaySample(Start+start[track]);
                     Number_to_String(BufferDisplay1,Start,5);
                     OnlyRefresh(&GGStringPosition1,DisplayWindow);
                     } while(!(64 & *((UBYTE *)0xbfe001)));
                     if (DisplayModus)
                         {
                          NextPosition(Start,track);
                          DrawIt();
                         }
                     else DrawStart(Start);
                     SetStart(track,Start);
                     SetStatus(track);
                     RefreshPosition(Start,&GGPosition1);
                     break;
                     case LEFT:
                     SoundOFF(track);
                     if (!DisplayModus) DrawEnd(End);
                     do {
                     if (!(End>=allocated[track]-2)) End+=2;
                     Number_to_String(BufferDisplay2,End,5);
                     OnlyRefresh(&GGStringPosition2,DisplayWindow);
                     } while(!(64 & *((UBYTE *)0xbfe001)));
                     if (!DisplayModus) DrawEnd(End);
                     SetEnd(track,End);
                     SetStatus(track);
                     RefreshPosition(End,&GGPosition2);
                     break;
                     case RIGHT:
                     SoundOFF(track);
                     if (!DisplayModus) DrawEnd(End);
                     do {
                     if (!(End-2==Start)) End-=2;
                     Number_to_String(BufferDisplay2,End,5);
                     OnlyRefresh(&GGStringPosition2,DisplayWindow);
                     } while(!(64 & *((UBYTE *)0xbfe001)));
                     if (!DisplayModus) DrawEnd(End);
                     SetEnd(track,End);
                     SetStatus(track);
                     RefreshPosition(End,&GGPosition2);
                     break;
                    }
                 break;
                 case GADGETUP:
                 switch(ID)
                       {
                        case EXIT:
                        RefreshOneShot(track);
                        CloseWindow(DisplayWindow);
                        return;
                        break;
                        case ONEONE:
                        DisplayModus=ONE_TO_ONE;
                        NextPosition(Start,track);
                        DrawIt();
                        break;
                        case ALL:
                        DisplayModus=DIS_ALL;
                        WindowRequest("Working...",0);
                        CalculateAll(track);
                        CloseWindow(RequestWindow);
                        DrawIt();
                        RangeStart=Start;
                        RangeEnd=End;
                        DrawStart(Start);
                        DrawEnd(End);
                        break;
                        case STRPOSITION1:
                        SoundOFF(track);
                        if (!DisplayModus) DrawStart(Start);
                        position=DisplayPositionInfo1.LongInt;
                        if (position<End) Start=position;
                        else {
                              Number_to_String(BufferDisplay1,Start,5);
                              OnlyRefresh(&GGStringPosition1,DisplayWindow);
                             }
                        if (!DisplayModus) DrawStart(Start);
                        SetStart(track,Start);
                        SetStatus(track);
                        RefreshPosition(Start,&GGPosition1);
                        break;
                        case STRPOSITION2:
                        SoundOFF(track);
                        if (!DisplayModus) DrawEnd(End);
                        position=DisplayPositionInfo2.LongInt;
                        if (position>Start && position<allocated[track])
                            End=position;
                        else {
                              Number_to_String(BufferDisplay2,End,5);
                              OnlyRefresh(&GGStringPosition2,DisplayWindow);
                             }
                        if (!DisplayModus) DrawEnd(End);
                        SetEnd(track,End);
                        SetStatus(track);
                        RefreshPosition(End,&GGPosition2);
                        break;
                       }
                 break;
                 case CLOSEWINDOW:
                 DisplayRequest("Close window!");
                 CloseWindow(DisplayWindow);
                 return;
                 break;
                }
         }
 }
}

NextPosition(Position,track)

 ULONG Position;
 UBYTE track;

{
 register UWORD fast;
 register UWORD index;
 UBYTE *value;
 UBYTE sampledvalue;
 ULONG MemoryStart;
 ULONG MemoryEnd;

 fast=0;
 MemoryStart=start[track]+Position;
 MemoryEnd=start[track]+allocated[track];

 while (fast<512)
       {
        index=fast<<1;
        value=(UBYTE *)(MemoryStart+fast);
        sampledvalue=*value;
        if (value > MemoryEnd) sampledvalue=0;
        sampledvalue ^=128;
        sampledvalue=sampledvalue>>1;
        coordinates[index]=fast+8;
        coordinates[index+1]=142-sampledvalue;
        fast++;
       }
}

DisplaySample(Position)

 UBYTE *Position;

{
 Number_to_String(BufferSample,(ULONG)(*Position ^ 128),2);
 OnlyRefresh(&GGSample,DisplayWindow);
}

CalculateAll(Track)

 UBYTE Track;

{
 register UWORD fast1,fast2,index;
 register char *value;
 UBYTE sampledvalue;
 UWORD part;
 ULONG sum,endpos;
 char  min,max,sample;

 endpos=start[Track]+allocated[Track];
 part=length[Track]/512+1;
 value=(char *)(start[Track]+startpos[Track]);
 for (fast1=0;fast1<512;fast1++)
      {
       index=fast1<<1;
       if (value < endpos) min=max=*value;
       value++;
       for (fast2=1;fast2<part;fast2++)
            {
             sample=*value;
             if (value >= endpos) sample=0;
             if (max < sample) max=sample;
             if (min > sample) min=sample;
             value++;
            }
       if (min == -128) min=-127;
       if (max>ABS(min)) sampledvalue=(UBYTE)max;
       else sampledvalue=(UBYTE)min;
       sampledvalue^=128;
       sampledvalue=sampledvalue>>1;
       coordinates[index]=fast1+8;
       coordinates[index+1]=142-sampledvalue;
      }
}

/*
CalculateAll(Track)

 UBYTE Track;

{
 register UWORD fast1,fast2,index;
 register UBYTE *value;
 UBYTE sampledvalue;
 UWORD part;
 ULONG sum,endpos;
 
 endpos=start[Track]+allocated[Track];
 part=length[Track]/512+1;
 value=(UBYTE *)(start[Track]+startpos[Track]);
 for (fast1=0;fast1<512;fast1++)
      {
       index=fast1<<1;
       sum=0;
       for (fast2=0;fast2<part;fast2++)
            {
             if (value<endpos) sum += (*value ^128);
             else sum += 128;
             value++;
            }
       sampledvalue=(UBYTE)(sum/part);
       sampledvalue=sampledvalue>>1;
       coordinates[index]=fast1+8;
       coordinates[index+1]=142-sampledvalue;
      }
}
*/
/*
CalculateAll(Track)

 UBYTE Track;

{
 register UWORD fast1,fast2,index;
 register UBYTE *value;
 UBYTE sampledvalue;
 UWORD part;
 ULONG sum,endpos;
 
 endpos=allocated[Track];
 part=length[Track]/512+1;
 value=(UBYTE *)(start[Track]+startpos[Track]);
 for (fast1=0;fast1<512;fast1++)
      {
       index=fast1<<1;
       endpos=fast1*part;
       if (endpos<allocated[Track]) sampledvalue=(UBYTE)value[fast1*part];
       else sampledvalue=0;
       sampledvalue^=128;
       sampledvalue=sampledvalue>>1;
       coordinates[index]=fast1+8;
       coordinates[index+1]=142-sampledvalue;
      }
}
*/
/*
CalculateAll(Track)

 UBYTE Track;

{
 register UWORD fast1,fast2,index;
 register char *value,*endpos;
 char sampledvalue;
 UBYTE m1,m2;
 UWORD part;
 ULONG sum1,sum2,c1,c2;
 
 endpos=start[Track]+allocated[Track];
 part=(length[Track]/256);
 value=(char *)(start[Track]+startpos[Track]);
 for (fast1=0;fast1<256;fast1++)
      {
       index=fast1*4;
       sum1=c1=0;
       sum2=c2=0;
       for (fast2=0;fast2<part;fast2++)
            {
             if (value<endpos)
                 {
                  sampledvalue=*value;
                  if (sampledvalue<0)
                      {
                       sum1+=(ULONG)(sampledvalue & 127);
                       c1++;
                       value++;
                      }
                  else {
                        sum2+=(ULONG)sampledvalue;
                        c2++;
                        value++;
                       }
                 }
             else
                { c2++;
                  value++;
                }
            }
       if (c1) m1=(UBYTE)(sum1/c1);
       m1=m1>>1;
       if (c2) m2=(UBYTE)(sum2/c2);
       m2^=128;
       m2=m2>>1;
       if (!c1) m2=m1;
       if (!c2) m1=m2;
       coordinates[index]=(SHORT)((fast1<<1)+8);
       coordinates[index+1]=(SHORT)142-m1;
       coordinates[index+2]=(SHORT)(fast1<<1)+9;
       coordinates[index+3]=(SHORT)142-m2;
      }
}
*/
DrawIt()
{
 SetDrMd(DrawRast,JAM1);
 SetAPen(DrawRast,0);
 RectFill(DrawRast,2,13,527,142);
 SetAPen(DrawRast,1);
 Move(DrawRast,coordinates[0],coordinates[1]);
 PolyDraw(DrawRast,511,&coordinates[2]);
}

RefreshPosition(Value,Gadget)

 ULONG Value;
 struct Gadget *Gadget;

{
 ULONG SetValue;

 if (partition) SetValue=(Value*256/partition)*100;
 else SetValue=0;
 if (SetValue>65535) SetValue=65535;
 ((struct PropInfo *)(Gadget->SpecialInfo))->HorizPot=(UWORD)SetValue;
 OnlyRefresh(Gadget,DisplayWindow);
}

DrawStart(Start)

 ULONG Start;

{
 ULONG LineStart;

 if (RangeStart>=RangeEnd) return;
 if (Start>=RangeStart && Start<=RangeEnd)
     {
      LineStart=512*(Start-RangeStart)/(RangeEnd-RangeStart);
      SetDrMd(DrawRast,COMPLEMENT);
      Move(DrawRast,LineStart+8,142);
      Draw(DrawRast,LineStart+8,14);
     }
}

DrawEnd(End)

 ULONG End;

{
 ULONG LineEnd;

 if (RangeEnd<=RangeStart) return;
 if (End>=RangeStart && End<=RangeEnd)
     {
      LineEnd=512*(End-RangeStart)/(RangeEnd-RangeStart);
      SetDrMd(DrawRast,COMPLEMENT);
      Move(DrawRast,LineEnd+8,142);
      Draw(DrawRast,LineEnd+8,14);
     }
}
