billr@saab.CNA.TEK.COM (Bill Randle) (04/24/91)
Submitted-by: routley@tle.ENET.DEC.COM (Kevin Routley)
Posting-number: Volume 12, Issue 63
Archive-name: larn2/Part10
Supersedes: larn: Volume 11, Issue 84-94
Environment: Unix, VMS, MS-DOS, OS/2, termcap
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 10 (of 12)."
# Contents: fortune.c iventory.c larnhlp.uue msdos.c tgetent.c
# Wrapped by billr@saab on Tue Apr 23 13:50:35 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'fortune.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'fortune.c'\"
else
echo shar: Extracting \"'fortune.c'\" \(4263 characters\)
sed "s/^X//" >'fortune.c' <<'END_OF_FILE'
X/* fortune.c */
X#ifdef VMS
X#include <types.h>
X#include <stat.h>
X#include <file.h>
X#else
X# include <sys/types.h>
X# include <sys/stat.h>
X# ifndef BSD4.1
X# include <fcntl.h>
X# else BSD4.1
X# define O_RDONLY 0
X# endif BSD4.1
X#endif VMS
X
X#include "header.h"
X#include "player.h"
X#include "larndefs.h"
Xextern char fortfile[];
X
Xoutfortune()
X {
X char *p;
X
X lprcat("\nThe cookie was delicious.");
X if (c[BLINDCOUNT])
X return;
X#ifdef MSDOS
X msdosfortune();
X#else
X if (p=fortune(fortfile))
X {
X lprcat(" Inside you find a scrap of paper that says:\n");
X lprcat(p);
X }
X#endif
X }
X
X# ifdef MSDOS
X# include <stdio.h>
X/* Rumors has been entirely rewritten to be disk based. This is marginally
X * slower, but requires no mallocked memory. Notice this in only valid for
X * files smaller than 32K.
X */
Xstatic int fortsize = 0;
X
Xstatic msdosfortune()
X{
X int fd, status, i;
X char buf[BUFSIZ], ch;
X
X if (fortsize < 0) /* We couldn't open fortunes */
X return;
X if ((fd = open(fortfile, O_RDONLY | O_BINARY)) >= 0) {
X if (fortsize == 0)
X fortsize = (int) lseek(fd, 0L, 2);
X if (lseek(fd, (long) rund(fortsize), 0) < 0)
X return;
X
X /* Skip to next newline or EOF
X */
X do {
X status = read(fd, &ch, 1);
X } while (status != EOF && ch != '\n');
X if (status == EOF)
X if (lseek(fd, 0L, 0) < 0) /* back to the beginning */
X return;
X
X /* Read in the line. Search for CR ('\r'), not NL
X */
X for (i = 0; i < BUFSIZ - 1; i++)
X if (read(fd, &buf[i], 1) == EOF || buf[i] == '\r')
X break;
X buf[i] = '\0';
X
X /* And spit it out
X */
X lprcat(" Inside you find a scrap of paper that says:\n");
X lprcat(buf);
X close(fd);
X } else
X fortsize = -1; /* Don't try opening it again */
X}
X
X# else
X
X/*
X * function to return a random fortune from the fortune file
X */
Xstatic char *base=0; /* pointer to the fortune text */
Xstatic char **flines=0; /* array of pointers to each fortune */
Xstatic int fd=0; /* true if we have load the fortune info */
Xstatic int nlines=0; /* # lines in fortune database */
X
Xstatic char *fortune(file)
Xchar *file;
X{
X register char *p;
X register int lines,tmp;
X struct stat stat;
X void *malloc();
X
X if (fd == 0) {
X if ((fd=open(file,O_RDONLY)) < 0) /* open the file */
X return(0); /* can't find file */
X
X /* find out how big fortune file is and get memory for it */
X stat.st_size = 16384;
X if ((fstat(fd,&stat) < 0)
X || ((base=(char *)malloc(1+stat.st_size)) == 0)) {
X close(fd);
X fd= -1;
X free((char*)base);
X return(0); /* can't stat file */
X }
X
X /* read in the entire fortune file */
X#ifdef VMS
X /*
X * fstat lies about the size (each record has up to
X * three bytes of fill reported as actual size).
X * vread returns correct size.
X */
X stat.st_size = vread(fd,base,stat.st_size);
X if (stat.st_size <= 0)
X#else
X if (vread(fd,base,stat.st_size) != stat.st_size)
X#endif
X {
X close(fd);
X fd= -1;
X free((char*)base);
X return(0); /* can't read file */
X }
X close(fd);
X base[stat.st_size]=0; /* final NULL termination */
X
X /* count up all the lines (and 0 terminate) to know memory
X * needs
X */
X for (p=base,lines=0; p<base+stat.st_size; p++) /* count lines */
X if (*p == '\n') *p=0,lines++;
X nlines = lines;
X
X /* get memory for array of pointers to each fortune */
X if ((flines=(char**)malloc(nlines*sizeof(char*))) == 0) {
X free((char*)base);
X fd= -1;
X return(0); /* malloc() failure */
X }
X
X /* now assign each pointer to a line */
X for (p=base,tmp=0; tmp<nlines; tmp++)
X {
X flines[tmp]=p; while (*p++); /* advance to next line */
X }
X }
X
X if (fd > 2) /* if we have a database to look at */
X return(flines[rund((nlines<=0)?1:nlines)]);
X else
X return(0);
X}
X# endif
END_OF_FILE
if test 4263 -ne `wc -c <'fortune.c'`; then
echo shar: \"'fortune.c'\" unpacked with wrong size!
fi
# end of 'fortune.c'
fi
if test -f 'iventory.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'iventory.c'\"
else
echo shar: Extracting \"'iventory.c'\" \(12705 characters\)
sed "s/^X//" >'iventory.c' <<'END_OF_FILE'
X#include "header.h"
X#include "larndefs.h"
X#include "objects.h"
X#include "player.h"
X
X#ifdef __STDC__
X show1( int, char*[] );
X show3( int );
Xstatic show2( int );
Xstatic void t_setup( int );
Xstatic void t_endup( int );
X
X#define SIGNED signed
X#else
X show1( );
X show3( );
Xstatic show2( );
Xstatic void t_setup( );
Xstatic void t_endup( );
X
X#define SIGNED
X#endif
X
Xstatic int qshowstr();
Xshowwear();
Xshowwield();
Xshowread();
Xshowquaff();
Xshoweat();
Xextern int dropflag;
X
X/* Allow only 26 items (a to z) in the player's inventory */
X#define MAXINVEN 26
X
X/* The starting limit to the number of items the player can carry.
X The limit should probably be based on player strength and the
X weight of the items.
X*/
X#define MIN_LIMIT 15
X
X/* define a sentinel to place at the end of the sorted inventory.
X (speeds up display reads )
X*/
X#define END_SENTINEL 255
X
X/* declare the player's inventory. These should only be referenced
X in this module.
X iven - objects in the player's inventory
X ivenarg - attribute of each item ( + values, etc )
X ivensort - sorted inventory (so we don't sort each time)
X*/
Xchar iven[MAXINVEN];
XSIGNED short ivenarg[MAXINVEN];
Xunsigned char ivensort[MAXINVEN+1]; /* extra is for sentinel */
X
Xstatic char srcount = 0 ; /* line counter for showstr() */
X
X/*
X Initialize the player's inventory
X*/
Xvoid init_inventory( )
X {
X int i;
X
X for ( i = 0; i < MAXINVEN ; i++ )
X {
X iven[i] = ivenarg[i] = 0;
X ivensort[i] = END_SENTINEL ;
X }
X ivensort[MAXINVEN] = END_SENTINEL;
X
X /* For zero difficulty games, start the player out with armor and weapon.
X We can sort the inventory right away because a dagger is 'later' than
X leather armor.
X */
X if (c[HARDGAME] <= 0)
X {
X iven[0] = OLEATHER;
X iven[1] = ODAGGER;
X ivenarg[0] = ivenarg[1] = c[WEAR] = ivensort[0] = 0;
X ivensort[1] = c[WIELD] = 1;
X }
X }
X
X/*
X show character's inventory
X*/
Xshowstr(select_allowed)
Xchar select_allowed;
X {
X register int i,number, item_select;
X
X for (number=3, i=0; i<MAXINVEN; i++)
X if (iven[i])
X number++; /* count items in inventory */
X t_setup(number);
X item_select = qshowstr(select_allowed);
X t_endup(number);
X return( item_select );
X }
X
Xstatic int qshowstr(select_allowed)
Xchar select_allowed;
X {
X register int i,j,k,sigsav,itemselect=0;
X
X srcount=0;
X sigsav=nosignal;
X nosignal=1; /* don't allow ^c etc */
X if (c[GOLD])
X {
X lprintf(".) %d gold pieces",(long)c[GOLD]);
X srcount++;
X }
X for (k=(MAXINVEN-1); k>=0; k--)
X if (iven[k])
X {
X for (i=22; i<84; i++)
X for (j=0; j<=k; j++)
X if (i==iven[j])
X {
X itemselect = show2(j);
X if (itemselect && select_allowed)
X goto quitit;
X }
X k=0;
X }
X
X lprintf("\nElapsed time is %d. You have %d mobuls left",(long)((gtime+99)/100+1),(long)((TIMELIMIT-gtime)/100));
X itemselect = more(select_allowed);
Xquitit:
X nosignal=sigsav;
X if (select_allowed)
X return( (itemselect > 0) ? itemselect : 0 );
X else
X return( 0 );
X }
X
X/*
X subroutine to clear screen depending on # lines to display
X
X*/
Xstatic void t_setup(count)
Xregister int count;
X {
X if (count<20) /* how do we clear the screen? */
X {
X cl_up(79,count);
X cursor(1,1);
X }
X else
X {
X resetscroll();
X clear();
X }
X }
X
X/*
X subroutine to restore normal display screen depending on t_setup()
X
X*/
Xstatic void t_endup(count)
Xregister int count;
X {
X if (count<18) /* how did we clear the screen? */
X draws(0,MAXX,0,(count>MAXY) ? MAXY : count);
X else
X {
X drawscreen();
X setscroll();
X }
X }
X
X/*
X function to show the things player is wearing only
X */
Xshowwear()
X {
X register int i,j,sigsav,count,itemselect=0;
X
X sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
X srcount=0;
X
X for (count=2,j=0; j< MAXINVEN; j++) /* count number of items we will display */
X if (i=iven[j])
X switch(i)
X {
X case OLEATHER: case OPLATE: case OCHAIN:
X case ORING: case OSTUDLEATHER: case OSPLINT:
X case OPLATEARMOR: case OSSPLATE: case OSHIELD:
X count++;
X };
X
X t_setup(count);
X
X for (i=22; i<84; i++)
X for (j=0; j< MAXINVEN; j++)
X if (i==iven[j])
X switch(i)
X {
X case OLEATHER: case OPLATE: case OCHAIN:
X case ORING: case OSTUDLEATHER: case OSPLINT:
X case OPLATEARMOR: case OSSPLATE: case OSHIELD:
X if (itemselect = show2(j))
X goto quitit;
X };
X itemselect = more(TRUE);
Xquitit:
X nosignal=sigsav;
X t_endup(count);
X return( (itemselect > 1) ? itemselect : 0 );
X }
X
X/*
X function to show the things player can wield only
X */
Xshowwield()
X {
X register int i,j,sigsav,count,itemselect=0;
X sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
X srcount=0;
X
X for (count=2,j=0; j< MAXINVEN; j++) /* count how many items */
X if (i=iven[j])
X switch(i)
X {
X case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE:
X case OBOOK: case OCHEST: case OLARNEYE: case ONOTHEFT:
X case OSPIRITSCARAB: case OCUBEofUNDEAD:
X case OPOTION: case OSCROLL: break;
X default: count++;
X };
X
X t_setup(count);
X
X for (i=22; i<84; i++)
X for (j=0; j< MAXINVEN; j++)
X if (i==iven[j])
X switch(i)
X {
X case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE:
X case OBOOK: case OCHEST: case OLARNEYE: case ONOTHEFT:
X case OSPIRITSCARAB: case OCUBEofUNDEAD:
X case OPOTION: case OSCROLL:
X break;
X default:
X if (itemselect = show2(j))
X goto quitit;
X };
X itemselect = more(TRUE);
Xquitit:
X nosignal=sigsav;
X t_endup(count);
X return( (itemselect > 1) ? itemselect : 0 );
X }
X
X/*
X * function to show the things player can read only
X */
Xshowread()
X {
X register int i,j,sigsav,count,itemselect = 0;
X sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
X srcount=0;
X
X for (count=2,j=0; j< MAXINVEN; j++)
X switch(iven[j])
X {
X case OBOOK: case OSCROLL: count++;
X };
X t_setup(count);
X
X for (i=22; i<84; i++)
X for (j=0; j< MAXINVEN; j++)
X if (i==iven[j])
X switch(i)
X {
X case OBOOK: case OSCROLL:
X if (itemselect = show2(j))
X goto quitit;
X };
X itemselect = more(TRUE);
Xquitit:
X nosignal=sigsav;
X t_endup(count);
X return((itemselect > 1) ? itemselect : 0 );
X }
X
X/*
X * function to show the things player can eat only
X */
Xshoweat()
X {
X register int i,j,sigsav,count,itemselect=0;
X sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
X srcount=0;
X
X for (count=2,j=0; j< MAXINVEN; j++)
X switch(iven[j])
X {
X case OCOOKIE: count++;
X };
X t_setup(count);
X
X for (i=22; i<84; i++)
X for (j=0; j< MAXINVEN; j++)
X if (i==iven[j])
X switch(i)
X {
X case OCOOKIE:
X if (itemselect=show2(j))
X goto quitit;
X };
X itemselect = more(TRUE);
Xquitit:
X nosignal=sigsav;
X t_endup(count);
X return( (itemselect > 1) ? itemselect : 0 );
X }
X
X/*
X function to show the things player can quaff only
X */
Xshowquaff()
X {
X register int i,j,sigsav,count,itemselect=0;
X sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
X srcount=0;
X
X for (count=2,j=0; j< MAXINVEN; j++)
X switch(iven[j])
X {
X case OPOTION: count++;
X };
X t_setup(count);
X
X for (i=22; i<84; i++)
X for (j=0; j< MAXINVEN; j++)
X if (i==iven[j])
X switch(i)
X {
X case OPOTION:
X if (itemselect=show2(j))
X goto quitit;
X };
X itemselect = more(TRUE);
Xquitit:
X nosignal=sigsav;
X t_endup(count);
X return( (itemselect > 1 ) ? itemselect : 0 );
X }
X
Xshow1(idx,str2)
X register int idx;
X register char *str2[];
X {
X lprc('\n');
X cltoeoln();
X if (str2==0)
X lprintf("%c) %s",idx+'a',objectname[iven[idx]]);
X else if (*str2[ivenarg[idx]]==0)
X lprintf("%c) %s",idx+'a',objectname[iven[idx]]);
X else
X lprintf("%c) %s of%s",idx+'a',objectname[iven[idx]],str2[ivenarg[idx]]);
X }
X
Xshow3(index)
Xregister int index ;
X {
X srcount=0;
X return( show2(index) );
X }
X
Xstatic int show2(index)
Xregister int index;
X {
X register int itemselect = 0;
X
X switch(iven[index])
X {
X case OPOTION: show1(index,potionname); break;
X case OSCROLL: show1(index,scrollname); break;
X
X case OLARNEYE: case OBOOK: case OSPIRITSCARAB:
X case ODIAMOND: case ORUBY: case OCUBEofUNDEAD:
X case OEMERALD: case OCHEST: case OCOOKIE:
X case OSAPPHIRE: case ONOTHEFT: show1(index,(char **)0); break;
X
X default:
X lprc('\n');
X cltoeoln();
X lprintf("%c) %s",index+'a',objectname[iven[index]]);
X if (ivenarg[index]>0)
X lprintf(" + %d",(long)ivenarg[index]);
X else if (ivenarg[index]<0)
X lprintf(" %d",(long)ivenarg[index]);
X break;
X }
X if (c[WIELD]==index) lprcat(" (weapon in hand)");
X if ((c[WEAR]==index) || (c[SHIELD]==index)) lprcat(" (being worn)");
X if (++srcount>=22)
X {
X srcount=0;
X itemselect = more(TRUE);
X clear();
X }
X return( itemselect );
X }
X
X/*
X function to put something in the players inventory
X returns 0 if success, 1 if a failure
X*/
Xtake(itm,arg)
X int itm,arg;
X {
X register int i,limit;
X/* cursors(); */
X if ((limit = 15+(c[LEVEL]>>1)) > MAXINVEN)
X limit=MAXINVEN;
X for (i=0; i<limit; i++)
X if (iven[i]==0)
X {
X iven[i] = itm; ivenarg[i] = arg; limit=0;
X switch(itm)
X {
X case OPROTRING: case ODAMRING: case OBELT: limit=1; break;
X case ODEXRING: c[DEXTERITY] += ivenarg[i]+1; limit=1; break;
X case OSTRRING: c[STREXTRA] += ivenarg[i]+1; limit=1; break;
X case OCLEVERRING: c[INTELLIGENCE] += ivenarg[i]+1; limit=1; break;
X case OHAMMER: c[DEXTERITY] += 10; c[STREXTRA]+=10;
X c[INTELLIGENCE]-=10; limit=1; break;
X
X case OORBOFDRAGON: c[SLAYING]++; break;
X case OSPIRITSCARAB: c[NEGATESPIRIT]++; break;
X case OCUBEofUNDEAD: c[CUBEofUNDEAD]++; break;
X case ONOTHEFT: c[NOTHEFT]++; break;
X case OSWORDofSLASHING: c[DEXTERITY] +=5; limit=1; break;
X };
X lprcat("\nYou pick up:"); show3(i);
X if (limit) bottomline(); return(0);
X }
X lprcat("\nYou can't carry anything else"); return(1);
X }
X
X/*
X subroutine to drop an object returns 1 if something there already else 0
X */
Xdrop_object(k)
X int k;
X {
X int itm;
X if ((k<0) || (k>=MAXINVEN))
X return(0);
X itm = iven[k]; cursors();
X if (itm==0) { lprintf("\nYou don't have item %c! ",k+'a'); return(1); }
X if (item[playerx][playery])
X { beep(); lprcat("\nThere's something here already"); return(1); }
X if (playery==MAXY-1 && playerx==33) return(1); /* not in entrance */
X item[playerx][playery] = itm;
X iarg[playerx][playery] = ivenarg[k];
X lprcat("\n You drop:"); show3(k); /* show what item you dropped*/
X know[playerx][playery] = 0; iven[k]=0;
X if (c[WIELD]==k) c[WIELD]= -1; if (c[WEAR]==k) c[WEAR] = -1;
X if (c[SHIELD]==k) c[SHIELD]= -1;
X adjustcvalues(itm,ivenarg[k]);
X dropflag=1; /* say dropped an item so wont ask to pick it up right away */
X return(0);
X }
X
X/*
X routine to tell if player can carry one more thing
X returns 1 if pockets are full, else 0
X*/
Xpocketfull()
X {
X register int i,limit;
X if ((limit = MIN_LIMIT + (c[LEVEL]>>1) ) > MAXINVEN )
X limit = MAXINVEN;
X for (i=0; i<limit; i++)
X if (iven[i]==0)
X return(0);
X return(1);
X }
END_OF_FILE
if test 12705 -ne `wc -c <'iventory.c'`; then
echo shar: \"'iventory.c'\" unpacked with wrong size!
fi
# end of 'iventory.c'
fi
if test -f 'larnhlp.uue' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'larnhlp.uue'\"
else
echo shar: Extracting \"'larnhlp.uue'\" \(11735 characters\)
sed "s/^X//" >'larnhlp.uue' <<'END_OF_FILE'
Xbegin 644 larn.hlp
XM-R`@("!796QC;VUE('1O('1H92!G86UE(&]F($QA<FXN("!!="!T:&ES(&UO
XM;65N="P@>6]U(&9A8V4@82!G<F5A="!P<F]B;&5M+@I9;W5R(&1A=6=H=&5R
XM(&AA<R!C;VYT<F%C=&5D(&$@<W1R86YG92!D:7-E87-E+"!A;F0@;F]N92!O
XM9B!Y;W5R(&AO;64@<F5M961I97,*<V5E;2!T;R!H879E(&%N>2!E9F9E8W0N
XM("!9;W4@<V5N<V4@=&AA="!S:&4@:7,@:6X@;6]R=&%L(&1A;F=E<BP@86YD
XM('EO=2!M=7-T"G1R>2!T;R!S879E(&AE<BX@(%1I;64@86=O('EO=2!H96%R
XM9"!O9B!A(&QA;F0@;V8@9W)E870@9&%N9V5R(&%N9"!O<'!O<G1U;FET>2X*
XM4&5R:&%P<R!H97)E(&ES('1H92!S;VQU=&EO;B!Y;W4@;F5E9"X*"B`@("!)
XM="!H87,@8F5E;B!S86ED('1H870@=&AE<F4@;VYC92!W87,@82!G<F5A="!M
XM86=I8VEA;B!W:&\@8V%L;&5D(&AI;7-E;&8*4&]L:6YN96%U<RX@($UA;GD@
XM>65A<G,@86=O+"!A9G1E<B!H879I;F<@;6%N>2!M:7)A8W5L;W5S('-U8V-E
XM<W-E<RP@4&]L:6YN96%U<PIR971I<F5D('1O('1H92!C879E<FYS(&]F($QA
XM<FXL('=H97)E(&AE(&1E=F]T960@;6]S="!O9B!H:7,@=&EM92!T;R!T:&4*
XM8W)E871I;VX@;V8@;6%G:6,N("`@4G5M;W)S(&AA=F4@:70@=&AA="!O;F4@
XM9&%Y(%!O;&EN;F5A=7,@<V5T(&]U="!T;R!D:7-P96P*86X@871T86-K:6YG
XM(&%R;7D@:6X@82!F;W)E<W0@<V]M92!D:7-T86YC92!T;R!T:&4@;F]R=&@N
XM("!)="!I<R!B96QI979E9"!T:&%T"FAE<F4@:&4@;65T(&AI<R!D96UI<V4N
XM"@H@("`@5&AE(&-A=F5R;G,@;V8@3&%R;BP@:70@:7,@=&AO=6=H="P@;75S
XM="!B92!M86=N:69I8V5N="!I;B!D97-I9VXL"F%N9"!C;VYT86EN(&UU8V@@
XM;6%G:6,@86YD('1R96%S=7)E+B`@3VYE(&]P=&EO;B!Y;W4@:&%V92!I<R!T
XM;R!U;F1E<G1A:V4@80IJ;W5R;F5Y(&EN=&\@=&AE<V4@8V%V97)N<RX*"@H@
XM("`@1V]O9"!,=6-K(2`@66]U)W)E(&=O:6YG('1O(&YE960@:70A"@H*"@H@
XM("`@("`@("`@("`@("`@&ULW;4AE;'`@1FEL92!F;W(@5&AE($-A=F5R;G,@
XM;V8@3&%R;BP@4')O;7!T($UO9&4;6VT*"F(@(&UO=F4@<V]U=&AW97-T("`@
XM("`@("`@($(@(')U;B!S;W5T:'=E<W0@("`@("`@("`@("!3("!S879E('1H
XM92!G86UE"F@@(&UO=F4@;&5F="`@("`@("`@("`@("`@($@@(')U;B!L969T
XM("`@("`@("`@("`@("`@("`N("!S=&%Y(&AE<F4*:B`@;6]V92!D;W=N("`@
XM("`@("`@("`@("`@2B`@<G5N(&1O=VX@("`@("`@("`@("`@("`@(%X@(&ED
XM96YT:69Y(&$@=')A<`IK("!M;W9E('5P("`@("`@("`@("`@("`@("!+("!R
XM=6X@=7`@("`@("`@("`@("`@("`@("`@5"`@=&%K92!O9F8@87)M;W(*;"`@
XM;6]V92!R:6=H="`@("`@("`@("`@("`@3"`@<G5N(')I9VAT"FX@(&UO=F4@
XM<V]U=&AE87-T("`@("`@("`@($X@(')U;B!S;W5T:&5A<W0*=2`@;6]V92!N
XM;W)T:&5A<W0@("`@("`@("`@52`@<G5N(&YO<G1H96%S=`IY("!M;W9E(&YO
XM<G1H=V5S="`@("`@("`@("!9("!R=6X@;F]R=&AW97-T("`@("`@("`@("`@
XM7DP@<F5D<F%W('1H92!S8W)E96X*8R`@8V%S="!A('-P96QL("`@("`@("`@
XM("`@6B`@=&5L97!O<G0@>6]U<G-E;&8*9"`@9')O<"!A;B!I=&5M("`@("`@
XM("`@("`@92`@96%T('-O;65T:&EN9PIG("!G970@<')E<V5N="!P86-K('=E
XM:6=H="!0("!G:79E('1A>"!S=&%T=7,*:2`@:6YV96YT;W)Y('EO=7(@<&]C
XM:V5T<R`@22`@;&ES="!A;&P@:71E;7,@9F]U;F0@("`@(#\@('1H:7,@:&5L
XM<"!S8W)E96X*<2`@<75A9F8@82!P;W1I;VX@("`@("`@("`@42`@<75I="!T
XM:&4@9V%M90IR("!R96%D(&$@<V-R;VQL("`@("`@("`@("!V("!P<FEN="!P
XM<F]G<F%M('9E<G-I;VX*=R`@=VEE;&0@82!W96%P;VX@("`@("`@("`@5R`@
XM=V5A<B!A<FUO<B`@("`@("`@("`@("`@(%Y,(')E9')A=R!T:&4@<V-R965N
XM"@H*"@H*"B`@("`@("`@("`@("`@("`;6S=M2&5L<"!&:6QE(&9O<B!4:&4@
XM0V%V97)N<R!O9B!,87)N+"!#;VUM86YD($UO9&4;6VT*"F(@(&UO=F4@<V]U
XM=&AW97-T("`@("`@("`@($(@(')U;B!S;W5T:'=E<W0@("`@("`@("`@("!!
XM("!D97-E8W)A=&4@86X@86QT87(*8R`@8V%S="!A('-P96QL("`@("`@("`@
XM("`@0R`@8VQO<V4@82!D;V]R("`@("`@("`@("`@(%H@('1E;&5P;W)T('EO
XM=7)S96QF"F0@(&1R;W`@86X@:71E;2`@("`@("`@("`@($0@(&1R:6YK(&%T
XM(&$@9F]U;G1A:6X@("`@("`\("!G;R!U<"!S=&%I<G,@;W(*92`@96%T('-O
XM;65T:&EN9R`@("`@("`@("`@12`@96YT97(@82!S=&]R92P@9'5N9V5O;B`@
XM("`@('9O;&-A;FEC('-H869T"F<@(&=E="!P<F5S96YT('!A8VL@=V5I9VAT
XM("`@("`@("`@("`@("`@("`@("`@("`@("`@("`^("!G;R!D;W=N('-T86ER
XM<R!O<@IH("!M;W9E(&QE9G0@("`@("`@("`@("`@("!(("!R=6X@;&5F="`@
XM("`@("`@("`@("`@("`@("`@=F]L8V%N:6,@<VAA9G0*:2`@:6YV96YT;W)Y
XM('EO=7(@<&]C:V5T<R`@22`@;&ES="!A;&P@:71E;7,@9F]U;F0@("`@(#\@
XM('1H:7,@:&5L<"!S8W)E96X*:B`@;6]V92!D;W=N("`@("`@("`@("`@("`@
XM2B`@<G5N(&1O=VX@("`@("`@("`@("`@("`@(%X@(&ED96YT:69Y(&$@=')A
XM<`IK("!M;W9E('5P("`@("`@("`@("`@("`@("!+("!R=6X@=7`@("`@("`@
XM("`@("`@("`@("`@+"`@<&EC:R!U<"!I=&5M"FP@(&UO=F4@<FEG:'0@("`@
XM("`@("`@("`@($P@(')U;B!R:6=H="`@("`@("`@("`@("`@("`Z("!L;V]K
XM(&%T(&]B:F5C="!Y;W4*;B`@;6]V92!S;W5T:&5A<W0@("`@("`@("`@3B`@
XM<G5N('-O=71H96%S="`@("`@("`@("`@("`@(&%R92!S=&%N9&EN9R!O;@H@
XM("`@("`@("`@("`@("`@("`@("`@("`@("!/("!O<&5N(&$@9&]O<B!O<B!C
XM:&5S="`@("`@+B`@<W1A>2!H97)E"G`@('!R87D@870@86X@86QT87(@("`@
XM("`@(%`@(&=I=F4@=&%X('-T871U<R`@("`@("`@("!M("!M;W9E('=I=&AO
XM=70@<&EC:VEN9PIQ("!Q=6%F9B!A('!O=&EO;B`@("`@("`@("!1("!Q=6ET
XM('1H92!G86UE("`@("`@("`@("`@("`@=7`@86X@;V)J96-T"G(@(')E860@
XM82!S8W)O;&P@("`@("`@("`@(%(@(')E;6]V92!G96US(&9R;VT@=&AR;VYE
XM("!`("!T;V=G;&4@875T;RUP:6-K=7`*<R`@<VET(&]N(&$@=&AR;VYE("`@
XM("`@("`@4R`@<V%V92!T:&4@9V%M92`@("`@("`@("`@("\@(&ED96YT:69Y
XM(&]B:F5C=',@:6X*="`@=&ED>2!U<"!A="!A(&9O=6YT86EN("`@5"`@=&%K
XM92!O9F8@87)M;W(@("`@("`@("`@("`@('1H92!G86UE"G4@(&UO=F4@;F]R
XM=&AE87-T("`@("`@("`@(%4@(')U;B!N;W)T:&5A<W0*=B`@<')I;G0@<')O
XM9W)A;2!V97)S:6]N"G<@('=I96QD(&$@=V5A<&]N("`@("`@("`@(%<@('=E
XM87(@87)M;W(*>2`@;6]V92!N;W)T:'=E<W0@("`@("`@("`@62`@<G5N(&YO
XM<G1H=V5S="`@("`@("`@("`@(%Y,(')E9')A=R!T:&4@<V-R965N"B`@("`@
XM("`@("`@("`@("`;6S=M4W!E8VEA;"!.;W1E<QM;;0H*5VAE;B`;6S=M9')O
XM<'!I;F<@9V]L9!M;;2P@:68@>6]U('1Y<&4@)RHG(&%S('EO=7(@86UO=6YT
XM+"!A;&P@>6]U<B!G;VQD(&=E=',@9')O<'!E9"X*26X@9V5N97)A;"P@='EP
XM:6YG(&EN("<J)R!M96%N<R!A;&P@;V8@=VAA="!Y;W5R(&EN=&5R97-T960@
XM:6XN("!4:&ES(&ES('1R=64*=VAE;B!V:7-I=&EN9R!T:&4@8F%N:RP@;W(@
XM=VAE;B!C;VYT<FEB=71I;F<@870@86QT87)S+@H*3&%R;B!N965D<R!T:&4@
XM04Y322Y365,@*&]R('!R969E<F%B;'DL('1H92!.04Y322Y365,I(&1E=FEC
XM92!D<FEV97(@:6YS=&%L;&5D"FEN('EO=7(@0T].1DE'+E-94R!F:6QE+B`@
XM5&AE('-U<'!L:65D(")T97)M8V%P(B!F:6QE(&1E<V-R:6)E<R!T:&4@97-C
XM87!E"G-E<75E;F-E<R!T;R!C:&%N9V4@=FED96\@;6]D97,@*'-E92!C:"`Q
XM,R!O9B!T:&4@1$]3(#(N,"!M86YU86PI+B`@4V5E('1H90HB5$5234-!4"(@
XM<V5C=&EO;B!I;B!,05).+D1/0R!F;W(@9G5R=&AE<B!D971A:6QS+@H*5VAE
XM;B!I;B!T:&4@<W1O<F4L('1R861I;F<@<&]S="P@<V-H;V]L+"!O<B!H;VUE
XM+"!A;B`;6S=M/&5S8V%P93X;6VT@=VEL;"!G970@>6]U(&]U="X*"E=H96X@
XM8V%S=&EN9R!A('-P96QL+"!I9B!Y;W4@;F5E9"!A(&QI<W0@;V8@<W!E;&QS
XM('EO=2!C86X@8V%S="P@='EP92`G&ULW;4D;6VTG(&%S"G1H92!F:7)S="!L
XM971T97(@;V8@>6]U<B!S<&5L;"X@(%1H92!A=F%I;&%B;&4@;&ES="!O9B!S
XM<&5L;',@=VEL;"!B92!S:&]W;BP*869T97(@=VAI8V@@>6]U(&UA>2!E;G1E
XM<B!T:&4@<W!E;&P@8V]D92X@(%1H:7,@;VYL>2!W;W)K<R!O;B!T:&4@,7-T
XM(&QE='1E<@IO9B!T:&4@<W!E;&P@>6]U(&%R92!C87-T:6YG+@H*5VAE;B!A
XM;B!I;G9E;G1O<GD@;&ES="!I<R!O;B!T:&4@<V-R965N(&9R;VT@82!D<F]P
XM+"!Q=6%F9BP@<F5A9"P@;W(@<VEM:6QA<@IC;VUM86YD+"!Y;W4@8V%N('1Y
XM<&4@=&AE(&QE='1E<B!O9B!T:&4@;V)J96-T('1H870@>6]U('=I<V@@=&\@
XM86-T(&%P;VXL"G=I=&AO=70@:&%V:6YG('1O('1Y<&4@82!S<&%C92!T;R!G
XM970@8F%C:R!T;R!T:&4@<')O;7!T+@H*5&AI<R!V97)S:6]N(&]F($QA<FX@
XM:7,@8GD@2V5V:6X@4F]U=&QE>2X*("`@("`@("`@("`@("`@("`@("`@("`@
XM&ULW;4QA<FX@0V]M;6%N9"!,:6YE($]P=&EO;G,;6VT*"FQA<FX@*RL@("`@
XM("`@("`@("`@("`@(')E<W1O<F4@8VAE8VMP;VEN=&5D(&=A;64*;&%R;B`M
XM<R`@("`@("`@("`@("`@("`@;&ES="!T:&4@<V-O<F5B;V%R9`IL87)N("UI
XM("`@("`@("`@("`@("`@("!L:7-T('-C;W)E<R!W:71H(&EN=F5N=&]R:65S
XM"FQA<FX@+6X@("`@("`@("`@("`@("`@('-U<'!R97-S('=E;&-O;64@;65S
XM<V%G92!W:&5N(&)E9VEN;FEN9R!A(&=A;64*;&%R;B`M:"`@("`@("`@("`@
XM("`@("`@<')I;G0@;W5T(&%L;"!T:&4@8V]M;6%N9"!L:6YE(&]P=&EO;G,*
XM;&%R;B`M/R`@("`@("`@("`@("`@("`@<')I;G0@;W5T(&%L;"!T:&4@8V]M
XM;6%N9"!L:6YE(&]P=&EO;G,*;&%R;B`M/&YU;6)E<CX@("`@("`@("`@<W!E
XM8VEF>2!D:69F:6-U;'1Y(&]F('1H92!G86UE"FQA<FX@+6\\;W!T<V9I;&4^
XM("`@("`@('-P96-I9GD@=&AE(&]P=&EO;B!F:6QE('1O(&)E('5S960*;&%R
XM;B`M8R`@("`@("`@("`@("`@("`@8W)E871E(&YE=R!S8V]R96)O87)D<R`M
XM+2!P<F]M<'1S(&9O<B!A('!A<W-W;W)D"FQA<FX@+6P@("`@("`@("`@("`@
XM("`@('!R:6YT(&]U="!T:&4@;&%R;B!L;V<@9FEL90IL87)N("UP("`@("`@
XM("`@("`@("`@("!P;&%Y(&EN('!R;VUP="!M;V1E"@H*"@H*"@H*"@H@("`@
XM("`@("`@("`;6S=M0F%C:V=R;W5N9"!);F9O<FUA=&EO;B!F;W(@3&%R;AM;
XM;0H*("`@(%=E;&-O;64@=&\@=&AE(&=A;64@;V8@3&%R;BX@($%T('1H:7,@
XM;6]M96YT+"!Y;W4@9F%C92!A(&=R96%T('!R;V)L96TN"EEO=7(@9&%U9VAT
XM97(@:&%S(&-O;G1R86-T960@82!S=')A;F=E(&1I<V5A<V4L(&%N9"!N;VYE
XM(&]F('EO=7(@:&]M92!R96UE9&EE<PIS965M('1O(&AA=F4@86YY(&5F9F5C
XM="X@(%EO=2!S96YS92!T:&%T('-H92!I<R!I;B!M;W)T86P@9&%N9V5R+"!A
XM;F0@>6]U(&UU<W0*=')Y('1O('-A=F4@:&5R+B`@5&EM92!A9V\@>6]U(&AE
XM87)D(&]F(&$@;&%N9"!O9B!G<F5A="!D86YG97(@86YD(&]P<&]R='5N:71Y
XM+@I097)H87!S(&AE<F4@:7,@=&AE('-O;'5T:6]N('EO=2!N965D+@H*("`@
XM($ET(&AA<R!B965N('-A:60@=&AA="!T:&5R92!O;F-E('=A<R!A(&=R96%T
XM(&UA9VEC:6%N('=H;R!C86QL960@:&EM<V5L9@I0;VQI;FYE875S+B`@36%N
XM>2!Y96%R<R!A9V\L(&%F=&5R(&AA=FEN9R!M86YY(&UI<F%C=6QO=7,@<W5C
XM8V5S<V5S+"!0;VQI;FYE875S"G)E=&ER960@=&\@=&AE(&-A=F5R;G,@;V8@
XM3&%R;BP@=VAE<F4@:&4@9&5V;W1E9"!M;W-T(&]F(&AI<R!T:6UE('1O('1H
XM90IC<F5A=&EO;B!O9B!M86=I8RX@("!2=6UO<G,@:&%V92!I="!T:&%T(&]N
XM92!D87D@4&]L:6YN96%U<R!S970@;W5T('1O(&1I<W!E;`IA;B!A='1A8VMI
XM;F<@87)M>2!I;B!A(&9O<F5S="!S;VUE(&1I<W1A;F-E('1O('1H92!N;W)T
XM:"X@($ET(&ES(&)E;&EE=F5D('1H870*:&5R92!H92!M970@:&ES(&1E;6ES
XM92X*"B`@("!4:&4@8V%V97)N<R!O9B!,87)N+"!I="!I<R!T:&]U9VAT+"!M
XM=7-T(&)E(&UA9VYI9FEC96YT(&EN(&1E<VEG;BP*86YD(&-O;G1A:6X@;75C
XM:"!M86=I8R!A;F0@=')E87-U<F4N("!/;F4@;W!T:6]N('EO=2!H879E(&ES
XM('1O('5N9&5R=&%K92!A"FIO=7)N97D@:6YT;R!T:&5S92!C879E<FYS+@H*
XM("`@($=O;V0@3'5C:R$@(%EO=2=R92!G;VEN9R!T;R!N965D(&ET(0H*"@H@
XM("`@("`@("`@("`;6S=M2&]W('1O('5S92!T:&4@;&%R;BYO<'0@;W!T:6]N
XM(&9I;&4;6VT*"E1H92!F:6QE(")L87)N+F]P="(L(&EF('5S960L('-H;W5L
XM9"!B92!I;B!A(&1I<F5C=&]R>2!A;&]N9R!Y;W5R(%!!5$@N"D$@<V5Q=65N
XM8V4@;V8@=V]R9',@=&5R;6EN871E9"!B>2!W:&ET97-P86-E(&ES('5S960@
XM=&\@<W!E8VEF>2!O<'1I;VYS+@H*("`@(%=O<F0@("`@("`@("`@("`@("`@
XM("`@("`@365A;FEN9PH@("`@8W5R<V]R.B!L;W=S8V%N(&AI9VAS8V%N("!C
XM:&%N9V4@=&AE('-H87!E(&]F('1H92!C=7)S;W(*("`@($1%0U)A:6YB;W<@
XM("`@("`@("`@("`@("`@=&5L;"!,05).('EO=2!H879E('1H870@8V]M<'5T
XM97(*("`@(&5N86)L92UC:&5C:W!O:6YT:6YG("`@("`@='5R;B!O;B!P97)I
XM;V1I8R!C:&5C:W!O:6YT:6YG"B`@("!G<F%P:&EC<SH@=V%L;&,@9FQO;W)C
XM("`@('-E;&5C="!G<F%P:&EC<R!M87IE(&-H87)A8W1E<G,*("`@(&ME>7!A
XM9"`@("`@("`@("`@("`@("`@("`@96YA8FQE('1H92!N=6UE<FEC(&ME>7!A
XM9"!F;W(@;6]V:6YG"B`@("!L87)N9&ER.B`@9&ER96-T;W)Y("`@("`@('1H
XM92!D:7)E8W1O<GD@=&\@=7-E(&9O<B!L87)N(&9I;&5S"B`@("!M;VYS=&5R
XM.B`@(FUO;G-T(&YA;64B("`@(&-H;V]S92!A(&YA;64@9F]R(&$@;6]N<W1E
XM<@H@("`@;F%M93H@("`@(")Y;W5R(&YA;64B("`@("!C:&]O<V4@>6]U<B!P
XM;&%Y:6YG(&YA;64*("`@(&YO+6)E97`@("`@("`@("`@("`@("`@("`@9&ES
XM86)L92!B965P:6YG(&]F('1H92!T97)M:6YA;`H@("`@;F\M:6YT<F]D=6-T
XM:6]N("`@("`@("`@("!D;R!N;W0@9&ES<&QA>2!I;G1R;R!M97-S86=E"B`@
XM("!S879E9FEL93H@<V%V92UF:6QE+6YA;64@(&1E9FEN92!W:&%T('1H92!S
XM879E9V%M92!F:6QE;F%M92!W:6QL(&)E"B`@("!S=V%P9FEL93H@<W=A<"UF
XM:6QE+6YA;64@(&1E9FEN92!T:&4@;F%M92!O9B!T:&4@<W=A<&9I;&4*"EEO
XM=7(@;F%M92!A;F0@;6]N<W1E<B!N86UE<R!M=7-T(&)E(&5N8VQO<V5D(&EN
XM(&1O=6)L92!Q=6]T871I;VX@;6%R:W,@86YD(&UA>0IB92!U<"!T;R`S-"!C
XM:&%R86-T97)S(&QO;F<N("!,;VYG97(@;F%M97,@87)E('1R=6YC871E9"X@
XM($%N>71H:6YG(&5N8VQO<V5D(&EN"G%U;W1A=&EO;B!M87)K<R!I<R!C;VYS
XM:61E<F5D(&]N92!W;W)D+"!A;F0@;75S="!B92!S97!A<F%T960@9G)O;2!O
XM=&AE<B!W;W)D<PIB>2!W:&ET97-P86-E+@H@("`@("`@("`@(!M;-VU%>'!L
XM86YA=&EO;B!O9B!T:&4@3&%R;B!S8V]R96)O87)D(&9A8VEL:71Y&UMM"@H@
XM("`@3&%R;B!S=7!P;W)T<R!45T\@<V-O<F5B;V%R9',L(&]N92!F;W(@=VEN
XM;F5R<RP@86YD(&]N92!F;W(@9&5C96%S960*8VAA<F%C=&5R<RX@($5A8V@@
XM<&QA>65R("AB>2!U<V5R:60@;W(@<&QA>65R:60L('-E92!524130T]212!I
XM;B!-86ME9FEL92D*:7,@86QL;W=E9"!O;F4@<VQO="!O;B!E86-H('-C;W)E
XM8F]A<F0L(&EF('1H92!S8V]R92!I<R!I;B!T:&4@=&]P('1E;B!F;W(*=&AA
XM="!S8V]R96)O87)D+B`@5&AI<R!D97-I9VX@:&5L<',@:6YS=7)E('1H870@
XM9G)E<75E;G0@<&QA>65R<R!O9B!,87)N"F1O(&YO="!H;V<@=&AE('-C;W)E
XM8F]A<F0L(&%N9"!G:79E<R!M;W)E('!L87EE<G,@82!C:&%N8V4@9F]R(&=L
XM;W)Y+B`@3&5V96P*;V8@9&EF9FEC=6QT>2!I<R!A;'-O(&YO=&5D(&]N('1H
XM92!S8V]R96)O87)D<RP@86YD('1H:7,@=&%K97,@<')E8V5D96YC90IO=F5R
XM('-C;W)E(&9O<B!D971E<FUI;FEN9R!W:&%T(&5N=')Y(&ES(&]N('1H92!S
XM8V]R96)O87)D+B`@1F]R(&5X86UP;&4Z"FEF(")987(L('1H92!"=6<@4VQA
XM>65R(B!H87,@82!S8V]R92!O9B`Q,C@P,#,@;VX@=&AE('-C;W)E8F]A<F0@
XM870@9&EF9B`P+`IT:&5N(&$@9V%M92!A="!D:69F(#$@86YD(&$@<V-O<F4@
XM;V8@-#$Q,B!W;W5L9"!R97!L86-E('1H92!P<F5V:6]U<PIE;G1R>2!O;B!T
XM:&4@<V-O<F5B;V%R9"X@($YO=&4@=&AA="!W:&5N(&$@<&QA>65R(&1I97,L
XM('1H92!I;G9E;G1O<GD@:7,*<W1O<F5D(&EN('1H92!S8V]R96)O87)D('-O
XM('1H870@979E<GEO;F4@8V%N('-E92!W:&%T(&ET96US('1H92!P;&%Y97(@
XE:&%D"F%T('1H92!T:6UE(&]F(&1E871H+@H*"@H*"@H*"@HN"B!P
X`
Xend
END_OF_FILE
if test 11735 -ne `wc -c <'larnhlp.uue'`; then
echo shar: \"'larnhlp.uue'\" unpacked with wrong size!
fi
# end of 'larnhlp.uue'
fi
if test -f 'msdos.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'msdos.c'\"
else
echo shar: Extracting \"'msdos.c'\" \(11570 characters\)
sed "s/^X//" >'msdos.c' <<'END_OF_FILE'
X#ifdef MSDOS
X# include <stdio.h>
X# include <process.h>
X# include <dos.h>
X# include <fcntl.h>
X# include <sys/types.h>
X# include <sys/stat.h>
X# include "header.h"
X# include "larndefs.h"
X
X# define DEVICE 0x80
X# define RAW 0x20
X# define IOCTL 0x44
X# define STDIN 0
X# define STDOUT 1
X# define GETBITS 0
X# define SETBITS 1
X# define PATHSEP ';'
X
X/* Normal characters are output when the shift key is not pushed.
X * Shift characters are output when either shift key is pushed.
X */
X# define KEYPADHI 83
X# define KEYPADLOW 71
X# define iskeypad(x) (KEYPADLOW <= (x) && (x) <= KEYPADHI)
Xstatic struct {
X char normal, shift;
X } pad[KEYPADHI - KEYPADLOW + 1] = {
X {'y', 'Y'}, /* 7 */
X {'k', 'K'}, /* 8 */
X {'u', 'U'}, /* 9 */
X {' ', ' '}, /* - */
X {'h', 'H'}, /* 4 */
X {' ', ' '}, /* 5 */
X {'l', 'L'}, /* 6 */
X {' ', ' '}, /* + */
X {'b', 'B'}, /* 1 */
X {'j', 'J'}, /* 2 */
X {'n', 'N'}, /* 3 */
X {'i', 'i'}, /* Ins */
X {'.', '.'} /* Del */
X};
X
X/* BIOSgetch gets keys directly with a BIOS call.
X */
X#ifdef OS2LARN
X# define SHIFT (RIGHTSHIFT | LEFTSHIFT)
X#else
X# define SHIFT (0x1 | 0x2)
X#endif
X# define KEYBRD_BIOS 0x16
X
Xstatic char
XBIOSgetch() {
X unsigned char scan, shift, ch;
X union REGS regs;
X
X#ifdef OS2LARN
X KBDKEYINFO kbd;
X
X KbdCharIn(&kbd,IO_WAIT,(HKBD) 0);
X ch = kbd.chChar;
X scan = kbd.chScan;
X shift = kbd.fsState;
X#else
X /* Get scan code.
X */
X regs.h.ah = 0;
X int86(KEYBRD_BIOS, ®s, ®s);
X ch = regs.h.al;
X scan = regs.h.ah;
X
X /* Get shift status.
X */
X regs.h.ah = 2;
X int86(KEYBRD_BIOS, ®s, ®s);
X shift = regs.h.al;
X#endif
X
X /* If scan code is for the keypad, translate it.
X */
X if (iskeypad(scan)) {
X if (shift & SHIFT)
X ch = pad[scan - KEYPADLOW].shift;
X else
X ch = pad[scan - KEYPADLOW].normal;
X }
X return ch;
X}
X
Xkgetch()
X{
X /* BIOSgetch can use the numeric key pad on IBM compatibles. */
X if (keypad)
X return BIOSgetch();
X else
X return getch();
X}
X
Xdoshell()
X{
X char *comspec = getenv("COMSPEC");
X
X clear();
X lflush();
X if (comspec == NULL
X || (spawnl(P_WAIT, comspec, comspec, NULL) < 0)) {
X write(2, "A> ", 3);
X while (getche() != '\r')
X ;
X }
X}
X
Xstatic unsigned old_stdin, old_stdout, ioctl();
X
Xstatic unsigned
Xioctl(handle, mode, setvalue)
Xunsigned setvalue;
X{
X#ifndef OS2LARN
X union REGS regs;
X
X regs.h.ah = IOCTL;
X regs.h.al = mode;
X regs.x.bx = handle;
X regs.h.dl = setvalue;
X regs.h.dh = 0; /* Zero out dh */
X intdos(®s, ®s);
X return (regs.x.dx);
X#endif
X}
X
Xint rawio;
Xvoid
Xsetraw()
X{
X if (!rawio)
X return;
X old_stdin = ioctl(STDIN, GETBITS, 0);
X old_stdout = ioctl(STDOUT, GETBITS, 0);
X if (old_stdin & DEVICE)
X (void) ioctl(STDIN, SETBITS, old_stdin | RAW);
X if (old_stdout & DEVICE)
X (void) ioctl(STDOUT, SETBITS, old_stdout | RAW);
X}
X
Xvoid
Xunsetraw()
X{
X if (!rawio)
X return;
X if (old_stdin)
X (void) ioctl(STDIN, SETBITS, old_stdin);
X if (old_stdout)
X (void) ioctl(STDOUT, SETBITS, old_stdout);
X}
X
X
X/* Add a backslash to any name not ending in /, \ or : There must
X * be room for the \
X */
Xvoid
Xappend_slash(name)
Xchar *name;
X{
X char *ptr;
X
X if (!*name)
X return;
X ptr = name + (strlen(name) - 1);
X if (*ptr != '\\' && *ptr != '/' && *ptr != ':') {
X *++ptr = '\\';
X *++ptr = '\0';
X }
X}
X
X/* Lopen a file somewhere along the PATH
X */
Xplopen(name)
Xchar *name;
X{
X char buf[PATHLEN], *bp, *pp, lastch, *strchr();
X int fd;
X
X /* Try the default directory first. Then look along PATH unless
X * the name has path components.
X */
X if ((fd = lopen(name)) >= 0)
X return fd;
X else if (strpbrk(name, "\\/:") == NULL) {
X pp = getenv("PATH");
X while (pp && *pp) {
X bp = buf;
X while (*pp && *pp != PATHSEP)
X lastch = *bp++ = *pp++;
X if (strchr("\\/:", lastch) == NULL)
X *bp++ = '\\';
X strcpy(bp, name);
X if ((fd = lopen(buf)) >= 0)
X return fd;
X if (*pp)
X pp++;
X }
X }
X return -1;
X}
X
X
X/* Follow the PATH, trying to fopen the file. Takes one additional
X * argument which can be NULL. Otherwise this argument gets filled
X * in the full path to the file. Returns as does fopen().
X */
XFILE *
Xfopenp(name, mode, pathname)
Xchar *name, *mode, *pathname;
X{
X char buffer[BUFSIZ], *buf, *bufp, *pathp, *getenv(), lastch;
X FILE *fp;
X
X /* If pathname is given, use it instead of buf so the calling
X * process knows the path we found name under
X */
X if (pathname)
X buf = pathname;
X else
X buf = buffer;
X
X /* Try the default directory first. If the file can't be opened,
X * start looking along the path.
X */
X strcpy(buf, name);
X if (fp = fopen(buf, mode))
X return fp;
X else if (strpbrk(name, "\\/:") == NULL) {
X pathp = getenv("PATH");
X while (pathp && *pathp) {
X bufp = buf;
X while (*pathp && *pathp != PATHSEP)
X lastch = *bufp++ = *pathp++;
X if (lastch != '\\' && lastch != '/')
X *bufp++ = '\\';
X strcpy(bufp, name);
X if (fp = fopen(buf, mode))
X return fp;
X if (*pathp)
X pathp++;
X }
X }
X return NULL;
X}
X
X/* Diagnositic information about the disposition of levels between ram
X * and disk.
X */
Xlevelinfo()
X{
X DISKBLOCK *dp;
X RAMBLOCK *rp;
X
X cursors();
X lflush();
X fprintf(stderr, "\nRAM:\n");
X for (rp = ramblks; rp; rp = rp->next)
X fprintf(stderr, "%4d gt:%6ld\n", rp->level, rp->gtime);
X fprintf(stderr, "\nDISK:\n");
X for (dp = diskblks; dp; dp = dp->next)
X fprintf(stderr, "%4d gt:%6ld fpos:%ld\n",
X dp->level, dp->gtime, dp->fpos);
X nomove=1;
X return (yrepcount = 0);
X}
X
Xint swapfd = 0; /* file descriptor for the swap file */
Xint ramlevels = MAXLEVEL + MAXVLEVEL; /* the maximum */
X
X
X/* Allocate as many levels as possible, then check that the swap file
X * will have enough storage for the overflow. You must be able to allocate
X * at least one level or there will be nowhere to swap to/from. If a swap
X * file is opened it remains open for the whole game.
X */
Xallocate_memory()
X{
X register int i;
X DISKBLOCK *dp, *dp2;
X RAMBLOCK *rp;
X
X /* First allocate the maximum number of disk blocks, some of which
X * may not be used, but must do the allocation now since we don't
X * yet know how many levels will be allocatable.
X */
X for (i = 0; i < MAXLEVEL + MAXVLEVEL; i++) {
X if ((dp = (DISKBLOCK *) malloc(sizeof(DISKBLOCK))) == NULL)
X died(-285);
X dp->next = diskblks;
X diskblks = dp;
X }
X dp = diskblks; /* Move this along in the next loop */
X
X /* Now allocate ram storage, up to ramlevels in count.
X */
X for (i = 0; i < MAXLEVEL + MAXVLEVEL; i++) {
X if (i < ramlevels)
X rp = (RAMBLOCK *) malloc(sizeof(RAMBLOCK));
X else
X rp = NULL;
X if (rp == NULL) {
X if (i == 0)
X died(-285); /* have to have at least one */
X
X /* Open the swap file if not yet done so
X */
X if (swapfd == 0) {
X swapfd = open(swapfile,
X O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
X S_IWRITE | S_IREAD);
X if (swapfd < 0)
X error("Can't open swapfile `%s'\n",
X swapfile);
X
X /* First block is FREE and will be used to
X * swap out the first level. When another
X * level gets swapped in, its block will be
X * FREE.
X */
X if (dp == NULL)
X error("NULL1 disk pointer?\n");
X dp->level = FREEBLOCK;
X dp->fpos = 0;
X dp->gtime = 0;
X lseek(swapfd, (long) sizeof rp->cell, 0);
X }
X
X /* And try to seek the size of this level
X */
X dp = dp->next;
X if (dp == NULL)
X error("NULL2 disk pointer?\n");
X dp->level = FREEBLOCK;
X dp->gtime = 0;
X dp->fpos = tell(swapfd);
X if (lseek(swapfd, (long) sizeof rp->cell, 1) < 0L)
X error("Not enough disk space for swapfile `%s'\n",
X swapfile);
X } else {
X rp->next = ramblks;
X ramblks = rp;
X rp->level = FREEBLOCK;
X rp->gtime = 0;
X }
X }
X
X /* dp now points to the last diskblock used. Truncate the diskblock
X * list here and free up the other blocks (for what it's worth ...)
X */
X dp2 = dp->next;
X dp->next = NULL;
X dp = dp2;
X while (dp) {
X dp2 = dp->next;
X free((char *) dp);
X dp = dp2;
X }
X}
X
X
X/* VARARGS1 */
Xwarn(format, a1, a2, a3)
Xchar *format;
Xlong a1, a2, a3;
X{
X fprintf(stderr, format, a1, a2, a3);
X}
X
X/* VARARGS1 */
Xerror(format, a1, a2, a3, a4)
Xchar *format;
Xlong a1, a2, a3, a4;
X{
X unsetraw();
X resetcursor();
X fputc('\n', stderr);
X fprintf(stderr, format, a1, a2, a3, a4);
X sleep(5);
X exit(1);
X}
X
Xstatic unsigned char ocursorstart, ocursorend;
Xunsigned char cursorstart, cursorend;
Xint cursorset;
X
X/* Save the old value of the cursor then put in the new value.
X */
X# define READCURSORPOS 0x03
X# define SETCURSORTYPE 0x01
X# define BIOSVIDEO 0x10
Xsetcursor()
X{
X#ifdef OS2LARN
X USHORT rc;
X VIOCURSORINFO curinfo;
X
X if (cursorset == 0)
X return;
X
X /* Save the cursor type in 'ocursorstart' and 'ocursorend'.
X */
X rc = VioGetCurType((PVIOCURSORINFO) &curinfo, (HVIO) NULL);
X if (rc != 0)
X {
X /* errors don't happen. */
X }
X ocursorstart = curinfo.yStart;
X ocursorend = curinfo.cEnd;
X
X /* set the cursor type according to global variables
X 'cursorstart' and 'cursorend'.
X */
X curinfo.cEnd = cursorend;
X curinfo.yStart = cursorstart;
X curinfo.cx = 0; /* default width, 1 char */
X curinfo.attr = 0; /* 'Normal' attribute */
X
X rc = VioSetCurType((PVIOCURSORINFO) &curinfo, (HVIO) NULL);
X if (rc != 0)
X {
X /* errors don't happen. */
X }
X
X#else
X union REGS regs;
X
X if (cursorset == 0)
X return;
X
X regs.h.ah = READCURSORPOS;
X regs.h.bh = 0;
X int86(BIOSVIDEO, ®s, ®s);
X ocursorstart = regs.h.ch;
X ocursorend = regs.h.cl;
X
X regs.h.ah = SETCURSORTYPE;
X regs.h.bh = 0;
X regs.h.ch = cursorstart;
X#if 0
X regs.h.ch = 0x20 ;
X#endif
X regs.h.cl = cursorend;
X int86(BIOSVIDEO, ®s, ®s);
X#endif
X}
X
X/* Restore the old cursor upon exit
X */
Xresetcursor()
X{
X#ifdef OS2LARN
X VIOCURSORINFO curinfo;
X
X if (cursorset == 0)
X return;
X
X curinfo.cEnd = ocursorend;
X curinfo.yStart = ocursorstart;
X curinfo.cx = 0; /* default width, 1 char */
X curinfo.attr = 0; /* 'Normal' attribute */
X
X VioSetCurType((PVIOCURSORINFO) &curinfo, (HVIO) NULL);
X#else
X union REGS regs;
X
X if (cursorset == 0)
X return;
X regs.h.ah = SETCURSORTYPE;
X regs.h.bh = 0;
X regs.h.ch = ocursorstart;
X regs.h.cl = ocursorend;
X int86(BIOSVIDEO, ®s, ®s);
X#endif
X}
X# endif /* MSDOS */
END_OF_FILE
if test 11570 -ne `wc -c <'msdos.c'`; then
echo shar: \"'msdos.c'\" unpacked with wrong size!
fi
# end of 'msdos.c'
fi
if test -f 'tgetent.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tgetent.c'\"
else
echo shar: Extracting \"'tgetent.c'\" \(10470 characters\)
sed "s/^X//" >'tgetent.c' <<'END_OF_FILE'
X/************************************************************************
X * *
X * Copyright (c) 1982, Fred Fish *
X * All Rights Reserved *
X * *
X * This software and/or documentation is released for public *
X * distribution for personal, non-commercial use only. *
X * Limited rights to use, modify, and redistribute are hereby *
X * granted for non-commercial purposes, provided that all *
X * copyright notices remain intact and all changes are clearly *
X * documented. The author makes no warranty of any kind with *
X * respect to this product and explicitly disclaims any implied *
X * warranties of merchantability or fitness for any particular *
X * purpose. *
X * *
X ************************************************************************
X */
X
X/*
X * LIBRARY FUNCTION
X *
X * tgetent load buffer with entry for specified terminal
X *
X * KEY WORDS
X *
X * termcap functions
X * utility routines
X *
X * SYNOPSIS
X *
X * int tgetent(bp,name)
X * char *bp;
X * char *name;
X *
X * DESCRIPTION
X *
X * Extracts the entry for terminal <name> from the termcap file
X * and places it in the character buffer <bp>. It is currently
X * assumed that bp is at least 1024 characters. If the entry in
X * the termcap file is larger than 1023 characters the excess
X * characters will be discarded and appropriate status will
X * be returned.
X *
X * Also note that since bp is used by other termcap
X * routines, the storage associated with the termcap entry
X * cannot be freed until all termcap calls are completed.
X *
X * Tgetent can be directed to look in a file other than
X * the default (/etc/termcap) by defining an environment
X * variable called TERMCAP to be the pathname of the desired
X * termcap file. This is useful for debugging new entries.
X#ifndef VMS
X * NOTE: the pathname MUST begin with a '/' character.
X *
X * Also, if the string assigned to TERMCAP does not begin with
X * a '/' and if the environment variable TERM matches <name> then
X * the string assigned to TERMCAP is copied to buffer <bp>
X * instead of reading a termcap file.
X#endif
X *
X * If the termcap entry contains a "tc" string then the termcap
X * entry named in the string is appended to the buffer (minus the
X * names).
X *
X * RETURNS
X *
X * -1 if the termcap file cannot be opened
X * 0 if no entry in termcap file matches <name>
X * 1 if extraction is successful with no errors
X * 2 if extraction is successful but entry truncated
X *
X * SEE ALSO
X *
X * tgetnum extract numeric type capability
X * tgetflag test boolean type capability
X * tgetstr get string value of capability
X *
X * AUTHOR
X *
X * Fred Fish
X *
X */
X
X#include <stdio.h>
X
X#define TRUE 1
X#define FALSE 0
X#define BUFSIZE 1024 /* Assumed size of external buffer */
X
X#define NO_FILE -1 /* Returned if can't open file */
X#define NO_ENTRY 0 /* Returned if can't find entry */
X#define SUCCESS 1 /* Returned if entry found ok */
X#define TRUNCATED 2 /* Returned if entry found but trunc */
X
X#ifdef MSDOS
XFILE *fopenp();
X#endif
X
X#define DEFAULT_ROOT "termcap" /* name without path component */
X#ifdef VMS
X#define DEFAULT_FILE "sys$library:termcap"
X#else
X#define DEFAULT_FILE "/etc/termcap" /* default termcap filename */
X#endif VMS
X
Xchar *_tcpbuf; /* Place to remember buffer pointer */
X
X/*
X * PSEUDO CODE
X *
X * Begin tgetent
X * Erase any previous buffer contents.
X * Remember the buffer pointer.
X * If termcap file is not found then
X * If buffer was filled anyway then
X * Return SUCCESS.
X * Else
X * Return NO_FILE.
X * End if
X * Else
X * While records left to process
X * If this is entry is what we want then
X * Close the termcap file.
X * If entry was truncated then
X * Return TRUNCATED status
X * Else
X * Return SUCCESS status.
X * End if
X * End if
X * End while
X * Return NO_ENTRY status.
X * End if
X * End tgetent
X *
X */
X
Xint tgetent(bp,name)
Xchar *bp; /* Pointer to buffer (1024 char min) */
Xchar *name; /* Pointer to terminal entry to find */
X{
X FILE *fp, *find_file();
X char *nbp, tc[80];
X
X *bp = (char)NULL;
X _tcpbuf = bp;
X if ((fp = find_file(bp)) == NULL) {
X if (*bp != NULL) {
X return(SUCCESS);
X } else {
X return(NO_FILE);
X }
X } else {
X while (fgetlr(bp,BUFSIZE,fp)) {
X if (gotcha(bp,name)) {
X fclose(fp);
X nbp = &bp[strlen(bp)-1];
X if (*nbp != '\n') {
X return(TRUNCATED);
X } else {
X /* check for a recursive call (i.e. :tc=vt100:)
X * added 18-dec-86 RDE (single recursion...)
X */
X char *area;
X area = &tc[0];
X if (tgetstr("tc", &area) == NULL)
X return(SUCCESS);
X else {
X fp = find_file(0); /* know it works and is file */
X while (fgetlr(nbp, BUFSIZE-(nbp-bp), fp)) {
X if (gotcha(nbp,tc)) {
X char *cp1, *cp2; /* scrunch out names */
X fclose(fp);
X cp1 = nbp;
X while (*cp1++ != ':') /* search for first */
X ;
X cp2 = nbp;
X while (*cp2++ = *cp1++) /* move the chars. */
X ;
X if (bp[strlen(bp)-1] != '\n') {
X return(TRUNCATED);
X } else {
X return(SUCCESS);
X }
X }
X }
X return (NO_ENTRY);
X }
X }
X }
X }
X return(NO_ENTRY);
X }
X}
X
X/*
X * INTERNAL FUNCTION
X *
X * find_file find the termcap file and open it if possible
X *
X * KEY WORDS
X *
X * internal functions
X * find_file
X *
X * SYNOPSIS
X *
X * static FILE *find_file(bp)
X * char *bp;
X *
X * DESCRIPTION
X *
X * Attempts to locate and open the termcap file. Also handles
X * using the environment TERMCAP string as the actual buffer
X * (that's why bp has to be an input parameter).
X *
X#ifdef VMS
X * If TERMCAP is defined as a valid filespec then it will be
X * opened. If this fails then the default termcap file will
X * be used.
X#else
X * If TERMCAP is defined an begins with a '/' character then
X * it is taken to be the pathname of the termcap file and
X * an attempt is made to open it. If this fails then
X * the default termcap file is used instead.
X *
X * If TERMCAP is defined but does not begin with a '/' then
X * it is assumed to be the actual buffer contents provided
X * that <name> matches the environment variable TERM.
X#endif
X *
X * BUGS
X *
X * There is currently no way to be sure which termcap
X * file was opened since the default will always be
X * tried.
X *
X */
X
X/*
X * PSEUDO CODE
X *
X * Begin find_file
X * If there is a TERMCAP environment string then
X * If the string is not null then
X * If the string is a pathname then
X * If that file is opened successfully then
X * Return its pointer.
X * End if
X * Else
X * If there is a TERM environment string then
X * If TERM matches <name> then
X * Copy TERMCAP string to buffer.
X * Return NULL for no file.
X * End if
X * End if
X * End if
X * End if
X * End if
X * Open default termcap file and return results.
X * End find_file
X *
X */
X
Xstatic FILE *find_file(bp)
Xchar *bp;
X{
X FILE *fp, *fopen();
X char *cp, *ncp, *getenv();
X
X if ((cp = getenv("TERMCAP")) != NULL) {
X if (*cp != NULL) {
X#ifdef VMS
X if ((fp = fopen(cp, "r")) != NULL)
X return(fp);
X#else
X if (*cp == '/' || *cp == '\\') {
X if ((fp = fopen(cp,"r")) != NULL) {
X return(fp);
X }
X } else {
X if ((ncp = getenv("TERM")) != NULL) {
X if (strcmp(cp,ncp) == 0) {
X strcpy(bp,cp);
X return((FILE *)NULL);
X }
X }
X }
X#endif
X }
X }
X /*
X * Try current directory, then /etc/termcap
X */
X if (fp = fopen(DEFAULT_ROOT, "r"))
X return fp;
X else
X#ifdef MSDOS
X if (fp = fopen(DEFAULT_FILE, "r") )
X return fp;
X else /* try along the PATH */
X return( fopenp(DEFAULT_ROOT, "r", NULL));
X#else
X return (fopen(DEFAULT_FILE, "r"));
X#endif
X}
X
X
X/*
X * INTERNAL FUNCTION
X *
X * gotcha test to see if entry is for specified terminal
X *
X * SYNOPSIS
X *
X * gotcha(bp,name)
X * char *bp;
X * char *name;
X *
X * DESCRIPTION
X *
X * Tests to see if the entry in buffer bp matches the terminal
X * specified by name. Returns TRUE if match is detected, FALSE
X * otherwise.
X *
X */
X
X/*
X * PSEUDO CODE
X *
X * Begin gotcha
X * If buffer character is comment character then
X * Return FALSE since remainder is comment
X * Else
X * Initialize name scan pointer.
X * Compare name and buffer until end or mismatch.
X * If valid terminators for both name and buffer strings
X * Return TRUE since a match was found.
X * Else
X * Find next non-name character in buffer.
X * If not an alternate name separater character
X * Return FALSE since no more names to check.
X * Else
X * Test next name and return results.
X * End if
X * End if
X * End if
X * End gotcha
X *
X */
X
Xgotcha(bp,name)
Xchar *bp;
Xchar *name;
X{
X char *np;
X
X if (*bp == '#') {
X return(FALSE);
X } else {
X np = name;
X while (*np == *bp && *np != NULL) {np++; bp++;}
X if (*np == NULL && (*bp == NULL || *bp == '|' || *bp == ':')) {
X return(TRUE);
X } else {
X while (*bp != NULL && *bp != ':' && *bp != '|') {bp++;}
X if (*bp != '|') {
X return(FALSE);
X } else {
X return(gotcha(++bp,name));
X }
X }
X }
X}
X
X#ifdef MSDOS
X/*
X * index(buffer, char)
X * Find character in buffer. Return the pointer
X * to it. Shouldn't be necessary to write this
X * myself but VMS didn't. Oh Well...
X * Used by lots of files in the termcap library.
X * Rich Ellison, 16-DEC-1986
X */
Xchar
X*index(buf, ch)
Xchar *buf;
Xchar ch;
X{
X register int c;
X while ((c= *buf++) != '\0')
X if (c == ch)
X return (buf-1);
X return (NULL);
X}
X#endif
END_OF_FILE
if test 10470 -ne `wc -c <'tgetent.c'`; then
echo shar: \"'tgetent.c'\" unpacked with wrong size!
fi
# end of 'tgetent.c'
fi
echo shar: End of archive 10 \(of 12\).
cp /dev/null ark10isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 12 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0