home *** CD-ROM | disk | FTP | other *** search
- From: slamont@network.ucsd.edu (Steve Lamont)
- Newsgroups: alt.sources
- Subject: Replacement MORE for MeSs-DOS
- Message-ID: <5542@network.ucsd.edu>
- Date: 2 Jul 91 16:27:51 GMT
-
- Here is a replacement for the MeSs-DOS parody of MORE that understands input
- from either standard input or as a list of files from the command line.
-
- It is intended as a better MS-DOS MORE and not as an accurate mimic of the
- Un*x more(1) command, so there are features missing, such as regular expression
- searching, and so forth.
-
- I hereby bequeath this monstrosity to the public domain. Share and enjoy.
-
- spl (the p stands for
- parody of a parody)
- ------------------------ gnaw on dotted line and feed to sh ------------------
- #!/bin/sh
- # shar: Shell Archiver (v1.22)
- #
- # Run the following text with /bin/sh to create:
- # makefile
- # more.c
- #
- sed 's/^X//' << 'SHAR_EOF' > makefile &&
- X#
- X# In case it isn't painfully obvious, this is a makefile for use with
- X# the bizarre parody of MAKE that comes with Microsoft C. If you use
- X# something other than MSC, then you'll probably have to come up with
- X# your own.
- X#
- X
- XCC = cl
- XOPT = -Ox
- X#DEBUG = -Zi
- XCFLAGS = $(OPT) $(DEBUG)
- X
- X#
- X# We include \lib\setargv.obj here to replace the default setargv,
- X# which has insufficient brains to expand the rather simple globbing
- X# that MeSs-DOS inflicts -- er -- I mean, provides. The /noe option
- X# suppresses LINK's complaints about duplicate object modules.
- X#
- X
- XLFLAGS = \lib\setargv.obj -link /noe
- X
- Xmore.obj: more.c makefile
- X $(CC) $(CFLAGS) more.c -c
- X
- Xmore.exe: more.obj
- X $(CC) $(CFLAGS) more.obj -o more.exe $(LFLAGS)
- SHAR_EOF
- chmod 0644 makefile || echo "restore of makefile fails"
- sed 's/^X//' << 'SHAR_EOF' > more.c &&
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <string.h>
- X#include <varargs.h>
- X#include <ctype.h>
- X
- X/*
- X * MSC specific includes.
- X */
- X
- X#include <graph.h>
- X#include <dos.h>
- X
- X/*
- X * More: a replacement pager for MeSs-DOS.
- X *
- X * Copyright relinquished and placed in the public domain by Steve Lamont,
- X * July 2, 1991, at the Naval Postgraduate School, Monterey, CA 93943.
- X * Use at your own risk.
- X *
- X * This program will read from either standard input or from a file or
- X * files specified on the command line. While it sort of acts like Un*x
- X * more(1) it is not intended to be a complete or accurate emulation.
- X *
- X * I guess, in reality, upon reviewing the code, it is kind of a hack,
- X * written while in bed with a Zenith laptop on my stomach. Really!
- X *
- X * This more supports a limited collection of paging options at the prompt:
- X *
- X * Pressing the space bar, the enter key, and the 'N' or 'n' keys all page
- X * forward one screen.
- X *
- X * Pressing the 'p' or 'P' key will cause more to page backward one page.
- X *
- X * Pressing 'x' or 'X' will cause the pager to quit paging the current file
- X * and if there is another specified on the command line, the next file will
- X * then be displayed.
- X *
- X * 'Q', 'q', or Ctrl-C all terminate paging immediately.
- X *
- X * This code is designed to compile under Microsoft C 5.1 (or, probably,
- X * later) and has a couple of MSC dependencies in it.
- X *
- X * MSC library functions used:
- X *
- X * _getvideoconfig() - fetches the monitor adaptor width and height,
- X * among other things.
- X *
- X * int86() - calls a BIOS function via the interrupt vector.
- X * In this case, it reads directly from the keyboard.
- X *
- X * If ported to another compiler, these dependencies will obviously have
- X * to be corrected.
- X */
- X
- X#if !defined( TRUE )
- X#define TRUE ( 1 == 1 )
- X#define FALSE ( 1 == 0 )
- X#endif
- X
- Xchar *me = "?";
- Xint fatal = FALSE;
- X
- X/*
- X * Page dimensions, etc.
- X */
- X
- X#define PAGES ( 5 )
- X
- Xint pagelines;
- Xint buffsize;
- X
- Xint maxlines;
- X
- X#define BAIL ( TRUE )
- X
- X/*
- X * Page buffers.
- X */
- X
- Xchar **ring;
- Xint pmax;
- X
- Xchar *fgetbuffer();
- X
- Xmain( argc, argv )
- X
- X int argc;
- X char **argv;
- X
- X{
- X
- X int i;
- X FILE *f;
- X extern char *me;
- X
- X me = argv[0];
- X
- X setup();
- X
- X /*
- X * Work our way through files specified on the command line.
- X */
- X
- X for ( i = 1; i < argc; i++ )
- X if ( f = fopen( argv[i], "r" ) )
- X process( f, argv[i] );
- X else
- X abend( "%s %s", sys_errlist[errno], argv[i] );
- X
- X /*
- X * If there is input from stdin from a file, page it. If there is
- X * neither a file specified via stdin or any command line arguments,
- X * print a usage message.
- X */
- X
- X if ( !isatty( fileno( stdin ) ) )
- X process( stdin, "stdin" );
- X else if ( argc == 1 )
- X usage( "[files]" );
- X
- X exit( 0 );
- X
- X}
- X
- X/*
- X * Fish up the video configuration.
- X *
- X * Herein lies an MSC dependency.
- X */
- X
- Xsetup()
- X
- X{
- X
- X struct videoconfig config;
- X
- X _getvideoconfig( &config );
- X
- X /*
- X * Allow for the prompt.
- X */
- X
- X pagelines = config.numtextrows - 1;
- X buffsize = config.numtextcols;
- X maxlines = pagelines * PAGES;
- X
- X /*
- X * Allocate the page buffers.
- X */
- X
- X ring = ( char **) malloc( sizeof( char *) * maxlines );
- X if ( !ring )
- X abend( "Whoops! Out of memory!" );
- X
- X return;
- X
- X}
- X
- XclearRing()
- X
- X{
- X
- X int n;
- X
- X for ( n = 0; n < maxlines; n++ )
- X ring[n] = ( char *) NULL;
- X
- X return;
- X
- X}
- X
- Xprocess( f, fn )
- X
- X FILE *f;
- X char *fn;
- X
- X{
- X
- X int current = 0;
- X int bail = FALSE;
- X
- X clearRing();
- X
- X /*
- X * If we're piped out to something else, then just act like a cat(1)
- X * function.
- X */
- X
- X if ( !isatty( fileno( stdout ) ) )
- X cat( f );
- X else {
- X
- X int n;
- X char *buffer = ( char *) malloc( sizeof( char ) * buffsize );
- X int current;
- X int newline = TRUE;
- X int wasWrap = FALSE;
- X
- X pmax = 0;
- X n = 0;
- X while ( fgetbuffer( buffer, buffsize, f ) ) {
- X
- X int ll = strlen( buffer );
- X
- X /*
- X * If the line is long, then wrap it around and adjust our
- X * buffer appropriately.
- X */
- X
- X wasWrap = !newline;
- X if ( newline = ( buffer[ll - 1] == '\n' ) )
- X buffer[--ll] = '\0';
- X
- X if ( ll || ( !wasWrap && !ll ) ) {
- X
- X current = n % maxlines;
- X
- X if ( ring[current] )
- X free( ring[current] );
- X ring[current] = strdup( buffer );
- X
- X if ( !( ++n % pagelines ) && ( bail = view( current, fn ) ) )
- X break;
- X
- X }
- X
- X }
- X if ( ( n % pagelines ) && !bail )
- X view( current, fn );
- X
- X dropRing();
- X
- X }
- X fclose( f );
- X
- X return;
- X
- X}
- X
- XdropRing()
- X
- X{
- X
- X int i;
- X
- X for ( i = 0; i < maxlines; i++ )
- X if ( ring[i] ) {
- X
- X free( ring[i] );
- X ring[i] = ( char *) NULL;
- X
- X }
- X
- X return;
- X
- X}
- X
- Xint view( lastLine, fn )
- X
- X int lastLine;
- X char *fn;
- X
- X{
- X
- X int bottomLine = lastLine;
- X int amount;
- X int topLine;
- X int l;
- X union REGS regs;
- X int pcount;
- X int doSomething = TRUE;
- X
- X if ( pmax < PAGES )
- X pmax++;
- X pcount = pmax;
- X
- X while ( TRUE ) {
- X
- X if ( doSomething ) {
- X
- X amount = bottomLine % pagelines;
- X if ( !amount )
- X amount = pagelines;
- X topLine = bottomLine - amount;
- X if ( topLine < 0 )
- X topLine = 0;
- X
- X for ( l = topLine; l <= bottomLine; l++ )
- X printf( "%s\n", ring[l] );
- X
- X printf( "[more] %s:", fn );
- X fflush( stdout );
- X
- X } else
- X doSomething = TRUE;
- X
- X regs.h.ah = 0x00;
- X int86( 0x16, ®s, ®s ); /* Read directly from keyboard */
- X switch ( regs.h.al ) {
- X
- X case 'q':
- X case 'Q':
- X case 0x03: {
- X
- X printf( "\r\t\t\t\t\t\t\r" );
- X exit( 0 );
- X
- X }
- X case 'x':
- X case 'X': {
- X
- X printf( "\r\t\t\t\t\t\t\r" );
- X return( BAIL );
- X
- X }
- X case 'p':
- X case 'P': {
- X
- X if ( --pcount ) {
- X
- X bottomLine = topLine - 1;
- X if ( bottomLine < 0 )
- X bottomLine = maxlines - 1;
- X printf( "\r\t\t\t\t\t\t\r" );
- X
- X } else {
- X
- X printf( "\rCan't scroll back further\t\t\t\r" );
- X fflush( stdout );
- X pcount = 1;
- X doSomething = FALSE;
- X
- X }
- X break;
- X
- X }
- X case '\r':
- X case ' ':
- X case 'n':
- X case 'N': {
- X
- X printf( "\r\t\t\t\t\t\t\r" );
- X if ( ++pcount < pmax ) {
- X
- X bottomLine += pagelines;
- X bottomLine %= maxlines;
- X
- X } else if ( pcount == pmax )
- X bottomLine = lastLine;
- X else
- X return( !BAIL );
- X
- X break;
- X
- X }
- X default: {
- X
- X doSomething = FALSE;
- X break;
- X
- X }
- X
- X }
- X
- X }
- X
- X}
- X
- Xcat( f )
- X
- X FILE *f;
- X
- X{
- X
- X int ch;
- X
- X while ( ( ch = fgetc( f ) ) != EOF )
- X putchar( ch );
- X
- X return;
- X
- X}
- X
- Xchar *fgetbuffer( buffer, buflen, f )
- X
- X char *buffer;
- X int buflen;
- X FILE *f;
- X
- X{
- X
- X static int tab = 0;
- X char *b = buffer;
- X static int eoffed = FALSE;
- X
- X if ( eoffed )
- X return( ( char *) NULL );
- X
- X while ( b < buffer + buflen - 1 ) {
- X
- X if ( tab ) {
- X
- X *b++ = ' ';
- X tab--;
- X
- X } else {
- X
- X int ch;
- X
- X switch ( ch = fgetc( f ) ) {
- X
- X case '\n': {
- X
- X *b++ = ch;
- X *b = '\0';
- X return( buffer );
- X
- X }
- X case '\t': {
- X
- X *b = '\0';
- X tab = 8 - ( strlen( buffer ) % 8 );
- X break;
- X
- X }
- X case EOF: {
- X
- X eoffed = TRUE;
- X *b = '\0';
- X return( buffer );
- X
- X }
- X default: {
- X
- X *b++ = ch;
- X break;
- X
- X }
- X
- X }
- X
- X }
- X
- X }
- X
- X *b = '\0';
- X
- X return( buffer );
- X
- X}
- X
- Xabend( va_alist )
- X
- X va_dcl
- X
- X{
- X
- X va_list ap;
- X char *fmt;
- X#if defined( MSDOS )
- X char *parseMe();
- X
- X me = parseMe( me );
- X#endif
- X fprintf( stderr, "%s: ", me );
- X va_start( ap );
- X fmt = va_arg( ap, char *);
- X vfprintf( stderr, fmt, ap );
- X fprintf( stderr, "\n" );
- X va_end( ap );
- X
- X if ( fatal ) {
- X
- X#if !defined( MSDOS )
- X fprintf( stderr,
- X "We're gonna dump core here, just in case we need it.\n" );
- X#endif
- X ( void ) abort();
- X
- X } else
- X exit( 1 );
- X
- X }
- X
- Xusage( va_alist )
- X
- X va_dcl
- X
- X{
- X
- X va_list ap;
- X char *fmt;
- X extern char *me;
- X#if defined( MSDOS )
- X char *parseMe();
- X
- X me = parseMe( me );
- X#endif
- X fprintf( stderr, "Usage: %s ", me );
- X va_start( ap );
- X fmt = va_arg( ap, char *);
- X vfprintf( stderr, fmt, ap );
- X fprintf( stderr, "\n" );
- X va_end( ap );
- X
- X exit( 1 );
- X
- X}
- X
- X#if defined( MSDOS )
- Xchar *parseMe( me )
- X
- X char *me;
- X
- X{
- X
- X char drive[_MAX_DRIVE];
- X char path[_MAX_PATH];
- X static char fname[_MAX_FNAME];
- X char ext[_MAX_EXT];
- X char *f = fname;
- X
- X _splitpath( me, drive, path, fname, ext );
- X while ( *f ) {
- X
- X if ( isupper( *f ) )
- X *f = tolower( *f );
- X ++f;
- X
- X }
- X
- X return( &fname[0] );
- X
- X}
- X#endif
- SHAR_EOF
- chmod 0644 more.c || echo "restore of more.c fails"
- exit 0
- --
- Steve Lamont, SciViGuy -- (408) 646-2752 -- a guest at network.ucsd.edu --
- NPS Confuser Center / Code 51 / Naval Postgraduate School / Monterey, CA 93943
- I have discovered a truly marvelous demonstration which this .signature is too
- small to contain...
-