[net.sources] seebib - a replacement for lookbib

isaac@mulga.UUCP (05/18/84)

----------------------
[going going goanna]

The following is a shar archive of seebib. It is a much nicer and more
powerful replacement for lookbib. It can function on a refer-type database
either in the old format or the newer one. As well it works fine on "bib"
databases although it assumes indxbib and hunt but not invert.
This is version one: any comments, bugs etc would be appreciated.

----
UUCP: {decvax,vax135}!mulga!isaac
Isaac Balbin			
Department of Computer Science
University of Melbourne,
Parkville 3052
Melbourne, AUSTRALIA.

Cut Here:
------------------------------------/\----------------------------------------
echo x - Makefile
cat > Makefile <<!EOF!
#/******************************************************************************
#+
#+		(C) 1984	Isaac Balbin
#+				Department of Computer Science,
#+				University of Melbourne,
#+				Parkville 3052,
#+				Melbourne, AUSTRALIA
#+				UUCP: ...{decvax, vax135}!mulga!isaac
#+
#+		All rights reserved. This program may not be sold, however,
#+		permission is given to distribute it provided that this header
#+		remains intact.
#+		Mail any comments etc to the author.
#+******************************************************************************

SOURCES	=		seebib.c popen2.c
OBJECTS	=		seebib.o popen2.o
LFLAGS	=		-lcurses -ltermcap
CFLAGS	=		-O
DEST	=		/mnt/pgrad/isaac/bin

seebib	:	$(OBJECTS)
			$(CC) -o seebib $(CFLAGS) $(OBJECTS) $(LFLAGS)

install	:	seebib
			chmod 711 seebib
			mv seebib $(DEST)

clean	:	
			/bin/rm -f $(OBJECTS)
!EOF!
echo x - seebib.c
cat > seebib.c <<!EOF!
/******************************************************************************
+
+		(C) 1984	Isaac Balbin
+				Department of Computer Science,
+				University of Melbourne,
+				Parkville 3052,
+				Melbourne, AUSTRALIA
+				UUCP: ...{decvax, vax135}!mulga!isaac
+
+		All rights reserved. This program may not be sold, however,
+		permission is given to distribute it provided that this header
+		remains intact.
+		Mail any comments etc to the author.
+******************************************************************************/

#ifndef lint
static char *sccsid = "@(#)seebib.c	2.0 (Melbourne) 7/5/84";
#endif

/*
**			seebib.
**
**	Visually displays and formats entries from
**	a bibliography database according to Key words
**
*/

#define HUNTMAX		"1024"
#define MAXREFS		8128
#define LARGE		1024
#define	MEDIUM		256
#define	SMALL		64
#define TINY 		16
#define ALPHABET	26
#define UNUSED		1
#define SLEEP		2
#define addblank(S)	if (S[0] != '\0') { strcat(S," ");   }
#define addcomma(S)	if (S[0] != '\0') { strcat(S,",  "); }
#define preamble(S)	wstandout(big);mvwaddstr(big,cury++,0,S);wstandend(big);
#define ord(S)		(S - 'A')
#define cntrl(S)	(S  & 037)

#include <curses.h>
#include <signal.h>
#include <ctype.h>

FILE *pin,*pout;		/* file pointers for i/o with hunt	*/
WINDOW *big,*small;		/* top and bottom windows		*/

char A[MEDIUM];			/* author				*/
char B[MEDIUM];			/* book					*/
char C[MEDIUM];			/* city					*/
char D[SMALL];			/* date					*/
char E[MEDIUM];			/* editors				*/
char F[UNUSED];			/* footnote number			*/
char G[UNUSED];			/* government order number		*/
char H[SMALL];			/* header rubbish			*/
char I[MEDIUM];			/* institute				*/
char J[MEDIUM];			/* journal				*/
char K[MEDIUM];			/* extra key words			*/
char L[SMALL];			/* refer override label			*/
char M[UNUSED];			/* bell labs rubbish			*/
char N[TINY];			/* number				*/
char O[LARGE];			/* other                    		*/
char P[SMALL];			/* page number(s)			*/
char Q[MEDIUM];			/* Corporate or foreign author		*/
char R[MEDIUM];			/* research report			*/
char S[MEDIUM];			/* series title				*/
char T[MEDIUM];			/* title				*/
char U[UNUSED];			/* unused				*/
char V[TINY];			/* volume				*/
char W[UNUSED];			/* unused				*/
char X[LARGE];			/* abstract				*/
char Y[MEDIUM];			/* who owns the reference		*/
char Z[UNUSED];			/* unused				*/

