home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
win100.tar.gz
/
win100.tar
/
winkpx.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-10-20
|
18KB
|
687 lines
/*
* Windows Kermit
*
* Written by William S. Hall
* 3665 Benton Street, #66
* Santa Clara, CA 95051
*
* protocol function support module
*/
#define NOKANJI
#define NOATOM
#define NOMINMAX
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include "winasc.h"
#include "winkpr.h"
#include "winkpf.h"
extern int cid;
struct DisplayWnd {
HWND hWnd;
HANDLE hVidBuffer;
BYTE *pVidBuffer;
short Width, Height;
short CharWidth, CharHeight;
short Xpos, Ypos;
short MaxLines, MaxCols;
short MaxLineLength;
short oCurrentLine;
short oVidLastLine;
short CurrLineOffset;
};
typedef struct DisplayWnd *PDISPLAYWND;
static struct DisplayWnd DWnd;
/* local functions */
static void near ResetFTParams(HWND hWnd, int mode);
BOOL FAR PASCAL krmShowChildren(HWND hWnd, LONG lParam);
static void NEAR krmGrayMenus(HWND hWnd, int mode, int style);
static void NEAR krmShowResult(HWND hWnd, int mode);
static void NEAR DoMCR(PDISPLAYWND pDWnd);
static void NEAR DoMLF(PDISPLAYWND pDWnd);
static void NEAR DoMBS(PDISPLAYWND pDWnd);
static void NEAR DoMTab(PDISPLAYWND pDWnd);
static void NEAR krmLongReplyUpdate(HDC hDC);
static void NEAR krmShowPackets(HWND hWnd, HDC hDC);
/* show packets when iconic */
static void NEAR krmShowPackets(HWND hWnd, HDC hDC)
{
char numstr[10];
register char *ptr;
register int num;
RECT rcPaint;
GetClientRect(hWnd, (LPRECT)&rcPaint);
num = unchar(sndpkt.pktbuf[2]);
numstr[0] = sndpkt.pktbuf[3];
numstr[1] = numstr[6] = '-';
if (num < 10) {
numstr[2] = '0';
ptr = numstr + 3;
}
else
ptr = numstr + 2;
itoa(num, ptr, 10);
numstr[4] = SP;
numstr[5] = rcvpkt.type;
if ((num = rcvpkt.num) < 10) {
numstr[7] = '0';
ptr = numstr + 8;
}
else
ptr = numstr + 7;
itoa(num, ptr, 10);
DrawText(hDC, (LPSTR)numstr,-1,(LPRECT)&rcPaint,
DT_LEFT | DT_NOCLIP | DT_WORDBREAK | DT_EXTERNALLEADING);
}
/* show large responses or data when iconic */
void krmShowTransferData(HWND hWnd, HDC hDC, BOOL iconic)
{
if (iconic)
krmShowPackets(hWnd, hDC);
else
if (DWnd.hVidBuffer)
krmLongReplyUpdate(hDC);
}
/* show long responses */
static void NEAR krmLongReplyUpdate(HDC hDC)
{
BYTE *pBuf = DWnd.pVidBuffer; /* top of buffer */
BYTE *pEnd = pBuf + DWnd.oVidLastLine; /* last line in buffer */
register BYTE *lineptr = pBuf + DWnd.oCurrentLine; /* current line in buf */
short base = DWnd.Ypos; /* starting screen position of current line */
short lines = DWnd.MaxLines; /* number of lines in tty window */
short length = DWnd.MaxLineLength; /* byte increment to next line */
short cheight = DWnd.CharHeight;
register int i;
SetBkMode(hDC, TRANSPARENT);
SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
/* loop through the lines, starting with the current one */
for (i = 0; i < lines; i++) {
TextOut(hDC, 0, base, lineptr, strlen(lineptr));
/* update the line pointer */
if ((lineptr -= length) < pBuf)
lineptr = pEnd;
base -= cheight; /* move the position of the next line */
}
}
/* process Kermit menu items */
void krmProcessKermitMenu(HWND hWnd, WORD menuitem)
{
HANDLE hInstance = (HANDLE)GetWindowWord(hWnd, GWW_HINSTANCE);
FARPROC fp;
LPSTR boxstr;
switch (menuitem) {
case IDM_MXPARAMS:
fp = MakeProcInstance((FARPROC)SetMiscParams, hInstance);
DialogBox(hInstance, MAKEINTRESOURCE(DT_KRM_MXPARAMS),hWnd,fp);
FreeProcInstance(fp);
break;
case IDM_CANCELFILE:
Kermit.fileabort = TRUE;
break;
case IDM_CANCELBATCH:
Kermit.batchabort = TRUE;
break;
case IDM_ERRORCANCEL:
Kermit.protocolabort = TRUE;
break;
case IDM_CANCELPROTOCOL:
clsif(); clsof(TRUE);
ResetFTParams(hWnd, krmState);
krmState = 0;
break;
case IDM_KRM_RECEIVE:
Kermit.sstate = 'v';
krmState = menuitem;
break;
case IDM_KRM_FINISH:
case IDM_KRM_LOGOUT:
case IDM_KRM_BYE:
Kermit.sstate = 'g';
krmState = menuitem;
break;
case IDM_KRM_GET:
Kermit.remotecmd = 'R';
Kermit.ids_title = IDS_KRM_GETFILES;
Kermit.nullstrOK = FALSE;
Kermit.sstate = 'r';
boxstr = MAKEINTRESOURCE(DT_KRM_GETFILE);
fp = MakeProcInstance((FARPROC)GetFileList, hInstance);
if (DialogBox(hInstance, boxstr, hWnd, fp))
krmState = menuitem;
FreeProcInstance(fp);
break;
case IDM_KRM_REMOTEHOST:
Kermit.remotecmd = 'C';
Kermit.ids_title = IDS_KRM_REMOTEHOST;
Kermit.nullstrOK = FALSE;
Kermit.sstate = 'c';
boxstr = MAKEINTRESOURCE(DT_KRM_GETFILE);
fp = MakeProcInstance((FARPROC)GetFileList, hInstance);
if (DialogBox(hInstance, boxstr, hWnd, fp))
krmState = menuitem;
FreeProcInstance(fp);
break;
case IDM_KRM_SEND:
Kermit.sstate = 's';
boxstr = MAKEINTRESOURCE(DT_KRM_SENDFILE);
fp = MakeProcInstance((FARPROC)SendFileDlgProc, hInstance);
if (DialogBox(hInstance, boxstr, hWnd, fp))
krmState = menuitem;
FreeProcInstance(fp);
break;
case IDM_KRM_CWD:
Kermit.sstate = 'g';
boxstr = MAKEINTRESOURCE(DT_KRM_REMOTE2);
fp = MakeProcInstance((FARPROC)krmRemoteChdir, hInstance);
if (DialogBox(hInstance, boxstr, hWnd, fp))
krmState = menuitem;
FreeProcInstance(fp);
break;
case IDM_KRM_REMOTEDIR:
Kermit.remotecmd = 'D';
Kermit.ids_title = IDS_KRM_REMOTEDIR;
Kermit.nullstrOK = TRUE;
Kermit.sstate = 'g';
boxstr = MAKEINTRESOURCE(DT_KRM_GETFILE);
fp = MakeProcInstance((FARPROC)krmRemoteCmdDlgBox, hInstance);
if (DialogBox(hInstance, boxstr, hWnd, fp))
krmState = menuitem;
FreeProcInstance(fp);
break;
case IDM_KRM_REMOTETYPE:
Kermit.remotecmd = 'T';
Kermit.ids_title = IDS_KRM_REMOTETYPE;
Kermit.nullstrOK = FALSE;
Kermit.sstate = 'g';
boxstr = MAKEINTRESOURCE(DT_KRM_GETFILE);
fp = MakeProcInstance((FARPROC)krmRemoteCmdDlgBox, hInstance);
if (DialogBox(hInstance, boxstr, hWnd, fp))
krmState = menuitem;
FreeProcInstance(fp);
break;
case IDM_KRM_REMOTEHELP:
Kermit.remotecmd = 'H';
Kermit.ids_title = IDS_KRM_REMOTEHELP;
Kermit.nullstrOK = TRUE;
Kermit.sstate = 'g';
boxstr = MAKEINTRESOURCE(DT_KRM_GETFILE);
fp = MakeProcInstance((FARPROC)krmRemoteCmdDlgBox, hInstance);
if (DialogBox(hInstance, boxstr, hWnd, fp))
krmState = menuitem;
FreeProcInstance(fp);
break;
case IDM_KRM_REMOTEDEL:
Kermit.remotecmd = 'E';
Kermit.ids_title = IDS_KRM_REMOTEDEL;
Kermit.nullstrOK = FALSE;
Kermit.sstate = 'g';
boxstr = MAKEINTRESOURCE(DT_KRM_GETFILE);
fp = MakeProcInstance((FARPROC)krmRemoteCmdDlgBox, hInstance);
if (DialogBox(hInstance, boxstr, hWnd, fp))
krmState = menuitem;
FreeProcInstance(fp);
break;
case IDM_KRM_REMOTEWHO:
Kermit.remotecmd = 'W';
Kermit.ids_title = IDS_KRM_REMOTEWHO;
Kermit.nullstrOK = TRUE;
Kermit.sstate = 'g';
boxstr = MAKEINTRESOURCE(DT_KRM_GETFILE);
fp = MakeProcInstance((FARPROC)krmRemoteCmdDlgBox, hInstance);
if (DialogBox(hInstance, boxstr, hWnd, fp))
krmState = menuitem;
FreeProcInstance(fp);
break;
case IDM_KRM_REMOTESPACE:
Kermit.remotecmd = 'U';
Kermit.ids_title = IDS_KRM_REMOTESPACE;
Kermit.nullstrOK = TRUE;
Kermit.sstate = 'g';
boxstr = MAKEINTRESOURCE(DT_KRM_GETFILE);
fp = MakeProcInstance((FARPROC)krmRemoteCmdDlgBox, hInstance);
if (DialogBox(hInstance, boxstr, hWnd, fp))
krmState = menuitem;
FreeProcInstance(fp);
break;
}
}
/* init protocol */
void tinit(HWND hWnd, int mode)
{
HANDLE hInstance = (HANDLE)GetWindowWord(hWnd, GWW_HINSTANCE);
FARPROC fp;
TEXTMETRIC TM;
HDC hDC;
Kermit.fpTimer = MakeProcInstance((FARPROC)krmDoTimeout, hInstance);
hDC = GetDC(hWnd);
GetTextMetrics(hDC, &TM);
Kermit.DispCharWidth = TM.tmAveCharWidth;
Kermit.DispCharHeight = TM.tmHeight + TM.tmExternalLeading;
ReleaseDC(hWnd, hDC);
krmGrayMenus(hWnd, mode, MF_GRAYED);
fp = MakeProcInstance((FARPROC)krmShowChildren, hInstance);
EnumChildWindows(hWnd, fp, (LONG)SW_HIDE);
FreeProcInstance(fp);
switch(mode) {
case IDM_KRM_SEND:
if (Kermit.waitsendtime > 0) {
Kermit.waitsend = TRUE;
SetTimer(hWnd,KRM_WAITSEND,Kermit.waitsendtime,Kermit.fpTimer);
}
case IDM_KRM_RECEIVE:
case IDM_KRM_GET:
fpXfer = MakeProcInstance(krmXferDlgBox, hInstance);
hWndXfer = CreateDialog(hInstance,MAKEINTRESOURCE(DT_KRM_XFER),
hWnd,fpXfer);
break;
}
Kermit.numtry = 0;
Kermit.pktnum = 0;
Kermit.pktcount = 0;
Kermit.retrycount = 0;
Kermit.bytesmoved = 0;
Kermit.filesize = 0;
Kermit.percentage = 0;
Kermit.displayfile = 0;
Kermit.inpacket = FALSE;
Kermit.fileabort = FALSE;
Kermit.batchabort = FALSE;
Kermit.protocolabort = FALSE;
Kermit.newname_flag = FALSE;
Kermit.chksumtype = 1;
remote.chksumtype = local.chksumtype;
Kermit.ebqflg = FALSE;
Kermit.ebq = 0;
Kermit.rqf = -1;
local.binquote = 'Y';
Kermit.rptflg = FALSE;
Kermit.hInFile = Kermit.hOutFile = NULL;
Kermit.filename = NULL;
Kermit.mstimeout = 1000 * remote.timeout;
Kermit.timeout = FALSE;
rcvpkt.state = PS_SYNCH;
rcvpkt.type = 'N';
rcvpkt.num = 0;
sndpkt.len = 0;
}
/* hide or show terminal and status windows */
BOOL FAR PASCAL krmShowChildren(HWND hWnd, LONG lParam)
{
ShowWindow(hWnd, LOWORD(lParam));
return TRUE;
}
/* gray or restore menus */
static void NEAR krmGrayMenus(HWND hWnd, int mode, int style)
{
register int i;
register HMENU hMenu = GetMenu(hWnd);
int opstyle, checkstyle;
opstyle = (style == MF_GRAYED) ? MF_ENABLED : MF_GRAYED;
checkstyle = (style == MF_GRAYED) ? MF_CHECKED : MF_UNCHECKED;
for (i = IDM_KRM_SEND; i <= IDM_KRM_REMOTEHOST; i++)
EnableMenuItem(hMenu, i, style);
for (i = IDM_CANCELFILE; i <= IDM_CANCELPROTOCOL; i++)
EnableMenuItem(hMenu, i, opstyle);
CheckMenuItem(hMenu, mode, checkstyle);
}
/* show result of transfer based on exit state */
static void NEAR krmShowResult(HWND hWnd, int mode)
{
int len;
int style;
int msgnum;
char szMessage[80];
char szCaption[40];
HANDLE hInstance = (HANDLE)GetWindowWord(hWnd, GWW_HINSTANCE);
if ((msgnum = Kermit.sstate) >= 0)
msgnum = KRM_USERCNX;
if (msgnum == KRM_COMPLETE)
style = MB_OK | MB_ICONASTERISK;
else
style = MB_OK | MB_ICONEXCLAMATION;
/* get the string corresponding to msgnum */
LoadString(hInstance, IDS_KRM_KERMIT, (LPSTR)szCaption, sizeof(szCaption));
len = strlen(szCaption);
LoadString(hInstance, mode, (LPSTR)(szCaption+len),sizeof(szCaption) - len);
if (((msgnum == KRM_COMPLETE) && (rcvpkt.len > 0)) ||
((msgnum == KRM_ERROR_PKT) && (rcvpkt.len > 0)))
strcpy(szMessage,rcvpkt.data);
else
LoadString(hInstance, msgnum, (LPSTR)szMessage, sizeof(szMessage));
/* put up this simple message box */
if (Kermit.bell)
MessageBeep(style);
MessageBox(hWnd,(LPSTR)szMessage, (LPSTR)szCaption, style);
}
/* reset things after transaction */
static void near ResetFTParams(HWND hWnd, int mode)
{
FARPROC fp;
HANDLE hInstance = (HANDLE)GetWindowWord(hWnd, GWW_HINSTANCE);
KillTimer(hWnd, KRM_WAITPACKET);
krmGrayMenus(hWnd, mode, MF_ENABLED);
krmShowResult(hWnd, mode);
switch(mode) {
case IDM_KRM_RECEIVE:
case IDM_KRM_GET:
case IDM_KRM_SEND:
if (hWndXfer != NULL) {
DestroyWindow(hWndXfer);
hWndXfer = NULL;
FreeProcInstance(fpXfer);
}
break;
case IDM_KRM_BYE:
if (Kermit.sstate == KRM_COMPLETE)
PostMessage(hWnd, WM_SYSCOMMAND, SC_CLOSE,0L);
break;
}
if (DWnd.hVidBuffer != NULL) {
DWnd.pVidBuffer = NULL;
LocalUnlock(DWnd.hVidBuffer);
DWnd.hVidBuffer = LocalFree(DWnd.hVidBuffer);
InvalidateRect(hWnd, (LPRECT)NULL, TRUE);
}
fp = MakeProcInstance((FARPROC)krmShowChildren, hInstance);
EnumChildWindows(hWnd, fp, (LONG)SW_RESTORE);
FreeProcInstance(fp);
if (Kermit.hRemoteCommand != NULL) {
Kermit.pRemoteCommand = NULL;
LocalUnlock(Kermit.hRemoteCommand);
Kermit.hRemoteCommand = LocalFree(Kermit.hRemoteCommand);
}
if (Kermit.hfilelist != NULL) {
Kermit.pfilelist = NULL;
LocalUnlock(Kermit.hfilelist);
Kermit.hfilelist = LocalFree(Kermit.hfilelist);
}
FreeProcInstance(Kermit.fpTimer);
}
/* adjust height of long displays if window is resized */
void krmAdjustHeight(short width, short height)
{
DWnd.Width = width;
DWnd.Height = height;
DWnd.Ypos = height - DWnd.CharHeight - 1;
InvalidateRect(DWnd.hWnd, (LPRECT)NULL, TRUE);
}
/* init display for long replies */
BOOL krmInitMainDisplay(HWND hWnd, short cwidth, short cheight)
{
HDC hDC;
RECT drect;
DWnd.hWnd = hWnd;
DWnd.CharWidth = cwidth;
DWnd.CharHeight = cheight;
if (DWnd.MaxCols == 0) {
hDC = GetDC(hWnd);
DWnd.MaxCols = GetDeviceCaps(hDC, HORZRES) / cwidth;
DWnd.MaxLines = GetDeviceCaps(hDC, VERTRES) / cheight;
DWnd.MaxLineLength = DWnd.MaxCols + 1;
ReleaseDC(hWnd, hDC);
}
GetClientRect(hWnd, (LPRECT)&drect);
DWnd.Width = drect.right;
DWnd.Height = drect.bottom;
if (DWnd.hVidBuffer = LocalAlloc(LPTR,DWnd.MaxLines * DWnd.MaxLineLength)) {
DWnd.pVidBuffer = LocalLock(DWnd.hVidBuffer);
DWnd.oCurrentLine = 0;
DWnd.oVidLastLine = DWnd.MaxLineLength * (DWnd.MaxLines - 1);
DWnd.CurrLineOffset = 0;
DWnd.Xpos = 0;
DWnd.Ypos = DWnd.Height - DWnd.CharHeight - 1;
return TRUE;
}
return (FALSE);
}
/* display received strings on long replies */
void krmMainStringDisplay(HWND hWnd, BYTE *str, short len)
{
HDC hDC;
register BYTE *ptr;
register short ctr;
short cols = DWnd.MaxCols;
short width = DWnd.Width;
short toff, txpos;
BYTE *tBuf;
while (len) {
ptr = str;
ctr = 0;
txpos = DWnd.Xpos;
tBuf = DWnd.pVidBuffer + DWnd.oCurrentLine;
toff = DWnd.CurrLineOffset;
/* first loop on any printable characters until none left or end of line */
while ((*ptr &= 0x7f) >= SP) {
if ((len) && (toff < cols)) {
ctr += 1;
*(tBuf + toff++) = *ptr++; /* store them in the buffer */
txpos += DWnd.CharWidth;
len -= 1;
}
else /* quit if we find a control character */
break;
}
if (ctr) { /* if we have some characters, show them */
if (!IsIconic(hWnd)) {
hDC = GetDC(hWnd);
SetBkMode(hDC, TRANSPARENT);
SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
TextOut(hDC, DWnd.Xpos, DWnd.Ypos, (LPSTR)str, ctr);
ReleaseDC(hWnd, hDC);
}
/* if not at end of line yet */
if (toff < cols) { /* update buffer and caret variables */
DWnd.CurrLineOffset = toff;
DWnd.Xpos = txpos;
}
else { /* end of line, so wrap */
DoMCR(&DWnd);
DoMLF(&DWnd);
}
}
while ((*ptr &= 0x7f) < SP) { /* now loop on any control characters */
if (len) {
switch (*ptr) {
case BEL:
MessageBeep(0);
break;
case HT:
DoMTab(&DWnd);
break;
case BS:
DoMBS(&DWnd);
break;
case LF:
DoMLF(&DWnd);
break;
case CR:
DoMCR(&DWnd);
break;
}
len -= 1; /* reduce buffer count */
ptr++; /* update pointer */
}
else
break; /* no more control characters */
}
str = ptr; /* reset string pointer and do again if len > 0 */
}
}
/* do carriage return */
static void NEAR DoMCR(PDISPLAYWND pDWnd)
{
pDWnd->Xpos = pDWnd->CurrLineOffset = 0;
}
/* Do a line feed */
static void NEAR DoMLF(PDISPLAYWND pDWnd)
{
register BYTE *pCurr;
register int i;
short cols = pDWnd->MaxCols;
short offset;
RECT scrollrect;
/* update the circular text buffer parameters */
if ((pDWnd->oCurrentLine += pDWnd->MaxLineLength) > pDWnd->oVidLastLine)
pDWnd->oCurrentLine = 0;
pCurr = pDWnd->pVidBuffer + pDWnd->oCurrentLine;
offset = pDWnd->CurrLineOffset;
/* fill in any places from beginning of line with spaces */
for (i = 0; i < offset; i++)
*(pCurr + i) = SP;
/* fill in the rest with nuls */
for (i = offset; i < cols; i++)
*(pCurr + i) = NUL;
/* now move the tty window up exactly one line and refresh it */
if (!IsIconic(pDWnd->hWnd)) {
GetClientRect(pDWnd->hWnd, (LPRECT)&scrollrect);
ScrollWindow(pDWnd->hWnd,0,-pDWnd->CharHeight,
(LPRECT)&scrollrect,(LPRECT)NULL);
UpdateWindow(pDWnd->hWnd);
}
}
/* Horizontal tab */
static void NEAR DoMTab(PDISPLAYWND pDWnd)
{
RECT myrect;
BYTE *pCurr = pDWnd->pVidBuffer + pDWnd->oCurrentLine;
short cols = pDWnd->MaxCols;
register short xpos = pDWnd->Xpos;
register short curoffset = pDWnd->CurrLineOffset;
if (curoffset < (cols - 1)) {
do {
if (*(pCurr + curoffset) == NUL) /* if null, replace with space */
*(pCurr + curoffset) = SP;
curoffset += 1; /* update offsets */
xpos += DWnd.CharWidth;
} while ((curoffset % 8 != 0) && (curoffset < (cols - 1)));
/* now invalidate the part of the screen affected */
if (!IsIconic(pDWnd->hWnd)) {
SetRect((LPRECT)&myrect, pDWnd->Xpos, pDWnd->Ypos, pDWnd->Width,
pDWnd->Height);
InvalidateRect(pDWnd->hWnd, (LPRECT)&myrect, TRUE);
}
/* finally, reset the tty window variables */
pDWnd->Xpos = xpos;
pDWnd->CurrLineOffset = curoffset;
}
}
/* Backspace */
static void NEAR DoMBS(PDISPLAYWND pDWnd)
{
/* don't back up if at beginning of line! */
if (pDWnd->CurrLineOffset > 0) {
pDWnd->Xpos -= pDWnd->CharWidth;
pDWnd->CurrLineOffset -= 1;
}
}