[comp.sources.misc] v09i089: Mpage

mark@pyrdc.UUCP (Mark Hahn) (12/27/89)

Posting-number: Volume 9, Issue 89
Submitted-by: mark@pyrdc.UUCP (Mark Hahn)
Archive-name: mpage/part02

. . . . . . . . . . . The Obligitory Dotted Line . . . . . . . . . . . .
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# If this archive is complete, you will see the following message at the end:
#		"End of archive 2 (of 2)."
# Contents:  Makefile.mpage TODO mp_args.c mp_main.c mp_page.c
#   mp_sample.c mpage.1
# Wrapped by mark@pyrdc on Tue Dec 26 16:29:23 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile.mpage' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile.mpage'\"
else
echo shar: Extracting \"'Makefile.mpage'\" \(1172 characters\)
sed "s/^X//" >'Makefile.mpage' <<'END_OF_FILE'
X#
X# $Header: Makefile,v 1.3 89/05/25 09:06:55 mark Exp $
X#
XHEAD =  mp_head.h
XSRCS =  mp_main.c mp_glob.c mp_text.c mp_post.c mp_file.c mp_page.c mp_args.c
XMOBJ =  mp_main.o mp_glob.o mp_text.o mp_post.o mp_file.o mp_page.o mp_args.o
XSMPL =  mp_sample.c mp_page.c mp_glob.c mp_args.c
XSOBJ =  mp_sample.o mp_page.o mp_glob.o mp_args.o
X
X
X#CFLAGS = -gx -DDEBUG
XCFLAGS = -gx
X
X.SUFFIXES:	.c,v
X
Xdefault:	mpage msample Makefile.mpage
X	@echo Done!
X
Xmpage:	$(MOBJ)
X	$(CC) $(CFLAGS) -o mpage $(MOBJ)
X
Xmsample:	$(SOBJ)
X	$(CC) $(CFLAGS) -o msample $(SOBJ)
X
XMakefile.mpage:	Makefile
X
Xclean:
X	rm -rf $(MOBJ) mpage mpage.ps
X
Xmp_main.o:	$(HEAD) mp_main.c
X	$(CC) -c $(CFLAGS) mp_main.c
X
Xmp_glob.o:	$(HEAD) mp_glob.c
X	$(CC) -c $(CFLAGS) mp_glob.c
X
Xmp_text.o:	$(HEAD) mp_text.c
X	$(CC) -c $(CFLAGS) mp_text.c
X
Xmp_post.o:	$(HEAD) mp_post.c
X	$(CC) -c $(CFLAGS) mp_post.c
X
Xmp_file.o:	$(HEAD) mp_file.c
X	$(CC) -c $(CFLAGS) mp_file.c
X
Xmp_page.o:	$(HEAD) mp_page.c
X	$(CC) -c $(CFLAGS) mp_page.c
X
Xmp_args.o:	$(HEAD) mp_args.c
X	$(CC) -c $(CFLAGS) mp_args.c
X
Xmp_sample.o:	$(HEAD)
X	$(CC) -c $(CFLAGS) $*.c
X
Xmpage.ps:	mpage.1
X	psroff -t -man mpage.1 > mpage.ps
X
X
X# add your proper install stuff
Xinstall:

END_OF_FILE
echo shar: NEWLINE appended to \"'Makefile.mpage'\"
if test 1173 -ne `wc -c <'Makefile.mpage'`; then
    echo shar: \"'Makefile.mpage'\" unpacked with wrong size!