struct {
	char *s;		/* string */
	char *p;		/* prompt  NOTE: SHOULD ALL BE THE SAME LENGTH*/
	int   l;		/* max buffer length */
}	refs[ALPHABET] = {
	&(A[0]),	"Author(s): ",	MEDIUM,
	&(B[0]),	"Book     : ",	MEDIUM,
	&(C[0]),	"City     : ",	MEDIUM,
	&(D[0]),	"Date     : ",	SMALL,
	&(E[0]),	"Editor(s): ",	MEDIUM,
	&(F[0]),	(char *)NULL,	UNUSED,
	&(G[0]),	(char *)NULL,	UNUSED,
	&(H[0]),	"Header   : ",	SMALL,
	&(I[0]),	"Institute: ",	MEDIUM,
	&(J[0]),	"Journal  : ",	MEDIUM,
	&(K[0]),	"Keywords : ",	MEDIUM,
	&(L[0]),	"Label    : ",	SMALL,
	&(M[0]),	(char *)NULL,	UNUSED,
	&(N[0]),	"Number   : ",	TINY,
	&(O[0]),	"Other    : ",	LARGE,
	&(P[0]),	"Pages    : ",	SMALL,
	&(Q[0]),	"Author(s): ",	MEDIUM,
	&(R[0]),	"Report   : ",	MEDIUM,
	&(S[0]),	"Series   : ",	MEDIUM,
	&(T[0]),	"Title    : ",	MEDIUM,
	&(U[0]),	(char *)NULL,	UNUSED,
	&(V[0]),	"Volume   : ",	TINY,
	&(W[0]),	(char *)NULL,	UNUSED,
	&(X[0]),	"Abstract : ",	LARGE,
	&(Y[0]),	"Owned-by : ",	MEDIUM,
	&(Z[0]),	(char *)NULL,	UNUSED,
};

long offsets[MAXREFS];		/* holds byte offset of ref in tmp file */

/* 
** 	order holds the order in which we want to print out the entries	
**	ie 0 == A(uthor) is first, 19 == T(itle) is second etc 
*/
int order[ALPHABET] =
{ 0,19,18,9,1,4,17,8,2,21,13,3,15,11,10,24,23,14,7,-1,-1,-1,-1,-1,-1,-1};
/*A T  S  J B E R  I C V  N  D P  L  K  Y  X  O  H			*/

extern	char *strcpy(),*strcat(),*rindex();
int	nrefs = 0;		/* running total of refs found		*/
int 	totrefs = 0;		/* sum of refs found in first pass	*/
int	number = 0;		/* optional number before a command	*/
int	prompt_length;		/* the CONSTANT length of the prompt	*/
char	temp[20];		/* holds temporary file name		*/
char	mbuf[80];		/* buffer for messages			*/
char	*huntv[5] =		{"/usr/lib/refer/hunt","-l",HUNTMAX,0,NULL};
char	bib_file[80];		/* name of bib_file			*/
char	bib_buf[80];		/* buffer for new bib files		*/
char	user[40];		/* holds name of user output file	*/
bool	tty = TRUE;		/* true if terminal has cursor movement	*/
bool	Terse_flag = FALSE;	/* terse mode flag			*/
bool	Safe_flag = FALSE;	/* only allows q to skip past last ref	*/
FILE	*userf;			/* file pointer for user file		*/
FILE	*tmpf;			/* holds result of hunt search		*/

