#include <stdio.h>
#include <string.h>
#include <exec/types.h>
#include <devices/keymap.h>
#include <libraries/dos.h>
#include <graphics/sprite.h>
#include <intuition/intuition.h>
#include <proto/dos.h>
#include <proto/exec.h>

#include "main.h"

#define SEOF        "\x1A"

#define TERMCHAR    '%'
#define TERMLEN     4
#define TERMSTRING  "%%%%"
#define TERMDEL     "\x7f\x7f\x7f\x7f"

#define DEVLEN      32
#define COMLEN      128
#define PATHLEN     128
#define PACKET      512
#define MAXLINE     512

#define PAUSE       (50 * 2)
#define ATTR        0

transfer(register struct console *con)
{
register char   *cp;
USHORT          len;
BOOL            stat = TRUE;

conprint(con,"\nS = send, R = receive, Q = Quit, F4 = host setup ? ");
while (stat) {
    len = readconsole(con);
    *(con->buf + len) = '\0';
    cp = con->buf;
    while ((*cp)&&(stat)) {
        switch (*cp) {
            case 'r':
            case 'R':
                conprint(con,"R");
                receive(con);
                stat = FALSE;
                break;
            case 's':
            case 'S':
                conprint(con,"S");
                send(con);
                stat = FALSE;
                break;
            case 'q':
            case 'Q':
                con->gstat &= (MASK - ON);
                stat = FALSE;
                break;
            case PU1:
                conprint(con,"F4\n");
                host_setup(con);
                stat = FALSE;
                break;
            default:
                writeserial(con,"\x0D",1);
                stat = FALSE;
                break;
            }
        cp++;
        }
    }
return(0);
}

host_setup(register struct console *con)
{
FILEHANDLE          fp;
register USHORT     len;
char                c;

if (fp = OPEN_FOR_READING(HOSTSETUP)) {
    while (READ(fp,&c,1)) {
        if (c == LF) c = CR;
        writeserial(con,&c,1);
        len = readserial(con,0);
        if (len) interpret(con,len);
        }
    CLOSEFILE(fp);
    }
return(0);
}

send(register struct console *con)
{
struct FileInfoBlock    fib;
FILEHANDLE              fp;
register USHORT         cnt,lenght,termcount,error,stat;
register char           *ccp,*cp;
char                    dest[PATHLEN],filename[PATHLEN];
char                    command[COMLEN],files[COMLEN];
char                    device[] = "SYS$INPUT";
char                    readsync[] = "SET TERMINAL/READSYNC/NOPASTHRU\x0D";
char                    vms[] = "\x0D",notopen[] = "Can't open file %s\n";

sendstring(con,readsync);
stat = TRUE;
ccp = readsync;
while (stat) {
    cnt = readserial(con,0);
    cp = con->buf;
    while (cnt) {
        if (*cp++ != *ccp++) ccp = readsync;
        if (!*ccp) {
            stat = FALSE;
            break;
            }
        cnt--;
        }
    }
stat = TRUE;
while (cnt) {
    if (*cp++ == LF) {
        stat = FALSE;
        break;
        }
    cnt--;
    }
while (stat) {
    cnt = readserial(con,0);
    cp = con->buf;
    while (cnt) {
        if (*cp++ == LF) {
            stat = FALSE;
            break;
            }
        cnt--;
        }
    }
conprint(con,"\nVMS destination directory: ");
congets(con,dest);
forever {
    conprint(con,"AmigaDOS file expression: ");
    congets(con,files);
    if (files[0] == '\0') {
        sendstring(con,vms);
        return(0);
        }
    error = dfind(&fib,files,ATTR);
    cnt = strlen(files);
    cp = files + cnt - 1;
    while ((cnt)&&(*cp != ':')&&(*cp != '/')) {
        cp--;
        cnt--;
        }
    cp++;
    *cp = '\0';
    while (!error) {
        strcpy(filename,files);
        strcat(filename,fib.fib_FileName);
        fp = OPEN_FOR_READING(filename);
        if (fp == NULL) {
            sprintf(command,notopen,fib.fib_FileName);
            conprint(con,command);
            sendstring(con,vms);
            return(0);
            }
        sprintf(command,"sending file: %s\n",fib.fib_FileName);
        conprint(con,command);
        sprintf(command,"COPY %s %s%s\x0D",device,dest,fib.fib_FileName);
        sendstring(con,command);
        ccp = command;
        while (stat) {
            cnt = readserial(con,0);
            cp = con->buf;
            while (cnt) {
                if (*cp++ != *ccp++) ccp = command;
                if (!*ccp) {
                    stat = FALSE;
                    break;
                    }
                cnt--;
                }
            }
        stat = TRUE;
        while (cnt) {
            if (*cp++ == LF) {
                stat = FALSE;
                break;
                }
            cnt--;
            }
        while (stat) {
            cnt = readserial(con,0);
            cp = con->buf;
            while (cnt) {
                if (*cp++ == LF) {
                    stat = FALSE;
                    break;
                    }
                cnt--;
                }
            }
        for (cnt = 0; cnt < PAUSE; cnt++) WaitTOF();
        lenght = PACKET;
        while (lenght == PACKET) {
            lenght = READ(fp,con->conv,PACKET);
            cp = con->conv;
            cnt = lenght;
            while (cnt--) {
                if (*cp == LF) *cp = CR;
                cp++;
                }
            if (lenght)
                if (writeasync(con,lenght)) break;
            while (readserial(con,0));
            }
        CLOSEFILE(fp);
        sendstring(con,SEOF);
        readserial(con,0);
        sendstring(con,TERMSTRING);
        termcount = 0;
        while (termcount < TERMLEN) {  
            lenght = readserial(con,0);
            cp = con->buf;
            while (lenght) {
                if (*cp++ == TERMCHAR) termcount++; else termcount = 0;
                lenght--;
                }
            }
        sendstring(con,TERMDEL);
        lenght = 0;
        while (lenght < TERMLEN) lenght += readserial(con,0);
        error = dnext(&fib);
        }
    }
}

