
/***************************************************************************
*
* Winsnd
*
* File send module for Windows Kermit
*
***************************************************************************/
#include <windows.h>
#include "winkrm.h"
#include <string.h>
     
/* these can be near procedures */
int NEAR sendsw();
char NEAR sinit();
char NEAR sfile();
char NEAR sdata();
char NEAR seof();
char NEAR sbreak();
int NEAR bufill(char*);
     
static char filelist[100];	/* file names to send */
static char *nextfile;		/* pointer to next file to be sent */
     
/***************************************************************************
*
* send
*
* This routine creates the send popup window and calls the send state machine
*
* Entry: None
*
* Exit: File(s) sent or failure.
*
***************************************************************************/
int FAR send()
{
     
    RECT rect;		/* will contain screen location of main window */
    char TXTitle[20];	/* popup window title */
    int result;
     
/* create a dialog box to get file to be sent */
    result = DialogBox(hInst,MAKEINTRESOURCE(SENDBOX),hKermWnd,lpprocSendBox);
    if (result <= 0) {
        MessageBox(hKermWnd, (LPSTR)"No filename(s) specified",
	 	       (LPSTR)szWinTitle, MB_OK | MB_ICONEXCLAMATION);
        SendMessage(hKermWnd, WM_COMMAND, SENDSTATE, (LONG)NULL);
	return;
    }
     
    nextfile = strtok(filelist, " ,");	/* parse file list */
     
    eol = CR;				/* eol for outgoing packet */
    quote = MYQUOTE;			/* standard quote */
    pad = MYPAD;			/* no padding */
    padchar = MYPCHAR;			/* if any, use this */
     
    StateStr[0] = '\0';		/* initialize popup window parameters */
    PacketStr[0] = '\0';
    filnam1[0] = '\0';
     
    debug = FALSE;		/* need to make these menu items */
    pktdeb = FALSE;
     
    ThisState = SENDSTATE;
     
    GetWindowRect(hKermWnd, (LPRECT)&rect);	/* set up popup parameters */
    strcpy(TXTitle,szWinTitle);
    strcat(TXTitle," Send");
     
/* create the send popup window */
     
    hRXWnd = CreateWindow((LPSTR)szAppName,
                        (LPSTR)TXTitle,
			WS_POPUP | WS_CAPTION,
			5*CharWidth + rect.left,
			4*CharHeight + rect.top,
			21*CharWidth,
			5*CharHeight - CharHeight/2,
                        (HWND)hKermWnd,
                        (HMENU)NULL,
                        (HANDLE)hInst,
                        (LPSTR)NULL
                        );
     
/* kill off the menu, and show the window */
     
    SetMenu(hRXWnd, (HANDLE)NULL);
    ShowWindow(hRXWnd, SHOW_OPENNOACTIVATE);
    UpdateWindow(hRXWnd);
     
    if (pktdeb) {
	dpfp = fopen("PACKET.LOG", "wb");
        if (dpfp == NULL)
            MessageBox(hKermWnd, (LPSTR)"Cannot open packet debug file",
	 	       (LPSTR)szWinTitle, MB_OK | MB_ICONEXCLAMATION);
    }
     
    if (sendsw() == FALSE)		/* send it */
	printmsg("Send failed");
    else
	printmsg("Send Done");
     
    if (pktdeb)
        fclose(dpfp);
     
    DestroyWindow(hRXWnd);		/* get rid of popup window */
     
    if (CurrentState == SENDSTATE)	/* simulate a mouse press */
	SendMessage(hKermWnd, WM_COMMAND, SENDSTATE, (LONG)NULL);
     
}
     
