#include "filedoor_protos.h"
#include "filedoor_structs_defines.h"

#include "xpr_lib.h"
#include "xproto.h"

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <devices/serial.h>
#include <devices/timer.h>
#include <exec/io.h>
#include <intuition/intuitionbase.h>

#include <stdlib.h>
#include <stdio.h>
#include <strings.h>


/**** debugger joe! *****/
BPTR debugcon;


/* Protokollens navn - skal nok kunne ændres udefra */
char *protocolname;

/* Vinduet */
static struct Window *win;
static BOOL abortbutton;

/* Den font jeg vil bruge i min intuitext - min font attribute */
static __far struct TextAttr mfa = {
  "topaz.font", /* Font, good ol' topaz */
  8,            /* Siz 8 */
  0,            /* Style 0 */
  FPB_ROMFONT,  /* Flag: Fra ROM.. */
};

/* Intuitext til at udskrive i statusvindue */
static __far struct IntuiText txt = {
  1,0,JAM2,       /* x,y,mode */
  0,0,            /* Koordinater */
  &mfa,           /* Min fontattribut */
  NULL,           /* Tekstpointer */
  NULL,           /* Den næste tekst */
};

/* Intuitext til at udskrive i statusvindue - med en anden farve */
static __far struct IntuiText txt2 = {
  3,0,JAM2,       /* x,y,mode */
  0,0,            /* Koordinater */
  &mfa,           /* Min fontattribut */
  NULL,           /* Tekstpointer */
  NULL,           /* Den næste tekst */
};

/* Et vindue til når vi ikke er ikonificerede */
struct TagItem wintags[]= {
  {WA_CustomScreen,0L},
  {WA_IDCMP,IDCMP_CLOSEWINDOW},
  {WA_Left,10},
  {WA_Top,20},
  {WA_InnerWidth,61*8},
  {WA_InnerHeight,94},
  {WA_Title,(ULONG)"XPR transfer"},
  {WA_DragBar,TRUE},
  {WA_DepthGadget,TRUE},
  {WA_CloseGadget,TRUE},
  {WA_AutoAdjust,TRUE},
  {TAG_DONE,NULL},
};

/* Et vindue til når vi er ikonificerede */
struct TagItem wintagsicon[]= {
  {WA_IDCMP,IDCMP_CLOSEWINDOW},
  {WA_Left,10},
  {WA_Top,20},
  {WA_InnerWidth,61*8},
  {WA_InnerHeight,94},
  {WA_Title,(ULONG)"XPR transfer - M A X iconified"},
  {WA_DragBar,TRUE},
  {WA_DepthGadget,TRUE},
  {WA_CloseGadget,TRUE},
  {WA_AutoAdjust,TRUE},
  {TAG_DONE,NULL},
};

/* Nogle globale variabler der angvier hvilke filer/hvor mange der skal sendes */
static int filenumber;                     /* Angiver antal filer der er flyttet */
static int filetotal;                      /* Angiver antal filer der skal flyttes */
static char **filenameptrs;                /* Pointere til filnavne.. max 50 pr. batch */

/* Prototyper til xpr library funktioner - sakset fra ZModem, men er vel ens overalt */
/* Saveds og asm og register er dybt ligemeget, xpr_lib.h indeholder pragmaer som */
/* fortæller hvilken librarybase der skal i a6 og hvilke arg. der skal i hvilke reg. */
long __saveds __asm XProtocolSend(register __a0 struct XPR_IO *xio);
long __saveds __asm XProtocolReceive(register __a0 struct XPR_IO *xio);
long __saveds __asm XProtocolSetup(register __a0 struct XPR_IO *xio);
long __saveds __asm XProtocolCleanup(register __a0 struct XPR_IO *xio);
long __saveds __asm XProtocolHostMon(register __a0 struct XPR_IO *xio,
                                     register __a1 char *serbuff,
                                     register __d0 long actual,
                                     register __d1 long maxsize);
