home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3574 < prev    next >
Internet Message Format  |  1991-07-02  |  11KB

  1. From: slamont@network.ucsd.edu (Steve Lamont)
  2. Newsgroups: alt.sources
  3. Subject: Replacement MORE for MeSs-DOS
  4. Message-ID: <5542@network.ucsd.edu>
  5. Date: 2 Jul 91 16:27:51 GMT
  6.  
  7. Here is a replacement for the MeSs-DOS parody of MORE that understands input
  8. from either standard input or as a list of files from the command line.  
  9.  
  10. It is intended as a better MS-DOS MORE and not as an accurate mimic of the
  11. Un*x more(1) command, so there are features missing, such as regular expression
  12. searching, and so forth.
  13.  
  14. I hereby bequeath this monstrosity to the public domain.  Share and enjoy.
  15.  
  16.                             spl (the p stands for
  17.                             parody of a parody)
  18. ------------------------ gnaw on dotted line and feed to sh ------------------
  19. #!/bin/sh
  20. # shar:    Shell Archiver  (v1.22)
  21. #
  22. #    Run the following text with /bin/sh to create:
  23. #      makefile
  24. #      more.c
  25. #
  26. sed 's/^X//' << 'SHAR_EOF' > makefile &&
  27. X#
  28. X#  In case it isn't painfully obvious, this is a makefile for use with
  29. X#  the bizarre parody of MAKE that comes with Microsoft C.  If you use
  30. X#  something other than MSC, then you'll probably have to come up with
  31. X#  your own.
  32. X#
  33. X
  34. XCC = cl
  35. XOPT = -Ox
  36. X#DEBUG = -Zi
  37. XCFLAGS = $(OPT) $(DEBUG)
  38. X
  39. X#
  40. X#  We include \lib\setargv.obj here to replace the default setargv,
  41. X#  which has insufficient brains to expand the rather simple globbing
  42. X#  that MeSs-DOS inflicts -- er -- I mean, provides.  The /noe option
  43. X#  suppresses LINK's complaints about duplicate object modules.
  44. X#
  45. X
  46. XLFLAGS = \lib\setargv.obj -link /noe
  47. Xmore.obj:    more.c makefile
  48. X       $(CC) $(CFLAGS) more.c -c
  49. Xmore.exe:    more.obj
  50. X       $(CC) $(CFLAGS) more.obj -o more.exe $(LFLAGS)
  51. SHAR_EOF
  52. chmod 0644 makefile || echo "restore of makefile fails"
  53. sed 's/^X//' << 'SHAR_EOF' > more.c &&
  54. X#include <stdio.h>
  55. X#include <stdlib.h>
  56. X#include <string.h>
  57. X#include <varargs.h>
  58. X#include <ctype.h>
  59. X/*
  60. X *  MSC specific includes.
  61. X */
  62. X
  63. X#include <graph.h>
  64. X#include <dos.h>
  65. X/*
  66. X *  More:  a replacement pager for MeSs-DOS.
  67. X *
  68. X *  Copyright relinquished and placed in the public domain by Steve Lamont,
  69. X *  July 2, 1991, at the Naval Postgraduate School, Monterey, CA 93943.
  70. X *  Use at your own risk.
  71. X *
  72. X *  This program will read from either standard input or from a file or
  73. X *  files specified on the command line.  While it sort of acts like Un*x
  74. X *  more(1) it is not intended to be a complete or accurate emulation.
  75. X *
  76. X *  I guess, in reality, upon reviewing the code, it is kind of a hack,
  77. X *  written while in bed with a Zenith laptop on my stomach.  Really!
  78. X *
  79. X *  This more supports a limited collection of paging options at the prompt:
  80. X *
  81. X *  Pressing the space bar, the enter key, and the 'N' or 'n' keys all page
  82. X *  forward one screen.
  83. X *
  84. X *  Pressing the 'p' or 'P' key will cause more to page backward one page.
  85. X *
  86. X *  Pressing 'x' or 'X' will cause the pager to quit paging the current file
  87. X *  and if there is another specified on the command line, the next file will
  88. X *  then be displayed.
  89. X *
  90. X *  'Q', 'q', or Ctrl-C all terminate paging immediately.
  91. X *
  92. X *  This code is designed to compile under Microsoft C 5.1 (or, probably,
  93. X *  later) and has a couple of MSC dependencies in it.
  94. X *
  95. X *  MSC library functions used:
  96. X *
  97. X *      _getvideoconfig() - fetches the monitor adaptor width and height,
  98. X *                          among other things.
  99. X *
  100. X *      int86()           - calls a BIOS function via the interrupt vector.
  101. X *                          In this case, it reads directly from the keyboard.
  102. X *
  103. X *  If ported to another compiler, these dependencies will obviously have
  104. X *  to be corrected.
  105. X */
  106. X#if !defined( TRUE )
  107. X#define TRUE ( 1 == 1 )
  108. X#define FALSE ( 1 == 0 )
  109. X#endif
  110. Xchar *me = "?";
  111. Xint fatal = FALSE;
  112. X/*
  113. X *  Page dimensions, etc.
  114. X */
  115. X#define PAGES ( 5 )
  116. Xint pagelines;
  117. Xint buffsize;
  118. Xint maxlines;
  119. X#define BAIL ( TRUE )
  120. X/*
  121. X *  Page buffers.
  122. X */
  123. Xchar **ring;
  124. Xint pmax;
  125. Xchar *fgetbuffer();
  126. Xmain( argc, argv )
  127. X    int argc;
  128. X    char **argv;
  129. X{
  130. X    int i;
  131. X    FILE *f;
  132. X    extern char *me;
  133. X    me = argv[0];
  134. X    setup();
  135. X    /*
  136. X     *  Work our way through files specified on the command line.
  137. X     */
  138. X    for ( i = 1; i < argc; i++ )
  139. X    if ( f = fopen( argv[i], "r" ) )
  140. X        process( f, argv[i] );
  141. X    else
  142. X        abend( "%s %s", sys_errlist[errno], argv[i] );
  143. X    /*
  144. X     *  If there is input from stdin from a file, page it.  If there is
  145. X     *  neither a file specified via stdin or any command line arguments,
  146. X     *  print a usage message.
  147. X     */
  148. X    if ( !isatty( fileno( stdin ) ) )
  149. X    process( stdin, "stdin" );
  150. X    else if ( argc == 1 )
  151. X    usage( "[files]" );
  152. X    exit( 0 );
  153. X}
  154. X/*
  155. X *  Fish up the video configuration.
  156. X *
  157. X *  Herein lies an MSC dependency.
  158. X */
  159. Xsetup()
  160. X{
  161. X    struct videoconfig config;
  162. X    _getvideoconfig( &config );
  163. X    /*
  164. X     *  Allow for the prompt.
  165. X     */
  166. X    pagelines = config.numtextrows - 1;
  167. X    buffsize = config.numtextcols;
  168. X    maxlines = pagelines * PAGES;
  169. X    /*
  170. X     *  Allocate the page buffers.
  171. X     */
  172. X    ring = ( char **) malloc( sizeof( char *) * maxlines );
  173. X    if ( !ring )
  174. X    abend( "Whoops!  Out of memory!" );
  175. X    return;
  176. X}
  177. XclearRing()
  178. X{
  179. X    int n;
  180. X    for ( n = 0; n < maxlines; n++ )
  181. X    ring[n] = ( char *) NULL;
  182. X    return;
  183. X}
  184. Xprocess( f, fn )
  185. X    FILE *f;
  186. X    char *fn;
  187. X{
  188. X    int current = 0;
  189. X    int bail = FALSE;
  190. X    clearRing();
  191. X    /*
  192. X     *  If we're piped out to something else, then just act like a cat(1)
  193. X     *  function.
  194. X     */
  195. X    if ( !isatty( fileno( stdout ) ) )
  196. X    cat( f );
  197. X    else {
  198. X    int n;
  199. X    char *buffer = ( char *) malloc( sizeof( char ) * buffsize );
  200. X    int current;
  201. X    int newline = TRUE;
  202. X    int wasWrap = FALSE;
  203. X    pmax = 0;
  204. X    n = 0;
  205. X    while ( fgetbuffer( buffer, buffsize, f ) ) {
  206. X        int ll = strlen( buffer );
  207. X        /*
  208. X         *  If the line is long, then wrap it around and adjust our
  209. X         *  buffer appropriately.
  210. X         */
  211. X        wasWrap = !newline;
  212. X        if ( newline = ( buffer[ll - 1] == '\n' ) )
  213. X        buffer[--ll] = '\0';
  214. X        if ( ll || ( !wasWrap && !ll ) ) {
  215. X        current = n % maxlines;
  216. X        if ( ring[current] )
  217. X            free( ring[current] );
  218. X        ring[current] = strdup( buffer );
  219. X        if ( !( ++n % pagelines ) && ( bail = view( current, fn ) ) )
  220. X            break;
  221. X        }
  222. X    }
  223. X    if ( ( n % pagelines ) && !bail )
  224. X        view( current, fn );
  225. X    dropRing();
  226. X    }
  227. X    fclose( f );
  228. X    return;
  229. X}
  230. XdropRing()
  231. X{
  232. X    int i;
  233. X    for ( i = 0; i < maxlines; i++ )
  234. X    if ( ring[i] ) {
  235. X        free( ring[i] );
  236. X        ring[i] = ( char *) NULL;
  237. X    }
  238. X    return;
  239. X}
  240. Xint view( lastLine, fn )
  241. X    int lastLine;
  242. X    char *fn;
  243. X{
  244. X    int bottomLine = lastLine;
  245. X    int amount;
  246. X    int topLine;
  247. X    int l;
  248. X    union REGS regs;
  249. X    int pcount;
  250. X    int doSomething = TRUE;
  251. X    if ( pmax < PAGES )
  252. X    pmax++;
  253. X    pcount = pmax;
  254. X    while ( TRUE ) {
  255. X    if ( doSomething ) {
  256. X        amount = bottomLine % pagelines;
  257. X        if ( !amount )
  258. X        amount = pagelines;
  259. X        topLine = bottomLine - amount;
  260. X        if ( topLine < 0 )
  261. X        topLine = 0;
  262. X        for ( l = topLine; l <= bottomLine; l++ )
  263. X        printf( "%s\n", ring[l] );
  264. X        printf( "[more] %s:", fn );
  265. X        fflush( stdout );
  266. X    } else
  267. X        doSomething = TRUE;
  268. X    regs.h.ah = 0x00;
  269. X    int86( 0x16, ®s, ®s );    /* Read directly from keyboard    */
  270. X    switch ( regs.h.al ) {
  271. X        case 'q':
  272. X        case 'Q':
  273. X        case 0x03: {
  274. X        printf( "\r\t\t\t\t\t\t\r" );
  275. X        exit( 0 );
  276. X        }
  277. X        case 'x':
  278. X        case 'X': {
  279. X        printf( "\r\t\t\t\t\t\t\r" );
  280. X        return( BAIL );
  281. X        }
  282. X        case 'p':
  283. X        case 'P': {
  284. X        if ( --pcount ) {
  285. X            bottomLine = topLine - 1;
  286. X            if ( bottomLine < 0 )
  287. X            bottomLine = maxlines - 1;
  288. X            printf( "\r\t\t\t\t\t\t\r" );
  289. X        } else {
  290. X            printf( "\rCan't scroll back further\t\t\t\r" );
  291. X            fflush( stdout );
  292. X            pcount = 1;
  293. X            doSomething = FALSE;
  294. X        }
  295. X        break;
  296. X        }
  297. X        case '\r':
  298. X        case ' ':
  299. X        case 'n':
  300. X        case 'N': {
  301. X        printf( "\r\t\t\t\t\t\t\r" );
  302. X        if ( ++pcount < pmax ) {
  303. X            bottomLine += pagelines;
  304. X            bottomLine %= maxlines;
  305. X        } else if ( pcount == pmax )
  306. X            bottomLine = lastLine;
  307. X        else
  308. X            return( !BAIL );
  309. X        break;
  310. X        }
  311. X        default: {
  312. X        doSomething = FALSE;
  313. X        break;
  314. X        }
  315. X    }
  316. X    }
  317. X}
  318. Xcat( f )
  319. X    FILE *f;
  320. X{
  321. X    int ch;
  322. X    while ( ( ch = fgetc( f ) ) != EOF )
  323. X    putchar( ch );
  324. X    return;
  325. X}
  326. Xchar *fgetbuffer( buffer, buflen, f )
  327. X    char *buffer;
  328. X    int buflen;
  329. X    FILE *f;
  330. X{
  331. X    static int tab = 0;
  332. X    char *b = buffer;
  333. X    static int eoffed = FALSE;
  334. X    if ( eoffed )
  335. X    return( ( char *) NULL );
  336. X    while ( b < buffer + buflen - 1 ) {
  337. X    if ( tab ) {
  338. X        *b++ = ' ';
  339. X        tab--;
  340. X    } else {
  341. X        int ch;
  342. X        switch ( ch = fgetc( f ) ) {
  343. X        case '\n': {
  344. X            *b++ = ch;
  345. X            *b = '\0';
  346. X            return( buffer );
  347. X        }
  348. X        case '\t': {
  349. X            *b = '\0';
  350. X            tab = 8 - ( strlen( buffer ) % 8 );
  351. X            break;
  352. X        }
  353. X        case EOF: {
  354. X            eoffed = TRUE;
  355. X            *b = '\0';
  356. X            return( buffer );
  357. X        }
  358. X        default: {
  359. X            *b++ = ch;
  360. X            break;
  361. X        }
  362. X        }
  363. X    }
  364. X    }
  365. X    *b = '\0';
  366. X    return( buffer );
  367. X}
  368. Xabend( va_alist )
  369. X    va_dcl
  370. X{
  371. X    va_list ap;
  372. X    char *fmt;
  373. X#if defined( MSDOS )
  374. X    char *parseMe();
  375. X    me = parseMe( me );
  376. X#endif
  377. X    fprintf( stderr, "%s: ", me );
  378. X    va_start( ap );
  379. X    fmt = va_arg( ap, char *);
  380. X    vfprintf( stderr, fmt, ap );
  381. X    fprintf( stderr, "\n" );
  382. X    va_end( ap );
  383. X    if ( fatal ) {
  384. X#if !defined( MSDOS )
  385. X        fprintf( stderr,
  386. X                "We're gonna dump core here, just in case we need it.\n" );
  387. X#endif
  388. X        ( void ) abort();
  389. X    } else
  390. X        exit( 1 );
  391. X  }
  392. Xusage( va_alist )
  393. X    va_dcl
  394. X{
  395. X    va_list ap;
  396. X    char *fmt;
  397. X    extern char *me;
  398. X#if defined( MSDOS )
  399. X    char *parseMe();
  400. X    me = parseMe( me );
  401. X#endif
  402. X    fprintf( stderr, "Usage: %s ", me );
  403. X    va_start( ap );
  404. X    fmt = va_arg( ap, char *);
  405. X    vfprintf( stderr, fmt, ap );
  406. X    fprintf( stderr, "\n" );
  407. X    va_end( ap );
  408. X    exit( 1 );
  409. X}
  410. X#if defined( MSDOS )
  411. Xchar *parseMe( me )
  412. X    char *me;
  413. X{
  414. X    char drive[_MAX_DRIVE];
  415. X    char path[_MAX_PATH];
  416. X    static char fname[_MAX_FNAME];
  417. X    char ext[_MAX_EXT];
  418. X    char *f = fname;
  419. X    _splitpath( me, drive, path, fname, ext );
  420. X    while ( *f ) {
  421. X        if ( isupper( *f ) )
  422. X            *f = tolower( *f );
  423. X        ++f;
  424. X    }
  425. X    return( &fname[0] );
  426. X}
  427. X#endif
  428. SHAR_EOF
  429. chmod 0644 more.c || echo "restore of more.c fails"
  430. exit 0
  431. -- 
  432. Steve Lamont, SciViGuy -- (408) 646-2752 -- a guest at network.ucsd.edu --
  433. NPS Confuser Center / Code 51 / Naval Postgraduate School / Monterey, CA 93943
  434. I have discovered a truly marvelous demonstration which this .signature is too
  435. small to contain...
  436.