/***************************************************************************
*
* sendsw
*
* State table switcher for send
*
* Entry: None.
*
* Exit: File sent or aborted.
*
***************************************************************************/
int NEAR sendsw()
{
     
    state = 'S';
    n = 0;
    numtry = 0;
    PacketCount = 0;
     
    while (TRUE) {
	if (debug)
	    printf("rendsw state %c\n", state);
        StateStr[0] = state;
	strcpy(PacketStr, itoa(PacketCount, PacketStr,10));
	hRXWndDC = GetDC(hRXWnd);
	TextOut(hRXWndDC,9*CharWidth,2,(LPSTR)StateStr,1);
	TextOut(hRXWndDC,10*CharWidth,CharHeight+2,(LPSTR)PacketStr,strlen(PacketStr));
	ReleaseDC(hRXWnd, hRXWndDC);
	PacketCount += 1;
	switch (state) {
	    case 'S':
		state = sinit();
		break;
	    case 'F':
		state = sfile();
		break;
	    case 'D':
		state = sdata();
		break;
	    case 'Z':
		state = seof();
		break;
	    case 'B':
		state = sbreak();
		break;
	    case 'C':
		return (TRUE);
	    case 'A':
		return (FALSE);
	}
    }
}
     
/***************************************************************************
*
* sinit
*
* Send init packet
*
* Entry: none.
*
* Exit: next state.
*
***************************************************************************/
char NEAR sinit()
{
    int num, len;
     
    if (debug)
	printf("In sinit retries: %d\n", numtry);
     
    if (numtry++ > MAXTRY)
	return('A');
    spar(packet);
     
    FlushComm(cid, 1);
     
    spack('S',n,6, packet);
    switch(rpack(&len, &num, recpkt)) {
	case 'N':
	    return(state);
     
	case 'Y':
	    if (n != num)
		return (state);
	    rpar(recpkt);
	    if (eol == 0)
		eol = CR;
	    if (quote == 0)
		quote = '#';
	    numtry = 0;
	    n = (n+1) % 64;
	    return('F');
     
	case 'E':
	    prerrpkt(recpkt);
	    return('A');
     
	case FALSE:
	    return(state);
     
	default:
	    return('A');
    }
}
	
/***************************************************************************
*
* sfile
*
* Send file name.
*
* Entry: none.
*
* Exit: next state.
*
***************************************************************************/
char NEAR sfile()
{
    int num, len;
    char *temp;
     
    if (numtry++ > MAXTRY)
	return('A');
     
    if (fp == NULL)
	if (debug)
	    printf("    Opening %s for sending.\n", nextfile);
	fp = fopen(nextfile, "rb");
	if (fp == NULL) {
            MessageBox(hKermWnd, (LPSTR)"Cannot send file",
	 	       (LPSTR)szWinTitle, MB_OK | MB_ICONEXCLAMATION);
	    return('A');
	}
     
    temp = strpbrk(nextfile,":\\");
    if (temp != NULL) {
        nextfile = temp + 1;
        temp = strrchr(nextfile, '\\');
        if (temp != NULL)
            nextfile = temp+1;
    }
    strncpy(filnam1, strupr(nextfile), NAMESIZE);	
    len = strlen(filnam1);
    hRXWndDC = GetDC(hRXWnd);
    TextOut(hRXWndDC,8*CharWidth,2*CharHeight+2,
	    (LPSTR)"            ", 12);
    TextOut(hRXWndDC,8*CharWidth,2*CharHeight+2,(LPSTR)filnam1,strlen(filnam1));
    ReleaseDC(hRXWnd, hRXWndDC);
    FlashWindow(hRXWnd, FALSE);
    spack('F', n, len, filnam1);
    switch(rpack(&len, &num, recpkt)) {
	case 'N':
	    num = (--num < 0 ? 63:num);
	    if (n != num)
		return('S');
     
	case 'Y':
	    if (n != num)
		return(state);
	    numtry = 0;
	    n = (n+1)%64;
	    size = bufill(packet);
	    return('D');
	
	case 'E':
	    prerrpkt(recpkt);
	    return('A');
     
	case FALSE:
	    return(state);
     
	default:
	    return('A');
    }
}
     
