/*
**     Glzy's SEEd.c
**         08.88
*/
#include <math.h>
#include <stdio.h>
#include <exec/types.h>
#include <intuition/intuition.h>
#include <graphics/gfx.h>
#include <devices/audio.h>
#include <exec/memory.h>
#define GH (0xFFFF/255)
#define GL (0xFFFF/255)
#define GC (0xFFFF/64)
#define GV (0xFFFF/64)
#define ENDE (((Ende-Start)/2)+1)
#define MOUSX (win->MouseX)
#define MOUSY (win->MouseY)
#define GAD_ID (((struct Gadget *)ADDR)->GadgetID)
APTR ADDR;
ULONG CLASS, CODE;
UBYTE *Data,buffer=15,name[31],undo[31],Titel[]=(UBYTE *)"-*- Glzy's SEEd -*-";
UWORD l,h,p,c,v;
struct Image HDummy,LDummy,CDummy,VDummy;
SHORT Start=0,Ende=510;
SHORT OKpairs[]        ={ 0,0,  61,0,  61,21, 0,21, 0,0  };
SHORT Reqpairs[]       ={ 0,0, 246,0, 246,67, 0,67, 0,0  };
SHORT Spairs[]         ={ 0,0, 210,0, 210,11, 0,11, 0,0  };
struct Border OKRand   ={ -1, -1, 1,0, JAM1, 5,&OKpairs[0], NULL       };
struct Border ReqR     ={ 2, 1, 1,0, JAM1, 5,&Reqpairs[0], NULL        };
struct Border SRand    ={ -1, -2, 1,0, JAM1, 5,&Spairs[0], NULL        };
struct IntuiText OKT2  ={ 1,0,JAM1,14,6,NULL,(UBYTE *)"QUIT",NULL      };
struct IntuiText OKText={ 3,0,JAM1,15,7,NULL,(UBYTE *)"QUIT",&OKT2     };
struct IntuiText SaText={ 1,0,JAM1,14,6,NULL,(UBYTE *)"Save",NULL      };
struct IntuiText MText ={ 1,0,JAM1,10,6,NULL,(UBYTE *)"Multi",NULL     };
struct IntuiText RText ={ 1,0,JAM1,14,6,NULL,(UBYTE *)"REck",NULL      };
struct IntuiText ZText ={ 1,0,JAM1,10,6,NULL,(UBYTE *)"SZahn",NULL     };
struct IntuiText DText ={ 1,0,JAM1,14,6,NULL,(UBYTE *)"3Eck",NULL      };
struct IntuiText SText ={ 1,0,JAM1,10,6,NULL,(UBYTE *)"Sinus",NULL     };
struct IntuiText NText ={ 1,0,JAM1,14,6,NULL,(UBYTE *)"Null",NULL      };
struct IntuiText ReqT2 ={ 1,0,JAM1,45,6,NULL,Titel,NULL                };
struct IntuiText ReqT  ={ 3,0,JAM1,46,7,NULL,Titel,&ReqT2              };
struct IntuiText RCaT  ={ 1,0,JAM1,10,6,NULL,(UBYTE *)"Break",NULL     };
struct IntuiText RTGT  ={1,0,JAM1,70,-10,NULL,(UBYTE *)"Filename:",NULL};
struct PropInfo PHInfo ={ FREEVERT|AUTOKNOB,0,0,     0,GH,0,0,0,0,0,0  };
struct PropInfo PLInfo ={ FREEVERT|AUTOKNOB,0,GL*255,0,GL,0,0,0,0,0,0  };
struct PropInfo CInfo  ={ FREEVERT|AUTOKNOB,0,GC*64, 0,GC,0,0,0,0,0,0  };
struct PropInfo VInfo  ={ FREEVERT|AUTOKNOB,0,0,     0,GV,0,0,0,0,0,0  };
struct StringInfo Sinfo={ name,undo,0,31,0,0,0,0,0,0,0,0,NULL          };
struct Gadget RTGad    ={ NULL,20,30,210,10,GADGHCOMP,
    GADGIMMEDIATE|RELVERIFY,STRGADGET|REQGADGET,
    (APTR)&SRand,NULL,&RTGT,0,(APTR)&Sinfo,14,NULL          };
struct Gadget RCa    ={ &RTGad,20,45,60,20,GADGHCOMP,
    ENDGADGET|GADGIMMEDIATE|RELVERIFY,BOOLGADGET|REQGADGET,
    (APTR)&OKRand,NULL,&RCaT,0,0,13,NULL                    };