receive(register struct console *con)
{
BOOL                wild,stat;
FILEHANDLE          fp;
register USHORT     lenght,bufcount,termcount,len,tlen;
USHORT              saved,first;
register char       *cp,*dcp,*icp,*name,*outbuf;
char                filename[COMLEN],line[MAXLINE];
char                files[COMLEN],command[COMLEN],dest[PATHLEN];
char                vms[] = "\x0D",notopen[] = "Can't open file %s\n";

outbuf = con->conv;
conprint(con,"\nAmigaDOS destination directory: ");
congets(con,dest);
if (dest[0]) {
    cp = dest + strlen(dest) - 1;
    if ((*cp != ':')&&(*cp != '/')) {
        cp++;
        *cp++ = '/';
        *cp = '\0';              
        }
    }
forever {
    conprint(con,"VMS file expression: ");
    congets(con,files);
    if (files[0] == '\0') {
        sendstring(con,vms);
        return(0);
        }
    if (strchr(files,'*') != NULL) {
        wild = TRUE;
        fp = NULL;
        }
    else {
        wild = FALSE;
        strcpy(filename,dest);
        lenght = strlen(files);
        cp = files + lenght - 1;
        while (lenght--) {
            if ((*cp == ']')||(*cp == '>')||(*cp == ':'))
                break;
            cp--;
            }
        cp++;
        strcat(filename,cp);
        fp = OPEN_FOR_WRITING(filename);
        if (fp == NULL) {
            sprintf(command,notopen,filename);
            conprint(con,command);
            sendstring(con,vms);
            return(0);
            }
        }
    sprintf(command,"type %s\x0D",files);
    sendstring(con,command);
    stat = TRUE;
    while (stat) {
        tlen = readserial(con,0);
        cp = con->buf;
        while (tlen) {
            tlen--;
            if (*cp++ == LF) {
                stat = FALSE;
                break;
                }
            }
        }
    sendstring(con,TERMSTRING);
    if (!wild) {
        sprintf(command,"receiving file: %s\n",filename);
        conprint(con,command);
        }
    termcount = 0;
    saved = 0;
    bufcount = 0;
    dcp = line;
    lenght = 0;
    first = 0;
    while (termcount < TERMLEN) {
        if (tlen) {
            icp = cp;
            len = tlen;
            tlen = 0;
            }
        else {
            len = readserial(con,0);
            icp = con->buf;
            }
        while (len) {
            if ((*icp == CR)||(!*icp)) {
                icp++;
                len--;
                }
            if (len) {
                if (*icp == TERMCHAR) termcount++; else termcount = 0;
                if ((*icp == LF)||(lenght == MAXLINE-2)) {
                    if (first) {
                        first = 0;
                        lenght = 0;
                        }
                    else {
                        *dcp++ = *icp;
                        lenght++;
                        }
                    *dcp = '\0';
                    cp = line;
                    if ((wild)&&(*cp != '%')) {
                        while ((cp = strchr(cp,':')) != NULL) {
                            cp++;
                            if ((*cp == '[')||(*cp == '<')) {
                                if ((name = strchr(cp,']')) == NULL)
                                     name = strchr(cp,'>');
                                if (name != NULL) {
                                    name++;
                                    if ((cp = strchr(name,';')) != NULL) {
                                        *cp = '\0';
                                        if (fp != NULL) {
                                            WRITE(fp,outbuf,bufcount);
                                            bufcount = 0;
                                            }
                                        dcp = line;
                                        lenght = 0;
                                        saved = 0;
                                        first = 1;
                                        if (fp != NULL) CLOSEFILE(fp);
                                        strcpy(filename,dest);
                                        strcat(filename,name);
                                        fp = OPEN_FOR_WRITING(filename);
                                        if (fp == NULL) {
                                            sprintf(command,notopen,filename);
                                            conprint(con,command);
                                            sendstring(con,vms);
                                            return(0);
                                            }
                                        sprintf(command,
                                            "receiving file: %s\n",name);
                                        conprint(con,command);
                                        }
                                    }
                                }
                            }
                        }
                    if (fp != NULL) {
                        cp = line + lenght - 2;
                        while ((lenght > 1)&&(*cp <= ' ')&&(*cp >= '\0')) {
                            *cp = LF;
                            cp--;
                            lenght--;
                            }
                        if (lenght == 1) {
                            lenght = 0;
                            saved++;
                            }
                        dcp = outbuf + bufcount;
                        if (saved == 2) {
                            *dcp++ = LF;
                            bufcount++;
                            if (bufcount > CONVSIZE-2) {
                                WRITE(fp,outbuf,bufcount);
                                bufcount = 0;
                                dcp = outbuf;
                                }
                            saved = 1;
                            }
                        if (lenght) {
                            if (saved) {
                                *dcp++ = LF;
                                bufcount++;
                                saved = 0;
                                }
                            cp = line;
                            while (lenght) {
                                *dcp++ = *cp++;
                                bufcount++;
                                if (bufcount > CONVSIZE-2) {
                                    WRITE(fp,outbuf,bufcount);
                                    bufcount = 0;
                                    dcp = outbuf;
                                    }
                                lenght--;
                                }
                            }
                        }
                    dcp = line;
                    lenght = 0;
                    }
                else {
                    *dcp++ = *icp;
                    lenght++;
                    }
                len--;
                icp++;
                }
            }
        }
    if (fp != NULL) {
        if (bufcount) WRITE(fp,outbuf,bufcount);
        CLOSEFILE(fp);
        }
    sendstring(con,TERMDEL);
    lenght = 0;
    while (lenght < TERMLEN) lenght += readserial(con,0);
    }
}