main( argc, argv )
	int argc;
	char **argv;
{
	FILE *fopen();
	char s[MEDIUM], *sprintf(),*get_key_word();
	register char *c;
	int die();
	bool finished = FALSE;

	while(--argc > 0 && (*++argv)[0] == '-')
		switch(*(argv[0] + 1))
		{
		case 't':
			Terse_flag = TRUE;
			break;
		case 's':
			Safe_flag = TRUE;
			break;
		default:
			usage();
		}
	if ( argc > 1 )
		usage();
	else
		if ( argc == 1 )
			strcpy(bib_file, *argv);
		else
			strcpy(bib_file,"bib");	/* set up default */
	sprintf(temp,"/tmp/see%06d",getpid());
	sprintf(s, "%s.ia", bib_file);

	if ( access(s, 0) == -1 ) 
	{
		fprintf(stderr, "Index file %s not found\n", s);
		exit(1);
	}

	huntv[3] = &(bib_file[0]);
	signal(SIGINT,die);
	initscr();
	if ( strlen(CM) == 0 ) 
	{
		fprintf(stderr,
		"Visual mode needs terminal with cursor motion capability\n");
		fprintf(stderr,"Using non-visual (open) mode...\n\n");
		tty = FALSE;
		Safe_flag = TRUE;
	}
	clear();
	signal(SIGINT,die);
	fflush(stdin);
	addstr("Instructions? (y/n) ");
	crmode();
	refresh();
	if ( getchar() == 'y')
		instruct();
	clear();
	refresh();
	if ( tty ) 
	{
		big = newwin(LINES-2,COLS,0,0);
		small = newwin(1,COLS,LINES-1,0);
	}
	 /* only one screen needed */
	else
		big = small = stdscr; 
	wstandout(small);
	get_prompt_length();
	while ( ! finished ) 
	{
		if ( tty )
		{
			wclear(big);
			wrefresh(big);
		}
		wclear(small);
		do_prompt();
		if ( get_key_word(s) != NULL )
		{
			for( c = &(s[0]); isspace(*c); c++ )
				;
			if ( strcmp(c,"?\n") == 0 ) 
			{
				instruct();
				clear();
				refresh();
				continue;
			}
			if ( c[0] == '<' )
			{
				if ( sscanf(c,"<%s",bib_buf) == -1 ) /* trick */
					print_bib_file();
				else if ( access(strcat(bib_buf,".ia"),0) == -1)
				{
					message(sprintf(mbuf,
					"Index file %s not found", bib_buf));
					wclear(small);
					sleep(SLEEP);
				}
				else
				{
					*rindex(bib_buf,'.') = '\0';
					strcpy(bib_file,bib_buf);
					print_bib_file();
				}
				continue;
			}
			if ( strlen(c) > 3 ) { /* key words <=2 + \n are out */
				message("Searching database ...");
				noecho();
				wclear(small);
				if ( strncmp(c,"$all",4) != 0 )
				{
					popen2(huntv,&pin,&pout);
					map_lower(c);
					fprintf(pout,"%s",c);
					fclose(pout);
					process_lines();
					pclose2(pin,pout);
				}
				else { /* just use "cat" instead of "hunt"*/
					if ( (pin = fopen(bib_file,"r"))!= NULL)
					{
						process_lines();
						fclose(pin);
					}
				}
				echo();
			}
		}
		else 
		{
			finished = TRUE;
		}
	}
	die();
}

map_lower(s)		/* map string s to lower case */
	register char *s;
{
	for ( ; *s; ++s)
		if ( isupper(*s) )
			*s = tolower(*s);
}

char map_upper(s)		/* map character s to upper case */
	register char s;
{
	if ( islower(s) ) 
		s = toupper(s);
	return(s);
}

instruct()
{
	register int c;
	noecho();
	mvaddstr(2,0,"Type key words (eg Author and Date) after the prompt.");
	mvaddstr(3,0,"References with those key words are shown if they exist");
	mvaddstr(4,0,"if nothing matches you are given another prompt.");
	mvaddstr(5,0,"To quit seebib, press CTRL-d after the > prompt.");
	mvaddstr(6,0,"NOTE: key words <=2 characters long are ignored,");
	mvaddstr(7,0,"and only the first 6 characters are significant.");
	mvaddstr(8,0,"the special key word \"$all\" lists every reference.");
	mvaddstr(9,0,"Cntrl L will redraw the screen.");
	mvaddstr(10,0,"Cntrl T toggles between terse and verbose mode.");
	mvaddstr(11,0,"It is possible to save the results of a search by");
	mvaddstr(12,0,"following the keywords with '> filename'");
	mvaddstr(13,0,"You can change bib files by typing '< bib_file' in");
	mvaddstr(14,0,"in response to the prompt.");
	mvaddstr(15,0,"'<' on its own will indicate the name of the bib_file.");
	mvaddstr(LINES-1,0,"Press <space> to continue <q> to quit");
	refresh();
	while( (c = getchar()) != ' ' )
		if ( c == 'q' )
			die();
		else 
			write(fileno(stdout),"\07",1);
	echo();
}