long __saveds __asm XProtocolUserMon(register __a0 struct XPR_IO *xio,
                                     register __a1 char *serbuff,
                                     register __d0 long actual,
                                     register __d1 long maxsize);

/* Lille funktion til at skrive en intuitext */
void it(char *t,int x,int y)
{
  txt.IText=t;
  PrintIText(win->RPort,&txt,win->BorderLeft+x,win->BorderTop+y);
}

/* Lille funktion til at skrive en intuitext - med en anden farve */
void it2(char *t,int x,int y)
{
  txt2.IText=t;
  PrintIText(win->RPort,&txt2,win->BorderLeft+x,win->BorderTop+y);
}

/* Her kommer alle de dejlige call-backs */

/* Open file */
long __saveds __asm xpr_fopen(register __a0 char *filename,
                              register __a1 char *accessmode)
{
BPTR handle;
static __far char myfilename[150];

//  FPrintf(debugcon,"Open %s %s\n",filename,accessmode);
  strcpy(myfilename,filename);
  if(accessmode[1]!='+')
  {
    switch(accessmode[0])
    {
      case 'r':
      return(Open(myfilename,MODE_OLDFILE));
      break;

      case 'w':
      return(Open(myfilename,MODE_NEWFILE));
      break;

      case 'a':
      handle=Open(myfilename,MODE_READWRITE);
      if(handle) Seek(handle,0,OFFSET_END);
//      FPrintf(debugcon,"Handle:%ld\n",(ULONG)handle);
      return(handle);
      break;

      default:
      return(0);
      break;
    }
  }
  else
  {
    switch(accessmode[0])
    {
      case 'r':
      return(Open(myfilename,MODE_READWRITE));
      break;

      case 'w':
      return(Open(myfilename,MODE_READWRITE));
      break;

      case 'a':
      handle=Open(myfilename,MODE_READWRITE);
      if(handle) Seek(handle,0,OFFSET_END);
      return(handle);
      break;

      default:
      return(0);
      break;
    }
  }
}

/* Close file */
long __saveds __asm xpr_fclose(register __a0 long filepointer)
{
//  FPrintf(debugcon,"Close file\n");
  Close(filepointer);
  return(TRUE);
}

/* Get char from file */
long __saveds __asm xpr_fread(register __a0 char *buffer,
                              register __d0 long size,
                              register __d1 long count,
                              register __a1 long fileptr)
{
int ret;

  ret=Read(fileptr,buffer,size*count);
  if(ret>0) return(ret/size); else return(0);
}

/* Put string to file */
long __saveds __asm xpr_fwrite(register __a0 char *buffer,
                               register __d0 long size,
                               register __d1 long count,
                               register __a1 long fileptr)
{
int ret;

  ret=Write(fileptr,buffer,size*count);
  if(ret>0) return(ret/size); else return(0);
}

