[alt.sources] SEE: a program to view wide files.

andrew@tvcent.uucp (Andrew Cowie) (12/20/89)

This is SEE, a program I was asked to write in order to view oversized
files in two dimentions. Several people found it very useful and asked me
to post. More information from the 'I' command.

--
Andrew F. Cowie at TVC Enterprises, Toronto, Canada.
uunet!mnetor!lethe!tvcent!andrew  andrew@tvcent.uucp


#! /bin/sh
# This is a shell archive, meaning:
#   1. Remove anything before this line.
#   2. Save it.
#   3. Execute it with /bin/sh. (not csh)
# If this archive is complete, you will see the following at the end:
#		"End of shell archive."
# Contents:  see.c Makefile
# Wrapped by andrew@tvcent on Tue Dec 19 20:48:20 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f see.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"see.c\"
else
echo shar: Extracting \"see.c\" \(7900 characters\)
sed "s/^X//" >see.c <<'END_OF_see.c'
X/*
X * see.c -- view wide files with left/right scrolling (don't wrap)
X *
X * Written by
X *    Andrew F.Cowie,     88/08/31  <andrew@tvcent.uucp>
X * with the help of
X *    Drew Sullivan, 89/Jan/06 <drew@lethe.uucp>
X *
X * This program is in the public domain, do what you want with it,
X * but please tell me about it. (see I information)
X */
X
X/*
X * M_MSDOS and M_MACintosh imply nothing. However, this code works around here,
X * and it has been tested on some of the machines at the University of Waterloo
X * running BSD 4.2, so I hope that it will work wherever you are.
X */
X
X#define VERSION "1.1"
X
X/* I hope to make it handle larger files in the future */
X
X#ifndef MAXLINES
X#define MAXLINES 1000
X#endif
X
X#ifndef MAXCOLS
X#define MAXCOLS 400
X#endif
X
X#include <curses.h>	/* for curses... */
X#include <stdio.h>	/* for FILE... */
X#if M_MSDOS
X#include <stdlib.h>	/* for exit */
X#endif
X#include <string.h>	/* for strdup... */
X#include <ctype.h>	/* for isascii */
X#include <stdlib.h>	/* for calloc, free */
X#include <signal.h>	/* ^C handling */
X
X#ifdef M_MAC
X#include "getarg.h"
X#endif
X
X/* function declarations */
X
X/* if you compiler gives you trouble about the prototypes, change to a 0 */
X#define PROTO	1
X#if PROTO
X#define	P(x)	x
X#else
X#define P(x)	
X#endif
X
Xextern	void	loads	P((void));
Xextern	void	docmd	P((int));
Xextern	void	print	P((void));
Xextern	void	display	P((int, int));
Xextern	int	main	P((int, char **));
Xextern	void	usage	P((void));
Xextern	void	help	P((void));
Xextern	void	done	P((void));
Xextern	char *	strdup	P((char *));
Xextern	void	signon	P((void));
Xextern	void	information	P((void));
X
Xextern int optind;	/* for getopt */
X
X/* global variables */
X
Xchar	*Progname;
Xchar	**Lines;
Xchar	**Files;
Xint	NumLines;
Xint	CurLine;		/* current top line in file */
Xint	CurOff;			/* current left column in file */
Xint	JumpLines = 24;		/* number lines to move by */
Xint	JumpCols = 80;		/* number cols to move by */ 
Xint	LineCols = 0;		/* display line columns */
Xint	LineEnds = 0;		/* display '~' at end of lines */
X
X#define control(c)	((c)-'@')
X#define EOS		'\0'
X
Xint main(argc, argv) int argc; char *argv[]; {
X	int	c;
X
X	CurLine = CurOff = 0;
X	Progname = argv[0];
X#ifdef M_MAC
X	if (argc <= 1) {
X		usage();
X		argv = av_getargs();
X		argc = av_argcnt(argv);
X	}
X#endif
X	while ((c=getopt(argc, argv, "c")) != EOF) switch (c) {
X	case 'c':
X		LineCols = !LineCols;
X		break;
X	default:
X		usage();
X		return 1;
X	}
X
X	Files = argv + optind;
X	Files[-1] = NULL;
X	if (*Files == NULL) {
X		fprintf(stderr, "%s: No files specified\n", Progname);
X		usage();
X		return 2;
X	}
X
X	signal(SIGHUP, done);
X	signal(SIGINT, done);
X   	
X   	if (initscr() == NULL) {
X   		fprintf(stderr, "Can't initilise curses\n");
X		exit(1);
X	}
X
X	crmode();
X	noecho();
X
X	loads();
X
X	for (;;) {
X		move(LINES-1, 0);
X		printw("%s%s%s [%d:%d] Command (? for help): ",
X			Files[-1] ? "-- " : "",
X			*Files,
X			Files[1] ? " ++" : "",
X			CurLine+1, CurOff+1);
X		clrtoeol();
X		refresh();
X		docmd(getch());
X	}
X	endwin();
X	return (0);
X}
X
Xvoid done() {
X	endwin();
X	exit(0);
X}
X
X
Xvoid loads() {
X	char	*p, buf[MAXCOLS];
X	int	i = 0;
X	FILE *fp;
X
X	clear();
X
X	if (Lines == NULL) {
X		Lines = (char **)calloc(MAXLINES, sizeof(char *));
X	} else {
X		for (i=0 ; i < NumLines; ++i) {
X			if (Lines[i]) free(Lines[i]);
X			Lines[i] = NULL;
X		}
X	}
X	if ((fp=fopen(*Files, "r")) == NULL) {
X		Lines[1] = strdup("Can't open file");
X		Lines[2] = strdup(*Files);
X		NumLines = 3;
X		print();
X		return;
X	}
X
X	for (i = 0; fgets(buf,MAXCOLS,fp); ++i) {
X		if ((p=strchr(buf, '\n')) != NULL) {
X			*p = EOS;
X		} else {
X			strcat(buf,"");	/* cause strcat to append a \0 */
X		}
X
X/*
X * Version 2 (hopefully) will contain an ability to go beyond MAXLINES
X */
X		if (i == MAXLINES) {
X			move(LINES-1,0);
X			printw("%s: Warning: file too long, only partially (first %d lines) loaded...\n",Progname,MAXLINES);
X			refresh();
X			getch();
X			break;
X		}
X		if ((Lines[i] = strdup(buf)) == NULL) {
X			break;
X		}
X	}
X	NumLines = i;
X	fclose(fp);
X	print();
X}
X
X
Xvoid signon() {
X	printw("See Version %s by Andrew Cowie with Drew Sullivan.--", VERSION);
X}
X
Xvoid print() {
X	int	h = 0;
X	int	x;
X
X	if (LineCols) {
X		move(0, 0);
X		x = CurOff;
X		for (h=0; h < COLS; ++h) {
X			switch(++x % 10) {
X			case 0:  addch((x / 10) % 10 + '0'); break;
X			case 5:  addch('+'); break;
X			default: addch('-'); break;
X			}
X		}
X		h = 1;
X	}
X	for (x = CurLine; x < NumLines && h < LINES-1; ) {
X		display(x, h);
X		clrtoeol();
X		++x;
X		++h;
X	}
X	clrtobot();
X}
X
Xvoid docmd(c) int c; {
X	switch(c) {
X	case '?':
X		help();
X		break;
X
X	case 'q':
X	case 'Q':
X		endwin();
X		printf("\n");
X		exit(0);
X
X	case 'N':
X		if (Files[1]) ++Files;
X		loads();
X		return;
X
X	case 'P':
X		if (Files[-1]) --Files;
X		loads();
X		return;
X
X	case 'h':
X		CurOff--;
X		if (CurOff <= 0) CurOff = 0;
X		break;
X	case '<':
X		CurOff -= 10;
X		if (CurOff <= 0) CurOff = 0;
X		break;
X
X	case 'H':
X	case 'b':
X		CurOff -= JumpCols;
X		if (CurOff <= 0) CurOff = 0;
X		break;
X
X	case 'j':
X		if (CurLine >= NumLines-1) return;
X		CurLine++;
X		break;
X
X	case 'J':
X	case ' ':
X	case 'd':
X		CurLine += JumpLines;
X		if (CurLine >= NumLines) CurLine = NumLines-1;
X		break;
X
X	case 'p':
X		CurLine = CurOff = 0;
X		break;
X
X	case 'k':
X		if (CurLine <= 0) return;
X		CurLine--;
X		break;
X
X	case 'K':
X	case 'u':
X		CurLine -= JumpLines;
X		if (CurLine < 0) CurLine = 0;
X		break;
X
X	case 'l':
X		CurOff++;
X		break;
X	case '>':
X		CurOff += 10;
X		break;
X	case 'L':
X	case 'w':
X		CurOff += JumpCols;
X		break;
X
X	case '+':
X		LineEnds = !LineEnds;
X		break;
X	case '-':
X		LineCols = !LineCols;
X		break;
X
X	case control('L'):
X		clear();
X		break;
X
X	case 'v':
X		move(LINES-1, 0);
X		clrtoeol();
X		signon();
X		refresh();
X		getch();
X		break;
X
X	case 'I':
X		information();
X		break;
X
X	default:
X#ifndef M_BSD
X		beep();
X#endif
X		return;
X
X	}
X	print();
X}
X
Xvoid display(x, h) int x,h; {
X	char	*p,*s;
X	static	char	buf[MAXCOLS+2];		/* saftey */
X
X	move(h, 0);
X	clrtoeol();
X
X	if (Lines[x] == NULL) {
X		return;
X	}
X
X	p = Lines[x];
X	s = buf;
X
X	for (;*p; ++p) {
X		if (!isascii(*p)) {
X			*s++ = *p;
X			continue;
X		}
X		if (isprint(*p)) {
X			*s++ = *p;
X			continue;
X		}
X
X		if (*p == '\t') {
X			int	blanks;
X
X			blanks = 8 - ((s - buf) & 0x7);
X			while (blanks--) {
X				*s++ = ' ';
X			}
X			continue;
X		}
X		*s++ = '^';
X		*s++ = *p+'@';
X	}
X	if (LineEnds) {
X		*s++ = '^';
X		*s++ = 'J';
X	}
X	*s = EOS;
X 	if (CurOff > strlen(buf)) return;
X	printw("%.*s", COLS-1, buf+CurOff);
X}
X
Xvoid help() {
X	clear();
X	printw("Movement:\n\th\tmove one column left\n");
X	printw("\tj\tmove one line down\n\tk\tmove one line up\n"); 
X	printw("\tl\tmove one column right\n");
X
X	printw("\n\t<>\tjump 10 columns left/right\n");
X	printw("\tb\tjump %d columns left\n", JumpCols);
X	printw("\td\tjump %d lines down\n", JumpLines);
X	printw("\tu\tjump %d lines up\n",JumpLines);
X	printw("\tw\tjump %d columns right (forWards)\n", JumpCols);
X	printw("\tp\ttop of file\n");
X
X	printw("\nOther:\n");
X	printw("\t-\ttoggle column bar\n\t+\ttoggle end of lines\n");
X	printw("\tv\tversion\n\tI\tinformation\n\t^L\trefresh screen\n");
X	printw("\tq\tquit\n\tN\tnext file\n\tP\tprevious file\n");
X	refresh();
X	getch();
X	clear();
X}
X
Xvoid information() {
X	clear();
X	signon();
X	printw("\n\n\tSee was writen in response to the need for a program that could\n");
X	printw("view an printer ouput file that was more than 80 columns wide in two\n");
X	printw("directions without word wrap. This program is in the Public Domain, so\n");
X 	printw("do what you want with it, but please send me a copy of your changes,\n");
X	printw("or bug fixes. Also, any ideas for improvement would be welcome.\n");
X	printw("\n\tThank you.\n");
X
X	printw("\nReply to (uucp):\n");
X	printw("\nAndrew Cowie:\t...!uunet!mnetor!lethe!tvcent!andrew or andrew@tvcent.uucp\n");
X	refresh();
X	getch();
X	clear();
X}
X
Xvoid usage() {
X	fprintf(stderr, "Usage: %s [-c] filenames...\n",Progname);
X	fprintf(stderr, "Options:\n");
X	fprintf(stderr, "  -c   Display columns indicator at the top\n");
X	fprintf(stderr, "When running, type '?' to get help\n");
X}
END_OF_see.c
if test 7900 -ne `wc -c <see.c`; then
    echo shar: \"see.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(376 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
X#
X# Makefile for see - XENIX
X#
X
XCFLAGS= -O -DM_TERMINFO -DM_XENIX
X#CFLAGS= $(CFLAGS) -DMAXCOLS=400 -DMAXLINES=1000
X
Xinstall:
X	cp see /usr/local/bin/see
X
Xsee: see.o
X	cc -o see see.o -ltinfo -lx
X
Xsee.o: see.c
X	cc $(CFLAGS) -c see.c
X
Xshar:
X	shar see.c Makefile >see.sh
X
X#
X#The following was used on a BSD 4.2 system.
X#
X#see: see.c
X#	gcc see.c -DM_BSD -lcurses -ltermcap -o see 
X
END_OF_Makefile
if test 376 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0