home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!mcnc!gatech!cwjcc!hal!ncoast!allbery
- From: jbs@ll-xn.UUCP (Jeff Siegal)
- Newsgroups: comp.sources.misc
- Subject: v04i015: Support for MG2A under MS-DOS
- Message-ID: <8808060436.AA26237@EDDIE.MIT.EDU>
- Date: 6 Aug 88 04:36:30 GMT
- Sender: allbery@ncoast.UUCP
- Reply-To: jbs@ll-xn.UUCP (Jeff Siegal)
- Lines: 2174
- Approved: allbery@ncoast.UUCP
-
- Posting-number: Volume 4, Issue 15
- Submitted-by: "Jeff Siegal" <jbs@ll-xn.UUCP>
- Archive-name: dos-mg2a
-
- The enclosed shar file adds MS-DOS to the systems supported by the
- current release of MG (2A). It should be extracted into an empty
- directory called "msdos", under "sys" in the mg source directory.
-
- Jeff Siegal
- ----
- #! /bin/sh
- # To extract, remove mail header lines and type "sh filename"
- if [ ! -s ./README ]
- then
- if [ ! -d . ]
- then
- mkdir .
- echo mkdir .
- fi
- echo x - ./README
- sed -e 's/^X//' > ./README << '!FaR!OuT!'
- XThis is the source for the MS-DOS version of mg2a. These files are
- Xintended to reside in a directory sys/msdos underneath the main mg2a
- Xsource directory.
- X
- XThis code will run under both "Turbo C 1.5" and "Microsoft C 5.1"
- X
- XTo compile using Turbo C 1.5, copy makefile.tc from the sys/msdos
- Xdirectory into the main mg2a source directory, then cd into the main
- Xdirectory and use the Turbo C "make" program (just type "make").
- X
- XTo compile using Microsoft C 5.1, cd into the main directory and type
- X"make sys\msdos\makefile.msc"
- X
- XA few random notes:
- X
- Xo The display routines rely on the ROM BIOS interface. This has the
- X advantage of being more portable, but at the expense of display
- X speed. Direct memory-mapped display code or using ANSI sequences with
- X NANSI or FANSI-Console could be much faster. To keep the program
- X small and maintain portability, enhancements such as these should
- X be supported as compile-time options (e.g. with #ifdef's)
- X
- X The only display mode supported is 24 x 80. To fix this, you will
- X need to change NROW and NCOL ttydef.h to be the largest # of rows
- X and columns supported, then you will have to change either
- X ttresize() in "tty.c" or setttysize() in "ttyio.c" to check the
- X BIOS parameter memory for the current screen size.
- X
- Xo Note that the keyboard support also goes through the BIOS.
- X The "backspace" key generates DELETE (so that it does a
- X delete-backwards, while control-h still returns control-h (i.e.
- X HELP). Arrow keys, HOME, END, PgUp, PgDn, etc. are supported
- X (look in ttykbd.c) The ALT key works like a META key for alpha
- X keys, but the BIOS doesn't return keycodes for certain ALT
- X key combinations (I wish ALT-SHIFT-< worked!) 8 bit characters
- X (the line drawing set!) are supported, but to enter them, you
- X must use ALT-ddd (where ddd are digits on the numeric keypad).
- X
- Xo The dired mode SEEMS to work, but I am not real happy with "dired" in the
- X first place, and the MS-DOS implementation isn't very well tested.
- X Presumably this is one area which will be enhanced in mg 2b.
- X
- Xo REGEX compiles OK, but doesn't seem to work right. I haven't done any
- X extensive testing, and I'm not sure what is breaking down. If you
- X want to play with this, you must add the
- X string "-DREGEX" to the CDEFS macro in the makefile (don't try to
- X add it to sysdef.h: regex.c won't compile right (sigh)).
- X
- X Anyway, I've got no use for REGEX at the moment, and compiling it
- X in adds 15K to the base executable size of 90K. I pass.
- X
- XGood luck with this. We hope you find it useful. Please send any
- Ximprovements you make.
- X
- XCredits:
- X
- XJohn P. Nelson (decvax!genrad!jpn, jpn@genrad.com) did the Turbo C
- Xport and most of the work (based on his earlier work on
- XMicroGnuEmacs). Jeff Siegal (jbs@eddie.mit.edu) brought it up under
- XMicrosoft C and fixed a few bugs.
- X
- XThis document was written by John P. Nelson and modified by Jeff Siegal.
- !FaR!OuT!
- fi
- if [ ! -s ./alloca.c ]
- then
- if [ ! -d . ]
- then
- mkdir .
- echo mkdir .
- fi
- echo x - ./alloca.c
- sed -e 's/^X//' > ./alloca.c << '!FaR!OuT!'
- X/* alloca is only required by the GNU regex code */
- X#ifdef REGEX
- X/*
- X alloca -- (mostly) portable public-domain implementation
- X
- X last edit: 86/01/26 D A Gwyn
- X
- X This implementation of the PWB library alloca() function,
- X which is used to allocate space off the run-time stack so
- X that it is automatically reclaimed upon procedure exit,
- X was inspired by discussions with J. Q. Johnson of Cornell.
- X
- X It should work under any C implementation that uses an
- X actual procedure stack (as opposed to a linked list of
- X frames). There are some preprocessor constants that can
- X be defined when compiling for your specific system, for
- X improved efficiency; however, the defaults should be okay.
- X
- X The general concept of this implementation is to keep
- X track of all alloca()-allocated blocks, and reclaim any
- X that are found to be deeper in the stack than the current
- X invocation. This heuristic does not reclaim storage as
- X soon as it becomes invalid, but it will do so eventually.
- X
- X As a special case, alloca(0) reclaims storage without
- X allocating any. It is a good idea to use alloca(0) in
- X your main control loop, etc. to force garbage collection.
- X*/
- X#ifndef lint
- Xstatic char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */
- X#endif
- X
- X#ifdef X3J11
- Xtypedef void *pointer; /* generic pointer type */
- X#else
- Xtypedef char *pointer; /* generic pointer type */
- X#endif
- X
- X#define NULL 0 /* null pointer constant */
- X
- Xextern void free();
- Xextern pointer malloc();
- X
- X/*
- X Define STACK_DIRECTION if you know the direction of stack
- X growth for your system; otherwise it will be automatically
- X deduced at run-time.
- X
- X STACK_DIRECTION > 0 => grows toward higher addresses
- X STACK_DIRECTION < 0 => grows toward lower addresses
- X STACK_DIRECTION = 0 => direction of growth unknown
- X*/
- X
- X#ifndef STACK_DIRECTION
- X#define STACK_DIRECTION 0 /* direction unknown */
- X#endif
- X
- X#if STACK_DIRECTION != 0
- X
- X#define STACK_DIR STACK_DIRECTION /* known at compile-time */
- X
- X#else /* STACK_DIRECTION == 0; need run-time code */
- X
- Xstatic int stack_dir = 0; /* 1 or -1 once known */
- X#define STACK_DIR stack_dir
- X
- Xstatic void
- Xfind_stack_direction( /* void */ )
- X {
- X static char *addr = NULL; /* address of first
- X `dummy', once known */
- X auto char dummy; /* to get stack address */
- X
- X if ( addr == NULL )
- X { /* initial entry */
- X addr = &dummy;
- X
- X find_stack_direction(); /* recurse once */
- X }
- X else /* second entry */
- X if ( &dummy > addr )
- X stack_dir = 1; /* stack grew upward */
- X else
- X stack_dir = -1; /* stack grew downward */
- X }
- X
- X#endif /* STACK_DIRECTION == 0 */
- X
- X/*
- X An "alloca header" is used to:
- X (a) chain together all alloca()ed blocks;
- X (b) keep track of stack depth.
- X
- X It is very important that sizeof(header) agree with malloc()
- X alignment chunk size. The following default should work okay.
- X*/
- X
- X#ifndef ALIGN_SIZE
- X#define ALIGN_SIZE sizeof(double)
- X#endif
- X
- Xtypedef union hdr
- X {
- X char align[ALIGN_SIZE]; /* to force sizeof(header) */
- X struct {
- X union hdr *next; /* for chaining headers */
- X char *deep; /* for stack depth measure */
- X } h;
- X } header;
- X
- X/*
- X alloca( size ) returns a pointer to at least `size' bytes of
- X storage which will be automatically reclaimed upon exit from
- X the procedure that called alloca(). Originally, this space
- X was supposed to be taken from the current stack frame of the
- X caller, but that method cannot be made to work for some
- X implementations of C, for example under Gould's UTX/32.
- X*/
- X
- Xpointer
- Xalloca( size ) /* returns pointer to storage */
- X unsigned size; /* # bytes to allocate */
- X {
- X static header *last = NULL; /* -> last alloca header */
- X auto char probe; /* probes stack depth: */
- X register char *depth = &probe;
- X
- X#if STACK_DIRECTION == 0
- X if ( STACK_DIR == 0 ) /* unknown growth direction */
- X find_stack_direction();
- X#endif
- X
- X /* Reclaim garbage, defined as all alloca()ed storage that
- X was allocated from deeper in the stack than currently. */
- X
- X {
- X register header *hp; /* traverses linked list */
- X
- X for ( hp = last; hp != NULL; )
- X if ( STACK_DIR > 0 && hp->h.deep > depth
- X || STACK_DIR < 0 && hp->h.deep < depth
- X ) {
- X register header *np = hp->h.next;
- X
- X free( (pointer)hp ); /* collect garbage */
- X
- X hp = np; /* -> next header */
- X }
- X else
- X break; /* rest are not deeper */
- X
- X last = hp; /* -> last valid storage */
- X }
- X
- X if ( size == 0 )
- X return NULL; /* no allocation required */
- X
- X /* Allocate combined header + user data storage. */
- X
- X {
- X register pointer new = malloc( sizeof(header) + size );
- X /* address of header */
- X
- X if ( new == NULL )
- X return NULL; /* abort() is traditional */
- X
- X ((header *)new)->h.next = last;
- X ((header *)new)->h.deep = depth;
- X
- X last = (header *)new;
- X
- X /* User storage begins just after header. */
- X
- X return (pointer)((char *)new + sizeof(header));
- X }
- X }
- X#endif
- !FaR!OuT!
- fi
- if [ ! -s ./chrdef.h ]
- then
- if [ ! -d . ]
- then
- mkdir .
- echo mkdir .
- fi
- echo x - ./chrdef.h
- sed -e 's/^X//' > ./chrdef.h << '!FaR!OuT!'
- X/*
- X * sys/msdos/chardef.h: character set specific #defines for mg 2a
- X */
- X
- X#ifndef CHARMASK
- X/*
- X * casting should be at least as efficent as anding with 0xff,
- X * and won't have the size problems. Override in sysdef.h if no
- X * unsigned char type.
- X */
- X#define CHARMASK(c) ((unsigned char) (c))
- X#endif
- X
- X/*
- X * These flags, and the macros below them,
- X * make up a do-it-yourself set of "ctype" macros that
- X * understand the DEC multinational set, and let me ask
- X * a slightly different set of questions.
- X */
- X#define _W 0x01 /* Word. */
- X#define _U 0x02 /* Upper case letter. */
- X#define _L 0x04 /* Lower case letter. */
- X#define _C 0x08 /* Control. */
- X#define _P 0x10 /* end of sentence punctuation */
- X#define _D 0x20 /* is decimal digit */
- X
- X#define ISWORD(c) ((cinfo[CHARMASK(c)]&_W)!=0)
- X#define ISCTRL(c) ((cinfo[CHARMASK(c)]&_C)!=0)
- X#define ISUPPER(c) ((cinfo[CHARMASK(c)]&_U)!=0)
- X#define ISLOWER(c) ((cinfo[CHARMASK(c)]&_L)!=0)
- X#define ISEOSP(c) ((cinfo[CHARMASK(c)]&_P)!=0)
- X#define ISDIGIT(c) ((cinfo[CHARMASK(c)]&_D)!=0)
- X#define TOUPPER(c) ((c)-0x20)
- X#define TOLOWER(c) ((c)+0x20)
- X
- X/*
- X * generally useful thing for chars
- X */
- X#define CCHR(x) ((x) ^ 0x40) /* CCHR('?') == DEL */
- X
- X#ifndef METACH
- X#define METACH CCHR('[')
- X#endif
- X
- X#ifdef XKEYS
- X#define K00 256
- X#define K01 257
- X#define K02 258
- X#define K03 259
- X#define K04 260
- X#define K05 261
- X#define K06 262
- X#define K07 263
- X#define K08 264
- X#define K09 265
- X#define K0A 266
- X#define K0B 267
- X#define K0C 268
- X#define K0D 269
- X#define K0E 270
- X#define K0F 271
- X#define K10 272
- X#define K11 273
- X#define K12 274
- X#define K13 275
- X#define K14 276
- X#define K15 277
- X#define K16 278
- X#define K17 279
- X#define K18 280
- X#define K19 281
- X#define K1A 282
- X#define K1B 283
- X#define K1C 284
- X#define K1D 285
- X#define K1E 286
- X#define K1F 287
- X#define K20 288
- X#define K21 289
- X#define K22 290
- X#define K23 291
- X#define K24 292
- X#define K25 293
- X#define K26 294
- X#define K27 295
- X#define K28 296
- X#define K29 297
- X#define K2A 298
- X#define K2B 299
- X#define K2C 300
- X#define K2D 301
- X#define K2E 302
- X#define K2F 303
- X#endif
- !FaR!OuT!
- fi
- if [ ! -s ./cinfo.c ]
- then
- if [ ! -d . ]
- then
- mkdir .
- echo mkdir .
- fi
- echo x - ./cinfo.c
- sed -e 's/^X//' > ./cinfo.c << '!FaR!OuT!'
- X/*
- X * Character class tables.
- X * Do it yourself character classification
- X * macros, that understand the multinational character set,
- X * and let me ask some questions the standard macros (in
- X * ctype.h) don't let you ask.
- X */
- X#include "def.h"
- X
- X/*
- X * This table, indexed by a character drawn
- X * from the 256 member character set, is used by my
- X * own character type macros to answer questions about the
- X * type of a character. It handles the full multinational
- X * character set, and lets me ask some questions that the
- X * standard "ctype" macros cannot ask.
- X */
- Xchar cinfo[256] = {
- X _C, _C, _C, _C, /* 0x0X */
- X _C, _C, _C, _C,
- X _C, _C, _C, _C,
- X _C, _C, _C, _C,
- X _C, _C, _C, _C, /* 0x1X */
- X _C, _C, _C, _C,
- X _C, _C, _C, _C,
- X _C, _C, _C, _C,
- X 0, _P, 0, 0, /* 0x2X */
- X _W, _W, 0, _W,
- X 0, 0, 0, 0,
- X 0, 0, _P, 0,
- X _D|_W, _D|_W, _D|_W, _D|_W, /* 0x3X */
- X _D|_W, _D|_W, _D|_W, _D|_W,
- X _D|_W, _D|_W, 0, 0,
- X 0, 0, 0, _P,
- X 0, _U|_W, _U|_W, _U|_W, /* 0x4X */
- X _U|_W, _U|_W, _U|_W, _U|_W,
- X _U|_W, _U|_W, _U|_W, _U|_W,
- X _U|_W, _U|_W, _U|_W, _U|_W,
- X _U|_W, _U|_W, _U|_W, _U|_W, /* 0x5X */
- X _U|_W, _U|_W, _U|_W, _U|_W,
- X _U|_W, _U|_W, _U|_W, 0,
- X 0, 0, 0, 0,
- X 0, _L|_W, _L|_W, _L|_W, /* 0x6X */
- X _L|_W, _L|_W, _L|_W, _L|_W,
- X _L|_W, _L|_W, _L|_W, _L|_W,
- X _L|_W, _L|_W, _L|_W, _L|_W,
- X _L|_W, _L|_W, _L|_W, _L|_W, /* 0x7X */
- X _L|_W, _L|_W, _L|_W, _L|_W,
- X _L|_W, _L|_W, _L|_W, 0,
- X 0, 0, 0, 0,
- X _W, _W, _W, _W, /* 0x8X */
- X _W, _W, _W, _W,
- X _W, _W, _W, _W,
- X _W, _W, _W, _W,
- X _W, _W, _W, _W, /* 0x9X */
- X _W, _W, _W, _W,
- X _W, _W, _W, 0,
- X 0, 0, 0, 0,
- X _W, _W, _W, _W, /* 0xAX */
- X _W, _W, _W, _W,
- X 0, 0, 0, 0,
- X 0, 0, 0, 0,
- X 0, 0, 0, 0, /* 0xBX */
- X 0, 0, 0, 0,
- X 0, 0, 0, 0,
- X 0, 0, 0, 0,
- X 0, 0, 0, 0, /* 0xCX */
- X 0, 0, 0, 0,
- X 0, 0, 0, 0,
- X 0, 0, 0, 0,
- X 0, 0, 0, 0, /* 0xDX */
- X 0, 0, 0, 0,
- X 0, 0, 0, 0,
- X 0, 0, 0, 0,
- X 0, 0, 0, 0, /* 0xEX */
- X 0, 0, 0, 0,
- X 0, 0, 0, 0,
- X 0, 0, 0, 0,
- X 0, 0, 0, 0, /* 0xFX */
- X 0, 0, 0, 0,
- X 0, 0, 0, 0,
- X 0, 0, 0, 0,
- X};
- X
- X/*
- X * Find the name of a keystroke. Needs to be changed to handle 8-bit printing
- X * characters and function keys better. Returns a pointer to the terminating
- X * '\0'.
- X */
- X
- Xchar *keyname(cp, k)
- Xregister char *cp;
- Xregister int k;
- X{
- X register char *np;
- X#ifdef FKEYS
- X extern char *keystrings[];
- X#endif
- X
- X if(k < 0) k = CHARMASK(k); /* sign extended char */
- X switch(k) {
- X case CCHR('@'): np = "NUL"; break;
- X case CCHR('I'): np = "TAB"; break;
- X case CCHR('J'): np = "LFD"; break; /* yuck, but that's what GNU calls it */
- X case CCHR('M'): np = "RET"; break;
- X case CCHR('['): np = "ESC"; break;
- X case ' ': np = "SPC"; break; /* yuck again */
- X case CCHR('?'): np = "DEL"; break;
- X default:
- X#ifdef FKEYS
- X if(k >= KFIRST && k <= KLAST &&
- X (np = keystrings[k - KFIRST]) != NULL)
- X break;
- X#endif
- X if(k > CCHR('?')) {
- X *cp++ = '0';
- X *cp++ = ((k>>6)&7) + '0';
- X *cp++ = ((k>>3)&7) + '0';
- X *cp++ = (k&7) + '0';
- X *cp = '\0';
- X return cp;
- X }
- X if(k < ' ') {
- X *cp++ = 'C';
- X *cp++ = '-';
- X k = CCHR(k);
- X if(ISUPPER(k)) k = TOLOWER(k);
- X }
- X *cp++ = k;
- X *cp = '\0';
- X return cp;
- X }
- X (VOID) strcpy(cp, np);
- X return cp + strlen(cp);
- X}
- !FaR!OuT!
- fi
- if [ ! -s ./fileio.c ]
- then
- if [ ! -d . ]
- then
- mkdir .
- echo mkdir .
- fi
- echo x - ./fileio.c
- sed -e 's/^X//' > ./fileio.c << '!FaR!OuT!'
- X/*
- X * Name: Mg 2a
- X * MSDOS file I/O (TurboC 1.5)
- X */
- X#include "def.h"
- X#include <stdio.h>
- X
- X#ifdef MSC
- X#include <dos.h>
- X#endif /* MSC */
- X
- X#ifndef F_OK
- X#define F_OK 0
- X#define X_OK 1
- X#define W_OK 2
- X#define R_OK 4
- X#endif
- X
- X#ifndef NO_DIR
- Xextern char *wdir;
- X#endif
- X
- Xstatic FILE *ffp;
- X
- X/*
- X * Open a file for reading.
- X */
- Xffropen(fn)
- Xchar *fn;
- X{
- X if ((ffp=fopen(fn, "rb")) == NULL)
- X return (FIOFNF);
- X return (FIOSUC);
- X}
- X
- X/*
- X * Open a file for writing.
- X * Return TRUE if all is well, and
- X * FALSE on error (cannot create).
- X */
- Xffwopen(fn)
- Xchar *fn;
- X{
- X if ((ffp=fopen(fn, "wb")) == NULL) {
- X ewprintf("Cannot open file for writing");
- X return (FIOERR);
- X }
- X return (FIOSUC);
- X}
- X
- X/*
- X * Close a file.
- X * Should look at the status.
- X */
- Xffclose()
- X{
- X (VOID) fclose(ffp);
- X return (FIOSUC);
- X}
- X
- X/*
- X * Write a line to the already
- X * opened file. The "buf" points to the
- X * buffer, and the "nbuf" is its length, less
- X * the free newline. Return the status.
- X * Check only at the newline.
- X */
- Xffputline(buf, nbuf)
- Xregister char buf[];
- X{
- X register int i;
- X
- X for (i=0; i<nbuf; ++i)
- X putc(buf[i]&0xFF, ffp);
- X putc('\r', ffp); /* MSDOS wants \r\n line seperators */
- X putc('\n', ffp);
- X if (ferror(ffp) != FALSE) {
- X ewprintf("Write I/O error");
- X return (FIOERR);
- X }
- X return (FIOSUC);
- X}
- X
- X/*
- X * Write a buffer to the already
- X * opened file. bp points to the
- X * buffer. Return the status.
- X * Check only at the newline and
- X * end of buffer.
- X */
- Xffputbuf(bp)
- XBUFFER *bp;
- X{
- X register char *cp;
- X register char *cpend;
- X register LINE *lp;
- X register LINE *lpend;
- X
- X lpend = bp->b_linep;
- X lp = lforw(lpend);
- X do {
- X cp = <ext(lp)[0]; /* begining of line */
- X cpend = &cp[llength(lp)]; /* end of line */
- X while(cp != cpend) {
- X putc(*cp, ffp);
- X cp++; /* putc may evalualte arguments more than once */
- X }
- X lp = lforw(lp);
- X if(lp == lpend) break; /* no implied newline on last line */
- X putc('\r', ffp); /* MSDOS wants \r\n line seperators */
- X putc('\n', ffp);
- X } while(!ferror(ffp));
- X if(ferror(ffp)) {
- X ewprintf("Write I/O error");
- X return FIOERR;
- X }
- X return FIOSUC;
- X}
- X
- X/*
- X * Read a line from a file, and store the bytes
- X * in the supplied buffer. Stop on end of file or end of
- X * line. Don't get upset by files that don't have an end of
- X * line on the last line; this seem to be common on CP/M-86 and
- X * MS-DOS. Delete any CR followed by a NL: This is the normal
- X * format for MS_DOS files, but also occurs when files are transferred
- X * from VMS or MS-DOS to Unix.
- X */
- Xffgetline(buf, nbuf, nbytes)
- Xregister char buf[];
- Xregister int *nbytes;
- X{
- X register int c;
- X register int i;
- X
- X i = 0;
- X for (;;) {
- X c = getc(ffp);
- Xrescan:
- X if (c == '\r') { /* Delete any non-stray */
- X c = getc(ffp); /* carriage returns. */
- X if (c != '\n') {
- X buf[i++] = '\r';
- X if (i >= nbuf) return FIOLONG;
- X goto rescan;
- X }
- X }
- X if (c==EOF || c=='\n') /* End of line. */
- X break;
- X buf[i++] = c;
- X if (i >= nbuf) return FIOLONG;
- X }
- X if (c == EOF && ferror(ffp) != FALSE) {
- X ewprintf("File read error");
- X return FIOERR;
- X }
- X *nbytes = i;
- X return c==EOF ? FIOEOF : FIOSUC;
- X}
- X
- X#ifndef NO_BACKUP
- X/*
- X * Rename the file "fname" into a backup copy.
- X * On Unix the backup has the same name as the
- X * original file, with a "~" on the end - unfortunately
- X * this does not map well to MS-DOS - the old .bak convention
- X * is used.
- X */
- Xfbackupfile(fname)
- Xchar *fname;
- X{
- X register char *nname, *ptr;
- X char *strchr();
- X
- X if ((nname=malloc(strlen(fname)+3+1)) == NULL)
- X return (ABORT);
- X (void) strcpy(nname, fname);
- X if ((ptr = strchr(nname, '.')) != 0)
- X strcpy(ptr, ".bak");
- X else
- X strcat(ptr, ".bak");
- X
- X if (strcmp(fname, nname) == 0) {
- X free(nname);
- X return FALSE;
- X }
- X
- X (void) unlink(nname); /* Ignore errors. */
- X (void) rename(fname, nname);
- X free(nname);
- X return (TRUE);
- X}
- X#endif
- X
- X/*
- X * The string "fn" is a file name.
- X * convert all filenames to lower case, and convert all '\\' characters
- X * to forward slashes. This is simply my preference, uppercase and
- X * back slashes are also viable.
- X */
- X/*ARGSUSED*/
- Xadjustmsdos(fn)
- Xregister char *fn;
- X{
- X register char c;
- X
- X while ((c = *fn) != '0') {
- X if (ISUPPER(c))
- X *fn = TOLOWER(c);
- X if (c=='/')
- X *fn = '\\';
- X ++fn;
- X }
- X}
- X
- X
- X
- X#ifndef NO_STARTUP
- X#define STARTUPNAME ".mg"
- X/*
- X * find the users startup file, and return it's name. Check for
- X * if MGSTARTUP is defined, then use that. Otherwise, look
- X * for .mg in the current directory, then in the root directory.
- X */
- Xchar *
- Xstartupfile()
- X{
- X register char *file;
- X static char temp[NFILEN];
- X char *getenv();
- X
- X if ((file = getenv("MGSTARTUP")) != NULL )
- X {
- X if (access(file, F_OK) == 0)
- X return file;
- X return NULL;
- X }
- X if (access (STARTUPNAME, F_OK) == 0)
- X return STARTUPNAME;
- X strcpy(temp, "/");
- X strcat(temp, STARTUPNAME);
- X if (access (temp, F_OK) == 0)
- X return temp;
- X return NULL;
- X}
- X#endif
- X
- X/*******************************************************************/
- X/* new stuff between release 1a and 2a */
- X/*******************************************************************/
- X
- X/* convert all filenames to a canonical format, which in the case of
- X * MSDOS is X:/currentdir/filename. Note that each drive letter has
- X * it's OWN current directory, so if the user specifies a drive letter,
- X * we use that drive's current directory, not it's root.
- X */
- X
- X/* MSC doesn't have getdrive and getcurdir routines; simulate them.
- X * They are both pretty gross. Blame Microsoft */
- X
- X#ifdef MSC
- Xunsigned getdisk()
- X{
- X unsigned currentdrive;
- X
- X _dos_getdrive(¤tdrive);
- X return currentdrive-1;
- X}
- X
- Xvoid getcurdir(unsigned drivenumber, char *buf)
- X{
- X unsigned currentdrive = getdisk()+1;
- X unsigned number_of_drives; /* unused */
- X static char bufr[NFILEN];
- X
- X _dos_setdrive(drivenumber, &number_of_drives);
- X getcwd(&bufr[0], NFILEN-1);
- X _dos_setdrive(currentdrive, &number_of_drives);
- X strcpy(buf, &bufr[3]);
- X}
- X#endif
- X
- Xchar *adjustname(fn)
- Xregister char *fn;
- X{
- X register char *cp;
- X static char fnb[NFILEN];
- X struct passwd *pwent;
- X
- X cp = fnb;
- X /* handle A:foo\bar */
- X if (fn[0] && fn[1] == ':') {
- X *cp++ = *fn++;
- X *cp++ = *fn++;
- X *cp = '\0';
- X adjustmsdos(fnb); /* force case to lower */
- X if (*fn != '/' && *fn != '\\') {
- X *cp++ = '\\';
- X getcurdir(fnb[0]-'a'+1, cp);
- X cp = fnb + strlen(fnb);
- X }
- X else
- X *cp++ = *fn++;
- X }
- X /* handle \foo\bar */
- X else if (*fn == '/' || *fn == '\\') {
- X *cp++ = (char) (getdisk() + 'a');
- X *cp++ = ':';
- X *cp++ = *fn++;
- X }
- X else {
- X strcpy(fnb, wdir);
- X cp = fnb + strlen(fnb);
- X }
- X
- X if(cp != fnb && cp[-1] != '/' && cp[-1] != '\\') *cp++ = '\\';
- X
- X /* at this point, we should have a drive, and at least a single */
- X /* slash. Now copy over the rest of the filename, while handling */
- X /* certain pathalogical cases */
- X
- X /* convert "//" to "/", "/./" to "/", and "/x/../" to "/" */
- X while(*fn) {
- X switch(*fn) {
- X case '.':
- X switch(fn[1]) {
- X case '\0':
- X *--cp = '\0';
- X adjustmsdos(fnb);
- X return fnb;
- X case '/':
- X case '\\':
- X fn += 2;
- X continue;
- X case '.':
- X if(fn[2]=='/' || fn[2]=='\\' || fn[2] == '\0') {
- X --cp;
- X while(cp > fnb && *--cp != '/' && *cp != '\\')
- X ;
- X if (cp==fnb) cp += 2;
- X ++cp;
- X if(fn[2]=='\0') {
- X *--cp = '\0';
- X adjustmsdos(fnb);
- X return fnb;
- X }
- X fn += 3;
- X continue;
- X }
- X break;
- X default:
- X break;
- X }
- X break;
- X case '/':
- X case '\\':
- X fn++;
- X continue;
- X default:
- X break;
- X }
- X while(*fn && (*cp++ = *fn++) != '/' && fn[-1] != '\\')
- X ;
- X }
- X if (cp != fnb + 3 && cp[-1]=='\\') --cp;
- X *cp = '\0';
- X adjustmsdos(fnb);
- X return fnb;
- X}
- X
- X#ifndef NO_DIRED
- X#include "kbd.h"
- X#define DIRFILE "_dirlist_.$$$"
- X
- XBUFFER *dired_(dirname)
- Xchar *dirname;
- X{
- X register BUFFER *bp;
- X char line[256];
- X BUFFER *findbuffer();
- X char *strncpy();
- X int i;
- X
- X if((dirname = adjustname(dirname)) == NULL) {
- X ewprintf("Bad directory name");
- X return NULL;
- X }
- X if((bp = findbuffer(dirname)) == NULL) {
- X ewprintf("Could not create buffer");
- X return NULL;
- X }
- X if(bclear(bp) != TRUE) return FALSE;
- X (VOID) strcpy(line, "dir ");
- X (VOID) strcat(line, dirname);
- X (VOID) strcat(line, " > ");
- X (VOID) strcat(line, DIRFILE);
- X system(line);
- X if (ffropen(DIRFILE) != FIOSUC) {
- X ewprintf("Can't open temporary dir file");
- X return NULL;
- X }
- X line[0] = line[1] = ' ';
- X if (ffgetline(&line[2], sizeof(line)-3, &i) != FIOSUC) {
- X ffclose();
- X (void)unlink(DIRFILE);
- X ewprintf("No such directory: `%s'", dirname);
- X return NULL;
- X }
- X while (ffgetline(&line[2], sizeof(line)-3, &i) == FIOSUC) {
- X line[i+2] = '\0';
- X (VOID) addline(bp, line);
- X }
- X ffclose();
- X (void)unlink(DIRFILE);
- X
- X bp->b_dotp = lforw(bp->b_linep); /* go to first line */
- X (VOID) strncpy(bp->b_fname, dirname, NFILEN);
- X if((bp->b_modes[0] = name_mode("dired")) == NULL) {
- X bp->b_modes[0] = &map_table[0];
- X ewprintf("Could not find mode dired");
- X return NULL;
- X }
- X bp->b_nmodes = 0;
- X return bp;
- X}
- X
- X/* this is really ugly, but then so was the UNIX version! */
- X#define BASENAME 2
- X#define EXT 11
- X#define DIR 15
- Xd_makename(lp, fn)
- Xregister LINE *lp;
- Xregister char *fn;
- X{
- X register char *cp;
- X register char *last;
- X int len;
- X extern char *strchr();
- X
- X if(llength(lp) != 41) return ABORT;
- X if(lgetc(lp,BASENAME) == ' ') return ABORT;
- X if(lgetc(lp,EXT-1) != ' ') return ABORT;
- X (VOID) strcpy(fn, curbp->b_fname);
- X cp = fn + strlen(fn);
- X if ((cp[-1] != '\\') && (cp[-1] != '/')) /* append '/' if needed */
- X *cp++ = '\\';
- X if ((last = strchr(lp->l_text+BASENAME, ' ')) == 0) return ABORT;
- X len = last - (lp->l_text+BASENAME);
- X bcopy(lp->l_text+BASENAME, cp, len);
- X cp += len;
- X if ((last = strchr(lp->l_text+EXT, ' ')) == 0) return ABORT;
- X len = last - (lp->l_text+EXT);
- X if (len != 0) {
- X *cp++ = '.';
- X bcopy(lp->l_text+EXT, cp, len);
- X }
- X cp[len] = '\0';
- X return (strncmp(lp->l_text+DIR, "<DIR>", 5) == 0);
- X}
- X
- X/* sorry, this is a hack - jpn */
- X/* I should probably fix this */
- Xcopy(frname, toname)
- Xchar *frname, *toname;
- X{
- X char buffer[512];
- X int pid;
- X int status;
- X char cmdbuf[80];
- X
- X sprintf(cmdbuf, "Copy %s %s", frname, toname);
- X system(cmdbuf);
- X return TRUE;
- X}
- X
- Xunlinkdir(f)
- Xchar *f;
- X{
- X return (rmdir(f));
- X}
- X
- X#endif /* NO_DIRED */
- !FaR!OuT!
- fi
- if [ ! -s ./makefile.msc ]
- then
- if [ ! -d . ]
- then
- mkdir .
- echo mkdir .
- fi
- echo x - ./makefile.msc
- sed -e 's/^X//' > ./makefile.msc << '!FaR!OuT!'
- X# Microsoft C 5.1 Makefile for MG 2A.
- XSYS = msdos
- XCDEFS = /DMSC
- XDEBUG =
- XCFLAGS = /AL /Oilt /Gs $(CDEFS) $(DEBUG)
- XCC = cl
- X
- X# standard headers
- XDEF = def.h sysdef.h ttydef.h chrdef.h
- X
- X# implicit compilation rule
- X.c.obj:
- X $(CC) /c $(CFLAGS) $*.c
- X
- X# files that can be removed, because they are really just copies
- XHCLEAN = sysdef.h ttydef.h chrdef.h varargs.h
- XCCLEAN = cinfo.c fileio.c spawn.c tty.c ttyio.c ttykbd.c
- X
- X# object file list
- XOBJ = alloca.obj basic.obj buffer.obj cinfo.obj dir.obj dired.obj display.obj \
- X echo.obj extend.obj file.obj fileio.obj help.obj kbd.obj keymap.obj \
- X line.obj macro.obj main.obj match.obj modes.obj paragrap.obj \
- X random.obj regex.obj region.obj re_searc.obj search.obj spawn.obj \
- X tty.obj ttyio.obj ttykbd.obj version.obj window.obj word.obj
- X
- X# this doesn't work right: del only takes one argument (sigh).
- X#clean:
- X# -del $(HCLEAN)
- X# -del $(CCLEAN)
- X# -del *.obj
- X# -del mg.exe
- X
- X# files copied from msdos directory
- Xsysdef.h: sys\$(SYS)\sysdef.h
- X copy sys\$(SYS)\sysdef.h
- X
- Xttydef.h: sys\$(SYS)\ttydef.h
- X copy sys\$(SYS)\ttydef.h
- X
- Xchrdef.h: sys\$(SYS)\chrdef.h
- X copy sys\$(SYS)\chrdef.h
- X
- Xvarargs.h: sys\$(SYS)\varargs.h
- X copy sys\$(SYS)\varargs.h
- X
- Xalloca.c: sys\default\alloca.c
- X copy sys\default\alloca.c
- X
- Xcinfo.c: sys\$(SYS)\cinfo.c
- X copy sys\$(SYS)\cinfo.c
- X
- Xfileio.c: sys\$(SYS)\fileio.c
- X copy sys\$(SYS)\fileio.c
- X
- Xspawn.c: sys\$(SYS)\spawn.c
- X copy sys\$(SYS)\spawn.c
- X
- Xtty.c: sys\$(SYS)\tty.c
- X copy sys\$(SYS)\tty.c
- X
- Xttyio.c: sys\$(SYS)\ttyio.c
- X copy sys\$(SYS)\ttyio.c
- X
- Xttykbd.c: sys\$(SYS)\ttykbd.c
- X copy sys\$(SYS)\ttykbd.c
- X
- X# header dependencies
- X
- Xbasic.obj: basic.c $(DEF)
- X
- Xbuffer.obj: buffer.c $(DEF) kbd.h
- X
- Xdir.obj: dir.c $(DEF)
- X
- Xdired.obj: dired.c $(DEF)
- X
- Xdisplay.obj: display.c $(DEF) kbd.h
- X
- Xecho.obj: echo.c $(DEF) key.h varargs.h macro.h
- X
- Xextend.obj: extend.c $(DEF) kbd.h macro.h key.h
- X
- Xfile.obj: file.c $(DEF)
- X
- Xhelp.obj: help.c $(DEF) kbd.h key.h macro.h
- X
- Xkbd.obj: kbd.c $(DEF) kbd.h key.h macro.h
- X
- Xkeymap.obj: keymap.c $(DEF) kbd.h
- X
- Xline.obj: line.c $(DEF)
- X
- Xmacro.obj: macro.c $(DEF) key.h macro.h
- X
- Xmain.obj: main.c $(DEF) macro.h
- X
- Xmatch.obj: match.c $(DEF) key.h
- X
- Xmodes.obj: modes.c $(DEF) kbd.h
- X
- Xparagrap.obj: paragrap.c $(DEF)
- X
- Xrandom.obj: random.c $(DEF)
- X
- Xregex.obj: regex.c $(DEF) regex.h
- X
- Xregion.obj: region.c $(DEF)
- X
- Xre_searc.obj: re_searc.c $(DEF) macro.h regex.h
- X
- Xsearch.obj: search.c $(DEF) macro.h
- X
- Xversion.obj: version.c $(DEF)
- X
- Xwindow.obj: window.c $(DEF)
- X
- Xword.obj: word.c $(DEF)
- X
- Xalloca.obj: alloca.c
- X
- Xcinfo.obj: $(DEF) cinfo.c
- X
- Xfileio.obj: $(DEF) kbd.h fileio.c
- X
- Xspawn.obj: $(DEF) spawn.c
- X
- Xtty.obj: $(DEF) tty.c
- X
- Xttyio.obj: $(DEF) ttyio.c
- X
- Xttykbd.obj: $(DEF) ttykbd.c
- X
- X# add /Fm to the CC line to get a load map
- Xmg.exe: $(OBJ)
- X $(CC) $(CFLAGS) /FeMG.EXE *.obj
- X
- !FaR!OuT!
- fi
- if [ ! -s ./makefile.tc ]
- then
- if [ ! -d . ]
- then
- mkdir .
- echo mkdir .
- fi
- echo x - ./makefile.tc
- sed -e 's/^X//' > ./makefile.tc << '!FaR!OuT!'
- X# Turbo C Makefile for MG 2A.
- XSYS = msdos
- XCDEFS =
- X# suppress some annoying warnings
- XWARN = -w-stu -w-par
- XCFLAGS = -ml $(CDEFS) $(WARN)
- XCC = tcc
- X
- X# standard headers
- XDEF = def.h sysdef.h ttydef.h chrdef.h
- X
- X# implicit compilation rule
- X.c.obj:
- X $(CC) -c $(CFLAGS) $<
- X
- X# files that can be removed, because they are really just copies
- XHCLEAN = sysdef.h ttydef.h chrdef.h varargs.h
- XCCLEAN = cinfo.c fileio.c spawn.c tty.c ttyio.c ttykbd.c
- X
- X# object file list
- XOBJ = alloca.obj basic.obj buffer.obj cinfo.obj dir.obj dired.obj display.obj \
- X echo.obj extend.obj file.obj fileio.obj help.obj kbd.obj keymap.obj \
- X line.obj macro.obj main.obj match.obj modes.obj paragrap.obj \
- X random.obj regex.obj region.obj re_searc.obj search.obj spawn.obj \
- X tty.obj ttyio.obj ttykbd.obj version.obj window.obj word.obj
- X
- X# add -M to the CC line to get a load map
- Xmg.exe: $(OBJ)
- X $(CC) -emg $(CFLAGS) *.obj
- X
- X# this doesn't work right: del only takes one argument (sigh).
- Xclean:
- X -del $(HCLEAN)
- X -del $(CCLEAN)
- X -del *.obj
- X -del mg.exe
- X
- X# files copied from msdos directory
- Xsysdef.h: sys/$(SYS)/sysdef.h
- X copy sys/$(SYS)/sysdef.h
- X
- Xttydef.h: sys/$(SYS)/ttydef.h
- X copy sys/$(SYS)/ttydef.h
- X
- Xchrdef.h: sys/$(SYS)/chrdef.h
- X copy sys/$(SYS)/chrdef.h
- X
- Xvarargs.h: sys/$(SYS)/varargs.h
- X copy sys/$(SYS)/varargs.h
- X
- Xalloca.c: sys/$(SYS)/alloca.c
- X copy sys/$(SYS)/alloca.c
- X
- Xcinfo.c: sys/$(SYS)/cinfo.c
- X copy sys/$(SYS)/cinfo.c
- X
- Xfileio.c: sys/$(SYS)/fileio.c
- X copy sys/$(SYS)/fileio.c
- X
- Xspawn.c: sys/$(SYS)/spawn.c
- X copy sys/$(SYS)/spawn.c
- X
- Xtty.c: sys/$(SYS)/tty.c
- X copy sys/$(SYS)/tty.c
- X
- Xttyio.c: sys/$(SYS)/ttyio.c
- X copy sys/$(SYS)/ttyio.c
- X
- Xttykbd.c: sys/$(SYS)/ttykbd.c
- X copy sys/$(SYS)/ttykbd.c
- X
- X# header dependencies
- Xbasic.obj: $(DEF)
- Xbuffer.obj: $(DEF) kbd.h
- Xdir.obj: $(DEF)
- Xdired.obj: $(DEF)
- Xdisplay.obj: $(DEF) kbd.h
- Xecho.obj: $(DEF) key.h varargs.h macro.h
- Xextend.obj: $(DEF) kbd.h macro.h key.h
- Xfile.obj: $(DEF)
- Xhelp.obj: $(DEF) kbd.h key.h macro.h
- Xkbd.obj: $(DEF) kbd.h key.h macro.h
- Xkeymap.obj: $(DEF) kbd.h
- Xline.obj: $(DEF)
- Xmacro.obj: $(DEF) key.h macro.h
- Xmain.obj: $(DEF) macro.h
- Xmatch.obj: $(DEF) key.h
- Xmodes.obj: $(DEF) kbd.h
- Xparagrap.obj: $(DEF)
- Xrandom.obj: $(DEF)
- Xregex.obj: $(DEF) regex.h
- Xregion.obj: $(DEF)
- Xre_searc.obj: $(DEF) macro.h regex.h
- Xsearch.obj: $(DEF) macro.h
- Xversion.obj: $(DEF)
- Xwindow.obj: $(DEF)
- Xword.obj: $(DEF)
- X
- Xalloca.obj: alloca.c
- Xcinfo.obj: $(DEF) cinfo.c
- Xfileio.obj: $(DEF) kbd.h fileio.c
- Xspawn.obj: $(DEF) spawn.c
- Xtty.obj: $(DEF) tty.c
- Xttyio.obj: $(DEF) ttyio.c
- Xttykbd.obj: $(DEF) ttykbd.c
- !FaR!OuT!
- fi
- if [ ! -s ./spawn.c ]
- then
- if [ ! -d . ]
- then
- mkdir .
- echo mkdir .
- fi
- echo x - ./spawn.c
- sed -e 's/^X//' > ./spawn.c << '!FaR!OuT!'
- X/*
- X * Name: Mg 2a
- X * Spawn CLI for MSDOS (TurboC 1.5)
- X *
- X */
- X#include "def.h"
- X#include <process.h>
- X
- Xextern char *getenv();
- X
- X/*
- X * On MSDOS, we got no job control like system V, so always
- X * run a subshell. Bound to "C-C", and used
- X * as a subcommand by "C-Z". (daveb)
- X *
- X * Returns 0 if the shell executed OK, something else if
- X * we couldn't start shell or it exited badly.
- X */
- Xspawncli(f, n, k)
- X{
- X char *comspec;
- X int errp = FALSE;
- X
- X ttcolor(CTEXT);
- X ttnowindow();
- X ttmove(nrow-1, 0);
- X if (epresf != FALSE) {
- X tteeol();
- X epresf = FALSE;
- X }
- X ttclose();
- X sgarbf = TRUE; /* Force repaint. */
- X if ((comspec = getenv("COMSPEC")) == NULL)
- X errp = -1;
- X else
- X errp = spawnl(P_WAIT, comspec, "COMMAND.COM", (char *)NULL);
- X
- X ttopen();
- X if(errp == -1)
- X ewprintf("Failed to create process");
- X
- X return ( errp );
- X}
- !FaR!OuT!
- fi
- if [ ! -s ./sysdef.h ]
- then
- if [ ! -d . ]
- then
- mkdir .
- echo mkdir .
- fi
- echo x - ./sysdef.h
- sed -e 's/^X//' > ./sysdef.h << '!FaR!OuT!'
- X/*
- X * Name: Mg 2a
- X * MSDOS system header file (TurboC 1.5)
- X */
- X
- X/* can't include these, the ANSI style prototypes conflict with the
- X * definitions in defs.h
- X */
- X/* #include <stdlib.h> */
- X/* #include <string.h> */
- X/* #include <dir.h> */
- X/* #include <stdio.h> */
- X#define NULL 0L
- X
- X#define KBLOCK 1024 /* Kill grow. */
- X#define GOOD 0 /* Good exit status. */
- X#define MAXPATH 256 /* Maximum length of path for chdir */
- X
- X#define LOCAL_VARARGS /* use sys/default/varargs.h */
- X#define DO_METAKEY /* ALT acts like META */
- X#define METABIT 0x200
- X#define FKEYS /* we have dedicated function keys */
- X/* #define NO_DIRED */ /* dired works now */
- X#define C_ALLOCA /* used by regex, C version of alloca*/
- X
- Xtypedef long RSIZE; /* Type for file/region sizes */
- Xtypedef short KCHAR; /* Type for internal keystrokes */
- X/* typedef short KEY; /* Type for internal keystrokes */
- X
- X/*
- X * Macros used by the buffer name making code.
- X * Start at the end of the file name, scan to the left
- X * until BDC1 (or BDC2, if defined) is reached. The buffer
- X * name starts just to the right of that location, and
- X * stops at end of string (or at the next BDC3 character,
- X * if defined). BDC2 and BDC3 are mainly for VMS.
- X */
- X#define BDC1 '/'
- X#define BDC2 '\\'
- X
- X#define bcopy(s,d,n) memcpy(d,s,n) /* memory-to-memory copy */
- X#define bcmp(s1,s2,n) memcmp(s2,s1,n) /* memory comparison */
- X#define bzero(s,n) memset(s,0,n) /* memory zero */
- X
- X#define fncmp stricmp
- X#define getwd(cwd) getcwd(cwd,NFILEN) /* get current working dir */
- Xextern char *getcwd();
- X
- X#define MALLOCROUND(m) (m+=7,m&=~7) /* round up to 8 byte boundry */
- !FaR!OuT!
- fi
- if [ ! -s ./tty.c ]
- then
- if [ ! -d . ]
- then
- mkdir .
- echo mkdir .
- fi
- echo x - ./tty.c
- sed -e 's/^X//' > ./tty.c << '!FaR!OuT!'
- X/*
- X * Mg 2b (turboc 1.5/MSC 1.5)
- X * IBM-PC and compatible BIOS based display driver.
- X * - this will tend to be a bit slower than a driver that
- X * writes directly to the memory mapped screen, but with
- X * the large # of display adapters floating around, I'd
- X * rather let the bios do the work.
- X *
- X * I DO recommend FANSI-CONSOLE which significantly speeds
- X * up display bios calls, however.
- X */
- X#include "def.h"
- X#include <dos.h>
- X
- X#define BEL 0x07 /* BEL character. */
- X
- Xextern int ttrow;
- Xextern int ttcol;
- Xextern int tttop;
- Xextern int ttbot;
- Xextern int tthue;
- X
- Xstatic int biocol = 0;
- X
- Xint tceeol = 2; /* Costs are set later */
- Xint tcinsl = 5;
- Xint tcdell = 5;
- X
- Xstatic int insdel = TRUE; /* Do we have both insert & delete line? */
- Xstatic int rendition =0x07;
- X
- Xint ttputc();
- X
- X/*
- X * Initialize the terminal when the editor
- X * gets started up.
- X */
- Xttinit() {
- X}
- X
- X/*
- X * Clean up the terminal, in anticipation of
- X * a return to the command interpreter.
- X */
- Xtttidy() {
- X}
- X
- X/*
- X * Move the cursor to the specified
- X * origin 0 row and column position.
- X */
- Xttmove(row, col) {
- X ttcol = col;
- X ttrow = row;
- X _move(row, col);
- X}
- X
- X_move(row, col) {
- X union REGS rg;
- X
- X biocol = col;
- X rg.h.ah = 2; /* set cursor position function code */
- X rg.h.dl = col;
- X rg.h.dh = row;
- X rg.h.bh = 0; /* set screen page number */
- X int86(0x10, &rg, &rg);
- X}
- X
- X/*
- X * Erase to end of line.
- X */
- Xtteeol() {
- X union REGS rg;
- X
- X rg.h.ah = 9; /* write character/rendition */
- X rg.h.bh = 0;
- X rg.x.cx = ncol-biocol;
- X rg.h.al = ' ';
- X rg.h.bl = rendition;
- X
- X int86(0x10, &rg, &rg);
- X}
- X
- X/*
- X * Erase to end of page.
- X */
- Xtteeop() {
- X ttdell(ttrow, nrow, nrow - ttrow);
- X}
- X
- X/*
- X * Make a noise.
- X */
- Xttbeep() {
- X union REGS rg;
- X
- X rg.h.ah = 14; /* write tty */
- X rg.h.al = BEL;
- X
- X int86(0x10, &rg, &rg);
- X}
- X
- X/*
- X * Insert nchunk blank line(s) onto the
- X * screen, scrolling the last line on the
- X * screen off the bottom.
- X */
- Xttinsl(row, bot, nchunk) {
- X union REGS rg;
- X
- X if (row == bot) { /* Case of one line insert is */
- X ttmove(row, 0); /* special */
- X tteeol();
- X return;
- X }
- X
- X rg.h.ah = 7; /* scroll down */
- X rg.h.bh = 0x07;
- X rg.h.al = nchunk;
- X rg.h.ch = row;
- X rg.h.cl = 0;
- X rg.h.dh = bot;
- X rg.h.dl = ncol - 1;
- X
- X int86(0x10, &rg, &rg);
- X}
- X
- X/*
- X * Delete nchunk line(s) from "row", replacing the
- X * bottom line on the screen with a blank line.
- X */
- X
- Xttdell(row, bot, nchunk)
- X{
- X union REGS rg;
- X
- X if (row == bot) { /* One line special case */
- X ttmove(row, 0);
- X tteeol();
- X return;
- X }
- X rg.h.ah = 6; /* scroll up */
- X rg.h.bh = 0x07;
- X rg.h.al = nchunk;
- X rg.h.ch = row;
- X rg.h.cl = 0;
- X rg.h.dh = bot;
- X rg.h.dl = ncol - 1;
- X
- X int86(0x10, &rg, &rg);
- X}
- X
- X/*
- X * Switch to full screen scroll. This is
- X * used by "spawn.c" just before is suspends the
- X * editor, and by "display.c" when it is getting ready
- X * to exit.
- X */
- Xttnowindow()
- X{
- X}
- X
- X/*
- X * Set the current writing color to the
- X * specified color. Watch for color changes that are
- X * not going to do anything (the color is already right)
- X * and don't send anything to the display.
- X * The rainbow version does this in putline.s on a
- X * line by line basis, so don't bother sending
- X * out the color shift.
- X */
- Xttcolor(color) register int color; {
- X if (color != tthue) {
- X if (color == CTEXT) { /* Normal video. */
- X rendition = 0x07;
- X } else if (color == CMODE) { /* Reverse video. */
- X rendition = 0x70;
- X }
- X tthue = color; /* Save the color. */
- X }
- X}
- X
- X/*
- X * This routine is called by the
- X * "refresh the screen" command to try and resize
- X * the display. The new size, which must be deadstopped
- X * to not exceed the NROW and NCOL limits, it stored
- X * back into "nrow" and "ncol". Display can always deal
- X * with a screen NROW by NCOL. Look in "window.c" to
- X * see how the caller deals with a change.
- X */
- Xttresize() {
- X setttysize();
- X}
- X
- X/* calculate the cost of doing string s */
- Xcharcost (s) char *s; {
- X return strlen(s);
- X}
- X
- Xttputc(c)
- Xunsigned char c;
- X{
- X union REGS rg;
- X
- X if (c == '\b') {
- X if (biocol-1 > 0) {
- X _move(ttrow, biocol-1);
- X }
- X return;
- X }
- X else if (c == '\r') {
- X _move(ttrow, 0);
- X return;
- X }
- X rg.h.ah = 9; /* write character/rendition */
- X rg.h.bh = 0;
- X rg.x.cx = 1;
- X rg.h.al = c;
- X rg.h.bl = rendition;
- X
- X int86(0x10, &rg, &rg);
- X
- X if (biocol+1 >= ncol)
- X _move(ttrow + 1, 0);
- X else
- X _move(ttrow, biocol + 1);
- X}
- X
- Xstruct nap
- X {
- X long napvalue;
- X long basetime;
- X };
- X
- Xttwait()
- X {
- X struct nap timer;
- X napstart(200, &timer);
- X while (napchk(&timer) == 0)
- X if (typeahead())
- X return 0;
- X return 1;
- X }
- X
- X/***************************/
- X/* MSDOS time functions */
- X/***************************/
- X
- X/* Apparantly Turbo C has a sleep library routine; MSC doesn't -jbs */
- X
- X#define gettime(_a) ((((long)(_a.x.cx)) << 16)+_a.x.dx)
- X
- X#ifdef MSC
- Xsleep(amount)
- X {
- X while (amount--)
- X nap(100);
- X }
- X#endif
- X
- X/* nap in units of 100ths of seconds via busy loops. */
- Xnap(amount)
- X {
- X struct nap tim;
- X napstart(amount, &tim);
- X while(napchk(&tim) == 0)
- X ;
- X }
- X
- Xnapstart(amount,sav)
- Xint amount;
- Xregister struct nap *sav;
- X {
- X union REGS inregs, outregs;
- X int hunds, secs;
- X
- X inregs.h.ah = 0x2c; /* get time */
- X int86(0x21, &inregs, &outregs);
- X
- X /* glitch in hardware RTC (time warp) makes this necessary */
- X inregs = outregs;
- X inregs.h.dl = 0; /* seconds counter may be slow to increment */
- X if (inregs.h.dh > 0)
- X --inregs.h.dh; /* paranoia */
- X if (inregs.h.cl > 0)
- X --inregs.h.cl; /* more paranoia */
- X /* end of glitch handling */
- X
- X sav->basetime = gettime(inregs); /* in case of wraparound */
- X
- X /* convert hundredths of seconds to future time structure */
- X secs = outregs.h.dh;
- X hunds = outregs.h.dl + amount;
- X
- X while (hunds >= 100) {
- X hunds -= 100;
- X ++secs;
- X }
- X outregs.h.dl = hunds;
- X while (secs >= 60) {
- X secs -= 60;
- X ++outregs.h.cl; /* increment minutes */
- X }
- X outregs.h.dh = secs;
- X
- X /* check for minute and hour wraparound */
- X if (outregs.h.cl >= 60)
- X {
- X outregs.h.cl -= 60;
- X ++outregs.h.ch; /* increment hours */
- X }
- X if (outregs.h.ch >= 24)
- X {
- X outregs.h.ch -= 24;
- X }
- X sav->napvalue = gettime(outregs);
- X }
- X
- Xnapchk(sav)
- Xregister struct nap *sav;
- X {
- X union REGS inregs, outregs;
- X long current;
- X
- X inregs.h.ah = 0x2c; /* get time */
- X int86(0x21, &inregs, &outregs);
- X
- X current = gettime(outregs);
- X
- X if(sav->napvalue > sav->basetime)
- X {
- X if (current >= sav->napvalue || current < sav->basetime)
- X return 1;
- X }
- X else if (current >= sav->napvalue && current < sav->basetime)
- X return 1;
- X return 0;
- X }
- !FaR!OuT!
- fi
- if [ ! -s ./ttydef.h ]
- then
- if [ ! -d . ]
- then
- mkdir .
- echo mkdir .
- fi
- echo x - ./ttydef.h
- sed -e 's/^X//' > ./ttydef.h << '!FaR!OuT!'
- X/*
- X * Termcap terminal file, nothing special, just make it big
- X * enough for windowing systems.
- X */
- X
- X#define GOSLING /* Compile in fancy display. */
- X/* #define MEMMAP */ /* Not memory mapped video. */
- X
- X#define NROW 25 /* Rows. */
- X#define NCOL 80 /* Columns. */
- X#define MOVE_STANDOUT /* don't move in standout mode */
- X/* #define STANDOUT_GLITCH /* possible standout glitch */
- X#define XKEYS
- X
- X#define KFIRST K00
- X#define KHOME K00
- X#define KDOWN K01
- X#define KUP K02
- X#define KLEFT K03
- X#define KRIGHT K04
- X#define KPGUP K05
- X#define KPGDN K06
- X#define KEND K07
- X#define KDELETE K08
- X#define KINSERT K09
- X#define KCLEFT K0A
- X#define KCRIGHT K0B
- X#define KCPGUP K0C
- X#define KCPGDN K0D
- X#define KCHOME K0E
- X#define KCEND K0F
- X
- X#define KF1 K10
- X#define KF2 K11
- X#define KF3 K12
- X#define KF4 K13
- X#define KF5 K14
- X#define KF6 K15
- X#define KF7 K16
- X#define KF8 K17
- X#define KF9 K18
- X#define KF10 K19
- X#define KSF1 K1A
- X#define KSF2 K1B
- X#define KSF3 K1C
- X#define KSF4 K1D
- X#define KSF5 K1E
- X#define KSF6 K1F
- X#define KSF7 K20
- X#define KSF8 K21
- X#define KSF9 K22
- X#define KSF10 K23
- X#define KCF1 K24
- X#define KCF2 K25
- X#define KCF3 K26
- X#define KCF4 K27
- X#define KCF5 K28
- X#define KCF6 K29
- X#define KCF7 K2A
- X#define KCF8 K2B
- X#define KCF9 K2C
- X#define KCF10 K2D
- X#define KLAST K2D
- X
- X#define NFUND_XMAPS 1
- X#define FUND_XMAPS {KFIRST,KLAST,ibm_keys,(KEYMAP*)NULL}
- Xextern int (*(ibm_keys[]))(); /* should be FN ibmkeys[], but not defined yet */
- X/*
- X * Extra map segments for dired mode -- just use fundamental mode segments
- X */
- X#define NDIRED_XMAPS NFUND_XMAPS
- X#define DIRED_XMAPS FUND_XMAPS
- X
- !FaR!OuT!
- fi
- if [ ! -s ./ttyio.c ]
- then
- if [ ! -d . ]
- then
- mkdir .
- echo mkdir .
- fi
- echo x - ./ttyio.c
- sed -e 's/^X//' > ./ttyio.c << '!FaR!OuT!'
- X/*
- X * Name: Mg 2b
- X * MSDOS terminal I/O (TurboC 1.5)
- X *
- X * The functions in this file
- X * negotiate with the operating system for
- X * keyboard characters, and write characters to
- X * the display
- X *
- X * This version goes along with tty/ibmbios/tty.c.
- X * Terminal size is determined there, rather than here.
- X */
- X#include "def.h"
- X
- X#include <stdio.h>
- X#include <fcntl.h>
- X#include <signal.h>
- X
- Xstatic int ttyactivep = FALSE; /* terminal in editor mode? */
- X
- Xint nrow; /* Terminal size, rows. */
- Xint ncol; /* Terminal size, columns. */
- X
- X/*
- X * This function gets called once, to set up
- X * the terminal channel. This is essentially a no-op
- X * on msdos, since I/O will all be done via bios calls.
- X */
- Xttopen()
- X{
- X if (ttyactivep)
- X return;
- X
- X signal(SIGINT, SIG_IGN);
- X
- X nrow = 25; /* initial guess */
- X ncol = 80;
- X
- X ttyactivep = TRUE;
- X}
- X
- X/*
- X * This function gets called just
- X * before we go back home to the shell. Another
- X * MSDOS no_op.
- X */
- Xttclose()
- X{
- X if(!ttyactivep)
- X return;
- X ttyactivep = FALSE;
- X}
- X
- X/********************************************************************/
- X/* ttputc, ttgetc & typeahead have been deleted from this file, and */
- X/* moved into the tty specific code. There is no operating-system */
- X/* generic way to do these */
- X/********************************************************************/
- X
- X/*
- X * Flush output. This function is a no-op
- X */
- Xttflush()
- X{
- X}
- X
- X/*
- X * panic: print error and die, leaving core file.
- X */
- Xpanic(s)
- Xchar *s;
- X{
- X fprintf(stderr, "%s\r\n", s);
- X#ifdef SYSCLEANUP
- X SYSCLEANUP;
- X#endif
- X exit(1);
- X}
- X
- X
- X/*
- X** This should check the size of the window, and reset if needed.
- X*/
- X
- Xsetttysize()
- X{
- X nrow = 25;
- X ncol = 80;
- X}
- X
- X
- Xvoid interrupt donothing()
- X {
- X return; /* continue program */
- X }
- X
- X/* Turbo C does not have a "signal" function. */
- X/* since all I need to use it for is to ignore ^C, this substitute works ok */
- Xsignal(sig, action)
- Xint sig;
- Xint (*action)();
- X {
- X if (sig != SIGINT || action != SIG_IGN)
- X {
- X printf("Runtime error in signal: only SIGINT, SIG_IGN supported!\n");
- X exit(1);
- X }
- X setvect(0x23, donothing);
- X }
- !FaR!OuT!
- fi
- if [ ! -s ./ttykbd.c ]
- then
- if [ ! -d . ]
- then
- mkdir .
- echo mkdir .
- fi
- echo x - ./ttykbd.c
- sed -e 's/^X//' > ./ttykbd.c << '!FaR!OuT!'
- X/*
- X * Name: Mg 2a
- X * IBM BIOS keyboard driver (TurboC 1.5)
- X *
- X */
- X
- X#include "def.h"
- X#include <dos.h>
- X
- X#ifdef MSC
- X#include <bios.h>
- X#endif /* MSC */
- X
- X#define KMETA METABIT
- X
- Xchar *keystrings[] = {
- X "Home", "Down-Arrow", "Up-Arrow", "Left-Arrow",
- X "Right-Arrow", "Page-Up", "Page-Down", "End",
- X "Delete", "Insert", "Control-Left", "Control-Right",
- X "Control-PgUp", "Control-PgDn", "Control-Home", "Control-End",
- X "F1", "F2", "F3", "F4",
- X "F5", "F6", "F7", "F8",
- X "F9", "F10", "FS1", "FS2",
- X "FS3", "FS4", "FS5", "FS6",
- X "FS7", "FS8", "FS9", "FS10",
- X "FC1", "FC2", "FC3", "FC4",
- X "FC5", "FC6", "FC7", "FC8",
- X "FC9", "FC10",
- X};
- X
- X/* convert IBM bios extended scan codes to appropriate function key values */
- Xstatic KCHAR extended[] = {
- X -1, -1, -1, 0, /* 0-3 */
- X -1, -1, -1, -1, /* 4-7 */
- X -1, -1, -1, -1, /* 8-11 */
- X -1, -1, -1, -1, /* 12-15 */
- X KMETA|'Q', KMETA|'W', KMETA|'E', KMETA|'R',/* 16-19 */
- X KMETA|'T', KMETA|'Y', KMETA|'U', KMETA|'I',/* 20-23 */
- X KMETA|'O', KMETA|'P', -1, -1, /* 24-27 */
- X -1, -1, KMETA|'A', KMETA|'S',/* 28-31 */
- X KMETA|'D', KMETA|'F', KMETA|'G', KMETA|'H',/* 32-35 */
- X KMETA|'J', KMETA|'K', KMETA|'L', -1, /* 36-39 */
- X -1, -1, -1, -1, /* 40-43 */
- X KMETA|'Z', KMETA|'X', KMETA|'C', KMETA|'V',/* 44-47 */
- X KMETA|'B', KMETA|'N', KMETA|'M', -1, /* 48-51 */
- X -1, -1, /* oops - miscounted */ /* 52-53 */
- X -1, -1, -1, -1, /* 54-57 */
- X -1, KF1, KF2, KF3, /* 58-61 */
- X KF4, KF5, KF6, KF7, /* 62-65 */
- X KF8, KF9, KF10, -1, /* 66-69 */
- X -1, KHOME, KUP, KPGUP, /* 70-73 */
- X -1, KLEFT, -1, KRIGHT, /* 74-77 */
- X -1, KEND, KDOWN, KPGDN, /* 78-81 */
- X KINSERT, KDELETE, KSF1, KSF2, /* 82-85 */
- X KSF3, KSF4, KSF5, KSF6, /* 86-89 */
- X KSF7, KSF8, KSF9, KSF10, /* 90-93 */
- X KCF1, KCF2, KCF3, KCF4, /* 94-97 */
- X KCF5, KCF6, KCF7, KCF8, /* 98-101 */
- X KCF9, KCF10, KMETA|KF1, KMETA|KF2,/* 102-105 */
- X KMETA|KF3, KMETA|KF4, KMETA|KF5, KMETA|KF6,/* 106-109 */
- X KMETA|KF7, KMETA|KF8, KMETA|KF9, KMETA|KF10,/* 110-113 */
- X -1, KCLEFT, KCRIGHT, KCEND, /* 114-117 */
- X KCPGDN, KCHOME, KMETA|'1', KMETA|'2',/* 118-121 */
- X KMETA|'3', KMETA|'4', KMETA|'5', KMETA|'6',/* 122-125 */
- X KMETA|'7', KMETA|'8', KMETA|'9', KMETA|'0',/* 126-129 */
- X KMETA|'-', KMETA|'=', KCPGUP, /* 130-132 */
- X};
- X
- X#define NEXTENDED (sizeof(extended)-sizeof(KCHAR))
- X
- Xstatic KCHAR savedkey = -1;
- X
- Xgetkbd() {
- X return (ttgetc());
- X}
- X
- X/*
- X * Get keyboard character, and interpret
- X * any special keys on the keyboard.
- X */
- Xttgetc() {
- X KCHAR temp;
- X
- X while (savedkey == -1)
- X getakey();
- X
- X temp = savedkey;
- X savedkey = -1;
- X return temp;
- X}
- X
- Xgetakey() {
- X union REGS rg;
- X
- X rg.h.ah = 0; /* read keyboard */
- X int86(0x16, &rg, &rg);
- X if (rg.h.al) {
- X if (rg.h.al == '\b' && rg.h.ah == 0x0E)
- X rg.h.al = 0x7F; /* transform backspace key into delete */
- X /* control H is still backspace */
- X savedkey = rg.h.al; /* normal key value */
- X }
- X else {
- X if (rg.h.ah >= NEXTENDED)
- X savedkey = -1;
- X else
- X savedkey = extended[rg.h.ah];
- X }
- X}
- X
- Xpollkbd()
- X{
- X#ifdef MSC
- X return _bios_keybrd(_KEYBRD_READY);
- X#else
- X return bioskey(1);
- X#endif /* MSC */
- X}
- X
- Xtypeahead() {
- X if (savedkey != -1)
- X return 1;
- X if (pollkbd())
- X getakey();
- X return (savedkey != -1);
- X}
- X
- Xttykeymapinit() {
- X /* mg 2a no longer lets me easily bind things at run time. */
- X /* instead, I make up a keymap, and link it in at compile time */
- X}
- X
- Xextern int gotobol(); /* Move to start of line */
- Xextern int backchar(); /* Move backward by characters */
- Xextern int gotoeol(); /* Move to end of line */
- Xextern int forwchar(); /* Move forward by characters */
- Xextern int gotobob(); /* Move to start of buffer */
- Xextern int gotoeob(); /* Move to end of buffer */
- Xextern int gotobop(); /* Move to start of display page*/
- Xextern int gotoeop(); /* Move to end of display page */
- Xextern int forwline(); /* Move forward by lines */
- Xextern int backline(); /* Move backward by lines */
- Xextern int forwpage(); /* Move forward by pages */
- Xextern int backpage(); /* Move backward by pages */
- Xextern int openline(); /* Open up a blank line */
- Xextern int forwdel(); /* Forward delete */
- Xextern int rescan(); /* for unmapped keys */
- Xextern int backword(); /* Backup by words */
- Xextern int forwword(); /* Advance by words */
- Xextern int killline(); /* Kill forward */
- X
- XPF ibm_keys[] = {
- X gotobol, /* Home (0x100) */
- X forwline, /* Down */
- X backline, /* Up */
- X backchar, /* Left */
- X forwchar, /* Right */
- X backpage, /* Page Up */
- X forwpage, /* Page Dn */
- X gotoeol, /* End */
- X forwdel, /* Delete */
- X openline, /* Insert */
- X backword, /* Control Left */
- X forwword, /* Control Right */
- X gotobob, /* Control PgUp */
- X gotoeob, /* Control PgDn */
- X gotobop, /* Control HOME */
- X gotoeop, /* Control END */
- X
- X /* function keys - initially unassigned */
- X rescan, rescan, rescan, rescan,
- X rescan, rescan, rescan, rescan,
- X rescan, rescan, rescan, rescan,
- X rescan, rescan, rescan, rescan,
- X rescan, rescan, rescan, rescan,
- X rescan, rescan, rescan, rescan,
- X rescan, rescan, rescan, rescan,
- X rescan, rescan,
- X};
- !FaR!OuT!
- fi
- if [ ! -s ./varargs.h ]
- then
- if [ ! -d . ]
- then
- mkdir .
- echo mkdir .
- fi
- echo x - ./varargs.h
- sed -e 's/^X//' > ./varargs.h << '!FaR!OuT!'
- X/* varargs.h for MicroGnuEmacs 2a. This one will work on systems that */
- X/* the non-varargs version of mg 1 did. */
- X/* based on the one I wrote for os9/68k . I did not look at the bsd code. */
- X
- X/* by Robert A. Larson */
- X
- X/* assumptions made about how arguments are passed: */
- X/* arguments are stored in a block of memory with no padding between. */
- X/* The first argument will have the lowest address */
- X
- X/* varargs is a "portable" way to write a routine that takes a variable */
- X/* number of arguements. This implemination agrees with both the 4.2bsd*/
- X/* and Sys V documentation of varargs. Note that just because varargs.h*/
- X/* is used does not mean that it is used properly. */
- X
- X#define va_dcl unsigned va_alist;
- X
- Xtypedef char *va_list;
- X
- X#define va_start(pvar) ((pvar) = (char *)&va_alist)
- X
- X#define va_arg(pvar,type) (((pvar)+=sizeof(type)),*(((type *)(pvar)) - 1))
- X
- X#define va_end(pvar) /* va_end is simple */
- !FaR!OuT!
- fi
- exit
-