/* Get char from serial */
long __saveds __asm xpr_sread(register __a0 char *buffer,
                              register __d0 long size,
                              register __d1 long timeout)
{
struct MsgPort *port;       /* Messageport til timeren */
struct timerequest *treq;   /* IORequest + plads til timerværdier */
long ret;

  SerRequest->IOSer.io_Command=SDCMD_QUERY;
  SendIO((struct IORequest *)SerRequest);
  if(!SerRequest->io_Status&32) return(-1);
//  FPrintf(debugcon,"Size %ld\n",(ULONG)size);
  if(timeout>10)
  {
    if(port=CreatePort(0,0))
    {
      if(treq=(struct timerequest *)CreateExtIO(port,sizeof(struct timerequest)))
      {
        if(!OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)treq,0))
        {
          /* Sæt timerrequest op til at vente specificeret tid */
          treq->tr_node.io_Command=TR_ADDREQUEST;
          treq->tr_time.tv_secs=timeout/1000000;
          treq->tr_time.tv_micro=timeout%1000000;
          SendIO((struct IORequest *)treq);
          /* Sæt serialrequest op til at læse det ønskede antal bytes */
          SerRequest->IOSer.io_Length=size;
          SerRequest->IOSer.io_Data=buffer;
          SerRequest->IOSer.io_Command=CMD_READ;
          SendIO((struct IORequest *)SerRequest);
          /* Vent på at noget sker */
          while(TRUE)
          {
            Wait(1<<(port->mp_SigBit)|1<<(SerialPort->mp_SigBit));
            if(CheckIO((struct IORequest *)SerRequest)) break;
            if(CheckIO((struct IORequest *)treq)) break;
          }
          /* Myrd timer.device på en måde så det ikke får det dårligt */
          if(!CheckIO((struct IORequest *)treq))
          {
            AbortIO((struct IORequest *)treq);
          }
          WaitIO((struct IORequest *)treq);
          CloseDevice((struct IORequest *)treq);
          /* Myrd vores serial.device io-request, hvis det stadig kører.. */
          if(!CheckIO((struct IORequest *)SerRequest))
          {
            AbortIO((struct IORequest *)SerRequest);
          }
          WaitIO((struct IORequest *)SerRequest);
          /* Sæt returværdi til antal tegn faktisk læst */
          ret=SerRequest->IOSer.io_Actual;
//          FPrintf(debugcon,"Læste %ld med timeout\n",(ULONG)ret);
        }
      }
    }
  }
  else
  {
    /* Bare læs hvad der er, men ikke for meget */
    SerRequest->IOSer.io_Command=SDCMD_QUERY;
    SendIO((struct IORequest *)SerRequest);
    if(SerRequest->IOSer.io_Actual<size)
      SerRequest->IOSer.io_Length=SerRequest->IOSer.io_Actual;
    else
      SerRequest->IOSer.io_Length=size;
    SerRequest->IOSer.io_Data=buffer;
    SerRequest->IOSer.io_Command=CMD_READ;
    DoIO((struct IORequest *)SerRequest);
    ret=SerRequest->IOSer.io_Actual;
//    FPrintf(debugcon,"Læste %ld uden timeout\n",(ULONG)ret);
  }
  return(ret);
}

/* Put string to serial */
long __saveds __asm xpr_swrite(register __a0 char *buffer,
                               register __d0 long size)
{
  SerRequest2->IOSer.io_Command=SDCMD_QUERY;
  SendIO((struct IORequest *)SerRequest2);
  if(!SerRequest2->io_Status&32) return(-1);
  SerRequest2->IOSer.io_Length=size;
  SerRequest2->IOSer.io_Data=buffer;
  SerRequest2->IOSer.io_Command=CMD_WRITE;
  DoIO((struct IORequest *)SerRequest2);
  if(SerRequest2->IOSer.io_Actual==size) return(0); else return(1);
}

/* Flush serial input buffer */
long __saveds xpr_sflush(void)
{
  SerRequest->IOSer.io_Command=CMD_CLEAR; /* Not 100% sure but prob. this CMD */
  DoIO((struct IORequest *)SerRequest);
  return(0);
}

