/*  pc1.c -  Some other functions  */

#include "pcopy.h"

/*  Our startup is calling it, so we why shouldn't we define it?
 */
void MemCleanup(){}


/*
 *  Open all windows, open a Console device for the history window and
 *  a port to it.
 */

OpenUser()
{
  TxT[SHORTTIME]='\0';  /*  cut the string just before the sizing gadgets */
  WT=OpenWindow(&NwT);
  W1=OpenWindow(&Nw1);
  W0=OpenWindow(&Nw0);
  WH=OpenWindow(&NwH);
  WS=OpenWindow(&NwS);

  if (!(WT&&W1&&W0&&WH&&WS)) return(-1);  /* any missing window? */

  if (!(MPHist=CreatePort("History",0))) return(-1);
  if (!(IOHist=CreateStdIO(MPHist))) return(-1);
  IOHist->io_Data=(APTR)WH;
  IOHist->io_Length=sizeof(*WH);
  return(OpenDevice("console.device",0,IOHist,0));
}


/*
 *  The same as the preceding function but now  !
 */

void CloseUser()
{
  if (IOHist){
    if (IOHist->io_Device) CloseDevice(IOHist);
    DeleteStdIO(IOHist);
  }
  if (MPHist) DeletePort(MPHist);
  if (WT) CloseWindow(WT);
  if (WH) CloseWindow(WH);
  if (W1) CloseWindow(W1);
  if (W0) CloseWindow(W0);
  if (WS) CloseWindow(WS);
}


/*
 *  We donot want to refresh all gadgets, so a patch again
 */

void RefOneGadget(G,W,R)
struct Gadget *G; struct Window *W; struct Requester *R;
{
  RemoveGadget(W,G);
  AddGadget(W,G,-1);
  RefreshGadgets(G,W,R);
}


/*
 *  This way you should make a beep!  It's the multitasking way. It's a
 *  decent way.  No pumping words into a DAC which was just busy converting
 *  The Dutch National Anthem.
 */

Beep(type)
short type;
{
  /* We need these to get the adress of unmerged memory  */
  static UBYTE *SDA=SoundData;
  static UBYTE *SDA1=SoundData1;

  UBYTE sunit=0x0f;
  short done=0;
/*  
  if (!BeepAllowed) return(0);  
*/  
  if (Sound.ioa_Request.io_Message.mn_ReplyPort=CreatePort("p3",0)){
    Sound.ioa_Request.io_Message.mn_Node.ln_Pri=BEEP_PRI;
    Sound.ioa_Data=&sunit;
    Sound.ioa_Length=(ULONG)sizeof(sunit);
    Sound.ioa_Request.io_Flags=ADIOF_NOWAIT;
    if (!OpenDevice(AUDIONAME,0L,&Sound,0L)){

      Sound.ioa_Request.io_Command=CMD_WRITE;
      Sound.ioa_Request.io_Flags=ADIOF_PERVOL | IOF_QUICK;
      Sound.ioa_Data=SDA;
      Sound.ioa_Length=SDA1-SDA;
/*
      Sound.ioa_Data=GetSoundDataAddress();
      Sound.ioa_Length=GetSoundDataSize();
*/
      Sound.ioa_Volume=64;
      
      if (type){         /*  alarm tune  */
        DoBeep(406,26);
        Delay(1);
        DoBeep(406,45);
        DoBeep(304,35);
        DoBeep(406,26);
        DoBeep(304,35);
        DoBeep(406,80);
      } else{            /*  ready tune  */
        DoBeep(406,32);
        Delay(1);
        DoBeep(406,110);
      }

      CloseDevice(&Sound);
      done=1;
    }
    DeletePort(Sound.ioa_Request.io_Message.mn_ReplyPort);
  }
  if (!done)  DisplayBeep(IntuitionBase->ActiveScreen);
                         /*  if no Sound device at least this */
  return((int)done);
}


void DoBeep(period,cycles)
{
  Sound.ioa_Period=period;
  Sound.ioa_Cycles=cycles;
  BeginIO(&Sound);
  WaitIO(&Sound);
}


void ConPutStr(req,str)
struct IOStdReq *req;
char *str;
{
  register int saveD7; /*  Is it true that DoIO() to a console trashes D7?  */
  req->io_Command=CMD_WRITE;
  req->io_Data=(APTR)str;
  req->io_Length=-1;
  DoIO(req);
}


/*
 *  AutoRequest is not handsome enough, we make it nice here.
 */