die()
{
	signal(SIGINT,SIG_IGN);
	unlink(temp);
	echo();
	clear();
	refresh();
	nocrmode();
	if ( tty )
		mvcur(0,COLS-1,LINES-1,0);
	else
		wmove(small,0,0);
	endwin();
	exit(0);
}

static char info[LARGE];
static bool fname;	/* true if redirect to filename */

process_lines()
{
	char map_upper();
	register char *cc;
	register char *pos;
	register int newline;
	register int i;
	int type;
	int icount = 0;

	init_refs();
	nrefs = 0;
	totrefs = 0;
	newline = 1;

	if ( fname && ((userf = fopen(user,"a")) == NULL) )
	{
		message(sprintf(mbuf,"Can't open %s",user));
		fname = FALSE;
		sleep(SLEEP);
		message("Searching database ...");
	}
	if ( !Terse_flag)
	{
		if ( (tmpf = fopen(temp,"w")) == NULL )
			return;
		while( fgets(info,LARGE,pin) != NULL ) 
		{
			if ( info[0] == '.' && (info[1] == '['||info[1] == ']'))
				continue;
			icount++;
			if (*info == '\n')
				newline = 1;
			else
				if ( *info == '%' && newline) 
				{
					newline = 0;
					offsets[++totrefs] = ftell(tmpf);
				}
			fputs(info,tmpf);
			if ( fname ) 
				fputs(info,userf);
		}
		putc('\n',tmpf);/* need blank line to make loop homogeneous */
		fclose(tmpf);
		if ( fname ) 
			fclose(userf);

		/*
		 * Read refs again, displaying them ...
		 */

		if ( (tmpf = fopen(temp,"r")) == NULL )
			return;
	}
	else 
		tmpf = pin;

	while( fgets(info,LARGE,tmpf) != NULL ) 
	{
		if ( info[0] == '.' && (info[1] == '['||info[1] == ']') )
				continue;
		if ( Terse_flag && fname )
			fputs(info,userf);
		if ( *info != '\n' ) 
		{
			icount++;
			*rindex(info,'\n') = '\0';
			pos = info;
			if ( info[0] == '%' )
			{
				for(pos +=3;isspace(*pos);pos++)
					;
				type = map_upper(info[1]);
			}
			/*ignore unused */
			if ( refs[ord(type)].p == (char *)NULL )
				continue;
			cc = refs[ord(type)].s;
			i = refs[ord(type)].l  - strlen(cc);
			if ( i > 2 )
			{
				if ( type != 'A' && type != 'E' )
				{
					addblank(cc);
					if ( *cc != '\0' )
						i--;
				}
				else
				{
					addcomma(cc);
					if ( *cc != '\0' )
						i -= 2;
				}
				if ( i < strlen(pos) )
				{
					pos[i - 2] = '>';
					pos[i - 1] = '\0';
				}
				strcat(cc,pos);
			}
		}
		else
			print_refs();
	}
	if (*T || *B || *A)
		print_refs();
	if (Terse_flag && fname) 
		fclose(userf);
	if ( icount == 0 )
	{
		message("No match");
		sleep(SLEEP);
	}
}

char *get_key_word(s)
	register char *s;
{
	char *save = s;
	fname = FALSE;
	if ( tty ) 
		noecho();
	while( (*s = getchar()) != '\n') 
	{
		if (*s == cntrl('t'))
		{
			wstandout(small);
			if ( Terse_flag )
			{
				message("Exiting terse mode");
				Terse_flag = FALSE;
			}
			else
			{
				message("Entering terse mode");
				Terse_flag = TRUE;
			}
			if ( !tty ) 
				sleep(SLEEP);
			do_prompt();
			continue;
		}
		if (*s == cntrl('d'))
			return(NULL);
		if (*s == cntrl('l')) 
		{
			clearok(curscr,TRUE);
			if ( tty )
				touchwin(big);
			touchwin(small);
			if ( tty )
				wrefresh(big);
			wrefresh(small);
			continue;
		}
		if ( *s == _tty.sg_kill ) 
		{
			s = save;
			break;
		}
		if (*s == _tty.sg_erase || *s == '\b')
		{
			if ( s == save )
				write(fileno(stdout),"\07",1);
			else 
			{
				if ( BS )
					waddstr(small,"\b \b");
				else 
				{
					s = save;
					break;
				}
				s--;
			}
		}
		else 
		{
			if ( !(isprint(*s) || *s == ' ') )
				*s = '?';
			waddch(small,*s++);
		}
		if ( tty ) 
			wrefresh(small);
	}
	*++s = '\0';
	echo();
	wstandout(small);
	parse(save);
	return(save);
}

