home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Boot Disc 8
/
boot-disc-1997-04.iso
/
PDA_Soft
/
Psion
/
comms
/
p3nfs
/
nfsc
/
nfsc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-05-26
|
39KB
|
1,310 lines
/*
* In this file lines end with CR/LF, as our psion C-compiler lives in the
* DOS-WORLD
* Copyright GNU Public License
*/
#include <plib.h> /* NFS Client V3.10 N.N */
#include <p_serial.h>
#include <wlib.h>
#include <hwif.h>
#include "nfsc.h"
#define TXT_TYPE H_DTEXT_ALIGN_CENTRE
/*======================================================== NFSC set ===*/
#define NR_OF_DEVICES 5 /* do not change, configure over menu */
#ifdef HAVE_NFSSUPPORT
static char *dev_name[]={"LOC::M:", "LOC::A:", "LOC::B:", "LOC::C:", "ROM::"};
#endif
static char welcome[]= "Welcome to Nfsc 4.3b";
struct settings set = {
{P_BAUD_9600,P_BAUD_9600,P_DATA_8,0,P_IGN_CTS,0x11,0x13,0,0},
{0,0,P_SRDTR_ON}, /* modem sense, DTR assert */
{1,1,1,1,1}, /* all devices active */
FLAGS_SHOW_STATS | FLAGS_SMALL_STATWIN | FLAGS_NFSD_NEW | FLAGS_JUMPSCROLL,
WS_FONT_BASE+4, /* Roman 8 Point, s3 see bel. */
XY_YMODEM1K
};
TEXT *EnvironmentName="NFSC_v32";
/*========================================================== menu's used ===*/
static H_MENU_DATA mdata[]= {
#ifdef HAVE_NFSSUPPORT
"Nfsc", 4,
#else
"Nfsc", 2,
#endif
"Serial Line", 7,
#ifdef HAVE_TERMEMU
"Emulator",6,
#endif
#ifdef HAVE_XYMODEM
"XYmodem",3,
#endif
NULL
};
static TEXT * cmds[]= {
/* nfsc */
"aAbout...",
#ifdef HAVE_NFSSUPPORT
"dDevices...",
"nNfsd support...",
#endif
"xExit",
/* Serial Line */
"pParameters...",
"hHandshaking...",
"HExpert settings...",
"tToggle stats",
"cClear stats",
"uUpdate stats...",
"bSend a break",
#ifdef HAVE_TERMEMU
/* Emulator */
"rReset",
"zZoom: bigger",
"ZZoom: smaller",
"fFont...",
"FFn Keys...",
"sSettings...",
#endif
#ifdef HAVE_XYMODEM
/* XYmodem */
"CConfigure...",
"SSend file...",
"RReceive file...",
#endif
NULL
};
TEXT ** _cmds=cmds;
H_MENU_DATA * _mdata=mdata;
/*===================================================== global variables ===*/
ULONG stats_read, stats_write; /* Read / write statistics */
P_RECT hisrect; /* Rectangle for nfscmd history scrolling */
INT stat_y,modem_x,io_x; /* Y pos for stat printing (font descent),etc*/
UBYTE charwidth,charheight, /* Character data */
ascent, rows, cols;
WORD screenx,screeny, /* Character width */
t_w, t_h; /* terminal width & height in pixels */
BYTE clkwin;
BYTE debug = 0;
BYTE isnfsd = 0; /* used for sending a resize event *gulp* */
extern UWORD _UseFullScreen; /* use full s3a or only s3 screen */
char buf[256], buf2[256]; /* serial read buffers, not on stack */
char rfilename[256]; /* last filename read */
VOID *rfile = 0; /* last read filehandle */
LONG roff = 0; /* last read offset */
INT hgc; /* handle to graphics context */
UINT main_win; /* main window ID */
VOID *serial = 0; /* handle serial port */
LOCAL_D VOID *timH; /* handle timer */
LOCAL_D ULONG timint = 20; /* poll interval in 100msec units */
WORD zero=0,one=1; /* constants to interact with serial port */
TEXT mfb[40]; /* message formatting buffer; */
UBYTE pctrl = 0xff; /* store last pctrl */
UBYTE protocol; /* nfsd protocol none=0,old=1,new=2
* new = 0x80 as escape character for nfs cmd,
* old = no terminal capability
* none = only terminal
*/
UBYTE sch; /* Serial character */
WORD ttystat; /* We need it global */
UBYTE is_rtscts;
#ifdef HAVE_TERMEMU
struct fkey *fk;
static char logfile[129] = "\015\\opd\\nfsc.log";
static char fnkeyname[129] = "\017\\opd\\fnkeys.nfs";
char cur_appl; /* cursor keys in application mode */
BYTE fnkey = 0;
void *logfd = 0;
#include "cnv.h" /* charset conversion */
#endif
static char c_handshaking[] = "Handshaking";
static char c_ignore[] = "Ignore";
static char c_load[] = "Load";
static char c_save[] = "Save";
static char c_cfgserial[] = "configure serial";
static char c_dtr[] = "change DTR";
static char c_query[] = "query modem";
/*========================================================= AddToHistory ===*/
void AddToHistory (char ch) {
static char idle;
P_POINT o;
int i = hisrect.tl.x;
if(! ( set.flags & FLAGS_SHOW_STATS) )
return;
if (!ch) /* a heart beat indicator */
{
idle++;
if (idle != 2) /* Will wrap after 256 ticks. But that is o.k. */
return;
/* seen two heatbeats in a row. Print a '.' as idle indicator */
ch = '.';
}
else
idle = 0;
gPrintText(hisrect.br.x-charwidth, stat_y, &ch, 1);
o.y = 0;
o.x = -charwidth;
hisrect.tl.x += charwidth;
wScrollRect(main_win, &hisrect, &o); /* scroll one character leftward */
hisrect.tl.x = hisrect.br.x - charwidth;
gClrRect(&hisrect, G_TRMODE_CLR); /* clear space for next character */
hisrect.tl.x = i;
}
void Check (INT val,TEXT *msg)
{
if (!val) return;
p_atos(&mfb[0],"Failed to %s",msg);
if (!p_notifyerr(val,&mfb[0],"Abort",c_ignore,0))
p_exit(0);
}
void UpdateModem()
{
if(serial == 0 || !(set.flags & FLAGS_SHOW_STATS) )
return;
Check(p_iow(serial, P_FCTRL, set.pctrl), c_query);
if (set.pctrl[0] == pctrl)
return;
pctrl = set.pctrl[0];
p_atos(mfb, "%s %s %s",
(pctrl & P_SRCTRL_CTS) ? "CTS" : "cts",
(pctrl & P_SRCTRL_DSR) ? "DSR" : "dsr",
(pctrl & P_SRCTRL_DCD) ? "DCD" : "dcd");
set.pctrl[1] = 0x00; /* in case we did set it here */
gPrintText(modem_x, stat_y, mfb, p_slen(mfb));
}
/*=============== Check, if write would block, i.e. flow control is on === */
void
serial_write(char *p, int n)
{
int ret;
if(!(set.tty.hand & P_IGN_CTS))
{
Check(p_iow(serial, P_FCTRL, set.pctrl), c_query);
while(!(set.pctrl[0] & P_SRCTRL_CTS))
{
H_DI_TEXT line1={buf+ 0,TXT_TYPE},
line2={buf+ 50,TXT_TYPE};
uZTStoBCS (line1.str, "Hardware flowcontrol specified,");
uZTStoBCS (line2.str, "but modem line CTS is not set");
if ( uOpenDialog ("WARNING!")
|| uAddDialogItem (H_DIALOG_TEXT, NULL, &line1)
|| uAddDialogItem (H_DIALOG_TEXT, NULL, &line2)
|| (uAddButtonList ("Exit", 'x',
c_ignore, 'i',
"Retry", W_KEY_RETURN, NULL))
|| (ret = uRunDialog()) <= 0)
continue;
if(ret == 'x')
p_exit(0);
if(ret == 'i')
{
Sw_Serial(OFF);
set.tty.hand |= P_IGN_CTS;
p_waitstat (&ttystat);
if ((ret=p_iow(serial,P_FSET,&set.tty)) != 0) p_panic (ret);
Sw_Serial(ON);
break;
}
Check(p_iow(serial, P_FCTRL, set.pctrl), c_query);
}
}
p_write (serial, p, n);
stats_write += n;
}
/*============================================================ ShowStats ===*/
void ShowStats (void) {
if(! ( set.flags & FLAGS_SHOW_STATS) )
return;
p_atos (mfb, "I/O:%07Lu/%07Lu", stats_read, stats_write);
gPrintText(io_x, stat_y, mfb, p_slen(mfb));
}
/*=============================================================== Resize ===*/
/* Compute every position & redraw everything */
void Resize (void)
{
W_WINDATA wd;
WORD havestat;
P_RECT pr;
G_FONT_INFO fi;
G_GC gc;
int ret, l1, l2;
/*----------------------------------- draw screen with status window ---*/
if(clkwin)
{
if (_UseFullScreen) /* S3a */
{
if(clkwin == 2)
havestat = W_STATUS_WINDOW_BIG;
else
havestat = W_STATUS_WINDOW_SMALL;
wInquireStatusWindow (havestat, &wd.extent);
wd.extent.tl.x = wd.extent.tl.y = 0;
wd.extent.width = screenx - wd.extent.width;
wd.extent.height = screeny;
}
else
wsScreenExt (&wd.extent); /* Much easier */
}
else
{
wd.extent.tl.x = wd.extent.tl.y = 0;
wd.extent.width = screenx;
wd.extent.height = screeny;
}
wSetWindow (main_win, W_WIN_EXTENT, &wd);
if ((ret=wCheckPoint()) != 0) p_exit (ret);
pr.tl.x = pr.tl.y = 0;
pr.br.x = wd.extent.width;
pr.br.y = wd.extent.height;
gClrRect(&pr, G_TRMODE_CLR);
if(clkwin)
{
if(_UseFullScreen)
wStatusWindow(havestat);
else
wsEnable();
}
else
wsDisable();
/*-------------------------------------------------------- Change GC ---*/
gc.style = G_STY_MONO;
gc.font = WS_FONT_BASE + set.font;
gSetGC(hgc, G_GC_MASK_STYLE|G_GC_MASK_FONT, &gc);
/*----------------- compute layout of the graphics items: ---*/
gFontInfo(gc.font, G_STY_MONO, &fi);
charwidth = fi.max_width;
charheight = fi.height;
ascent = fi.ascent;
t_w = wd.extent.width;
t_h = screeny;
if ( set.flags & FLAGS_SHOW_STATS )
{
t_h -= charheight;
l1 = gTextWidth(gc.font, G_STY_MONO, "I/O:9999999/9999999", 19);
l2 = gTextWidth(gc.font, G_STY_MONO, "CTS DSR DCD", 11);
stat_y = screeny - fi.descent;
io_x = 0;
hisrect.tl.x = l1+1;
hisrect.tl.y = screeny - charheight;
hisrect.br.x = t_w - l2;
hisrect.br.y = screeny;
modem_x = hisrect.br.x;
/*
gDrawLine(0, t_y, t_w, t_y);
*/
ShowStats();
pctrl = 0xff;
UpdateModem();
}
rows = t_h / charheight; t_h = charheight * rows;
cols = t_w / charwidth; t_w = charwidth * cols;
if(isnfsd)
{
/* Resize event ... */
buf2[0] = 0; buf2[1] = rows; buf2[2] = cols;
P_WRITE(serial, buf2, 3);
}
#ifdef HAVE_TERMEMU
Reset();
LoadFnKey(fnkeyname, 0);
p_atos (mfb, "rows: %d, cols: %d", rows, cols);
wInfoMsgCorner(mfb, W_CORNER_BOTTOM_RIGHT);
#endif
}
/*=========================================== screen/menu initialization ===*/
void ScreenInitialize (void) {
INT len;
G_GC gc;
/*-------------------------------------------------- initialize HWIF ---*/
_UseFullScreen = TRUE; /* Set this to False for testing S3 */
hCrackCommandLine();
uCommonInit();
uEscape (FALSE);
/*----------------------------------- read set from environment ---*/
/* p_delenv (EnvironmentName);/* */
len = p_getenviron (EnvironmentName, p_slen(EnvironmentName), buf);
if (len==sizeof(set))
p_bcpy (&set, buf, sizeof(set));
else
{
if(!_UseFullScreen)
set.font = 0; /* S3 font for the first time */
}
clkwin = (set.flags >> 2) & 0x3;
protocol = (set.flags >> 4) & 0x3;
/*--------------------------------------------- set process priority ---*/
p_setpri (p_getpid(), E_MAX_PRIORITY);
if (_UseFullScreen) wSetPriorityControl (FALSE); /* S3a only */
/*----------------------------------------------------- first resize ---*/
main_win = uFindMainWid();
if(_UseFullScreen)
{
screenx = 480; screeny = 160;
}
else
{
screenx = 240; screeny = 80;
}
gc.textmode = G_TRMODE_REPL; /* Default ist _SET */
hgc = gCreateGC(main_win, G_GC_MASK_TEXTMODE, &gc);
Resize();
}
/*======================================== Cancel / Reenable serial input ==*/
void Sw_Serial(char on)
{
if(on)
{
one=1;
p_ioa (serial, P_FREAD, &ttystat, &sch, &one);
}
else
{
p_iow (serial, P_FCANCEL);
}
}
/*=============================================================== DoExit ===*/
void DoExit()
{
int ret;
set.flags &= ~0x3c; /* Delete bits for clkwin & protocol */
set.flags |= (clkwin << 2) | (protocol << 4);
ret = p_setenviron(EnvironmentName, p_slen(EnvironmentName),
&set, sizeof(set));
uErrorValue(ret);
p_exit(0);
}
#ifdef HAVE_TERMEMU
/*=============================================================== iso2cp ===*/
unsigned char
iso2cp(unsigned char ch) /* Called only with ch > 127 */
{
if(set.flags & FLAGS_NOCHARCONV)
return ch;
else
return tbl_iso2cp[ch-128];
}
#endif
/*=================================================== ExecuteMenuCommand ===*/
void ParseKey (UWORD key, UBYTE modifier) {
INT ret;
/*--------------------------------------------------- system event ---*/
if (key == 0x404)
{
wGetCommand((UBYTE *)buf);
if(*buf == 'X')
DoExit();
return;
}
if (key & 0x400) /* Some other system event */
return;
/*------------------------------------------- Function keys -----------*/
#ifdef HAVE_TERMEMU
if(fnkey) /* Define or delete it */
{
if(fnkey == 'd')
{
H_DI_TEXT l1={buf+ 0, TXT_TYPE},
l2={buf+ 50, TXT_TYPE},
l3={buf+100, TXT_TYPE},
l4={buf+150, TXT_TYPE};
H_DI_EDIT l5={buf+150, 100};
fnkey = 0;
uZTStoBCS(l1.str, "Type in the characters to be sent.");
uZTStoBCS(l2.str, "Use \\<nnn> for nonprintable (e.g. \\027=ESC)");
uZTStoBCS(l3.str, "and \\s<nn> for delay (e.g. \\s99=9.9 seconds)");
uZTStoBCS(l4.str, "");
if ( uOpenDialog ("Defining the function key")
|| uAddDialogItem (H_DIALOG_TEXT, NULL, &l1)
|| uAddDialogItem (H_DIALOG_TEXT, NULL, &l2)
|| uAddDialogItem (H_DIALOG_TEXT, NULL, &l3)
|| uAddDialogItem (H_DIALOG_TEXT, NULL, &l4)
|| uAddDialogItem (H_DIALOG_EDIT, NULL, &l5))
return;
if(uRunDialog() > 0)
AddFnKey(key, modifier, l5.str);
}
if(fnkey == 'r')
{
struct fkey **fp, *f;
for(fp = &fk, f = fk; *fp; f = *fp)
if(f->key == key && f->modifier == modifier)
{
*fp = f->next;
p_free(f);
wInfoMsgCorner("FnKey deleted", W_CORNER_BOTTOM_RIGHT);
}
else
fp = &f->next;
}
fnkey = 0;
return;
}
{ /* Was the key a function key ? */
struct fkey *f;
for(f = fk; f; f = f->next)
if(f->key == key && f->modifier == modifier)
{
SendFnKey(f);
return;
}
}
#endif
/*------------------------------------------- clock window ------------*/
if (key == W_KEY_MENU && modifier == W_CTRL_MODIFIER)
{
if(--clkwin < 0)
clkwin = _UseFullScreen ? 2 : 1;
Resize();
return;
}
/*------------------------------------- send key to the serial line ---*/
if (!(key & W_SPECIAL_KEY) && (key!=W_KEY_MENU))
{
#ifdef HAVE_TERMEMU
if(key >= 256 && key <= 259) /* Arrow key */
{
char mb[3];
mb[0] = 0x1b;
mb[1] = cur_appl ? 'O' : '[';
mb[2] = 'A' + (key - 256);
P_WRITE(serial, mb, 3);
}
else
{
key = key & 0xff;
if(key > 127 && !(set.flags & FLAGS_NOCHARCONV))
key = tbl_cp2iso[key-128];
P_WRITE(serial, (char *)&key, 1); /* BigEndian!!! */
}
#endif
return; /* terminal */
}
/*------------------------- strip Psion modifier and get menu option ---*/
key &= ~W_SPECIAL_KEY;
if((key==W_KEY_MENU) && ((key=uPresentMenus()) <= 0))
return;
if (modifier & W_SHIFT_MODIFIER)
key -= 0x20;
/*---------------------------------------- switch on command request ---*/
switch (key) {
case 'a': { /*-------------------------------------------- About ---*/
H_DI_TEXT line1={buf+ 0,TXT_TYPE},
line2={buf+ 50,TXT_TYPE},
line3={buf+100,TXT_TYPE},
line4={buf+150,TXT_TYPE},
line5={buf+200,TXT_TYPE};
uZTStoBCS (line1.str, "N.N, Rudolf König,");
uZTStoBCS (line2.str, "Michael Schröder, Jürgen Weigert");
uZTStoBCS (line3.str, "╕ 1995, 1996");
uZTStoBCS (line4.str, "jnweiger / rfkoenig@immd4.uni-erlangen.de");
uZTStoBCS (line5.str, "Distributed under GNU Copyleft (Version 2)");
if ( uOpenDialog ("About NFSC v4.3b")
|| uAddDialogItem (H_DIALOG_TEXT, NULL, &line1)
|| uAddDialogItem (H_DIALOG_TEXT, NULL, &line2)
|| uAddDialogItem (H_DIALOG_TEXT, NULL, &line3)
|| uAddDialogItem (H_DIALOG_TEXT, NULL, &line4)
|| uAddDialogItem (H_DIALOG_TEXT, NULL, &line5)
|| (_UseFullScreen && uAddButtonList ("", W_KEY_RETURN, NULL)) /* S3 doesn't fit */
|| uRunDialog() <= 0)
return;
return;
}
case 'p': { /*--------------------------------------------- Port ---*/
UWORD baud = set.tty.tbaud;
UWORD databits = (set.tty.frame & P_DATA_FRM) + 1;
UWORD stopbits = (set.tty.frame & P_TWOSTOP) ? 2 : 1;
UWORD parity = (set.tty.frame & P_PARITY) ?
set.tty.parity + 1 : 0x01 /*none*/;
UWORD ignore = (set.tty.flags & P_IGNORE_PARITY) ? 1 : 2;
if ( uOpenDialog ("Port")
|| uAddChoiceList ("Baud rate", &baud, "50","75","110","134",
"150","300","600","1200","1800","2000","2400",
"3600","4800","7200","9600",
_UseFullScreen ? "19200" : NULL, NULL)
|| uAddChoiceList ("Data bits",&databits,"5","6","7","8",NULL)
|| uAddChoiceList ("Stop bits", &stopbits, "1", "2", NULL)
|| uAddChoiceList ("Parity",&parity,"none","even","odd",NULL)
|| uAddChoiceList ("Ignore parity", &ignore,"yes","no", NULL)
|| uRunDialog() <= 0)
return;
set.tty.tbaud = set.tty.rbaud = baud;
set.tty.frame = databits - 1;
set.tty.frame |= (stopbits == 2) ? P_TWOSTOP : 0x00;
set.tty.frame |= (parity > 1 /*none*/) ? P_PARITY : 0x00;
set.tty.parity = parity - 1;
set.tty.flags = (ignore == 1) ? P_IGNORE_PARITY : 0x00;
Sw_Serial(OFF); /* otherwise panic with P_FSET! */
p_waitstat (&ttystat);
if ((ret=p_iow(serial,P_FSET,&set.tty)) != 0) p_panic (ret);
Sw_Serial(ON);
return;
}
case 'h': { /*-------------------------------------- Handshaking ---*/
UWORD flow;
if(set.tty.hand & P_SEND_XOFF) /* Software flow control */
flow = 1;
else if(set.tty.hand & P_IGN_CTS)
flow = 3;
else
flow = 2; /* Hw flow control */
if ( uOpenDialog(c_handshaking)
|| uAddChoiceList("Flowcontrol:",&flow,
"Software","Hardware","None", NULL)
|| uRunDialog() <= 0)
return;
if(flow == 1)
set.tty.hand = P_SEND_XOFF | P_IGN_CTS;
else if(flow == 2)
set.tty.hand = 0;
else
set.tty.hand = P_IGN_CTS;
set.pctrl[1] = set.pctrl[2] == P_SRDTR_ON;
Sw_Serial(OFF); /* otherwise panic with P_FSET! */
p_waitstat (&ttystat);
Check(p_iow(serial,P_FSET,&set.tty), c_cfgserial);
Check(p_iow(serial,P_FCTRL,&set.pctrl), c_dtr);
set.pctrl[1] = 0x00; /* or ModemUpdate will do it again */
Sw_Serial(ON);
return;
}
case 'H': { /*------------------------------- Expert Handshaking ---*/
UWORD xon_xoff = set.tty.hand & P_SEND_XOFF ? 2 : 1;
UWORD rts_cts = set.tty.hand & P_IGN_CTS ? 2 : 1;
UWORD dsr_dtr = set.tty.hand & P_OBEY_DSR ? 2 : 1;
UWORD dcd = set.tty.hand & P_OBEY_DCD ? 2 : 1;
UWORD dtr = set.pctrl[2] == P_SRDTR_ON ? 2 : 1;
if ( uOpenDialog (c_handshaking)
|| uAddChoiceList ("Send Xon/Xoff", &xon_xoff, "Off","On",NULL)
|| uAddChoiceList ("Ignore RTS/CTS", &rts_cts, "Off","On",NULL)
|| uAddChoiceList ("Obey DSR/DTR", &dsr_dtr, "Off","On",NULL)
|| uAddChoiceList ("Obey DCD", &dcd, "Off","On",NULL)
|| uAddChoiceList ("Assert DTR", &dtr, "Off","On",NULL)
|| uRunDialog() <= 0)
return;
set.tty.hand = 0x00; /* default is ZERO for RTS/CTS */
set.tty.hand |= (xon_xoff == 2) ? P_SEND_XOFF|P_OBEY_XOFF : 0;
set.tty.hand |= (rts_cts == 2) ? P_IGN_CTS : 0x00;
set.tty.hand |= (dsr_dtr == 2) ? P_OBEY_DSR : 0x00;
set.tty.hand |= (dcd == 2) ? P_OBEY_DCD : 0x00;
set.pctrl[2] = 0x00;
set.pctrl[2] |= (dtr == 2) ? P_SRDTR_ON : P_SRDTR_OFF;
set.pctrl[1] = set.pctrl[2];
Sw_Serial(OFF); /* otherwise panic with P_FSET! */
p_waitstat (&ttystat);
Check(p_iow(serial,P_FSET,&set.tty), c_cfgserial);
Check(p_iow(serial,P_FCTRL,&set.pctrl), c_dtr);
set.pctrl[1] = 0x00; /* or ModemUpdate will do it again */
Sw_Serial(ON);
return;
}
#ifdef HAVE_NFSSUPPORT
case 'd': { /*------------------------------------------ Devices ---*/
UWORD dev[5];
INT i;
if(uOpenDialog ("Devices"))
return;
for(i=0; i<NR_OF_DEVICES; i++)
{
dev[i] = set.devices[i] + 1;
if(uAddChoiceList(dev_name[i], &dev[i], "Off", "On", NULL))
return;
}
if(uRunDialog() <= 0)
return;
for(i=0; i<NR_OF_DEVICES; i++)
set.devices[i] = dev[i] - 1;
return;
}
case 'n': { /*---------------------------------------- Nfsd support */
UWORD prt = protocol+1;
if ( uOpenDialog ("Protocol")
|| uAddChoiceList("Support:",&prt,
"Terminal only", "Old p3nfsd", "Terminal + New p3nfsd", NULL)
|| uRunDialog() <= 0)
return;
protocol = prt-1;
return;
}
#endif
case 27: /* Psion-Esc */
case 'x': /*--------------------------------------------- Exit ---*/
DoExit();
case 't': /*-------------------------------- Statistics:Toggle ---*/
if ( set.flags & FLAGS_SHOW_STATS )
set.flags &= ~FLAGS_SHOW_STATS;
else
set.flags |= FLAGS_SHOW_STATS;
Resize();
return;
case 'c': /*--------------------------------- Statistics:Clear ---*/
stats_read = stats_write = 0;
ShowStats();
return;
case 'u': { /*------------------------------------------- Update ---*/
/* dialog to change update frequency: timint */
H_DI_NUMBER num;
num.value= (LONG *)&timint;
num.low = 5;
num.high = 1000;
if (uOpenDialog("Update frequency") ||
uAddDialogItem(H_DIALOG_NUMBER, "10ths of secs", &num) ||
uRunDialog() <= 0)
return;
return;
}
case 'b': { /*-------------------------------------- Send a break --*/
/* We can send a break of 10/50sec = 200msec at most. Should be
at least 250msec, but it could be better than nothing */
P_SRCHAR tty;
unsigned char z = 0, i;
Sw_Serial(OFF);
p_iow (serial, P_FFLUSH);
p_waitstat (&ttystat);
tty = set.tty;
tty.tbaud = tty.rbaud = P_BAUD_50;
tty.frame = P_DATA_8 | P_PARITY; /* This means 200ms */
tty.parity = P_PAR_EVEN;
tty.hand = P_IGN_CTS;
Check(p_iow(serial, P_FSET, &tty), c_cfgserial);
for(i = 0; i < 6; i++) /* little over 1 sec */
P_WRITE(serial, (char *)&z, 1);
Check(p_iow(serial,P_FSET,&set.tty), c_cfgserial);
set.pctrl[1] = 0x00; /* or ModemUpdate will do it again */
p_iow (serial, P_FFLUSH);
Sw_Serial(ON);
return;
}
#ifdef HAVE_TERMEMU
case 'r': /*--------------------------------------- Reset term --*/
Resize();
return;
case 'z': /*------------------------------------- Zoom bigger ---*/
if(!_UseFullScreen)
return;
if(set.font == 12)
set.font = 4;
else
set.font++;
Resize();
return;
case 'Z': /*------------------------------------- Zoom smaller ---*/
if(!_UseFullScreen)
return;
if(set.font == 4)
set.font = 12;
else
set.font--;
Resize();
return;
case 'f': { /*------------------------------------ Choose font ---*/
UWORD font = set.font > 7 ? 2 : 1;
UWORD size = set.font - (font == 1 ? 3 : 7);
if ( uOpenDialog ("Font & size")
|| uAddChoiceList ("Font", &font, "Roman", "Swiss", NULL)
|| uAddChoiceList ("Size", &size, "8", "11", "13", "16", NULL)
|| uRunDialog() <= 0)
return;
font = (font == 1 ? 3 : 7) + size;
if ( font != set.font )
{
set.font = font;
Resize();
}
return;
}
case 'F': { /*--------------------------------------- Fn keys ---*/
char title[] = "Function keys";
if (uOpenDialog (title)
|| (uAddButtonList ("Define", 'd', "Remove", 'r',
c_save, 's', c_load, 'l', NULL))
|| (ret = uRunDialog()) <= 0)
return;
if(ret == 'd' || ret == 'r')
{
wInfoMsgCorner("Type the function key",W_CORNER_BOTTOM_RIGHT);
fnkey = ret;
}
if(ret == 's' || ret == 'l')
{
H_DI_TEXT line1={buf+ 0,TXT_TYPE},
line2={buf+ 50,TXT_TYPE};
H_DI_FSEL line3={ fnkeyname, 0 };
if(ret=='s')
line3.flags |= H_FILE_NEW_EDITOR;
uZTStoBCS (line1.str, "nfsc is autoloading \\opd\\fnkeys.nfs");
uZTStoBCS (line2.str, "");
if ( uOpenDialog (title)
|| uAddDialogItem (H_DIALOG_TEXT, NULL, &line1)
|| uAddDialogItem (H_DIALOG_TEXT, NULL, &line2)
|| uAddDialogItem (H_DIALOG_FSEL,
ret=='s' ? c_load : c_save, &line3)
|| uRunDialog() <= 0)
return;
if(ret == 's')
SaveFnKey(fnkeyname);
else
LoadFnKey(fnkeyname, 1);
}
return;
}
case 's': { /*------------------------------ Settings ---*/
UWORD cnv = (set.flags & FLAGS_NOCHARCONV) ? 2 : 1;
UWORD jsc = (set.flags & FLAGS_JUMPSCROLL) ? 1 : 2;
UWORD log = logfd ? 1 : 2;
UWORD db = debug ? 1 : 2;
if ( uOpenDialog ("Terminal emulator settings")
|| uAddChoiceList ("ISO8859-1 to IBM850", &cnv,"On","Off",NULL)
|| uAddChoiceList ("Enable jumpscroll", &jsc,"On","Off",NULL)
|| uAddChoiceList ("Debugging", &db, "On","Off",NULL)
|| uAddChoiceList ("Log terminal output", &log,"Yes","No",NULL)
|| uRunDialog() <= 0)
return;
if(cnv == 1)
set.flags &= ~FLAGS_NOCHARCONV;
else
set.flags |= FLAGS_NOCHARCONV;
if(jsc == 1)
set.flags |= FLAGS_JUMPSCROLL;
else
set.flags &= ~FLAGS_JUMPSCROLL;
debug = 2 - db;
log = 2 - log;
if((logfd && !log) || (!logfd && log)) /* Changed */
{
if(!log)
{
p_close(logfd);
logfd = 0;
wInfoMsgCorner("Logging terminated", W_CORNER_BOTTOM_RIGHT);
}
else
{
extern char cant_open_the_file[];
H_DI_FSEL line3={ logfile, H_FILE_NEW_EDITOR };
logfile[*logfile+1] = 0;
if ( uOpenDialog ("Logging")
|| uAddDialogItem (H_DIALOG_FSEL, "Logfile:", &line3)
|| uRunDialog() <= 0)
return;
if(p_open(&logfd,logfile+1,P_FSTREAM|P_FREPLACE|P_FUPDATE))
wInfoMsgCorner(cant_open_the_file, W_CORNER_BOTTOM_RIGHT);
else
wInfoMsgCorner("Logging started", W_CORNER_BOTTOM_RIGHT);
}
}
return;
}
#endif /* HAVE_TERMEMU */
#ifdef HAVE_XYMODEM
case 'C': /*------------------------------------------ XYmodem ----*/
case 'S':
case 'R': /*------------------------------------------ XYmodem ----*/
/* XYmodem commands are only allowed in terminal-only mode */
if(protocol != 0)
{
H_DI_TEXT line1={buf+ 0,TXT_TYPE},
line2={buf+ 50,TXT_TYPE};
int ret;
uZTStoBCS (line1.str, "Sorry, XYmodem commands are only");
uZTStoBCS (line2.str, "allowed in the \"Terminal only\" mode");
if ( uOpenDialog ("XYmodem commands:")
|| uAddDialogItem (H_DIALOG_TEXT, NULL, &line1)
|| uAddDialogItem (H_DIALOG_TEXT, NULL, &line2)
|| (uAddButtonList ("", W_KEY_RETURN, NULL))
|| (ret = uRunDialog()) <= 0)
return;
return;
}
DoXYmodem(key);
return;
#endif
}
}
#ifdef HAVE_NFSSUPPORT
/*============================================================== Respond ===*/
VOID Respond(int rc) {
if(protocol == 1)
{
P_WRITE (serial, (char *)&rc, 1); /* Big Endian!!! */
}
else
{
char ret[2];
ret[0] = PREFIX;
ret[1] = rc;
P_WRITE (serial, ret, 2);
}
}
/*=============================================================== DoWork ===*/
VOID DoWork (void) {
struct { LONG offset; UINT len; UBYTE req; } *parms;
void *file;
char *str;
INT rc, to_read;
LONG offset;
P_INFO p_info;
UWORD crc, crc2;
WORD len;
/*-------------------------------------------------- read length&data ---*/
len = sch;
if(protocol == 2) /* We are reading the length here for the new proto */
{
len = 0;
P_READ (serial, &len, 1); /* Big Endian!! */
}
P_READ (serial, buf, len);
/*------------------ last (few) bytes contain request type and parms ---*/
parms = (void *) (buf + len - sizeof(*parms));
/*---------------- string is PASCAL string with C string termination ---*/
str = buf+1;
/*---------------------------------- piggyback statd code onto gattr ---*/
if (parms->req == 0x0C) {
AddToHistory ('f');
Respond(0);
}
/*------------------------------------ last byte in frame is request ---*/
switch (parms->req) {
case 0x01: /*------------------------------------------------- creat ---*/
rc = p_open (&file, str, P_FSTREAM|P_FREPLACE|P_FUPDATE);
AddToHistory ((rc == 0) ? 'c' : 'C');
if(!rc)
p_close (file);
Respond(rc);
return;
case 0x02: /*------------------------------------------------- gattr ---*/
rc = p_finfo (str, &p_info);
AddToHistory ((rc == 0) ? 'g' : 'G');
Respond(rc);
if (rc) return;
if (p_info.status & P_FADIR) {
case 0x0C: /* statd */
/* damned filesystem without linkcount :( */
p_info.version = 0;
p_scat (str, "\\");
p_open (&file, str, P_FDIR);
while(p_iow (file, P_FREAD, buf, (P_INFO*)buf2) != E_FILE_EOF)
if(((P_INFO *)buf2)->status & P_FADIR)
p_info.version++;
p_close (file);
}
P_WRITE (serial, (char *)&p_info, 12);
return;
case 0x03: /*--------------------------------------------------- mkd ---*/
AddToHistory ('m');
Respond(p_mkdir(str));
return;
case 0x04: /*-------------------------------------------------- read ---*/
/* Only close the read fd after the last file chunk was read */
offset = parms->offset;
len = parms->len;
rc = 0;
if(*rfilename == 0 || p_scmp(rfilename, str))
{
if(*rfilename)
{
p_close(rfile);
*rfilename = 0;
}
rc = p_open (&rfile,str,P_FOPEN|P_FSTREAM|P_FRANDOM|P_FSHARE);
if(!rc)
{
p_scpy(rfilename, str);
roff = 0;
}
}
if(rc == 0) rc = p_finfo (str, &p_info);
if(offset > p_info.size) offset = p_info.size;
if(offset + len > p_info.size) len = p_info.size - offset;
if(rc == 0 && roff != offset)
rc = p_seek (rfile, P_FABS, &offset);
AddToHistory ((rc == 0) ? 'r' : 'R');
Respond(rc);
if(rc)
return;
roff = offset;
P_WRITE (serial, (char *)&p_info, 12);
crc = 0;
while(len > 0) {
to_read = (len > sizeof(buf)) ? sizeof(buf) : len;
to_read = p_read (rfile, buf, to_read);
len -= to_read;
roff += to_read;
if(protocol > 1)
p_crc(&crc, (UBYTE *)buf, (UINT)to_read);
P_WRITE (serial, buf, to_read);
}
if(protocol > 1)
P_WRITE (serial, (char *)&crc, 2);
if(roff == p_info.size)
{
p_close (rfile);
*rfilename = 0;
}
return;
case 0x05: /*-------------------------------------------------- rdir ---*/
AddToHistory ('l');
Respond(0);
p_open (&file, str, P_FDIR);
while (p_iow (file, P_FREAD, buf, NULL) != E_FILE_EOF)
P_WRITE (serial, buf, p_slen(buf)+1);
p_close (file);
P_WRITE(serial, (char *)&zero, 1);
return;
case 0x06: /*-------------------------------------------------- remv ---*/
AddToHistory ('d');
Respond(p_delete(str));
return;
case 0x07: /*-------------------------------------------------- renm ---*/
AddToHistory ('n');
len = ((unsigned char *)(&parms->len))[1];
P_READ (serial, buf2, len);
buf2[len]=0;
rc = p_rename (str, buf2+1);
Respond(rc);
return;
case 0x08: /*--------------------------------------------------- rmd ---*/
AddToHistory ('z');
Respond(p_delete(str));
return;
case 0x09: /*------------------------------------------------- sattr ---*/
AddToHistory ('s');
Respond(p_sfstat (str, parms->len,/*attr*/ 0x0F2F));
return;
case 0x0A: /*------------------------------------------------- write ---*/
offset = parms->offset;
len = parms->len;
rc = p_open (&file, str, P_FOPEN | P_FSTREAM | P_FUPDATE | P_FRANDOM);
if(rc == 0 && offset > 0)
rc = p_seek (file, P_FABS, &offset);
crc = 0;
while (len) {
to_read = (len > sizeof(buf)) ? sizeof(buf) : len;
P_READ(serial, buf, to_read);
if(protocol > 1)
p_crc(&crc, (UBYTE *)buf, (UINT)to_read);
if(rc == 0)
rc = p_write (file, buf, to_read);
len -= to_read;
}
p_close (file);
if(protocol > 1)
{
P_READ (serial, &crc2, 2);
if(crc != crc2)
{
AddToHistory ('?');
if(rc == 0)
rc = 1;
}
}
Respond(rc);
AddToHistory ((rc == 0) ? 'w' : 'W');
return;
case 0x0B: /*-------------------------------------------------- getd ---*/
AddToHistory ('>');
Respond(0);
for(len=0; len<NR_OF_DEVICES; len++)
{
if(set.devices[len] && p_dinfo(dev_name[len], (P_DINFO *)buf) == 0)
{
P_WRITE (serial, dev_name[len], p_slen(dev_name[len])+1);
P_WRITE (serial, buf, 14);
}
}
P_WRITE (serial, (char *)&zero, 1);
return;
#ifdef HAVE_TERMEMU
case 0x0D: /*------------------------------------------------- ttydata -*/
if(protocol == 2)
{
AddToHistory ('+');
TtyEmu((UBYTE *)str, *(UBYTE *)buf); /* No return this time */
if(isnfsd == 0)
{
isnfsd = 1;
buf2[0] = 0; /* Resize event ... */
buf2[1] = rows;
buf2[2] = cols;
P_WRITE(serial, buf2, 3);
}
}
else
{
AddToHistory ('X');
Respond(1);
}
return;
#endif
default: /*----------------------------------------------- default ---*/
AddToHistory ('X');
Respond(1);
return;
}
}
#endif /* HAVE_NFSSUPPORT */
#define QueueTimer(when) p_ioa4(timH,P_FRELATIVE,&timstat,&when)
/*================================================================= main ===*/
void main (void) {
WORD keystat, timstat;
WMSG_KEY key;
char *str;
/*------------------------------------------- program initialization ---*/
stats_read = stats_write = 0;
ScreenInitialize ();
for(str = welcome; *str; str++)
AddToHistory(*str);
/*------------------------------------------------- open serial port ---*/
Check(p_open(&serial,"TTY:A",-1), "open TTY:A");
Check(p_iow(serial,P_FSET,&set.tty), "init serial line");
one=1; p_ioa (serial, P_FREAD, &ttystat, &sch, &one);
if (set.flags & FLAGS_SHOW_STATS)
UpdateModem();
Check(p_open(&timH,"TIM:",-1), "open timer");
QueueTimer(timint);
uGetKeyA (&keystat, &key);
/*-------------------------------------------------------- main loop ---*/
for (;;) {
/*--------------------------------- wait for something to happen ---*/
p_iowait();
/*------------------------------------------- was a key pressed? ---*/
if (keystat != E_FILE_PENDING) {
ParseKey (key.keycode, key.modifiers);
uGetKeyA (&keystat, &key);
continue;
}
/*------------------------------ did the serial port talk to us? ---*/
if (ttystat != E_FILE_PENDING) {
stats_read++;
#ifdef HAVE_NFSSUPPORT
if(protocol == 1 || (protocol == 2 && sch == PREFIX))
DoWork ();
else
#endif
{
#ifdef HAVE_TERMEMU
/*
Problem: bytewise reading and screen update is too slow.
Let's try to read more if there is available. The problem
is that there may be a protocol 2 command in the data.
Therefore this is restricted to the "terminal only" mode.
*/
if(protocol == 0)
{
*buf = sch;
p_iow(serial, P_FTEST, &one);
if(one > 0) /* hmmm */
{
if(one > 255) one = 255;
p_iow (serial, P_FREAD, buf+1, &one);
}
one++; /* the first byte is already read before */
TtyEmu((unsigned char *)buf, one);
}
else
TtyEmu(&sch, 1);
#endif
}
ShowStats ();
one=1; p_ioa (serial, P_FREAD, &ttystat, &sch, &one);
continue;
}
/*------------------------------------------ time for a timeout? ---*/
if (timstat != E_FILE_PENDING)
{
UpdateModem();
AddToHistory (0);
wFlush();
QueueTimer(timint);
}
}
}