-+-+-+-+-+-+-+-+ START OF PART 31 -+-+-+-+-+-+-+-+ X if (*ptr != '\\' && *ptr != '/' && *ptr != ':') `7B X *++ptr = '\\'; X *++ptr = '\0'; X `7D X`7D X X/* Lopen a file somewhere along the PATH X */ Xplopen(name) Xchar *name; X`7B X char buf`5BPATHLEN`5D, *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) `7B X pp = getenv("PATH"); X while (pp && *pp) `7B 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 `7D X `7D X return -1; X`7D 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`7B X char buffer`5BBUFSIZ`5D, *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) `7B X pathp = getenv("PATH"); X while (pathp && *pathp) `7B 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 `7D X `7D X return NULL; X`7D X X/* Diagnositic information about the disposition of levels between ram X * and disk. X */ Xlevelinfo() X`7B 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`7D 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`7B 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++) `7B X if ((dp = (DISKBLOCK *) malloc(sizeof(DISKBLOCK))) == NULL) X died(-285); X dp->next = diskblks; X diskblks = dp; X `7D 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++) `7B X if (i < ramlevels) X rp = (RAMBLOCK *) malloc(sizeof(RAMBLOCK)); X else X rp = NULL; X if (rp == NULL) `7B 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) `7B X swapfd = open(swapfile, X O_RDWR `7C O_CREAT `7C O_TRUNC `7C O_BINARY, X S_IWRITE `7C S_IREAD); X if (swapfd < 0) X error("Can't open swapfile `60%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 `7D 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 `60%s'\n", X swapfile); X `7D else `7B X rp->next = ramblks; X ramblks = rp; X rp->level = FREEBLOCK; X rp->gtime = 0; X `7D X `7D 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) `7B X dp2 = dp->next; X free((char *) dp); X dp = dp2; X `7D X`7D X X X/* VARARGS1 */ Xwarn(format, a1, a2, a3) Xchar *format; Xlong a1, a2, a3; X`7B X fprintf(stderr, format, a1, a2, a3); X`7D X X/* VARARGS1 */ Xerror(format, a1, a2, a3, a4) Xchar *format; Xlong a1, a2, a3, a4; X`7B X unsetraw(); X resetcursor(); X fputc('\n', stderr); X fprintf(stderr, format, a1, a2, a3, a4); X sleep(5); X exit(1); X`7D 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`7B 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'.`20 X */ X rc = VioGetCurType((PVIOCURSORINFO) &curinfo, (HVIO) NULL); X if (rc != 0) X `7B X /* errors don't happen. */ X `7D 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 `7B X /* errors don't happen. */ X `7D 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`7D X X/* Restore the old cursor upon exit X */ Xresetcursor() X`7B 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`7D X# endif /* MSDOS */ $ CALL UNPACK MSDOS.C;1 1182686716 $ create 'f' XSYNOPSIS X`09Include in \config.sys the line X`09`09device=nansi.sys X XDESCRIPTION X`09Nansi.sys is a console driver which understands ANSI control X`09sequences. It has several advantages over ANSI.SYS (the driver X`09supplied with DOS): X`091. It supports new escape sequences (see below). X`092. It provides MUCH faster output under certain conditions. X`093. It supports the 43-line mode of the EGA. X`094. The darned bell is now 1/4 second instead of 1/2 second long. X X`09What a console driver does: X`09When you, for example, type X`09`09C:> type foo.txt X`09COMMAND.COM opens the file foo.txt, reads it, and writes it to X`09the console driver, which puts it up on the screen. X X`09Both ansi.sys and nansi.sys use IBM Video BIOS to control the screen. X`09However, nansi.sys bypasses BIOS if the screen is in a text mode; this X`09allows much faster operation under certain conditions. X X`09While putting text up on the screen, (n)ansi.sys keeps a lookout for X`09the escape character (chr(27), known as ESC); this character signals X`09the start of a terminal control sequence. X`09Terminal control sequences follow the format X`09`09ESC `5B param; param; ...; param cmd X`09where X`09`09ESC`09is the escape character chr$(27). X`09`09`5B`09is the left bracket character. X`09`09param`09is an ASCII decimal number, or a string in quotes. X`09`09cmd`09is a case-specific letter identifying the command. X`09Usually, zero, one, or two parameters are given. If parameters X`09are omitted, they usually default to 1; however, some commands X`09(KKR and DKOCT) treat the no-parameter case specially. X`09Spaces are not allowed between parameters. X X`09For example, both ESC`5B1;1H and ESC`5BH send the cursor to the home X`09position (1,1), which is the upper left. X X`09Either single or double quotes may be used to quote a string. X`09Each character inside a quoted string is equivalent to one numeric X`09parameter. Quoted strings are normally used only for the Keyboard X`09Key Reassignment command. X XControl Sequences X`09The following table lists the sequences understood by nansi.sys. X`09Differences between nansi.sys and the standard ansi.sys are marked X`09with a vertical bar (`7C). X XCursor Positioning XShort`09Long name`09`09Format`09`09Notes XCUP`09cursor position`09`09ESC`5By;xH`09Sets cursor position. XHVP`09cursor position`09`09ESC`5By;xf`09Same as CUP; not recommended. XCUU`09cursor up`09`09ESC`5BnA`09`09n = # of lines to move XCUD`09cursor down`09`09ESC`5BnB XCUF`09cursor forward`09`09ESC`5BnC`09`09n = # of columns to move XCUB`09cursor backward`09`09ESC`5BnD XDSR`09Device Status, Report!`09ESC`5B6n`09`09Find out cursor position. XCPR`09Cursor Position report`09ESC`5By;xR`09Response to DSR, as if typed. XSCP`09Save Cursor Position`09ESC`5Bs`09`09Not nestable. XRCP`09Restore Cursor Position ESC`5Bu X XEditing XED`09Erase in Display`09ESC`5B2J`09Clears screen. XEL`09Erase in Line`09`09ESC`5BK`09Clears to end of line. XIL `7C`09Insert Lines`09`09ESC`5BnL`09Inserts n blank lines at cursor line. XDL `7C`09Delete Lines`09`09ESC`5BnM`09Deletes n lines including cursor line V. XICH `7C`09Insert Characters`09ESC`5Bn@`09Inserts n blank chars at cursor. XDCH `7C`09Delete Characters`09ESC`5BnP`09Deletes n chars including cursor ch Var. X X XMode-Setting XSGR`09Set Graphics Rendition`09ESC`5Bn;n;...nm`09See character attribute tab Vle. XSM`09Set Mode`09`09ESC`5B=nh`09`09See screen mode table. XRM`09Reset Mode`09`09ESC`5B=nl`09`09See screen mode table. XIBMKKR`09Keyboard Key Reass.`09ESC`5B"string"p X`09The first char of the string gives the key to redefine; the rest X`09of the string is the key's new value. X`09To specify unprintable chars, give the ASCII value of the char X`09outside of quotes, as a normal parameter. X`09IBM function keys are two byte strings; see the IBM Basic manual. X`09For instance, ESC`5B0;";dir a:";13;p redefines function key 1 to X`09have the value "dir a:" followed by the ENTER key. X `7C If no parameters given, all keys are reset to their default values V. X XDKOCT `7C Output char translate`09ESC`5Bn;ny X `7C When first char is encountered in output request, it is replaced w Vith X `7C the second char. This might be useful for previewing text before X `7C sending it to a printer with a funny print wheel. X `7C If no parameters are given, all chars are reset to normal. X X XCharacter Attributes X`09The Set Graphics Rendition command is used to select foreground X`09and background colors or attributes. X`09When you use multiple parameters, they are executed in sequence, and X`09the effects are cumulative. X`09 Attrib code`09`09Value X`09`090`09`09All attributes off (normal white on black) X`09`091`09`09Bold X`09`094`09`09Underline X`09`095`09`09Blink X`09`097`09`09Reverse Video X`09`098`09`09Invisible (but why?) X`09`0930-37`09`09foregnd blk/red/grn/yel/blu/magenta/cyan/white X`09`0940-47`09`09background X XScreen Modes X`09The IBM BIOS supports several video modes; the codes given in the X`09BIOS documentation are used as parameters to the Set Mode command. X `7C (In bitmap modes, the cursor is simulated with a small blob (`5EV) V.) X`09 Mode Code`09`09Value X`09`090`09`09text 40x25 Black & White X`09`091`09`09text 40x25 Color X`09`092`09`09text 80x25 Black & White X`09`093`09`09text 80x25 Color X`09`094`09`09bitmap 320x200 4 bits/pixel X`09`095`09`09bitmap 320x200 1 bit/pixel X`09`096`09`09bitmap 640x200 1 bit/pixel X`09`097`09`09(cursor wrap kludge) X`09`0913 (EGA)`09bitmap 320x200 4 bits/pixel ? X`09`0914 (EGA)`09bitmap 640x200 4 bits/pixel X`09`0916 (EGA)`09bitmap 640x350 4 bits/pixel X`09Mode 7 is an unfortunate kludge; Setting mode 7 tells the cursor X`09to wrap around to the next line when it passes the end of a line; +-+-+-+-+-+-+-+- END OF PART 31 +-+-+-+-+-+-+-+-