parse(s)
	register char *s;
{
	char key[MEDIUM];

	if ( (sscanf(s,"%[^>]>%s",key,user)) == 2 )
		fname = TRUE;
	strcpy(s,key);
}

init_refs()
{
	register int i;
	for( i = 0; i < ALPHABET; i++ )
		refs[i].s[0] = '\0';
}

static int cury;

display()
{
	register int i,j;
	cury = 0;
	for( i = 0; i < ALPHABET; i++) 
	{
		j = order[i];
		if (  j != -1 && refs[j].s[0] != '\0') 
		{
			preamble(refs[j].p);
			exhume(refs[j].s);
		}
	}
	wrefresh(big);
	init_refs();
}

getint(pn)
	register int *pn;
{
	register int c;
	*pn = 0;
	while ( (c = getchar()) >= '0' && c <= '9' )
		*pn = 10 * *pn + c - '0';
	return(c);
}

any_more()
{
	int more = ' ';
	wstandout(small);
	do 
	{
		if ( ! Terse_flag )
			mvwaddstr(small,0,0,
			"<space> to continue, <-> to back up, <q> to quit");
		else
			mvwaddstr(small,0,0,
			"<space> to continue, <q> to quit");
		wrefresh(small);
		clearerr(stdin);
		if (!Terse_flag) 
			more = getint(&number);
		else 
			more = getchar();
	} while ( ferror(stdin) != 0 );
	wstandend(small);
	return(more);
}

exhume(s)
	register char *s;
{
	register char *c;
	c = s;
	while ( strlen(c) > COLS - prompt_length )
	{
		c = &(s[COLS - prompt_length]);
		while(*c != ' ')
			c--;
		*c = '\0';
		if ( cury > big->_maxy )
			break;
		else
			waddstr(big,s);
		wmove(big,cury++,prompt_length);
		s = ++c;
	}
	if ( cury <= big->_maxy )
		waddstr(big,s);
	else
		message("Ref. too long - truncated");
}

put_out(n)
	register int n;
{
	wstandout(small);
	if ( Terse_flag )
		message(sprintf(mbuf,"Reference %d",n));
	else
		message(sprintf(mbuf,"Reference %d of %d",n,totrefs));
}

print_refs()
{
	bool finished = FALSE;
	if ( !*T && !*B && !*A )
		return;
	put_out(++nrefs);
	display();
	while ( ! finished ) 
	{
		switch( any_more() ) 
		{
		case 'q':
			if ( Terse_flag )
				fclose(tmpf);
			else
				fseek(tmpf,0L,2);
			finished = TRUE;
			break;
		case cntrl('l'):
			if ( !tty ) 
			{
				fseek(tmpf,offsets[nrefs],0);
				wclear(big);
				nrefs--;
				finished = TRUE;
				break;
			}
			clearok(curscr,TRUE);
			if ( tty )
				touchwin(big);
			touchwin(small);
			if ( tty )
				wrefresh(big);
			wrefresh(small);
			break;
		case '-':
			if ( !Terse_flag && nrefs > 1 ) 
			{
				if ( number > 1 ) 
					nrefs -= number-1;
				if ( nrefs > 1 ) 
				{
					nrefs--;
					fseek(tmpf, offsets[nrefs],0);
					nrefs--;
				}
				else 
				{
					nrefs = 0;
					fseek(tmpf,0L,0);
				}
				wclear(big);
				finished = TRUE;
			}
			else
				write(fileno(stdout),"\07",1);
			break;
		case ' ':
			wclear(big);
			if (!Terse_flag)
			{
				if ( nrefs == totrefs && Safe_flag ) 
				{
					write(fileno(stdout),"\07",1);
					break;
				} 
				else 
				{
					if ( number > 0 ) 
					{
						nrefs += number;
						if ( nrefs > totrefs )
							nrefs = totrefs;
						fseek(tmpf,offsets[nrefs],0);
						nrefs--;
					}
				}
			}
			if ( nrefs == totrefs && Safe_flag )
			{
				write(fileno(stdout),"\07",1);
				break;
			} 
			else
				finished = TRUE;
			break;
		default:
			write(fileno(stdout),"\07",1);
			break;
		}
	}
}

