[alt.sources] boxps: several postscript pages on one page

klamer@mi.eltn.utwente.nl (Klamer Schutte -- Universiteit Twente) (01/24/91)

The program boxps makes it possible to put several postscript pages
in reduced size on one page.

I assume this already is done earlier and better. However, i didn't
knew where to get it, so i wrote it myself.

Note this is a quick hack to get this job done. No responsibility for any
behaviour provided.

Klamer (.signature at end)

echo x - README
sed '/^X/s///' > README << '/'
XCopyright Klamer Schutte 1991
XThis software should not be sold without permission of the author.
XFree redistribution of original or modified sources of this program
Xis allowed.
X
XThe program boxps makes it possible to put several postscript pages
Xin reduced size on one page.
X
XThere are two source files, boxps.c and err.c. Boxps.c is the real thing;
Xerr.c is just my standard error handler. But to compile without any changes
Xyou need err.c so i provide this one as well. It could be usefull on its
Xown, though.
X
XThe program is developed and tested on a sun sparcstation 1 with SunOS 4.1
XHowever, it is rather portable. The only difficult part is making the
Xnew heading of the generated postscript file - but this can be skipped.
XAlso the file err.c might not be to portable - but calls to fatal,
Xerror and warning can easily be replaced by fprintf(stderr, and exit.
X
XBug fixes or enhancements as well as non-trivial ports are appreciated.
X
XKlamer Schutte
XFaculty of electrical engineering -- University of Twente, The Netherlands
Xklamer@mi.eltn.utwente.nl	{backbone}!mcsun!mi.eltn.utwente.nl!klamer
/
echo x - boxps.1
sed '/^X/s///' > boxps.1 << '/'
X\" Copyright Klamer Schutte 1991
X\" This software should not be sold without permission of the author.
X\" Free redistribution of original or modified sources of this program
X\" is allowed.
X
X.TH BOXPS 1 "24 Januari 1991" "University of Twente"
X.SH NAME 
Xboxps \- put several postscript pages in reduced size on one page
X.SH SYNOPSIS
X.B boxps  [-x x_nr][-y y_nr][-lg][-Pprinter] [files]
X.SH DESCRIPTION
X.B Boxps
Xtakes postscript files and makes it possible to display several of them on 
Xone page. The
X.B -x
Xand
X.B -y
Xoptions gives the number of pages in the x resp. y direction. With the
X.B -l
Xoption output is redirected to the printer. The default printer is
X.I postscipt,
Xthis can be changed using the
X.B -P
Xoption. The
X.B -g
Xoption causes the postscript commands
X.I gsave
Xand 
X.I grestore
Xto be mapped to dummy functions. This can be necessary for broken programs
Xwhich put a 
X.I showpage
Xin a
X.I gsave/grestore
Xpair. (Example: gnuplot).
X.SH SEE ALSO
Xpostscript(7).
X.SH BUGS
XThe whole system is not very robust.
X
XThe
X.B -g
Xoption redefines 
X.I gsave 
Xand 
X.I grestore 
Xglobally. So these operators are 
Xinaccessable in the rest of the postscript program.
X.SH AUTHOR
XKlamer Schutte -- klamer@mi.eltn.utwente.nl
/
echo x - boxps.c
sed '/^X/s///' > boxps.c << '/'
X/*
XCopyright Klamer Schutte 1991
XThis software should not be sold without permission of the author.
XFree redistribution of original or modified sources of this program
Xis allowed.
X*/
X/*
X *	boxps.c			KS 23/1/91
X *
X *	make several postscript pages one
X */
X
X#include	<stdio.h>
X#include        <sys/param.h>   /* */
X#include        <pwd.h>         /* */
X
Xusage(name)
Xchar	*name;
X{
X	fatal("Usage: %s [-x x_nr][-y y_nr][-lg][-Pprinter] [files]\n",
X		name );
X}
X
Xwrite_header(x,y,rotate,gsave,fp)
Xint	x,y,rotate;
Xint	gsave;
XFILE	*fp;
X{
X        char    hostname[MAXHOSTNAMELEN];
X        struct passwd   *pwd, *getpwuid();
X        int     uid, cur_time;
X
X	int	i,j;
X
X        uid = getuid();
X        pwd = getpwuid( uid );
X        gethostname( hostname, MAXHOSTNAMELEN );
X        fprintf(fp,"%%!\n%%%%Creator: %s:%s (%s)\n",
X                hostname,
X                pwd->pw_name, pwd->pw_gecos );
X        cur_time = time( NULL );
X        fprintf(fp,"%%%%CreationDate: %s%%%%EndComments\n",
X                ctime( &cur_time ) );
X	fprintf(fp,"statusdict begin /doprinterrors {true} def end\n");
X	
X	fprintf(fp,"/boxps 10 dict def boxps begin\n/WindowNumber -1 def\n");
X
X	fprintf(fp,"/XTArray [ ");
X	for(i=0;i<x;i++)
X		for(j=0;j<y;j++)
X			fprintf(fp,"%g ", 8*72*i/(double)x );
X	fprintf(fp," 0 ] def\n");
X			
X	fprintf(fp,"/YTArray [ ");
X	for(i=0;i<x;i++)
X		for(j=0;j<y;j++)
X			fprintf(fp,"%g ", 11*72*j/(double)y );
X	fprintf(fp," 0 ] def\n");
X
X	if (gsave)
X		fprintf(fp,"/gsave {} def\n/grestore {} def {}\n");
X
X	fprintf(fp,"/showpage {\n");
X	fprintf(fp,"initgraphics\n");
X	fprintf(fp,"boxps begin\n");
X	fprintf(fp,"WindowNumber 1 add dup /WindowNumber exch def\n");
X	fprintf(fp,"dup XTArray exch get exch YTArray exch get translate\n");
X	fprintf(fp, "end\n");
X	fprintf(fp,"%g %g scale\n", 1.0/x, 1.0/y);
X	/* should also set clippath! */
X	fprintf(fp,"} def\n");
X	fprintf(fp,"showpage\n");
X}
X
Xwrite_trailer(x,y,rotate,fp)
Xint	x,y,rotate;
XFILE	*fp;
X{
X	fprintf(fp,"end\nshowpage\n");
X}
X
Xcopy_file(fpin,name,fpout)
XFILE	*fpin, *fpout;
Xchar	*name;
X{
X	int	c;
X
X	while((c = getc(fpin)) != EOF)
X		putc(c,fpout);
X}
X
Xmain(argc,argv)
Xint	argc;
Xchar	*argv[];
X{
X	int	c, x=2, y=2, print = 0, rotate = 0, gsave = 0;
X	char	*printer = "postscript";
X	extern int	optind;
X	extern char	*optarg;
X	FILE		*out,*fp;
X	char		buf[80];
X
X	while((c = getopt(argc,argv,"x:y:lrP:g")) != EOF)
X		switch(c)
X		{case 'x':
X			x = atoi(optarg);
X			break;
X		case 'y':
X			y = atoi(optarg);
X			break;
X		case 'r':
X			rotate = 1;
X			warning("%s: rotate not implemented\n", argv[0]);
X			break;
X		case 'P':
X			printer = optarg;
X			/* FALL THROUGH */
X		case 'l':
X			print = 1;
X			break;
X		case 'g':
X			gsave = 1;
X			break;
X		default:
X			usage(argv[0]);
X		}
X
X	if (print)
X	{
X		sprintf(buf,"lpr -P%s",printer);
X		out = popen(buf,"w");
X		if (out == NULL)
X			fatal("%s: Can't popen to %s\n", argv[0], buf );
X	} else
X		out = stdout;
X
X	write_header(x,y,rotate,gsave,out);
X	if (argc - optind == 0)
X		copy_file(stdin,"(stdin)",out);
X	else
X		for(;argc-optind;optind++)
X		{
X			fp = fopen( argv[optind], "r" );
X			if (fp == NULL)
X			{
X				error("Can't open %s\n", argv[optind] );
X				continue;
X			}
X			copy_file(fp,argv[optind],out);
X			fclose(fp);
X		}
X	write_trailer(x,y,rotate,out);
X
X	if (print)
X		pclose(out);
X
X	return 0;
X}
/
echo x - err.3
sed '/^X/s///' > err.3 << '/'
X\" Copyright Klamer Schutte 1991
X\" This software should not be sold without permission of the author.
X\" Free redistribution of original or modified sources of this program
X\" is allowed.
X
X.TH ERR 3 "25 July 1990" "University of Twente" "Utility routines"
X.SH NAME 
Xwarning, error, fatal \- consistent error handling
X.SH SYNOPSIS
X#include <setjmp.h>
X.br
X#include <err.h>
X.LP
Xwarning( fmt, ... )
X.br
Xchar *fmt;
X.LP
Xerror( fmt, ... )
X.br
Xchar *fmt;
X.LP
Xfatal( fmt, ... )
X.br
Xchar *fmt;
X.LP
Xfatal_nr( nr, fmt, ... )
X.br
Xint	nr;
X.br
Xchar *fmt;
X.LP
Xextern int err_nr_errors, err_nr_warnings;
X.br
Xextern int *err_warning_jmpbuf, *err_error_jmpbuf, *err_fatal_jmpbuf;
X.SH DESCRIPTION
XThese routines provide a way to handle all kind of errors in a consistent way.
XThe differences between the routines are:
X.I warning()
Xis intended to be used when the error encountered is to be reported, but
Xwill probably not harm the result.
X.I error()
Xshould be called when the error will harm the result (it will probably not be 
Xvalid), but execution can continue;
X.I fatal()
Xshould be called when the error means that the program can not continue.
X.I fatal()
Xwill exit with a return value of 1;
X.I fatal_nr()
Xwill exit with the return value
X.I nr.
X.br
XThe integers
X.I err_nr_warnings
Xand 
X.I err_nr_errors
Xhold the number of time these routines are called.
X.br
XThe
X.I err_*_jmpbuf
Xvariables are pointers to a 
X.I jmp_buf.
XWhen these are not NULL they should point to a valid
X.I jmp_buf
Xfor use by
X.I longjmp(3).
XIn this way the program can catch errors as generated by these routines.
X.SH ARGUMENTS
XThe string
X.I fmt
Xand trailing arguments are handled in the way of
X.I printf(3).
X.SH SEE ALSO
Xsetjmp(3), printf(3), fprintf(3), exit(3).
X.SH NOTE
XObject in library /home/lib/libutil.a
X.br
Xerr.h can be found in /home/include.
X.SH AUTHOR
XKlamer Schutte
/
echo x - err.c
sed '/^X/s///' > err.c << '/'
X/*
XCopyright Klamer Schutte 1991
XThis software should not be sold without permission of the author.
XFree redistribution of original or modified sources of this program
Xis allowed.
X*/
X/*
X *	error.c				Klamer Schutte 25/7/90
X *
X *	handle errors in a consistent way.
X */
X
X#include	<stdio.h>
X#include	<varargs.h>
X#include	<setjmp.h>
X
Xint	err_nr_errors, err_nr_warnings;
X/* what is the type of a pointer to a jmp_buf? On sun4 int * will do */
Xint	*err_warning_jmpbuf, *err_error_jmpbuf, *err_fatal_jmpbuf;
X
X/*VARARGS1*/
Xwarning( fmt, va_alist )
Xchar	*fmt;
Xva_dcl
X{
X	va_list	args;
X
X	va_start( args );
X	vfprintf(stderr, fmt, args );
X	va_end(args );
X
X	err_nr_warnings++;
X
X	if (err_warning_jmpbuf != NULL)
X		longjmp( err_warning_jmpbuf, 1 );
X}	
X
X/*VARARGS1*/
Xerror( fmt, va_alist )
Xchar	*fmt;
Xva_dcl
X{
X	va_list	args;
X
X	va_start( args );
X	vfprintf(stderr, fmt, args );
X	va_end(args );
X
X	err_nr_errors++;
X
X	if (err_error_jmpbuf != NULL)
X		longjmp( err_error_jmpbuf, 1 );
X}	
X
X/*VARARGS2*/
Xfatal_exit_nr( nr, fmt, va_alist )
Xint	nr;
Xchar	*fmt;
Xva_dcl
X{
X	va_list	args;
X
X	va_start( args );
X	vfprintf(stderr, fmt, args );
X	va_end(args );
X
X	if (err_fatal_jmpbuf != NULL)
X		longjmp( err_fatal_jmpbuf, 1 );
X
X	exit( nr );
X}	
X
X/*VARARGS1*/
Xfatal( fmt, va_alist )
Xchar	*fmt;
Xva_dcl
X{
X	va_list	args;
X
X	va_start( args );
X	vfprintf(stderr, fmt, args );
X	va_end(args );
X
X	if (err_fatal_jmpbuf != NULL)
X		longjmp( err_fatal_jmpbuf, 1 );
X
X	exit( 1 );
X}	
/
-- 
Klamer Schutte
Faculty of electrical engineering -- University of Twente, The Netherlands
klamer@mi.eltn.utwente.nl	{backbone}!mcsun!mi.eltn.utwente.nl!klamer