Request(text0,text1,text2,text3)
char *text0, *text1, *text2, *text3;
{
  static struct IntuiText ITBod1={ 0,0,JAM1,10,14,0,0,0 };
  static struct IntuiText ITBod0={ 0,0,JAM1,10, 4,0,0,0 };
  static struct IntuiText  ITPos={ 0,0,JAM1, 6, 3,0,0,0 };
  static struct IntuiText  ITNeg={ 0,0,JAM1, 6, 3,0,0,0 };
  register int width0, width1;

  ITBod0.IText=text0;
  ITPos.IText=text2;
  ITNeg.IText=text3;
  if (ITBod1.IText=text1){
    ITBod0.NextText=&ITBod1;
    width1=IntuiTextLength(&ITBod1)+48;
  } else{
    ITBod0.NextText=0;
    width1=0;
  }
  width0=IntuiTextLength(&ITBod0)+48;
  if (width0<152) width0=152;     /* a minimum width  */
  return (AutoRequest(WS,&ITBod0,&ITPos,&ITNeg,
           GADGETDOWN,GADGETDOWN,(width1<width0)?width0:width1,60));
}


/*
 *  Careful analises of some Manx "objects", delivered this function.
 */

long dos_packet(port, type, arg1, arg2)
struct MsgPort *port;  long type, arg1, arg2;
{
  register struct StandardPacket *sp;
  register struct MsgPort *rp, *CreatePort();
  long ret;

  ret=0;
  if (rp=CreatePort(0L,0L)){
    if (sp=(struct StandardPacket *)
    AllocMem((long)sizeof(struct StandardPacket),PUBCLR)){
      sp->sp_Msg.mn_Node.ln_Name=(char *)&sp->sp_Pkt;
      sp->sp_Pkt.dp_Link=&sp->sp_Msg;
      sp->sp_Pkt.dp_Port=rp;
      sp->sp_Pkt.dp_Type=type;
      sp->sp_Pkt.dp_Arg1=arg1;
      sp->sp_Pkt.dp_Arg2=arg2;
      PutMsg(port,&sp->sp_Msg);
      WaitPort(rp);
      GetMsg(rp);
      ret=sp->sp_Pkt.dp_Res1;
      FreeMem(sp,(long)sizeof(*sp));
    }
    DeletePort(rp);
  }
  return(ret);
}


/*
 *  Some people donot have a df1:, but a df2:. Thats why this drive
 *  selection function is implemented. It builds up a requesterlike
 *  window, asking the user to select two drives. If he did not select
 *  them, ignore his done pushes. Then check if the names are not
 *  assigned to the same drive.
 */

AskDrives(){
  ULONG proc;
  struct InfoData *Info;
  struct Window *WR;
  short nr,i,dok,error;
  char *dname;
  
  if (!(Info=(struct InfoData *)AllocMem((long)sizeof(struct InfoData),
    MEMF_PUBLIC|MEMF_CLEAR))) return(-1);

  if (WR=OpenWindow(&NwR)){
    for (nr=0;nr!=2;){
      while (!(GDONE.Flags&SELECTED)) ;
      GDONE.Flags&=~SELECTED;
      for (nr=0,i=0;i<NDRIVES;++i) if (GList[i]->Flags&SELECTED) ++nr;
    }
    CloseWindow(WR);   /*  two names were selected, now get their #'s */
    for (i=0,nr=0,error=0;i<NDRIVES;++i){
      if (GList[i]->Flags&SELECTED){
        dname=GList[i]->GadgetText->IText;
        if (proc=DeviceProc(dname)){
          if (dok=dos_packet(proc,ACTION_DISK_INFO,((ULONG)Info)>>2)){
            DriveName[nr]=dname;
            DriveNr[nr++]=Info->id_UnitNumber;
          }
        }
        if (!(proc&&dok)) ++error;
      }
    }
  } else error=-1;  /*  no window  */
  FreeMem(Info,(long)sizeof(struct InfoData));
  return(error||(DriveNr[0]==DriveNr[1]));
}


/*
 *  Quite simple: a block of 1 kB is shifted over 32 bytes, to make place
 *  for the new name.
 */

void EnterHist(name)
char *name;
{
  register ULONG *s,*d;
  register short i;
  s=(ULONG *)(Hist+((MHIST-1)*MVOLNAME));
  d=(ULONG *)(Hist+(MHIST*MVOLNAME));
  for (i=0;i<((MHIST-1)*MVOLNAME/4);++i) *(--d)=*(--s);
  strncpy(Hist,name,MVOLNAME-1);
}


/*
 *  Here the Copy History window is completely written over again.
 */

void RefHist()
{
  short lines;
  ConPutStr(IOHist,"\x0c");  /* clear screen  */
  for (lines=(WH->Height-12)/8;lines>=0;--lines){
    ConPutStr(IOHist,"\n ");
    ConPutStr(IOHist,&Hist[lines*MVOLNAME]);
  }
}

/*  end of pc1.c  */
