[comp.sources.misc] v02i006: Side-by-side file paginator

nelson@MCNC.ORG (jim nelson) (01/15/88)

Comp.Sources.Misc: Volume 2, Issue 6

Submitted-By: jim nelson <nelson%mcnc.org@ecsvax.UUCP>

Archive-Name: sbs


Comp.Sources.Misc: Volume 2, Issue 6
Submitted-By: jim nelson <nelson%mcnc.org@ecsvax.UUCP>
Archive-Name: sbs

[Whatever happened to "pr -m -w80 file1 file2 | more"?  ++bsa]

This is a little thingie I (thought) I had to write myself, because
it warnt available.  Presumably I re-invented some wheel; but I
like it.  Pub Dom.  Take it.  If it belongs in comp.sources.misc,
I'll send it over there... it's short.
#  --- cut here ---
#/bin/sh
#This is a shar file.  To use:
#  1. Remove everything before the /bin/sh line
#  2. Execute with /bin/sh (not csh) to extract the files:
#         Makefile
#         sbs.c
file="${0}"
echo extracting Makefile 1>&2
sed -e 's/^X//'  >Makefile << 'EnD of Makefile'
XCFLAGS=
XLDFLAGS=-lcurses #-ltermlib
Xsbs: sbs.o
X	cc sbs.o -o sbs $(LDFLAGS)
EnD of Makefile
echo extracting sbs.c 1>&2
sed -e 's/^X//'  >sbs.c << 'EnD of sbs.c'
X/*puts two files side-by-side on terminal */
X/*for poor folks who don't have windows and suns and all that
Xother stuff*/
X/*no man page: it's not worth it; but i did make a Makefile
Xof sorts*/
X/*this compiles and works perfectly with no alterations on both
XSysVr2(3b2/300) and BSD4.1-derived-GENIX on a nsc16032(lmc)*/
X/*other systems at own risk ...*/
X/*'taint so hot at 1200 baud, but presumably i'm the only
Xperson on earth who still has to put up with measly 1200 baud*/
X/*no copyright, public domain, not worth the effort*/
X/*author: jim nelson, unc-wilmington, wilmington nc 28403;
X919-395-3300*/
X#include <curses.h>
X#define UNIX
X#include <stdio.h>
X#define MAXLINE 82
X#ifdef UNIX
X#include <ctype.h>
X#endif
X/*global variables: */
Xchar left[20][MAXLINE],rite[20][MAXLINE],lft[MAXLINE],rte[MAXLINE];
Xint efl,efr;
Xchar leader[MAXLINE];
Xchar *fnl,*fnr;
X/*end of global variables */
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X
X{
X	FILE *fp1,*fp2;
X	int jhn,prefix,zork,c,i,k,lp,rp;
X	efl=efr=0;
X	fnl=argv[1]; 
X	fnr=argv[2];
X
X	if(argc!=3){
X		printf("usage: sbs file1 file2\n"); 
X		exit (1); 
X	}
X
X
X	if(  (fp2=fopen(argv[2],"r"))  == NULL)
X	{
X		printf("not found:%s\n",argv[2]);
X		exit (1);
X	}
X
X	if(  (fp1=fopen(argv[1],"r"))  == NULL)
X	{
X		printf("not found:%s\n",argv[1]);
X		exit (1);
X	}
X
X	initscr();
X	clear();
X	nocrmode();
X	noecho();
X	raw();
X	lp = rp = (-1);
X	for (k=0;fnl[k];){
X		leader[k]=fnl[k];
X		k++;
X	}
X	while(k<39)leader[k++]='-';
X	leader[k++]=' ';
X	leader[k++]='|';
X	leader[k++]=' ';
X	for(i=0;fnr[i];)leader[k++]=fnr[i++];
X	while(k<75)leader[k++]='-';
X	leader[k]='\0';
X	for(i=0;i<20;i++){
X
X		if(!efl){
X			lp = (lp+1)%20;
X			if(!efl)if(fgets(left[lp],MAXLINE,fp1)==NULL)efl=1;
X			if(efl)strcpy(left[lp],"[EOF]\n");
X		}
X
X		if(!efr){
X			rp = (rp+1)%20;
X			if(!efr)if(fgets(rite[rp],MAXLINE,fp2)==NULL)efr=1;
X			if(efr)strcpy(rite[rp],"[EOF]\n");
X		}
X	}
X	display(lp,rp,' '); /* display is supposed to be fixed up so that
X				the lpth line from left and the rpth line from rite
X				will be the last ones displayed */
X	while(1)
X	{
X
X		prefix=0;
X		lbl: c=getch()&0177;
X		if(c>='0' && c<='9'){prefix=prefix*10+c-'0';goto lbl;}	
X		if(prefix==0)prefix=1;
X
X		if(c==('c'&037)||c==('y'&037)){
X			endwin();
X			exit();
X		}
X		if(isupper(c))c=tolower(c);
X		if(c=='t')c='y';
X		if(c=='j')c='f';
X
X		if(c==';'||c=='f')
X		for(jhn=0;jhn<prefix;jhn++)
X		{
X			rp = (rp+1) % 20;
X			if(!efr)if(fgets(rite[rp],MAXLINE,fp2)==NULL)efr=1;
X			if(efr)strcpy(rite[rp],"[EOF]\n");
X		}
X
X		if (c=='a'||c=='f')
X		for(jhn=0;jhn<prefix;jhn++)
X		{
X			lp = (lp+1) % 20;
X			if(!efl)if(fgets(left[lp],MAXLINE,fp1)==NULL)efl=1;
X			if(efl)strcpy(left[lp],"[EOF]\n");
X		}
X		if (c=='q'||c=='y'||c=='d')
X		for(jhn=0;jhn<prefix;jhn++)
X		{
X			for(i=0;i<20;i++){
X				lp = (lp+1)%20;
X				if(!efl)if(fgets(left[lp],MAXLINE,fp1)==NULL)efl=1;
X				if(efl)strcpy(left[lp],"[EOF]\n");
X			}
X		}
X
X		if (c=='p'||c=='y'||c=='d')
X		for(jhn=0;jhn<prefix;jhn++)
X		{
X			for(i=0;i<20;i++){
X				rp = (rp+1)%20;
X				if(!efr)if(fgets(rite[rp],MAXLINE,fp2)==NULL)efr=1;
X				if(efr)strcpy(rite[rp],"[EOF]\n");
X			}
X		}
X
X		if (c=='d')
X		for(jhn=0;jhn<prefix;jhn++)
X		{ 
X			zork=0;
X
X			for(i=0;i<20;i++){
X				lp = (lp+1)%20;
X				rp = (rp+1)%20;
X				if(!zork)if(jstrcmp(left[lp],rite[rp])!=0)zork=1;
X			}
X			while( !zork ) {
X				if(!efr){
X					rp = (rp+1)%20;
X					if(!efr)
X						if(fgets(rite[rp],MAXLINE,fp2)==NULL)efr=1;
X					if(efr)strcpy(rite[rp],"[EOF]\n");
X				}
X				if(!efl){
X					lp = (lp+1)%20;
X					if(!efl)
X						if(fgets(left[lp],MAXLINE,fp1)==NULL)efl=1;
X					if(efl)strcpy(left[lp],"[EOF]\n");
X				}
X				if(efl && efr)break;
X				zork=   jstrcmp(left[lp],rite[rp])   !=0 ;
X			}
X		}
X		display(lp,rp,c);
X	}
X}
X
Xfixline(p) char *p;
X{
X	int j;
X	char *q;
X	q=p;
X	for(j=0;j<37;j++){
X		if(*p=='\n')break; 
X		if(*p=='\t') *p=' '; 
X		p++;
X	}
X	if(q==lft)while(j<37){
X		*p++ = ' ';
X		j++;
X	}
X	else q[37]='\0';
X	*p='\0';
X}
X
Xdisplay(p,q,c) int p,q; 
Xchar c;
X{
X	int i,zork,cnt;
X
X	move(0,0);
X	for(i=0;i<20;i++)
X	{
X
X		p = (p+1) % 20; 
X		q = (q+1) % 20;
X		zork=jstrcmp(left[p],rite[q]);
X		if(c!='-' && c!='='){
X			strcpy(lft,left[p],38);
X			strcpy(rte,rite[q],38);
X		}
X		else {  /*fgets allows the \n in the string, and
X							appends a \0 after it.  strlen therefore will
X							count the \n in a string that has it.*/
X			if(c=='-')cnt=37;
X			if(c=='=')cnt=74;
X			if(strlen(left[p])>cnt)
X				strcpy(lft,&(left[p][cnt]),38);
X			else
X				strcpy(lft,"\n",2);
X			if(strlen(rite[q])>cnt)
X				strcpy(rte,&(rite[q][cnt]),38);
X			else
X				strcpy(rte,"\n",2);
X		}/*endelse*/
X
X		fixline(lft); 
X		fixline(rte);
X		printw("%c %s | %s\n",zork?'+':' ',lft,rte);
X
X	}
X
X
X	printw("%s\n",leader);
X	printw(
X	"a:upl, ;:upr, q:pgl, p:pgr, t|y:pgboth, f|j:upboth, d:gotodif, -|=:horiz\n");
X	printw(
X	"---------------------------------------------------------------------------\n"
X	    );
X	refresh();
X
X
X}
X#define white(c) ((c)==' ' || (c)=='\t')
Xjstrcmp(s1,s2)
Xchar *s1,*s2;
X{
X	while(*s1&&*s2)
X	{	
X		if(white(*s1)&&white(*s2)){
X			while(white(*s1))s1++;	
X			while(white(*s2))s2++;
X			continue;
X		}
X		if(*s1==*s2){s1++;s2++;continue;}
X		return(*s1 - *s2);
X	}
X	if(*s1=='\0' && *s2!='\0')return(-1);
X	if(*s1!='\0' && *s2=='\0')return(1);
X	if(*s1=='\0' && *s2=='\0')return(0);
X	exit(1);/*disaster*/
X}
EnD of sbs.c