/***************************************************************************
*
* sdata
*
* Send a data packet
*
* Entry: none.
*
* Exit: next state.
*
***************************************************************************/
char NEAR sdata()
{
    int num, len;
     
    if (numtry++ > MAXTRY)
	return('A');
     
    spack('D',n,size,packet);
    switch(rpack(&len, &num, recpkt)) {
     
	case 'N' :
	    num = (--num < 0 ? 63 : num);
	    if (n != num)
		return(state);
     
	case 'Y':
	    if (n != num)
		return(state);
	    numtry = 0;
	    n = (n+1)%64;
	    if ((size = bufill(packet)) == EOF)
		return('Z');
	    return('D');
     
	case 'E':
	    prerrpkt(recpkt);
	    return('A');
     
	case FALSE:
	    return(state);
     
	default:
	    return('A');
    }
}
     
/***************************************************************************
*
* seof
*
* Send end of file
*
* Entry: none.
*
* Exit: next state.
*
***************************************************************************/
char NEAR seof()
{
     
    int num, len;
     
    if (numtry++ > MAXTRY)
	return('A');
     
    spack('Z',n,0,packet);
    switch(rpack(&len, &num, recpkt)) {
     
	case 'N' :
	    num = (--num < 0 ? 63 : num);
	    if (n != num)
		return(state);
     
	case 'Y':
	    if (n != num)
		return(state);
	    numtry = 0;
	    n = (n+1)%64;
	    if (debug)
		printf("    Closing input file %s\n", nextfile);
	    fclose(fp);
	    fp == NULL;
	    if((nextfile = strtok(NULL, " ,")) == NULL)
		return('B');
	    if (debug)
		printf("    New file is %s\n", nextfile);
	    return('F');
     
	case 'E':
	    prerrpkt(recpkt);
	    return('A');
     
	case FALSE:
	    return(state);
     
	default:
	    return('A');
    }
}
     
/***************************************************************************
*
* sbreak
*
* send a break packet
*
* Entry: none.
*
* Exit: next state.
*
***************************************************************************/
char NEAR sbreak()
{
     
    int num, len;
     
    if (numtry++ > MAXTRY)
	return('A');
     
    spack('B',n,0,packet);
    switch(rpack(&len, &num, recpkt)) {
     
	case 'N' :
	    num = (--num < 0 ? 63 : num);
	    if (n != num)
		return(state);
     
	case 'Y':
	    if (n != num)
		return(state);
	    numtry = 0;
	    n = (n+1)%64;
	    return('C');
     
	case 'E':
	    prerrpkt(recpkt);
	    return('A');
     
	case FALSE:
	    return(state);
     
	default:
	    return('A');
    }
}
     
     
/***************************************************************************
*
* GetSendFile
*
* Windows function for get-file-name dialogue box.
*
* Entry: Usual windows function variables.
*
* Exit: box taken down or filenames list created.
*
***************************************************************************/
BOOL FAR PASCAL GetSendFile(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
     
    int count;
     
    if (message == WM_COMMAND) {
	switch(wParam) {
	    case IDOK:
		count = GetDlgItemText(hDlg,SNDFILENAME,(LPSTR)filelist,100);
		EndDialog(hDlg, count);
		break;
	    case IDCANCEL:
		EndDialog(hDlg, FALSE);
		break;
	    default:
		return FALSE;
        }
	return TRUE;
    }
    else if (message == WM_INITDIALOG)
	return TRUE;
    else
	return FALSE;
}
     
/***************************************************************************
*
* bufill
*
* Fill a buffer from file to be sent to remote Kermit.
*
* Entry: buffer to be filled.
*
* Exit: size of buffer.
*
* Side effects: buffer filled.
*
***************************************************************************/
int NEAR bufill(buffer)
char buffer[];
{
    int i, t;
    char t7;
     
    i = 0;
    while ((t = getc(fp)) != EOF) {
	t7 = unpar(t);
	if (t7 < SP || t7==DEL || t7==quote) {
	    buffer[i++] = quote;
	    if (t7 != quote) {
	    /*	t = ctl(t); */
		t7 = ctl(t7);
	    }
	}
	buffer[i++] = t7;
	if (i >= spsiz - 8)
	    return(i);
    }
    if (i == 0)
	return(EOF);
    return(i);
}