struct Gadget ROk    ={ &RCa,170,45,60,20,GADGHCOMP,
    ENDGADGET|GADGIMMEDIATE|RELVERIFY,BOOLGADGET|REQGADGET,
    (APTR)&OKRand,NULL,&SaText,0,0,12,NULL                  };
struct Gadget OKGad    ={ NULL,579,235,60,20,GADGHCOMP,
    GADGIMMEDIATE|RELVERIFY,BOOLGADGET,
    (APTR)&OKRand,NULL,&OKText,0,0,11,NULL                  };
struct Gadget SaGad    ={ &OKGad,579,211,60,20,GADGHCOMP,
    GADGIMMEDIATE|RELVERIFY,BOOLGADGET,
    (APTR)&OKRand,NULL,&SaText,0,0,10,NULL                  };
struct Gadget MGad    ={ &SaGad,579,187,60,20,GADGHCOMP,
    GADGIMMEDIATE|RELVERIFY,BOOLGADGET,
    (APTR)&OKRand,NULL,&MText,0,0,9,NULL                    };
struct Gadget RGad    ={ &MGad,579,163,60,20,GADGHCOMP,
    GADGIMMEDIATE|RELVERIFY,BOOLGADGET,
    (APTR)&OKRand,NULL,&RText,0,0,8,NULL                    };
struct Gadget ZGad    ={ &RGad,579,139,60,20,GADGHCOMP,
    GADGIMMEDIATE|RELVERIFY,BOOLGADGET,
    (APTR)&OKRand,NULL,&ZText,0,0,7,NULL                    };
struct Gadget DGad    ={ &ZGad,579,115,60,20,GADGHCOMP,
    GADGIMMEDIATE|RELVERIFY,BOOLGADGET,
    (APTR)&OKRand,NULL,&DText,0,0,6,NULL                    };
struct Gadget SGad    ={ &DGad,579,91,60,20,GADGHCOMP,
    GADGIMMEDIATE|RELVERIFY,BOOLGADGET,
    (APTR)&OKRand,NULL,&SText,0,0,5,NULL                    };
struct Gadget NGad    ={ &SGad,579,67,60,20,GADGHCOMP,
    GADGIMMEDIATE|RELVERIFY,BOOLGADGET,
    (APTR)&OKRand,NULL,&NText,0,0,4,NULL                    };
struct Gadget VGad    ={ &NGad,608,0,30,64,0,0,PROPGADGET,
    (APTR)&VDummy,NULL,NULL,0,(APTR)&VInfo,3,NULL           };
struct Gadget CGad    ={ &VGad,577,0,30,64,0,0,PROPGADGET,
    (APTR)&CDummy,NULL,NULL,0,(APTR)&CInfo,2,NULL           };
struct Gadget PGadL    ={ &CGad,546,0,30,256,0,0,PROPGADGET,
    (APTR)&LDummy,NULL,NULL,0,(APTR)&PLInfo,1,NULL          };
struct Gadget PGadH    ={ &PGadL,515,0,30,256,0,0,PROPGADGET,
    (APTR)&HDummy,NULL,NULL,0,(APTR)&PHInfo,0,NULL          };
struct Requester Req={ NULL,10,10,250,70,0,0,
    &ROk,&ReqR,&ReqT,0,0,NULL,NULL,NULL,NULL,NULL           };
struct NewWindow BW    ={
    0,0,640,256,-1,-1,VANILLAKEY|MOUSEBUTTONS|GADGETUP,
    ACTIVATE|BORDERLESS|RMBTRAP,&PGadH,NULL,NULL,NULL,NULL,
    0,0,0,0,WBENCHSCREEN                                    };