usage()
{
	fprintf(stderr,"Usage: seebib [-t] [-s] [database]\n");
	exit(0);
}

print_bib_file()
{
	wstandout(small);
	message(sprintf(mbuf,"Processing Bib File '%s'",bib_file));
	wstandend(small);
	sleep(SLEEP);
	wclear(small);
}

do_prompt()
{
	wstandout(small);
	mvwaddstr(small,0,0,"key(s)[? for help]> ");
	wrefresh(small);
	wstandend(small);
}

message(s)
	register char *s;
{
	wclear(small);
	if ( tty )
		wmove(small,0,COLS - strlen(s) -1);
	else
		wmove(small,0,0);
	waddstr(small,s);
	wrefresh(small);
}

get_prompt_length()
{
	register int i;
	for ( i=0; i < ALPHABET; i++)
		if( (prompt_length = strlen(refs[i].p)) > 0 )
			break;
}
!EOF!
echo x - popen2.c
cat > popen2.c <<!EOF!
/******************************************************************************
+
+		(C) 1984	Isaac Balbin
+				Department of Computer Science,
+				University of Melbourne,
+				Parkville 3052,
+				Melbourne, AUSTRALIA
+				UUCP: ...{decvax, vax135}!mulga!isaac
+
+		All rights reserved. This program may not be sold, however,
+		permission is given to distribute it provided that this header
+		remains intact.
+		Mail any comments etc to the author.
+******************************************************************************/

# include 	<stdio.h>
# define	newfd(old,new)	if (old != new) {dup2(old,new);close(old);}

static int child_pid;

/*
**	Two way popen: allows one to read and write to process "cmdv[0]"
**	via File pointers pin and pout
**
**			David Price
**			Isaac Balbin
*/

popen2(cmdv,pinptr,poutptr)
	char *cmdv[];
	FILE **pinptr,**poutptr;
{
	int	parentw[2],	/* parent (caller) write file descriptor */
		childw[2];	/* child  (called) write file descriptor */

	fflush(stdout);		/* clear toilet first		  	 */

	if ( pipe(parentw) < 0 || pipe(childw) < 0 )
	{
		perror("popen2: No pipe");
		exit(1);
	}

	if( (child_pid = fork()) == 0 )
	{
		/*	child	*/
		close(parentw[1]);
		close(childw[0]);
		newfd(parentw[0],0);
		newfd(childw[1],1);
		execv(cmdv[0], cmdv);
		perror(cmdv[0]);
		exit(1);
	}

	if( child_pid < 0 )
	{
		/*	parent	*/
		perror("popen2: Fork fails");
		exit(1);
	}
	close(parentw[0]);
	close(childw[1]);
	*pinptr  = fdopen(childw[0], "r");
	*poutptr = fdopen(parentw[1], "w");
	if (*pinptr == NULL || *poutptr == NULL)
		perror("Bad fdopen");
}