fi
# end of 'Makefile.mpage'
fi
if test -f 'TODO' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'TODO'\"
else
echo shar: Extracting \"'TODO'\" \(1684 characters\)
sed "s/^X//" >'TODO' <<'END_OF_FILE'
XCurrent Wish List:
X
X
X- Should print a help string when invoked as "mpage".  However, like
Xcat(1), I chose to default to processing standard input when no files
Xare specified.  I will change this so that the file "-" refers to
Xstandard input and hence you will have to type something like:
X	ls -Rl | mpage -8 -
XMore thought is required here.  (you comments solicited)
X
X
X- Add support for handeling ATT style spoolers.  Or any type spooler.
XShouldn't be that difficult.
X
X 
X- Support for reducing mpage output.  I.E. if I do:
X		mpage -8P file.txt | mpage -8
XI should get 64-up output.  Problems are that the PostScript code
Xproduced is not "recursive".  The end-of-page macro in particular
Xsuffers under re-definition, you get blank pages.  Another problems is
Xresolution of the printer.  See the next Wish item.
X
X 
X- Better handeling of PostScript input.  The current stuff works, but
Xit is not general enough.  I am currently learning more here, thanks
Xto the "Green Book" and will work on a cleaner parser for Version 3.
X(Oh-my-goodness, a pre-announcement ;-)
X
XPerhaps I should convert the whole PostScript processing routing to be
Xa "Finite Automata".  Each line will represent a "token" parsed by its
Xcomment, output will be based upon transitions from state to state.
XThe automata should allow states and transitions to be added dynamicly
Xso that we can adapt to differening structure conventions, and
Xdiffering PostScript code generators (psdit, dvi2ps, etc ...)
X
X
X- Fix A4 paper handeling.
X
X
X- Add better timing information, possible adding command line
Xarguments to control the amount of timing information added to the
Xfile.  (Eyuk, more arguments:-(
X
X
X- Lots more, I'm sure.

END_OF_FILE
echo shar: NEWLINE appended to \"'TODO'\"
if test 1685 -ne `wc -c <'TODO'`; then
    echo shar: \"'TODO'\" unpacked with wrong size!
fi
# end of 'TODO'
fi
if test -f 'mp_args.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mp_args.c'\"
else
echo shar: Extracting \"'mp_args.c'\" \(5080 characters\)
sed "s/^X//" >'mp_args.c' <<'END_OF_FILE'
X# include <stdio.h>
X# include <sys/types.h>
X
X# ifndef lint
Xstatic char *rcs_id =
X	"@(#) $Header: mp_args.c,v 2.6 89/05/25 15:43:07 mark Exp $";
X# endif
X
X# include "mp_head.h"
X
X/*
X * mpage:	a program to reduce pages of print so that several pages
X * 	  	of output appear on one printed page.
X *
X * Written by:
X *   ...!uunet!\                       Mark Hahn, Sr Systems Engineer
X *              >pyrdc!mark            Pyramid Technology Corporation
X * ...!pyramid!/                       Vienna, Va    (703)848-2050
X *
X *
X * Copyright (c) 1988 Mark P. Hahn, Herndon, Virginia
X *  
X *     Permission is granted to anyone to make or distribute verbatim
X *     copies of this document as received, in any medium, provided
X *     that this copyright notice notice is preserved, and that the
X *     distributor grants the recipient permission for further
X *     redistribution as permitted by this notice.
X *
X */
X
X/* $Log:	mp_args.c,v $
X * Revision 2.6  89/05/25  15:43:07  mark
X * added the -b options as a converse to the -o option.
X * 
X * Revision 2.5  89/05/25  10:42:39  mark
X * changes to print a page count on stderr after the print job is queued.
X * 
X * Revision 2.4  89/05/25  08:57:47  mark
X * rearranged the rcs header keywords for better readability.
X * 
X * Revision 2.3  89/05/22  14:41:03  mark
X * Fixed the type-o in the rcs identification string
X * 
X * Revision 2.2  89/05/22  14:38:06  mark
X * Added rcs identification usable with the "what" program
X * 
X * Revision 2.1  89/05/22  14:31:29  mark
X * New Major Revision
X * 
X * Revision 1.1  89/05/22  14:25:29  mark
X * Initial revision
X *  */
X
Xdo_args(argc, argv, envflag)
X int argc;
X char **argv;
X int envflag;
X{
X	char *optstr;
X	int consumed;
X	int currarg;
X	int opterrors;
X
X	opterrors = 0;
X	for (currarg = 1; currarg < argc; currarg++) {
X		if (*argv[currarg] != '-') {
X			if (envflag) {
X				opterrors++;
X			}
X			break;
X		}
X		optstr = argv[currarg];
X		consumed = 0;
X		while (*++optstr && ! consumed) {
X			switch (*optstr) {
X			default:
X				fprintf(stderr,"%s: unknown option -%c\n",
X				       MPAGE, *optstr);
X				opterrors++;
X				break;
X			case '1':
X				sheetindex = 0;
X				break;
X			case '2':
X				sheetindex = 1;
X				break;
X			case '4':
X				sheetindex = 2;
X				break;
X			case '8':
X				sheetindex = 3;
X				break;
X			case 'A':	/* A4 sized, european paper */
X				opt_a4 = 1;
X				set_page();
X				break;
X			case 'a':	/* across */
X				sheetorder = LEFTRIGHT;
X				break;
X			case 'h':
X				++optstr;
X				opt_doheader = 1;
X				(void)strcpy(opt_header, optstr);
X				consumed = 1;
X				break;
X			case 'L':
X				++optstr;
X				opt_lines = atoi(optstr);
X				consumed = 1;
X				break;
X			case 'l':	/* landscape */
X				sheetaspect = LANDSCAPE;
X				break;
X			case 'n':	/* normal */
X				sheetaspect = NORMAL;
X				break;
X			case 'o':	/* print outlines */
X				opt_outline = 1;
X				break;
X			case 'b':	/* don't print outlines */
X				opt_outline = 0;
X				break;
X			case 'P':	/* Printer */
X				++optstr;
X				(void) strcpy(printer, optstr);
X				consumed = 1;
X				break;
X			case 'p':	/* pr */
X				opt_pr++;
X				break;
X			case 's':	/* silent (don't print page count) */
X				opt_verbose = 0;
X				break;
X			case 'u':	/* updown */
X				sheetorder = UPDOWN;
X				break;
X			case 'v':	/* verbose (print page count) */
X				opt_verbose = 1;
X				break;
X			case 'W':
X				++optstr;
X				opt_width = atoi(optstr);
X				consumed = 1;
X				break;
X			}
X		}
X	}
X	if (opterrors) {
X		return -1;
X	}
X	return currarg;
X}
X
Xdo_env()
X{
X	int argc;
X	char **argv, **slice();
X	char copy[LINESIZE];
X	char *env, *getenv();
X
X	env = getenv("PRINTER");
X	if (env) {
X		strcpy(printer, env);
X	}
X
X	env = getenv("MPAGE");
X	if (env) {
X		strcpy(copy, env);
X		argv = slice(copy, &argc);
X		if (do_args(argc, argv, 1) < 0) {
X			fprintf(stderr, "%s: error in envronment \"%s\"\n",
X				MPAGE, env);
X			return 0;
X		}
X	}
X	return 1;
X}
X
Xchar *slc_argv[20];
X
Xchar **slice(string, cntp)
X char *string;
X int *cntp;
X{
X	int count;
X
X	/*
X	 * mimic the shell for conformity
X	 */
X	slc_argv[0] = MPAGE;
X	count = 1;
X	/*
X	 * while there are still characters to be processed
X	 */
X	while (*string) {
X		/*
X		 * skip any leading or leftover white space
X		 */
X		while (*string == ' ') {
X			string++;
X		}
X		/*
X		 * make sure we had more than just white space before
X		 * we believe we actually have an argument
X		 */
X		if (*string) {
X			/*
X			 * point the next slot in argv to this string
X			 */
X			slc_argv[count] = string;
X			count += 1;
X			/*
X			 * and go looking for the end of this string
X			 * which is delienated by a space or NULL
X			 */
X			while (*string && *string != ' ') {
X				string++;
X			}
X			/*
X			 * if this not the end of the string, then convert
X			 * the space into a NULL and move forward one byte.
X			 * if this is the end of the string, we already have
X			 * a suitable NULL byte for the string and it also
X			 * drops us out of all the loops
X			 */
X			if (*string) {
X				*string = 0;
X				string++;
X			}
X		}
X	}
X	/*
X	 * return the count via the integer pointer we were given
X	 * and put a null pointer into the argv array for conformity
X	 */
X	slc_argv[count] = 0;
X	*cntp = count;
X	return slc_argv;
X}

END_OF_FILE
echo shar: NEWLINE appended to \"'mp_args.c'\"
if test 5081 -ne `wc -c <'mp_args.c'`; then
    echo shar: \"'mp_args.c'\" unpacked with wrong size!
fi
# end of 'mp_args.c'
fi
if test -f 'mp_main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mp_main.c'\"
else
echo shar: Extracting \"'mp_main.c'\" \(4943 characters\)
sed "s/^X//" >'mp_main.c' <<'END_OF_FILE'
X# include <stdio.h>
X# include <sys/types.h>
X
X# ifndef lint
Xstatic char *rcs_id =
X	"@(#) $Header: mp_main.c,v 2.5 89/05/25 10:42:35 mark Exp $";
X# endif
X
X# include "mp_head.h"
X
X/*
X * mpage:	a program to reduce pages of print so that several pages
X * 	  	of output appear on one printed page.
X *
X * Written by:
X *   ...!uunet!\                       Mark Hahn, Sr Systems Engineer
X *              >pyrdc!mark            Pyramid Technology Corporation
X * ...!pyramid!/                       Vienna, Va    (703)848-2050
X *
X *
X * Copyright (c) 1988 Mark P. Hahn, Herndon, Virginia
X *  
X *     Permission is granted to anyone to make or distribute verbatim
X *     copies of this document as received, in any medium, provided
X *     that this copyright notice notice is preserved, and that the
X *     distributor grants the recipient permission for further
X *     redistribution as permitted by this notice.
X *
X */
X
X/* $Log:	mp_main.c,v $
X * Revision 2.5  89/05/25  10:42:35  mark
X * changes to print a page count on stderr after the print job is queued.
X * 
X * Revision 2.4  89/05/25  08:58:25  mark
X * rearranged the rcs header keywords for better readability.
X * 
X * Revision 2.3  89/05/22  14:40:28  mark
X * Fixed the type-o in the rcs identification string
X * 
X * Revision 2.2  89/05/22  14:37:30  mark
X * Added rcs identification usable with the "what" program
X * 
X * Revision 2.1  89/05/22  14:31:15  mark
X * New Major Revision
X * 
X * Revision 1.1  89/05/22  14:19:56  mark
X * Initial revision
X *  */
X
Xmain(argc,argv)
X int argc;
X char **argv;
X{
X	FILE *outfd;
X	int currarg;
X	struct sheet *thelist;
X	struct sheet *thesheet;
X
X	/*
X	 * examine the environment for PRINTER and MPAGE environment variables
X	 */
X	if (do_env() == 0) {
X		fprintf(stderr, usage, MPAGE);
X		exit(1);
X	}
X		
X	currarg = do_args(argc, argv, 0);
X	if (currarg < 0) {
X		fprintf(stderr, usage, MPAGE);
X		exit(1);
X	}
X
X	/*
X	 * if a printer was specified then create a lpr command using
X	 * the specified printer, else output goes to standard out
X	 */
X	if (*printer) {
X		(void)sprintf(outcommand, "ucb /usr/ucb/lpr -P%s", printer);
X		if ((outfd = popen(outcommand, "w")) == NULL) {
X			fprintf(stderr, "%s: cannot create pipe for '%s'\n",
X				outcommand);
X			perror(MPAGE);
X		}
X	} else {
X		outfd = stdout;
X	}
X
X	/*
X	 * pick the array of sheet lists based upon the specified option
X	 */
X	if (sheetorder == UPDOWN) {
X		sheetlist = up_down;
X	} else {
X		sheetlist = left_right;
X	}
X
X	/*
X	 * from the array of sheet lists pick the proper sheet list for
X	 * the given sheetaspect, then select the proper sheet format
X	 * for the given number of redueced pages per output page
X	 */
X	thelist = sheetlist[sheetaspect];
X	thesheet = &(thelist[sheetindex]);
X
X	/*
X	 * if either lines or columns were specified as options, over
X	 * the default sheets idea of the number of line or cloumns
X	 * per reduced page
X	 */
X	if (opt_lines > 0) {
X		thesheet->sh_plength = opt_lines;
X	}
X	if (opt_width > 0) {
X		thesheet->sh_cwidth = opt_width;
X	}
X
X	/*
X	 * if there are arguments left over after processing options, then
X	 * these are names of files to process, else process the standard
X	 * input
X	 */
X	if (currarg < argc) {
X		ps_title(argv[currarg], outfd);
X		for ( ;currarg < argc; currarg++) {
X			do_file(argv[currarg], thesheet, outfd);
X		}
X	} else {
X		ps_title("<stdin>", outfd);
X		do_stdin(thesheet, outfd);
X	}
X	/*
X	 * having processed all input, print out a PS trailer
X	 * (timeing stuff stolen from old adobe troff stuff)
X	 */
X	fprintf(outfd, "%%%%Trailer\n");
X	fprintf(outfd, "statusdict begin jobname print flush");
X	fprintf(outfd, " (: Job finished:\\n) print\n");
X	fprintf(outfd, "(\\tmpage time (s) = ) print flush usertime ");
X	fprintf(outfd, "mp_stm sub 1000 div ==\n(\\tmpage pages = ) print ");
X	fprintf(outfd, "flush pagecount mp_pgc sub ==\nend flush\n");
X	fprintf(outfd, "%%%%Pages: %d\n", ps_pagenum);
X	if (opt_verbose) {
X		fprintf(stderr, "[%s: %d pages, ", MPAGE, ps_pagenum);
X		if (*printer == 0) {
X			fprintf(stderr, "on <stdout>]\n");
X		} else {
X			fprintf(stderr, "printer %s]\n", printer);
X		}
X	}
X	/*
X	 * proper clean up to make sure the pipe is flushed
X	 */
X	if (*printer) {
X		(void)pclose(outfd);
X	}
X	return 0;
X}
X
X/*
X * ps_title prints a post script header suitable for PS processors
X */
Xps_title(name, outfd)
X char *name;
X FILE *outfd;
X{
X	time_t curr_time;
X	char *time_str;
X
X	fprintf(outfd, "%%!PS-Adobe-1.0\n");
X	fprintf(outfd, "%%%%DocumentFonts: Courier\n");
X	fprintf(outfd, "%%%%Title: %s (mpage)\n", name, MPAGE);
X	fprintf(outfd, "%%%%Creator: %s\n", MPAGE);
X	(void)time(&curr_time);
X	time_str = ctime(&curr_time);
X	fprintf(outfd, "%%%%CreationDate: %s",time_str);
X	fprintf(outfd, "%%%%Pages: (atend)\n");
X	fprintf(outfd, "%%%%BoundingBox: 20 20 596 776\n");
X	fprintf(outfd, "%%%%EndComments\n\n");
X	fprintf(outfd, "/mp_stm usertime def\n");
X	fprintf(outfd, "/mp_pgc statusdict begin pagecount end def\n");
X	fprintf(outfd, "statusdict begin /jobname (%s) def end\n", name);
X}

END_OF_FILE
echo shar: NEWLINE appended to \"'mp_main.c'\"
if test 4944 -ne `wc -c <'mp_main.c'`; then
    echo shar: \"'mp_main.c'\" unpacked with wrong size!
fi
# end of 'mp_main.c'
fi
if test -f 'mp_page.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mp_page.c'\"
else
echo shar: Extracting \"'mp_page.c'\" \(5452 characters\)
sed "s/^X//" >'mp_page.c' <<'END_OF_FILE'
X# include <stdio.h>
X# include <sys/types.h>
X
X# ifndef lint
Xstatic char *rcs_id =
X	"@(#) $Header: mp_page.c,v 2.4 89/05/25 08:58:28 mark Exp $";
X# endif
X
X# include "mp_head.h"
X
X/*
X * mpage:	a program to reduce pages of print so that several pages
X * 	  	of output appear on one printed page.
X *
X * Written by:
X *   ...!uunet!\                       Mark Hahn, Sr Systems Engineer
X *              >pyrdc!mark            Pyramid Technology Corporation
X * ...!pyramid!/                       Vienna, Va    (703)848-2050
X *
X *
X * Copyright (c) 1988 Mark P. Hahn, Herndon, Virginia
X *  
X *     Permission is granted to anyone to make or distribute verbatim
X *     copies of this document as received, in any medium, provided
X *     that this copyright notice notice is preserved, and that the
X *     distributor grants the recipient permission for further
X *     redistribution as permitted by this notice.
X *
X */
X
X/* $Log:	mp_page.c,v $
X * Revision 2.4  89/05/25  08:58:28  mark
X * rearranged the rcs header keywords for better readability.
X * 
X * Revision 2.3  89/05/22  14:41:01  mark
X * Fixed the type-o in the rcs identification string
X * 
X * Revision 2.2  89/05/22  14:38:04  mark
X * Added rcs identification usable with the "what" program
X * 
X * Revision 2.1  89/05/22  14:31:27  mark
X * New Major Revision
X * 
X * Revision 1.1  89/05/22  14:25:52  mark
X * Initial revision
X *  */
X
Xset_page()
X{
X	if (opt_a4) {
X		ps_width = 596;
X		ps_height = 842;
X	} else {
X		ps_width = 612;
X		ps_height = 792;
X	}
X}
X
Xxbase1()
X{
X	Debug(DB_POINTS, "%%xbase1: %d\n", pg_sheetmargin + pg_pagemargin);
X	return pg_sheetmargin + pg_pagemargin;
X}
X
Xxbase2()
X{
X	Debug(DB_POINTS, "%%xbase2: %d\n",  (ps_width / 2) + pg_pagemargin);
X	return (ps_width / 2) + pg_pagemargin;
X}
X
Xybase1()
X{
X	Debug(DB_POINTS, "%%ybase1: %d\n", pg_sheetmargin + pg_pagemargin);
X	return pg_sheetmargin + pg_pagemargin;
X}
X
Xybase2()
X{
X	Debug(DB_POINTS, "%%ybase2: %d\n",
X	      (((ps_height / 2) - pg_sheetmargin) / 2)
X	      + pg_sheetmargin + pg_pagemargin);
X	return (((ps_height / 2) - pg_sheetmargin) / 2)
X	  + pg_sheetmargin + pg_pagemargin;
X}
X
Xybase3()
X{
X	Debug(DB_POINTS, "%%ybase3: %d\n", (ps_height / 2) + pg_pagemargin);
X	return (ps_height / 2) + pg_pagemargin;
X}
X
Xybase4()
X{
X	Debug(DB_POINTS, "%%ybase4: %d\n",
X	      (((ps_height / 2) - pg_sheetmargin) / 2)
X	      + (ps_height / 2) + pg_pagemargin);
X	return (((ps_height / 2) - pg_sheetmargin) / 2)
X	  + (ps_height / 2) + pg_pagemargin;
X}
X
Xytop1()
X{
X	Debug(DB_POINTS, "%%ytop1: %d\n", ybase1() + yht4());
X	return ybase1() + yht4();
X}
X
Xytop2()
X{
X	Debug(DB_POINTS, "%%ytop2: %d\n", ybase2() + yht4());
X	return ybase2() + yht4();
X}
X
Xytop3()
X{
X	Debug(DB_POINTS, "%%ytop3: %d\n", ybase3() + yht4());
X	return ybase3() + yht4();
X}
X
Xytop4()
X{
X	Debug(DB_POINTS, "%%ytop4: %d\n", ybase4() + yht4());
X	return ybase4() + yht4();
X}
X
Xxwid1()
X{
X	Debug(DB_POINTS, "%%xwid1: %d\n",
X	      ps_width - ((2 * pg_sheetmargin) + (2 * pg_pagemargin)));
X	return ps_width - ((2 * pg_sheetmargin) + (2 * pg_pagemargin));
X}
X
Xxwid2()
X{
X	Debug(DB_POINTS, "%%xwid2: %d\n",
X	      (ps_width / 2) - (pg_sheetmargin + (2 * pg_pagemargin)));
X	return (ps_width / 2) - (pg_sheetmargin + (2 * pg_pagemargin));
X}
X
Xyht1()
X{
X	Debug(DB_POINTS, "%%yht1: %d\n",
X	      ps_height - ((2 * pg_sheetmargin) + (2 * pg_pagemargin)));
X	return ps_height - ((2 * pg_sheetmargin) + (2 * pg_pagemargin));
X}
X
Xyht2()
X{
X	Debug(DB_POINTS, "%%yht2: %d\n",
X	      (ps_height / 2) - (pg_sheetmargin + (2 * pg_pagemargin)));
X	return (ps_height / 2) - (pg_sheetmargin + (2 * pg_pagemargin));
X}
X
Xyht4()
X{
X	Debug(DB_POINTS, "%%yht4: %d\n",
X	      (((ps_height / 2) - pg_sheetmargin) / 2) - (2 * pg_pagemargin));
X	return (((ps_height / 2) - pg_sheetmargin) / 2) - (2 * pg_pagemargin);
X}
X
Xoutline_1(outfd)
X FILE *outfd;
X{
X	/* one page outline */
X	fprintf(outfd, "0 setlinewidth\n");
X        fprintf(outfd, "%3d %3d moveto\n", pg_sheetmargin, pg_sheetmargin);
X	fprintf(outfd, "%3d %3d lineto\n", pg_sheetmargin,
X		ps_height - pg_sheetmargin);
X	fprintf(outfd, "%3d %3d lineto\n", ps_width - pg_sheetmargin,
X		ps_height - pg_sheetmargin);
X	fprintf(outfd, "%3d %3d lineto\n", ps_width - pg_sheetmargin,
X		pg_sheetmargin);
X	fprintf(outfd, "closepath stroke\n");
X}
X
Xoutline_2(outfd)
X FILE *outfd;
X{
X	/* two page outline */
X	outline_1(outfd);
X	fprintf(outfd, "%3d %3d moveto\n", pg_sheetmargin, ps_height / 2);
X	fprintf(outfd, "%3d %3d lineto\n",  ps_width - pg_sheetmargin,
X		ps_height / 2);
X	fprintf(outfd, "stroke\n");
X}
X
Xoutline_4(outfd)
X FILE *outfd;
X{
X	/* four page outline */
X	outline_2(outfd);
X	fprintf(outfd, "%3d %3d moveto\n", ps_width / 2 , pg_sheetmargin);
X	fprintf(outfd, "%3d %3d lineto\n", ps_width / 2 ,
X		ps_height - pg_sheetmargin);
X	fprintf(outfd, "stroke\n");
X}
X
Xoutline_8(outfd)
X FILE *outfd;
X{
X	/* eight page outline */
X	outline_4(outfd);
X	fprintf(outfd, "%3d %3d moveto\n", pg_sheetmargin,
X		((ps_height / 2) - pg_sheetmargin) / 2 + pg_sheetmargin);
X	fprintf(outfd, "%3d %3d lineto\n", ps_width - pg_sheetmargin,
X		((ps_height / 2) - pg_sheetmargin) / 2 + pg_sheetmargin);
X	fprintf(outfd, "stroke\n");
X	fprintf(outfd, "%3d %3d moveto\n", pg_sheetmargin,
X		((ps_height / 2) - pg_sheetmargin) / 2 + (ps_height / 2));
X	fprintf(outfd, "%3d %3d lineto\n", ps_width - pg_sheetmargin,
X		((ps_height / 2) - pg_sheetmargin) / 2 + (ps_height / 2));
X	fprintf(outfd, "stroke\n");
X}
X
Xmp_outline(outfd, asheet)
X FILE *outfd;
X struct sheet *asheet;
X{
X	if (opt_outline) {
X		(*asheet->sh_outline)(outfd);
X	}
X}

END_OF_FILE
echo shar: NEWLINE appended to \"'mp_page.c'\"
if test 5453 -ne `wc -c <'mp_page.c'`; then
    echo shar: \"'mp_page.c'\" unpacked with wrong size!
fi
# end of 'mp_page.c'
fi
if test -f 'mp_sample.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mp_sample.c'\"
else
echo shar: Extracting \"'mp_sample.c'\" \(2579 characters\)
sed "s/^X//" >'mp_sample.c' <<'END_OF_FILE'
X# include <stdio.h>
X# include <sys/types.h>
X
X# ifndef lint
Xstatic char *rcs_id =
X  "@(#) $Header: mp_sample.c,v 1.1 89/05/25 08:58:34 mark Exp $";
X# endif
X
X# include "mp_head.h"
X
X/* $Log:	mp_sample.c,v $
X * Revision 1.1  89/05/25  08:58:34  mark
X * Initial revision
X *  */
X
Xmain( argc, argv)
X int argc;
X char **argv;
X{
X	int currarg;
X
X	/*
X	 * examine the environment for PRINTER and MPAGE environment variables
X	 */
X	if (do_env() == 0) {
X		fprintf(stderr, usage, MPAGE);
X		exit(1);
X	}
X		
X	currarg = do_args(argc, argv, 0);
X	if (currarg < 0) {
X		fprintf(stderr, usage, MPAGE);
X		exit(1);
X	}
X
X	do_sample();
X}
X
Xdo_sample()
X{
X	printf("%%!PS-mpage-layout\n");
X	printf("/Courier findfont 8 scalefont setfont\n");
X	printf("0 setlinewidth\n");
X
X	outline_8(stdout);
X
X	urshow(xbase1(), ybase1());
X	urshow(xbase1(), ybase2());
X	urshow(xbase1(), ybase3());
X	urshow(xbase1(), ybase4());
X	lrshow(xbase1(), ytop1());
X	lrshow(xbase1(), ytop2());
X	lrshow(xbase1(), ytop3());
X	lrshow(xbase1(), ytop4());
X	ulshow(xbase1()+xwid2(), ybase1());
X	ulshow(xbase1()+xwid2(), ybase2());
X	ulshow(xbase1()+xwid2(), ybase3());
X	ulshow(xbase1()+xwid2(), ybase4());
X	llshow(xbase1()+xwid2(), ytop1());
X	llshow(xbase1()+xwid2(), ytop2());
X	llshow(xbase1()+xwid2(), ytop3());
X	llshow(xbase1()+xwid2(), ytop4());
X
X	urshow(xbase2(), ybase1());
X	urshow(xbase2(), ybase2());
X	urshow(xbase2(), ybase3());
X	urshow(xbase2(), ybase4());
X	lrshow(xbase2(), ytop1());
X	lrshow(xbase2(), ytop2());
X	lrshow(xbase2(), ytop3());
X	lrshow(xbase2(), ytop4());
X	ulshow(xbase2()+xwid2(), ybase1());
X	ulshow(xbase2()+xwid2(), ybase2());
X	ulshow(xbase2()+xwid2(), ybase3());
X	ulshow(xbase2()+xwid2(), ybase4());
X	llshow(xbase2()+xwid2(), ytop1());
X	llshow(xbase2()+xwid2(), ytop2());
X	llshow(xbase2()+xwid2(), ytop3());
X	llshow(xbase2()+xwid2(), ytop4());
X	printf("showpage\n");
X}
X
Xurshow(x, y)
X{
X	printf("%%- point %d,%d\n", x, y);
X	box(x, y);
X	printf("\t%d %d moveto (%d,%d) show\n", x+2, y+2, x, y);
X}
X
Xlrshow(x, y)
X{
X	printf("%%- point %d,%d\n", x, y);
X	box(x, y);
X	printf("\t%d %d moveto (%d,%d) show\n", x+2, y-6, x, y);
X}
X
Xulshow(x, y)
X{
X	printf("%%- point %d,%d\n", x, y);
X	box(x, y);
X	printf("\t%d %d moveto\n", x-2, y+2);
X	printf("\t(%d,%d) dup stringwidth pop -1 mul 0 rmoveto show\n", x, y);
X}
X
Xllshow(x, y)
X{
X	printf("%%- point %d,%d\n", x, y);
X	box(x, y);
X	printf("\t%d %d moveto\n", x-2, y-6);
X	printf("\t(%d,%d) dup stringwidth pop -1 mul 0 rmoveto show\n", x, y);
X}
X
Xbox(x, y)
X{
X	printf("\t%d %d moveto %d %d lineto\n", x-1, y, x+1, y);
X	printf("\t%d %d moveto %d %d lineto\n", x, y-1, x, y+1);
X	printf("\tstroke\n");
X}

END_OF_FILE
echo shar: NEWLINE appended to \"'mp_sample.c'\"
if test 2580 -ne `wc -c <'mp_sample.c'`; then
    echo shar: \"'mp_sample.c'\" unpacked with wrong size!
fi
# end of 'mp_sample.c'
fi
if test -f 'mpage.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mpage.1'\"
else
echo shar: Extracting \"'mpage.1'\" \(3717 characters\)
sed "s/^X//" >'mpage.1' <<'END_OF_FILE'
X.TH MPAGE Local 1/13/87
X.SH NAME
Xmpage \- print muliple pages per sheet on POSTSCRIPT printer
X.SH SYNOPSIS
X\fBmpage [-1248povsnluaA] [-Llines] [-Wwidth] [-hheader] [-Pprinter]
X[files...]\fR
X.SH DESCRIPTION
X.I Mpage
Xreads plain text files or POSTSCRIPT documents and prints them on a
XPOSTSCRIPT printer with the text reduced in size so that several
Xpages apperar on one sheet of paper.  This is useful for
Xviewing large printouts on a small amount of paper.
X.PP
XThe following options are recognized:
X.TP
X.B -8
XPrint 8 normal pages per sheet.
X.TP
X.B -4
XPrint 4 normal pages per sheet
X.I [default].
X.TP
X.B -2
XPrint 2 normal pages per sheet.
X.TP
X.B -1
XPrint 1 normal page per sheet (included for symmetry).
X.TP
X.B -p
XPipe input through
X.BR pr ( 1 )
Xbefore printing (assumes the input is a text file).
X.TP
X.B -o
XPrint an outline around each reduced page.
X.I [default].
X.TP
X.B -b
XDon't print an outline, so the reduced pages appear on a blank
Xbackground.
X.TP
X.B -v
XPrint to the standard error output a count of the number of sheets
Xproduced for printing (verbose mode)
X.I [default].
X.TP
X.B -s
XDon't print the count of sheets (silent mode).
X.TP
X.B -n
XPrint in normal (portrait) mode.  The page is 66 lines long by 80
Xcharacters wide by default
X.I [default].
X.TP
X.B -l
XPrint in landscape mode.  The page is 55 lines long by 132
Xcharacters wide by default.
X.TP
X.B -u
XLayout the pages on the sheet so that sucessively numbered pages run
Xdown the sheet (as opposed to left to right)
X.I [default].
X.TP
X.B -a
XLayout the pages on the sheet so that sucessively numbered pages run
Xaccross the page from left to right.
X.TP
X.B -A
XPrepare output for European A4 sized paper.
X.TP
X.BI -P printer
XSpecify the printer to which the POSTSCRIPT output will be sent.
XUsing
X.B -P
Xwith no printer specified will send the POSTSCRIPT to the standard
Xoutput.
X.I [default:
X.BI PostScript\c
X.I ].
X.TP
X.BI -L lines
XAdjust the page reduction parameters so that
X.I lines
Xlines will fit in the space of one page.
XThis overides the default values normally supplied.  (See the
X.B -l
Xand
X.B -n
Xoptions.)
XIf used in conjunction with the
X.B -p
Xoption then this value is passed to pr as well.
X.TP
X.BI -W width
XAdjust the page reduction parameters so that a line
X.I width
Xcharacters long will fit in the space of one page.
XThis overides the default values normally supplied.  (See the
X.B -l
Xand
X.B -n
Xoptions.)
XIf used in conjunction with the
X.B -p
Xoption then this value is passed to pr as well.
X.TP
X.BI -h header
XThis is used only when the 
X.B -p
Xswitch is used and is passed as the "\fB-h\fI\ header\fR" option to
X.BR pr ( 1 ).
X.PP
XThe defaults are: mpage -4onuPPostScript.
X.SH ENVIRONMENT
X.I Mpage
Xexamines the
X.B PRINTER
Xenvironment variable to override its default printer.
X.PP
X.ne 10
X.I Mpage
Xalso examine the
X.B MPAGE
Xenvironment variable for default option settings.  Any option or
Xcombination of options can be specified in the
X.B MPAGE
Xenvironment variable.  For example, if MPAGE is set to the string:
X.in +1i
X.B -2oPqms -L60
X.br
X.in -1i
Xit would (in the absence of other command line arguments) print 2
Xpages per sheet, 60 lines per page, with outlines, on the printer
Xnamed
X.B "qms"
X(overriding the
X.B PRINTER
Xenvironment variable, if it exists.)  In the environment variable,
Xwhite space is used as an option delimeter, and no quoting is
Xrecognized.
X.PP
XAny command line options will override both the
X.B PRINTER
Xand 
X.B MPAGE
Xenvironment variables.
X.SH FILES
X/bin/pr	/bin/fold
X.br
X/usr/tmp/mpageXXXXXX
X.SH BUGS
X.PP
XSuffers under the burden of far too many switches.  (But
X.B I
Xwanted the choices!) 
X.PP
XMany others, I'm sure.
X.SH VERSION
XVersion 2, Released June 1989.
X.SH AUTHORS
XMark P. Hahn (uunet!pyrdc!mark), Pyramid Technology Corportation

END_OF_FILE
echo shar: NEWLINE appended to \"'mpage.1'\"
if test 3718 -ne `wc -c <'mpage.1'`; then
    echo shar: \"'mpage.1'\" unpacked with wrong size!
fi
# end of 'mpage.1'
fi
echo shar: End of archive 2 \(of 2\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

-- 
  ...!uunet!\                       Mark Hahn, Sr Systems Engineer
             >pyrdc!mark            Pyramid Technology Corporation
...!pyramid!/                       Vienna, Va    (703)848-2050