/* Print stuff */
long __saveds __asm xpr_update(register __a0 struct XPR_UPDATE *updatestruct)
{
static __far char t[80];

  if(updatestruct->xpru_updatemask&XPRU_FILENAME)
  {
    sprintf(t,"%-54s",updatestruct->xpru_filename);
    it(t,2+6*8,2);
  }
  if(updatestruct->xpru_updatemask&XPRU_MSG)
  {
    sprintf(t,"%-52s",updatestruct->xpru_msg);
    it(t,2+8*8,12);
  }
  if(updatestruct->xpru_updatemask&XPRU_ELAPSEDTIME)
  {
    sprintf(t,"%s",updatestruct->xpru_elapsedtime);
    it(t,2+15*8,30);
  }
  if(updatestruct->xpru_updatemask&XPRU_EXPECTTIME)
  {
    sprintf(t,"%s",updatestruct->xpru_expecttime);
    it(t,2+15*8,40);
  }
  if(updatestruct->xpru_updatemask&XPRU_ERRORS)
  {
    sprintf(t,"%-2i",updatestruct->xpru_errors);
    it(t,2+15*8,60);
  }
  if(updatestruct->xpru_updatemask&XPRU_TIMEOUTS)
  {
    sprintf(t,"%-2i",updatestruct->xpru_timeouts);
    it(t,2+15*8,70);
  }
  if(updatestruct->xpru_updatemask&XPRU_FILESIZE)
  {
    sprintf(t,"%-10i",updatestruct->xpru_filesize);
    it(t,2+46*8,30);
  }
  if(updatestruct->xpru_updatemask&XPRU_BYTES)
  {
    sprintf(t,"%-10i",updatestruct->xpru_bytes);
    it(t,2+46*8,40);
  }
  if(updatestruct->xpru_updatemask&XPRU_DATARATE)
  {
    sprintf(t,"%-5i",updatestruct->xpru_datarate);
    it(t,2+46*8,50);
  }
  if(updatestruct->xpru_updatemask&XPRU_BLOCKSIZE)
  {
    sprintf(t,"%-6i",updatestruct->xpru_blocksize);
    it(t,2+46*8,60);
  }
  if(updatestruct->xpru_updatemask&XPRU_BLOCKCHECK)
  {
    sprintf(t,"%s",updatestruct->xpru_blockcheck);
    it(t,2+46*8,70);
  }
  if(updatestruct->xpru_updatemask&XPRU_ERRORMSG)
  {
    sprintf(t,"%-48s",updatestruct->xpru_errormsg);
    it(t,2+12*8,84);
  }
  return(0);
}

/* Check for abort */
long __saveds xpr_chkabort(void)
{
struct IntuiMessage *msg;

  while(msg=(struct IntuiMessage *)GetMsg(win->UserPort))
  {
    if(msg->Class==IDCMP_CLOSEWINDOW) abortbutton=TRUE;
    ReplyMsg((struct Message *)msg);
  }
  if(abortbutton) return(1); else return(0);
  getivar(1);
}

/* Check misc. stuff */
void __saveds xpr_chkmisc(void)
{
struct IntuiMessage *msg;

  while(msg=(struct IntuiMessage *)GetMsg(win->UserPort))
  {
    if(msg->Class==IDCMP_CLOSEWINDOW) abortbutton=TRUE;
    ReplyMsg((struct Message *)msg);
  }
  getivar(1);
  return;
}

/* Set and Get serial info */
long __saveds __asm xpr_setserial(register __d0 long newstatus)
{
  return(newstatus); /* Hehe. snyd og bedrag. måske fixe senere.. */
}

/* Find first file name */
long __saveds __asm xpr_ffirst(register __a0 char *buffer,
                               register __a1 char *pattern)
{
//  FPrintf(debugcon,"First\n");
  filenumber=0;
  strcpy(buffer,filenameptrs[filenumber]);
  return(1);
}

/* Find next file name */
long __saveds __asm xpr_fnext(register __d0 long oldstate,
                              register __a0 char *buffer,
                              register __a1 char *pattern)
{
//  FPrintf(debugcon,"Nextfile\n");
  if(++filenumber==filetotal)
  {
    return(0);
  }
  else
  {
    strcpy(buffer,filenameptrs[filenumber]);
    return(1);
  }
}

/* Return file info */
long __saveds __asm xpr_finfo(register __a0 char *filename,
                              register __d0 long typeofinfo)
{
struct FileInfoBlock *fib;
BPTR lock;
long ret=0;
static __far char myfilename[150];

//  FPrintf(debugcon,"Fileinfo\n");
  strcpy(myfilename,filename);
  switch(typeofinfo&3)
  {
    /* Find størrelsen på en fil */
    case 1:
    if(fib=AllocDosObject(DOS_FIB,NULL))
    {
      if(lock=Lock(myfilename,ACCESS_READ))
      {
        if(Examine(lock,fib))
        {
          if(fib->fib_DirEntryType<0) ret=fib->fib_Size;
        }
        UnLock(lock);
      }
      FreeDosObject(DOS_FIB,fib);
    }
    return(ret);
    break;
    
    /* Afgør om fil er binær/ascii .. det kan vel ikke skade at sige binær altid.. */
    case 2:
    return(1);
    break;
    
    default:
    return(0);
    break;
  }
}

