-+-+-+-+-+-+-+-+ START OF PART 47 -+-+-+-+-+-+-+-+ X 20, /* Tenths of ms per char 4800 baud */ X 10 /* Tenths of ms per char 9600 baud */ X`7D; X# endif X X`0C X/* X * PSEUDO CODE X * X * Begin tgoto X * If string pointer is invalid then X * Return without doing anything. X * Else X * For each pad digit (if any) X * Do decimal left shift. X * Accumulate the lower digit. X * End for X * Adjust scale to tenths of milliseconds X * If there is a fractional field X * Skip the decimal point. X * If there is a valid tenths digit X * Accumulate the tenths. X * End if X * Discard remaining digits. X * End if X * If per line is specified then X * Adjust the pad time. X * Discard the per line flag char. X * End if X * While there are any characters left X * Send them out via output function. X * End while X * Transmit any padding required. X * End if X * End tgoto X * X */ X Xtputs(cp,affcnt,outc) Xchar *cp; Xint affcnt; Xint (*outc)(); X`7B X int ptime; /* Pad time in tenths of milliseconds */ X X if (cp == NULL `7C`7C *cp == NULL) `7B X return; X `7D else `7B X for (ptime = 0; isdigit(*cp); cp++) `7B X ptime *= 10; X ptime += (*cp - '0'); X `7D X ptime *= 10; X if (*cp == '.') `7B X cp++; X if (isdigit(*cp)) `7B X ptime += (*cp++ - '0'); X `7D X while (isdigit(*cp)) `7Bcp++;`7D X `7D X if (*cp == '*') `7B X ptime *= affcnt; X cp++; X `7D X while (*cp != NULL) `7B X (*outc)(*cp++); X `7D X# ifndef MSDOS X# ifndef VMS X do_padding(ptime,outc); X# endif X# endif X `7D X`7D X`0C X# ifndef MSDOS X/* X * FUNCTION X * X * do_padding transmit any pad characters required X * X * SYNOPSIS X * X * static do_padding(ptime,outc) X * int ptime; X * int (*outc)(); X * X * DESCRIPTION X * X * Does any padding required as specified by ptime (in tenths X * of milliseconds), the output speed given in the external X * variable ospeed, and the pad character given in the X * external variable PC. X * X */ X`0C X/* X * PSEUDO CODE X * X * Begin do_padding X * If there is a non-zero pad time then X * If the external speed is in range then X * Look up the delay per pad character. X * Round pad time up by half a character. X * Compute number of characters to send. X * For each pad character to send X * Transmit the pad character. X * End for X * End if X * End if X * End do_padding X * X */ X Xstatic do_padding(ptime,outc) Xint ptime; Xint (*outc)(); X`7B X register int nchars; X register int tpc; X X if (ptime != 0) `7B X if (ospeed > 0 && ospeed <= (sizeof(times)/ sizeof(int))) `7B X tpc = times`5Bospeed`5D; X ptime += (tpc / 2); X nchars = ptime / tpc; X for ( ; nchars > 0; --nchars) `7B X (*outc)(PC); X `7D X `7D X `7D X`7D X# endif $ CALL UNPACK TPUTS.C;1 610490742 $ create 'f' Xsys$share:vaxcrtl/share $ CALL UNPACK VAXCRTL.OPT;1 728066217 $ create 'f' X#ifdef VMS X#include "header.h" X X#include X#include X#include X#include X#include X#include X#include X#include X#include X X/* X * Read until end of file or until buffer is full. X * don't let the vms read (which stops once per record) X * fool the program. X */ Xvread(fd, buf, size) Xint fd; Xchar *buf; Xint size; X`7B X int csize; /* cumulative size */ X int isize; /* incremental size */ X X csize = 0; X do `7B X isize = read(fd, buf, size); X if (isize > 0) `7B X csize += isize; X buf += isize; X size -= isize; X `7D X `7D while (isize > 0); X return (csize); X`7D X X#else VMS X X#ifndef vread /* if not done as a macro in header.h */ Xvread(fd, buf, size) Xint fd; Xchar *buf; Xint size; X`7B X return (read(fd, buf, size)); X`7D X#endif vread X#endif VMS X X#ifdef VMS X/* X * Run a command in a subjob. Used for mailing the winners congratulations, X * tax bills, etc. Used for the shell escape command (!). Conditionalized X * for VMS wherever used (un*x has the right primitives). X */ Xlong Xoneliner(cstr) Xchar *cstr; X`7B X struct dsc$descriptor cdsc; X register long sts; X register long pstat; X X cdsc.dsc$a_pointer = cstr; X cdsc.dsc$w_length = strlen(cstr); X cdsc.dsc$b_dtype = DSC$K_DTYPE_T; X cdsc.dsc$b_class = DSC$K_CLASS_S; X X/* sts = LIB$SPAWN(&cdsc, 0, 0, 0, 0, 0, &pstat, 0, 0, 0, 0, 0); X if (sts != SS$_NORMAL) X return (sts); X else `20 X*/ X return (pstat); X`7D X`0C X/* X Data to convert the escape codes produced by VT style keypad keys to thing Vs X that LARN will understand. X*/ X#define MAX_KP_CONV 19 Xstruct`20 X `7B X char *inp_str; X char *out_str; X `7D keypad_conv`5BMAX_KP_CONV`5D = `7B `7B "\x1BOp", "i" `7D, /* KP V0 */ X `7B "\x1BOq", "b" `7D, /* KP1 */ X `7B "\x1BOr", "j" `7D, /* KP2 */ X `7B "\x1BOs", "n" `7D, /* KP3 */ X `7B "\x1BOt", "h" `7D, /* KP4 */ X `7B "\x1BOu", "." `7D, /* KP5 */ X `7B "\x1BOv", "l" `7D, /* KP6 */ X `7B "\x1BOw", "y" `7D, /* KP7 */ X `7B "\x1BOx", "k" `7D, /* KP8 */ X `7B "\x1BOy", "u" `7D, /* KP9 */ X `7B "\x1BOn", "." `7D, /* KP. */ X `7B "\x1BOl", "," `7D, /* KP, */ X `7B "\x1B`5BA", "K" `7D, /* uparrow */ X `7B "\x1B`5BB", "J" `7D, /* downarrow*/ X `7B "\x1B`5BC", "L" `7D, /* right arrow */ X `7B "\x1B`5BD", "H" `7D, /* left arrow */ X `7B "\x1BOP", "m" `7D, /* PF1 */ X `7B "\x1BOS", "@" `7D, /* PF4 */ X `7B "\x1B`5B23`7E", "\x1B" `7D /* (ESC) V */ X `7D; X X/* X VMS-specific terminal character read. Gets a character from the terminal, X translating keypad as necessary. Assumes VT-class terminals. X*/ Xvms_ttgetch() X `7B X X#define BUFFLEN 10 X X char *i; X int j; X register int incount; X static char buffer`5BBUFFLEN`5D; X static char *bufptr = buffer; X static char *bufend = buffer; X X lflush(); /* be sure output buffer is flushed */ X X /* Read the first char from the user X */ X if (bufptr >= bufend)`20 X `7B X bufptr = bufend = buffer; X incount = vmsread(buffer, BUFFLEN, 0); X while ( incount <= 0 ) X incount = vmsread(buffer, 1, 2); X bufend = &buffer`5Bincount`5D; X `7D X X /* If the first char was an ESCAPE, get the characters from an X escape sequence (eg pressing a key that generates such a X sequence). If it was a plain old escape, the vmsread() call X will return TIMEOUT. X */ X if (*bufptr == '\x1B' ) X `7B X incount = vmsread( bufend, (BUFFLEN - 1), 0 ); X if (incount >= 0) X bufend += incount ; X `7D X X /* Make sure the buffer is zero-terminated, since vmsread()`20 X doesn't zero-terminate the characters read. X */ X *bufend = '\0' ; X X /* run through the keypad conversion table to convert keypad X keys (escape sequences) and other supported escape sequences X to Larn command characters. X */ X for ( j = 0; j < MAX_KP_CONV ; j++ ) X if (strcmp( &buffer, keypad_conv`5Bj`5D.inp_str ) == 0 ) X `7B X strcpy( &buffer, keypad_conv`5Bj`5D.out_str ); X bufend = &buffer`5Bstrlen(&buffer)`5D; X break; X `7D X X /* If after running through the table the first character is still X ESCAPE, then we probably didn't get a match. Force unsupported X keys that generate escape sequences to just return an ESCAPE. X Effectively prevents key translations that generate escape X sequences. X */ X if (*bufptr == '\x1B' ) X `7B X bufend = &buffer`5B1`5D ; X `7D X *bufend = '\0' ; X X if (*bufptr == '\r') X *bufptr = '\n'; X X return (*bufptr++ & 0xFF); X `7D X Xtypedef struct`20 X `7B X short int status; X short int term_offset; X short int terminator; X short int term_size; X `7D IOSTAB; X Xint vmsread(buffer, size, timeout) Xchar *buffer; Xint size; Xint timeout; X `7B X X#define TIMEOUT (-2) X#define ERROR (-1) X X extern int iochan; X X register int status; X IOSTAB iostab; X static long termset`5B2`5D = `7B 0, 0 `7D; /* No terminator V */ X X status = SYS$QIOW(`20 X 0, /* Event flag */ X iochan, /* Input channel */ X IO$_READLBLK `7C IO$M_NOFILTR `7C IO$M_TIMED, X /* Read, no echo, no translate */ X &iostab, /* I/O status block */ X NULL, /* AST block (none) */ X 0, /* AST parameter */ X buffer, /* P1 - input buffer */ X size, /* P2 - buffer length */ X timeout, /* P3 - timeout */ X &termset, /* P4 - terminator set */ X NULL, /* P5 - ignored (prompt buffer) */ X 0 /* P6 - ignored (prompt size) */ X ); X if (status == SS$_TIMEOUT) X return (TIMEOUT); X else if (status != SS$_NORMAL) X return (ERROR); X else`20 X `7B X if ((status = iostab.term_offset + iostab.term_size) > 0) X return (status); X return (TIMEOUT); X `7D X `7D X X#endif VMS $ CALL UNPACK VMS.C;1 639851523 $ create 'f' XThis is a VMS version of LARN 12.3. To run it, larndir must be defined as a V`20 Xlogical name that points to the directory containing the support files`20 X(LARN.MAZ, LARN.HLP, etc). Larn looks for LARN.OPT in SYS$LOGIN. VMS Versi Von`20 X5.x may be required. X XThe first entry in the larn.pid file (1000) can be the wizard if the passwor Vd is Xknown (same password as in MS-DOS edition; see LARN122.DOC). X XThe sources have been compiled with termcap. It will look for the Xtermcap file either through the logical name "termcap", in the current Xdirectory as "termcap.", or as "sys$library:termcap." If there is Xa symbol or logical called "term" then the value of that will Xbe used for the terminal, otherwise the value from "terminal" will be Xused. X XThis version includes VMS Keypad support on VT class terminals. The keypad Xkeys must be set to application mode (SET TERM/APPLICATION) in order for LAR VN Xto recognise the keys. It is not necessary to set the KEYPAD option in the XLARN.OPT file. The key mappings are: X X`09`09`09`09PF1`09PF2`09PF3`09PF4 X`09`09`09`09`09`09`09'@' X`09`09`09`09KP7`09KP8`09KP9`09KP- X`09`09`09`09'y'`09'k'`09'u' X`09`09`09`09KP4`09KP5`09KP6`09KP, X`09`09`09`09'h'`09'.'`09'l'`09',' X`09`09 `5E`09`09KP1`09KP2`09KP3`09KP X`09`09'K'`09`09'b'`09'j'`09'n'`09Enter X`09 <`09 v`09 >`09KP0`09KP. X`09'H'`09'J'`09'L'`09'i'`09'.' X XKeypad mode occasionally seems flakey, especially on DECTerms. Until I can Xre-work it, this will have to do. Customization of the keypad is not`20 Xcurrently supported. `20 X X`09Kevin Routley $ CALL UNPACK VMSREADME.TXT;1 1510499198 $ v=f$verify(v) $ EXIT