conprint(register struct console *con,register char *cp)
{
while(*cp) {
    if ((*cp == BS)||(*cp == DEL)) {
        *con->buf = BS;
        interpret(con,1);
        *con->buf = ' ';
        interpret(con,1);
        *cp = BS;
        }
    if (*cp == LF) commit(con);
    else {
        *con->buf = *cp;
        interpret(con,1);
        }
    cp++;
    }
cursorout(con);
return(0);
}

congets(register struct console *con,register char *cp)
{
register char *icp,str[32];
register USHORT len,cnt = 0;

forever {
    len = readconsole(con);
    if (len) {
        *(con->buf + len) = '\0';
        strcpy(str,con->buf);
        conprint(con,str);
        icp = str;
        while (len) {
            if (*icp == CR) {
                commit(con);
                *cp = '\0';
                return(0);
                }
            else if (*icp == SS3) {
                if (*(icp + 1) == 'M') {
                    commit(con);
                    *cp = '\0';
                    return(0);
                    }
                }
            else {
                if ((*icp == DEL)||(*icp == BS)) {
                    if (cnt) {
                        cnt--;
                        cp--;
                        }
                    icp++;
                    }
                else {
                    *cp++ = *icp++;
                    cnt++;
                    }
                }
            len--;
            }
        }
    }
return(0);
}

commit(register struct console *con)
{
*con->buf = CR;
interpret(con,1);
*con->buf = LF;
interpret(con,1);
return(0);
}