struct Library             *OpenLibrary();
struct IntuiMessage        *GetMsg();
struct MsgPort             *SPort,*CreatePort();
struct Device              *SDev,*OpenDevice();
struct IntuitionBase       *IntuitionBase;
struct GfxBase             *GfxBase;
struct MathTransBase       *MathTransBase;
struct Window              *win,*OpenWindow();
struct RastPort            *RP;
struct IOAudio             Sound;
VOID closew()                   /* zum Programmende alle Resourcen freigeben */
{
    if(!SDev)         CloseDevice(&Sound);
    if(SPort)         DeletePort(SPort,sizeof(struct MsgPort));
    if(Data)          FreeMem(Data,256*sizeof(UBYTE));
    if(win)           CloseWindow(win);
    if(MathTransBase) CloseLibrary(MathTransBase);
    if(GfxBase)       CloseLibrary(GfxBase);
    if(IntuitionBase) CloseLibrary(IntuitionBase);
    exit(0);
}
VOID openw()             /* Programmstart: Libraries, Window, ChipMemory ... */
{
    UBYTE *AllocMem();
    if(!(IntuitionBase=(struct IntuitionBase *)
            OpenLibrary("intuition.library",0)))      closew();
    if(!(GfxBase=(struct GfxBase *)
            OpenLibrary("graphics.library",0)))       closew();
    if(!(MathTransBase=(struct MathTransBase *)
            OpenLibrary("mathtrans.library",0)))      closew();
    if(!(win=OpenWindow(&BW)))                        closew();
    if(!(Data=AllocMem(256*sizeof(UBYTE),MEMF_CHIP))) closew();
    if(!(SPort=CreatePort("SPort",0)))                closew();
    Sound.ioa_Request.io_Message.mn_ReplyPort  =SPort;
    Sound.ioa_Request.io_Message.mn_Node.ln_Pri=10;
    Sound.ioa_Data  =&buffer;
    Sound.ioa_Length=(ULONG)sizeof(buffer);
    if(SDev=OpenDevice(AUDIONAME,0,&Sound,0))         closew();
    Sound.ioa_Request.io_Command=CMD_WRITE;
    Sound.ioa_Request.io_Flags  =ADIOF_PERVOL|IOF_QUICK;
    RP =win->RPort;
}
ULONG GetMessage()                                   /* MessagePort auslesen */
{
    struct IntuiMessage *mes;
    CLASS=CODE=0;
    ADDR=NULL;
    if(mes=GetMsg(win->UserPort)){       CLASS=mes->Class;
                                         CODE=mes->Code;
                                         ADDR=mes->IAddress;
                                         ReplyMsg(mes);
    }
    return(CLASS);
}
VOID SetPoint(x,y)            /* Punkt (incl. Linie) im Zeichenfeld ausgeben */
    SHORT x;
    UBYTE y;
{
    SHORT col;
    col=2*((x==Ende)||(x==Start));
    Data[x/2]=127-y;
    SetDrMd(RP,JAM1);
    SetAPen(RP,1+col);
    Move(RP,x,0);
    Draw(RP,x,255);
    Move(RP,x+1,0);
    Draw(RP,x+1,255);
    SetAPen(RP, 2);
    WritePixel(RP,x,y);
    WritePixel(RP,x+1,y);
}
VOID NewW()                 /* neue Werte fr Period, Cycle und Volume lesen */
{
    l=PLInfo.VertPot/GL;
    h=PHInfo.VertPot/GH;
    p=256*h+l;
    p=(p<124?124:p);
    c=64-CInfo.VertPot/GC;
    c=(c==0?1:c);
    v=64-VInfo.VertPot/GV;
}
Play()                                                    /* Klang abspielen */
{
    NewW();
    Sound.ioa_Data  =Data+Start/2;
    Sound.ioa_Length=ENDE;
    Sound.ioa_Period=p;
    Sound.ioa_Cycles=c;
    Sound.ioa_Volume=v;
    BeginIO(&Sound);
    WaitIO(&Sound);
}
VOID Save()
{
  COUNT i,j;
  FILE *file;
  NewW();
  if(file=fopen(name,"w")){
     fprintf(file,"/*   -*- %s - erstellt mit Glzy's SEEd -*-   */\n\n",name);
     fprintf(file,"#include <devices/audio.h>\n");
     fprintf(file,"#include <exec/memory.h>\n");
     fprintf(file,"#define Play(); BeginIO(&Sound); WaitIO(&Sound);\n\n");
     fprintf(file,"UBYTE buffer=15,*SData,SD[%d]={\n\t",ENDE);
     for(i=Start/2,j=0;i<=Ende/2;i++,j++){
         fprintf(file,"%3d",Data[i]);
         if(i!=Ende/2)    fprintf(file,",");
         if(j==15){       fprintf(file,"\n\t");
                          j=-1;
         }
     }
     fprintf(file,"\n};\n");
     fprintf(file,"extern struct MsgPort\t*CreatePort();\n");
     fprintf(file,"extern struct Device\t*OpenDevice();\n");
     fprintf(file,"struct MsgPort\t\t*SPort;\n");
     fprintf(file,"struct Device\t\t*SDev;\n");
     fprintf(file,"struct IOAudio\t\t Sound;\n\n");
     fprintf(file,"VOID SoundOff()\n{\n");
     fprintf(file,"\tif(!SDev)\tCloseDevice(&Sound);\n");
     fprintf(file,"\tif(SPort)\tDeletePort(SPort,sizeof(struct MsgPort));\n");
     fprintf(file,"\tif(SData)\tFreeMem(SData,%d);\n}\n\n",ENDE);
     fprintf(file,"SHORT SoundOn()\n{\n");
     fprintf(file,"\tUBYTE *AllocMem();\n");
     fprintf(file,"\tCOUNT i;\n\n");
     fprintf(file,"\tif(!(SData=AllocMem(%d,MEMF_CHIP)))\treturn(1);\n",ENDE);
     fprintf(file,"\tfor(i=0;i<%d;i++)\n\t\tSData[i]=SD[i];\n",ENDE);
     fprintf(file,"\tif(!(SPort=CreatePort(\"SPort\",0))){\n");
     fprintf(file,"\t\tSoundOff();\n\t\treturn(1);\n\t}\n");
     fprintf(file,"\tSound.ioa_Request.io_Message.mn_ReplyPort=SPort;\n");
     fprintf(file,"\tSound.ioa_Request.io_Message.mn_Node.ln_Pri=10;\n");
     fprintf(file,"\tSound.ioa_Data=&buffer;\n");
     fprintf(file,"\tSound.ioa_Length=(ULONG)sizeof(buffer);\n");
     fprintf(file,"\tif(SDev=OpenDevice(AUDIONAME,0,&Sound,0)){\n");
     fprintf(file,"\t\tSoundOff();\n\t\treturn(1);\n\t}\n");
     fprintf(file,"\tSound.ioa_Request.io_Command\t=CMD_WRITE;\n");
     fprintf(file,"\tSound.ioa_Request.io_Flags\t=ADIOF_PERVOL|IOF_QUICK;\n");
     fprintf(file,"\tSound.ioa_Data\t\t\t=SData;\n");
     fprintf(file,"\tSound.ioa_Length\t\t=%d;\n",ENDE);
     fprintf(file,"\tSound.ioa_Period\t\t=(UWORD)%d;\n",p);
     fprintf(file,"\tSound.ioa_Volume\t\t=%d;\n",v);
     fprintf(file,"\tSound.ioa_Cycles\t\t=(UWORD)%d;\n",c);
     fprintf(file,"\treturn(0);\n}\n");
     fclose(file);
  }
  else DisplayBeep(0);
}
VOID CheckReq()                                   /* Requester kontrollieren */
{
    SHORT reqclear=0;
    while(reqclear==0){
        GetMessage();
        if(CLASS==GADGETUP){
            switch(GAD_ID){
                case 12:{
                    Save();
                    reqclear=1;
                    break;
                }
                case 13:{
                    reqclear=1;
                    break;
                }
                default:break;
            }
        }
    }
}
VOID main()
{
    SHORT x=0,y=0;
    BOOL ende=0;
    COUNT i,j;
    FLOAT k;
    openw();
    SetAPen(RP, 1);
    RectFill(RP,0,0,510,256);
    for(i=0;i<512;i+=2)    SetPoint(i,127);
    while(!ende){
        Wait(1<<win->UserPort->mp_SigBit);
        GetMessage();
        switch(CLASS){
            case MOUSEBUTTONS:{
                if(CODE==MENUDOWN){
                    Play();
                    while(CODE!=MENUUP) GetMessage();
                }
                else if(CODE==SELECTDOWN){
                    while(CODE!=SELECTUP){
                        GetMessage();
                        if((x!=MOUSX)||(y!=MOUSY)){
                            x=MOUSX;
                            y=MOUSY;
                            if(x<=510) SetPoint(2*(UBYTE)((FLOAT)x/2.0),y);
                        }
                    }
                }
                break;
            }
            case GADGETUP:{
                 switch(GAD_ID){
                     case 4:{    /* Null */
                         for(i=0;i<512;i+=2)    SetPoint(i,127);
                         break;
                     }
                     case 5:{    /* Sinus */
                         for(j=0;j<2;j++){
                             for(i=0;i<256;i+=2){
                                 k=sqrt((FLOAT)  ((256-i)*(256-i)+i*i));
                                 k=j?-k+128.0:k-128.0;
                                 SetPoint(i+256*j,(UBYTE)k);
                             }
                         }
                         break;
                     }
                     case 6:{    /* 3Eck */
                         for(j=0;j<2;j++){
                             for(i=j*256;i<128+j*256;i+=2){
                                 k=(FLOAT)i*.7;
                                 k=j?k+204.0:128.0-k;
                                 SetPoint(i,(UBYTE)k);
                             }
                             for(i=128+j*256;i<256+j*256;i+=2){
                                 k=(FLOAT)i*.7;
                                 k=j?-k-28:k-52.0;
                                 SetPoint(i,(UBYTE)k);
                             }
                         }
                         break;
                     }
                     case 7:{    /* SZahn */
                         for(j=0;j<2;j++){
                             for(i=j*256;i<128+j*256;i+=2){
                                 k=.7*(FLOAT)(j*256+180-i);
                                 SetPoint(i,(UBYTE)k);
                             }
                             for(i=128+j*256;i<256+j*256;i+=2){
                                 k=.7*(FLOAT)(j*256+436-i);
                                 SetPoint(i,(UBYTE)k);
                             }
                         }
                         break;
                     }
                     case 8:{    /* Recheck */
                         for(j=0;j<2;j++){
                             for(i=j*256;i<128+j*256;i+=2)     SetPoint(i,38);
                             for(i=128+j*256;i<256+j*256;i+=2) SetPoint(i,218);
                         }
                         break;
                     }
                     case 9:{    /* 2mal */
                         for(i=j=0;i<256;i+=2,j++) Data[j]=Data[i];
                         for(i=128;i<256;i++)      Data[i]=Data[i-128];
                         for(i=0;i<512;i+=2) SetPoint(i,(BYTE)(127-Data[i/2]));
                         break;
                     }
                     case 10:{    /* Save */
                         Request(&Req,win);
                         CheckReq();
                         break;
                     }
                     case 11:{
                         ende=1;
                         break;
                     }
                     default:break;
                }
                break;
            }
            case VANILLAKEY:{
                switch(CODE){
                     case 49:{    /* Ende links */
                         if((Ende>2)&&((Ende-2)>Start)){
                             Ende-=2;
                             SetPoint(Ende+2,(BYTE)(127-Data[(Ende+2)/2]));
                             SetPoint(Ende,(BYTE)(127-Data[Ende/2]));
                         }
                         break;
                     }
                     case 51:{    /* Ende rechts */
                         if(Ende<510){
                             Ende+=2;
                             SetPoint(Ende-2,(BYTE)(127-Data[(Ende-2)/2]));
                             SetPoint(Ende,(BYTE)(127-Data[Ende/2]));
                         }
                         break;
                     }
                     case 52:{    /* Ende links schnell */
                         if((Ende>8)&&((Ende-8)>Start)){
                             Ende-=8;
                             SetPoint(Ende+8,(BYTE)(127-Data[(Ende+8)/2]));
                             SetPoint(Ende,(BYTE)(127-Data[Ende/2]));
                         }
                         break;
                     }
                     case 54:{    /* Ende rechts schnell */
                         if(Ende<506){
                             Ende+=8;
                             SetPoint(Ende-8,(BYTE)(127-Data[(Ende-8)/2]));
                             SetPoint(Ende,(BYTE)(127-Data[Ende/2]));
                         }
                         break;
                     }
                     case 50:
                     case 53:{    /* Ende-Position */
                         i=Ende;
                         Ende=510;
                         SetPoint(i,(BYTE)(127-Data[i/2]));
                         SetPoint(510,(BYTE)(127-Data[255]));
                         break;
                     }
                     case 55:{    /* Start links */
                         if(Start>=8){
                             Start-=8;
                             SetPoint(Start+8,(BYTE)(127-Data[(Start+8)/2]));
                             SetPoint(Start,(BYTE)(127-Data[Start/2]));
                         }
                         break;
                     }
                     case 57:{    /* Start rechts */
                         if((Start<504)&&((Start+8)<Ende)){
                             Start+=8;
                             SetPoint(Start-8,(BYTE)(127-Data[(Start-8)/2]));
                             SetPoint(Start,(BYTE)(127-Data[Start/2]));
                         }
                         break;
                     }
                     case 56:{    /* Start-Position */
                         i=Start;
                         Start=0;
                         SetPoint(i,(BYTE)(127-Data[i/2]));
                         SetPoint(0,(BYTE)(127-Data[0]));
                         break;
                     }
                     default:break;
                 }
                 break;
            }
            default:break;
        }
    }
    closew();
}