/* Seek in a file */
long __saveds __asm xpr_fseek(register __a0 long fileptr,
                              register __d0 long offset,
                              register __d1 long origin)
{
long ret=0;

//  FPrintf(debugcon,"Seek\n");
  switch(origin)
  {
    /* Beginning */
    case 0:
    Seek(fileptr,offset,OFFSET_BEGINNING);
    break;
    
    /* Current */
    case 1:
    Seek(fileptr,offset,OFFSET_CURRENT);
    break;
    
    /* End */
    case 2:
    Seek(fileptr,offset,OFFSET_END);
    break;
    
    default:
    ret=-1;
    break;
  }
  return(ret);
}

/* Delete a file. */
long __saveds __asm xpr_unlink(register __a0 char *filename)
{
  if(DeleteFile(filename)) return(0); else return(-1L);
}

/* Query serial device */
long __saveds xpr_squery(void)
{
  SerRequest->IOSer.io_Command=SDCMD_QUERY;
  SendIO((struct IORequest *)SerRequest);
  return((long)SerRequest->IOSer.io_Actual);
}

/* Get various host ptrs 
long __saveds __asm xpr_getptr(register __d0 long type)
{
} */

int DoXprDl(int count,char *files[])
{
struct IntuitionBase *IntuitionBase;  
struct Library *GfxBase;
struct Screen *scr;
ULONG ilock;
static __far char xpropts[81]="";
static __far char xproptsfile[40];

//  debugcon=Open("con:10/10/600/200/Debugger",MODE_OLDFILE);
  if((protocolname=FindAttr('X'))==NULL) protocolname="xprzmodem.library";
  if(XProtocolBase=OpenLibrary(protocolname,0L))
  {
    if(SerialPort=CreateMsgPort())
    {
      if(SerRequest=(struct IOExtSer *)CreateExtIO(SerialPort,sizeof(struct IOExtSer)))
      {
        SerRequest->io_SerFlags=SERF_SHARED;
        if(!OpenDevice(serialname,serialunit,(struct IORequest *)SerRequest,0L))
        {
          /* Query, bare så vi har gjort NOGET (ellers kager CheckIO !) */
          SerRequest->IOSer.io_Command = SDCMD_QUERY;
          SendIO((struct IORequest *)SerRequest);
          /* Åben serial device EEN gang til */
          if(SerialPort2=CreateMsgPort())
          {
            if(SerRequest2=(struct IOExtSer *)CreateExtIO(SerialPort2,sizeof(struct IOExtSer)))
            {
              SerRequest2->io_SerFlags=SERF_SHARED;
              if(!OpenDevice(serialname,serialunit,(struct IORequest *)SerRequest2,0L))
              {
                /* Query, bare så vi har gjort NOGET (ellers kager CheckIO !) */
                SerRequest2->IOSer.io_Command = SDCMD_QUERY;
                SendIO((struct IORequest *)SerRequest2);
                /* Initialiser xpr-strukturen */
                /* options kommer fra ENV:protokolnavn */
                strcpy(xproptsfile,protocolname);
                *strchr(xproptsfile,'.')='\0';        /* Kan ikke bruge libraries med . i navnet! */
                strcat(xproptsfile,".bbs");
                GetVar(xproptsfile,xpropts,80,0L);
                xprio.xpr_filename=xpropts;
                /* En masse deeejlige call-back funktioner */
                xprio.xpr_fopen=&xpr_fopen;
                xprio.xpr_fclose=&xpr_fclose;
                xprio.xpr_fread=&xpr_fread;
                xprio.xpr_fwrite=&xpr_fwrite;
                xprio.xpr_sread=&xpr_sread;
                xprio.xpr_swrite=&xpr_swrite;
                xprio.xpr_sflush=&xpr_sflush;
                xprio.xpr_update=&xpr_update;
                xprio.xpr_chkabort=&xpr_chkabort;
                xprio.xpr_chkmisc=&xpr_chkmisc;
                xprio.xpr_gets=NULL;
                xprio.xpr_setserial=&xpr_setserial;
                xprio.xpr_ffirst=&xpr_ffirst;
                xprio.xpr_fnext=&xpr_fnext;
                xprio.xpr_finfo=&xpr_finfo;
                xprio.xpr_fseek=&xpr_fseek;
                /* Lad som om vi understøtter 4 extensions og nul nugle af dem ud */
                /* Det SKAL da vel være tilladt.. */
                xprio.xpr_extension=4;
                xprio.xpr_unlink=&xpr_unlink;
                xprio.xpr_squery=&xpr_squery;
                xprio.xpr_getptr=NULL;
                xprio.xpr_options=NULL;
                /* Initialiser xpr-librariets private data til null */
                xprio.xpr_data=NULL;
                /* Kald selve init-rutinen */
                XProtocolSetup(&xprio);
                /* Sæt filename til et eller andet ligegyldigt. vi bruger ffirst fnext */
                xprio.xpr_filename=files[0];
                /* Initialiser variable til dl status */
                abortbutton=FALSE;
                filetotal=count;
                filenameptrs=files;
                /* Skaf et par libraries til */
                if(IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",37));
                {
                  if(GfxBase=OpenLibrary("graphics.library",37))
                  {
                    /* Find MAX skærm så vi kan hacke os ind på den */
                    ilock=LockIBase(0);
                    scr=IntuitionBase->FirstScreen;
                    while(scr!=NULL)
                    {
                      if(scr->Title[0]==line_number)
                      {
                        if(!strncmp(scr->Title+1,": M A X's BBS",13)) break;
                      }
                      scr=scr->NextScreen;
                    }
                    UnlockIBase(ilock);
                    wintags[0].ti_Data=(ULONG)scr;
                    /* Åben vinduet på MAX eller default skærm */
                    if(scr==NULL)
                    {
                      txt2.FrontPen=1;
                      win=OpenWindowTagList(NULL,wintagsicon);
                    }
                    else
                    {
                      txt2.FrontPen=2;
                      win=OpenWindowTagList(NULL,wintags);
                    }
                    if(win)
                    {
                      /* Skriv lidt tekst i vinduet */
                      it2("File:",2,2);
                      it2("Status:",2,12);
                      it2("Elapsed time:",2+8,30);
                      it2("Expected time:",2,40);
                      it2("Errors:",2+7*8,60);
                      it2("Timeouts:",2+5*8,70);
                      it2("Filesize:",2+36*8,30);
                      it2("Filepos:",2+37*8,40);
                      it2("Datarate:",2+36*8,50);
                      it2("Block size:",2+34*8,60);
                      it2("Checksum:",2+36*8,70);
                      it2("Last error: -",2,84);
                      /* ROLL'EM */
                      XProtocolSend(&xprio);
                      /* Fjern evt. xtra IDCMP messages */
                      xpr_chkmisc();
                      /* Skriv noget JUNK .. høhø */
                      Delay(100);
                      xpr_sflush();
                      xpr_swrite("\x18\x18\x18\x18\x18\x18\x18\x18",8);
                      Delay(50);
                      /* Luk vinduet */
                      CloseWindow(win);
                    }
                    CloseLibrary(GfxBase);
                  }
                  CloseLibrary((struct Library *)IntuitionBase);
                }
                /* Bed xpr library om at rydde op */
                XProtocolCleanup(&xprio);
                /* Luk device på den besværlige og sikre måde. Gab */
                if(!CheckIO((struct IORequest *)SerRequest2))
                {
                  AbortIO((struct IORequest *)SerRequest2);
                }
                WaitIO((struct IORequest *)SerRequest2);
                CloseDevice((struct IORequest *)SerRequest2);
              }
              DeleteExtIO((struct IORequest *)SerRequest2);
            }
            DeleteMsgPort(SerialPort2);
          }
          /* Luk device på den besværlige og sikre måde. Gab */
          if(!CheckIO((struct IORequest *)SerRequest))
          {
            AbortIO((struct IORequest *)SerRequest);
          }
          WaitIO((struct IORequest *)SerRequest);
          CloseDevice((struct IORequest *)SerRequest);
        }
        DeleteExtIO((struct IORequest *)SerRequest);
      }
      DeleteMsgPort(SerialPort);
    }
    CloseLibrary(XProtocolBase);
  }
//  Close(debugcon);
  return(filenumber);
}

int DoXprUl(void)
{
struct IntuitionBase *IntuitionBase;  
struct Library *GfxBase;
struct Screen *scr;
ULONG ilock;
BPTR dirlock;
static __far char xpropts[81]="";
static __far char tempstr[80];


//  debugcon=Open("con:10/10/600/200/Debugger",MODE_OLDFILE);
  if((protocolname=FindAttr('X'))==NULL) protocolname="xprzmodem.library";
  if(XProtocolBase=OpenLibrary(protocolname,0L))
  {
    if(SerialPort=CreateMsgPort())
    {
      if(SerRequest=(struct IOExtSer *)CreateExtIO(SerialPort,sizeof(struct IOExtSer)))
      {
        SerRequest->io_SerFlags=SERF_SHARED;
        if(!OpenDevice(serialname,serialunit,(struct IORequest *)SerRequest,0L))
        {
          /* Query, bare så vi har gjort NOGET (ellers kager CheckIO !) */
          SerRequest->IOSer.io_Command = SDCMD_QUERY;
          SendIO((struct IORequest *)SerRequest);
          /* Åben serial device EEN gang til */
          if(SerialPort2=CreateMsgPort())
          {
            if(SerRequest2=(struct IOExtSer *)CreateExtIO(SerialPort2,sizeof(struct IOExtSer)))
            {
              SerRequest2->io_SerFlags=SERF_SHARED;
              if(!OpenDevice(serialname,serialunit,(struct IORequest *)SerRequest2,0L))
              {
                /* Lav skuffe bruger kan uploade i */
                strcpy(tempstr,"bbs:cydaldoor/upload/");
                strcat(tempstr,UserName);
                if(dirlock=CreateDir(tempstr)) UnLock(dirlock);
                /* Query, bare så vi har gjort NOGET (ellers kager CheckIO !) */
                SerRequest2->IOSer.io_Command = SDCMD_QUERY;
                SendIO((struct IORequest *)SerRequest2);
                /* Initialiser xpr-strukturen */
                strcpy(xpropts,"OR,AN,KY,SN,RN,Pbbs:cydaldoor/upload/");
                strcat(xpropts,UserName);
                xprio.xpr_filename=xpropts;
                /* En masse deeejlige call-back funktioner */
                xprio.xpr_fopen=&xpr_fopen;
                xprio.xpr_fclose=&xpr_fclose;
                xprio.xpr_fread=&xpr_fread;
                xprio.xpr_fwrite=&xpr_fwrite;
                xprio.xpr_sread=&xpr_sread;
                xprio.xpr_swrite=&xpr_swrite;
                xprio.xpr_sflush=&xpr_sflush;
                xprio.xpr_update=&xpr_update;
                xprio.xpr_chkabort=&xpr_chkabort;
                xprio.xpr_chkmisc=&xpr_chkmisc;
                xprio.xpr_gets=NULL;
                xprio.xpr_setserial=&xpr_setserial;
                xprio.xpr_ffirst=&xpr_ffirst;
                xprio.xpr_fnext=&xpr_fnext;
                xprio.xpr_finfo=&xpr_finfo;
                xprio.xpr_fseek=&xpr_fseek;
                /* Lad som om vi understøtter 4 extensions og nul nugle af dem ud */
                /* Det SKAL da vel være tilladt.. */
                xprio.xpr_extension=4;
                xprio.xpr_unlink=&xpr_unlink;
                xprio.xpr_squery=&xpr_squery;
                xprio.xpr_getptr=NULL;
                xprio.xpr_options=NULL;
                /* Initialiser xpr-librariets private data til null */
                xprio.xpr_data=NULL;
                /* Kald selve init-rutinen */
                XProtocolSetup(&xprio);
                /* Initialiser variable til dl status */
                abortbutton=FALSE;
                /* Skaf et par libraries til */
                if(IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",37));
                {
                  if(GfxBase=OpenLibrary("graphics.library",37))
                  {
                    /* Find MAX skærm så vi kan hacke os ind på den */
                    ilock=LockIBase(0);
                    scr=IntuitionBase->FirstScreen;
                    while(scr!=NULL)
                    {
                      if(scr->Title[0]==line_number)
                      {
                        if(!strncmp(scr->Title+1,": M A X's BBS",13)) break;
                      }
                      scr=scr->NextScreen;
                    }
                    UnlockIBase(ilock);
                    wintags[0].ti_Data=(ULONG)scr;
                    /* Åben vinduet på MAX eller default skærm */
                    if(scr==NULL)
                    {
                      txt2.FrontPen=1;
                      win=OpenWindowTagList(NULL,wintagsicon);
                    }
                    else
                    {
                      txt2.FrontPen=2;
                      win=OpenWindowTagList(NULL,wintags);
                    }
                    if(win)
                    {
                      /* Skriv lidt tekst i vinduet */
                      it2("File:",2,2);
                      it2("Status:",2,12);
                      it2("Elapsed time:",2+8,30);
                      it2("Expected time:",2,40);
                      it2("Errors:",2+7*8,60);
                      it2("Timeouts:",2+5*8,70);
                      it2("Filesize:",2+36*8,30);
                      it2("Filepos:",2+37*8,40);
                      it2("Datarate:",2+36*8,50);
                      it2("Block size:",2+34*8,60);
                      it2("Checksum:",2+36*8,70);
                      it2("Last error: -",2,84);
                      /* ROLL'EM */
                      XProtocolReceive(&xprio);
                      /* Fjern evt. xtra IDCMP messages */
                      xpr_chkmisc();
                      /* Skriv noget JUNK .. høhø */
                      Delay(50);
                      /* Luk vinduet */
                      CloseWindow(win);
                    }
                    CloseLibrary(GfxBase);
                  }
                  CloseLibrary((struct Library *)IntuitionBase);
                }
                /* Bed xpr library om at rydde op */
                XProtocolCleanup(&xprio);
                /* Fjern upload skuffen igen */
                DeleteFile(tempstr);
                /* Luk device på den besværlige og sikre måde. Gab */
                if(!CheckIO((struct IORequest *)SerRequest2))
                {
                  AbortIO((struct IORequest *)SerRequest2);
                }
                WaitIO((struct IORequest *)SerRequest2);
                CloseDevice((struct IORequest *)SerRequest2);
              }
              DeleteExtIO((struct IORequest *)SerRequest2);
            }
            DeleteMsgPort(SerialPort2);
          }
          /* Luk device på den besværlige og sikre måde. Gab */
          if(!CheckIO((struct IORequest *)SerRequest))
          {
            AbortIO((struct IORequest *)SerRequest);
          }
          WaitIO((struct IORequest *)SerRequest);
          CloseDevice((struct IORequest *)SerRequest);
        }
        DeleteExtIO((struct IORequest *)SerRequest);
      }
      DeleteMsgPort(SerialPort);
    }
    CloseLibrary(XProtocolBase);
  }
  Delay(50*3);
//  Close(debugcon);
  return(filenumber);
}