pclose2(pin,pout)
	FILE *pin, *pout;
{
	fclose(pin);
	fclose(pout);
}
!EOF!
echo x - seebib.1
cat > seebib.1 <<!EOF!
.TH SEEBIB 1 "April 1984"
.UC 4
.SH NAME
seebib \- interrogate a 
.I refer
or
.I bib
type bibliographic database
.SH SYNOPSIS
.B seebib
[ option ] [ file ]
.LP
.SH DESCRIPTION
.I  Seebib
is a program which allows the user to interrogate a database consisting
of a bibliography of references which are in 
.I refer
format.
It is assumed that the bibliography has been used to create an inverted index
in the files, file.ia, file.ib, and file.ic.
These may be created by using 
.I indxbib
for example.
It differs from 
.I lookbib
in that the user interface is much more friendly and versatile.
.PP
.I Seebib
(via the
.I curses
library) looks in the file
.I /etc/termcap
(or the designated 
.I environment
variable TERMCAP)
to determine the terminal characteristics, and to determine the default window sizes.
.PP
The command line arguments are:
.TP
[ file ]
.br
The file is used for two reasons.
Primarily, it is the prefix for the .i[abc] suffixed files which are assumed to
be resident.
In the case of multiple files with only one set of inverted index files, the 
user should run
.I indxbib
on the series of files, and then realise that the first file argument to
.I indxbib 
will be used as the prefix for the .i[abc] files and hence should 
also be used
.B solely
as the argument to 
.I seebib
(or
.I lookbib
for that matter.)
The default filename is "bib".
.IP [-t]
This enables the terse way of examining the database.
No backing up of references is possible, nor is a prior count of the number 
of references matched available.
.IP [-s]
This enables the "safe" mode for seebib.
Normally the user examines successive references by pressing the space bar.
When the space bar is pressed after the last reference matched, seebib erases 
all knowledge of the results of the current search and awaits a new keyword(s).
In the "safe" mode, the user must exit from the last reference matched by 
typing "q" thus saving the user from the requirement to redo the search if
he inadvertently hits the space bar.
.PP
In Line arguments (in response to the "key(s)[? for help]>" prompt):
.TP
.I keyword(s)
In response to the prompt, the user types key words which seek to identify
the reference(s) required.
Backspace and kill characters behave as would be expected whilst unprintable
characters are echoed as question marks.
.br
A sample would be
.sp 2
\fBkey(s)[? for help]>\fP	balbin stuart 1983
.sp 2
In this case only references which are identified by 
.I all
the aforementioned keywords are listed.
The minimum size of a key word is 3 characters and only the first 6 characters are significant.
It is possible to redirect the results of a search to filename by typing a ">" followed by a filename.
An example would be :-
.sp 2
\fBkey(s)[? for help]>\fP	logic > results
.sp 2
In verbose mode all the references matched will be output to the file.
In terse mode only those references actually viewed on the screen will be output to the file.
If the file already exists then the resultant output will be appended to that file otherwise it will be created.
.IP \fI$all\fP
This special key word is used to list every reference in the bibliographic database.
.IP "< [bib_file]"
It is possible to interrogate a new bibliography whilst within seebib by 
giving the new file name after the <.
Typing < on its own will print the name of the current bibliography file.
.IP "?"
If this is typed in response to the prompt (followed by a newline) then the help information is displayed.
.IP ^T
This key can be used to toggle between terse and verbose modes.
In verbose mode two passes of the bibliography are made so that there
is an indication of how many references are available matching a particular
keyword (or group of key words).
.IP ^D
Used to terminate a session.
.PP
In Line commands during output phase of the search:
.IP [integer]<space>
By hitting the space bar, the next reference matching the keywords is displayed.
If the <space> is preceded by an integer then that many references will be skipped.
.IP [integer]<->
Allows the user to back up to the previous reference.
This is enabled only for the verbose mode of
.I seebib.
If the <-> is preceded by an integer then that many references will be backed up.
.IP <q>
Pressing this key causes the current search to be aborted and the screen to be cleared.
.IP ^L
Redraws the screen when necessary.
.SH AUTHOR
Isaac Balbin
.br
Department of Computer Science,
.br
University of Melbourne, Parkville 3052, Australia.
.br
UUCP: ...{decvax,vax135}!mulga!isaac
.SH ACKNOWLEDGEMENTS
David Price (Univ. of Melb), Baron Grey (UCLA) and John Shepherd (Univ. of Melb).
.SH FILES
.DT
/etc/termcap		Terminal data base
/tmp/seeXXXX		temporary file
.SH "SEE ALSO"
refer(1), indxbib(1), hunt(1), mkey(1), inv(1).
.SH DIAGNOSTICS
.DT
Messages indicating that a search is being undertaken or that the mode has switched from terse to verbose are indicated on the lower window.
Any errors from 
.I hunt
are simply written to
.I stderr.
If a reference entry is too long and will overflow a buffer, it is truncated and an '>' appears at the last character position on the screen.
If all a references entries are too long to fit on one screen (very unlikely) then only as much as can be shown will be; an error message is printed.
.SH CAVEATS
The special key word "$all" works properly only when the references are in one file.
Essentially providing "$all" is not the function of a program which really only formats
.I hunt
output.
Of course,
.I
seebib
still works properly for any other key words even though the bibliography is in multiple files.
It is fairly easy to modify seebib so that "$all" works on multiple files but we decided against it.
.SH BUGS
.DT
If 
.I hunt
sends out some error message (eg the user does has not used indxbib properly) the screen will need to be redrawn using ^L.
!EOF!