[comp.lang.postscript] ASCII to PostScript COnvertor

root@alice.marlow.reuters.co.uk (Operator) (02/23/88)

Well, heres my version of an ASCII to PostScript translator.
It understands underline (either x <backspace> _, _ <backspace> x, or
x <CR> _), bold (ditto).

It understands a little about EPSON printer output, so if it sees
an ESCAPE followed by the # defines in the listing, it will even
do italic !!.

Also, by using the '-d' switch, you can get DRAFT sprawled across
each page.

You may have to watch the backslashed newlines in the shar, which will 
probably cause 'sh' to throw up.


     //        o      All opinions are my own.
   (O)        ( )     The powers that be ...
  /    \_____( )
 o  \         |
    /\____\__/      
  _/_/   _/_/         UUCP:     fox@alice.marlow.reuters.co.uk
#--------------------------------CUT HERE-------------------------------------
#! /bin/sh
#
# This is a shell archive.  Save this into a file, edit it
# and delete all lines above this comment.  Then give this
# file to sh by executing the command "sh file".  The files
# will be extracted into the current directory owned by
# you with default permissions.
#
# The files contained herein are:
#
# \c
-r--r--r--  1 root        10775 Feb 22 13:20 pscript.c
#
echo 'x - pscript.c'
if test -f pscript.c; then echo 'shar: not overwriting pscript.c'; else
sed 's/^X//' << '________This_Is_The_END________' > pscript.c
X# include	<stdio.h>
X# include	<string.h>
X
X# ifdef	lint
X# define	SCCSID(x)
X# else
X# define	SCCSID(x)	static char sccsid[] = x;
X# endif
X
X# ifndef TRUE
X# define	TRUE	1
X# define	FALSE	0
X# endif
X
X# ifndef	NULL
X# define	NULL	0
X# endif
X
X# ifndef	NIL
X# define	NIL		NULL
X# endif
X
X# ifndef	BOOL
X# define	BOOL	int
X# endif
X
X# define	ever (;;)
X# define	COL_WIDTH	11200	/* Max. column width. */
X
X# define	BS	0x08
X# define	ESC	0x1b
X# define	CTRL_Z	0x1a
X# define	BON	'G'
X# define	BON1	'E'
X# define	BON2	'8'
X# define	BOFF	'H'
X# define	BOFF1	'F'
X# define	BOFF2	'9'
X# define	ION	'4'
X# define	IOFF	'5'
X
Xchar	*version = "1.16";
X# define	BSIZE	4096
Xchar	lbuf[BSIZE];
Xunsigned char attr[BSIZE];
XFILE	*fp;
X
X/*-------------------------------------
X *   The following is used to print the
X *   draft string across each page.
X *-------------------------------------*/
Xchar	*draft_string = 
X"/Times-Bold findfont 180 scalefont setfont \
X215 215 moveto \
X56 rotate \
X.97 setgray \
X(Draft) show \
X0 0 moveto \
X-56 rotate \
X0 setgray \n";
X
X# define	A_UNDERLINE	0x01
X# define	A_BOLD		0x02
X# define	A_ITALIC	0x04
X
Xlong	x = 1680;
Xlong	y = 1200;
X
X
Xint	line_count;
Xint	page_size = 66;
Xint	font_size = 10;
Xint	font = 0;
Xint	tfont_size = 10;
Xint	tfont = 0;
Xlong	num_lines_in_file;
Xint	num_pages;
Xint	page_no = 1;
Xint	col_count;		/* Current column.	*/
Xint	num_cols = 1;		/* Number of columns.	*/
Xint	col_width = COL_WIDTH;
XBOOL	do_header = FALSE;
Xchar	*file_name;
Xint	draft_flag = FALSE;	/* TRUE if we want DRAFT across each page.*/
Xint	p_flag = FALSE;
X
Xstruct font_table {
X	char	*name;
X	int	value;
X	} font_table[] = {
X			"courier", 0,
X			"times-roman", 24,
X			"roman",	24,
X			"helvetica",	8,
X			"symbol",	56,
X			NULL
X			};
X
X
Xmain(argc, argv)
Xchar	**argv;
X{	register char *cp;
X	int	arg_index;
X
X	if (argc < 1)
X		usage();
X
X	arg_index = do_switches(argc, argv);
X
X	if (arg_index >= argc) {
X		file_name = "<stdin>";
X		fp = stdin;
X		}
X	else if ((fp = fopen(file_name = argv[arg_index], "rb")) == NULL) {
X		perror(argv[arg_index]);
X		exit(1);
X		}
X
X	if (p_flag) {
X		copy_postscript();
X		exit(0);
X		}
X	if (do_header) {
X		num_pages = 0;
X		while (!feof(fp)) {
X			get_line();
X			if (++num_lines_in_file >= page_size || lbuf[0] == '\f') {
X				num_pages++;
X				num_lines_in_file = 0;
X				}
X			}
X		if (num_lines_in_file)
X			num_pages++;
X		rewind(fp);
X		num_pages /= num_cols;
X		}
X
X	printf("%%!Pscript file version 1.16 (C) P. Fox 2/19/88\nPSp 16839 SFL\n");
X	if (draft_flag)
X		printf("%s", draft_string);
X	line_count = 0;
X	col_count = 0;
X	while (!feof(fp)) {
X		int ch = get_line();
X		if (++line_count > page_size) {
X			line_count = 1;
X			if (++col_count >= num_cols) {
X				col_count = 0;
X				printf("PE\n");
X				if (draft_flag)
X					printf("%s", draft_string);
X				}
X			x = 1680;
X			}
X		if (ch == '\f')
X			line_count = 9999;
X		if (line_count == 1 && col_count == 0)
X			do_top_line();
X		printf("%ld %ld P 8308 SLL %d %d F ", 
X			y + (col_count * col_width), x, font, font_size);
X		print_line(lbuf);
X		x += 240;
X		}
X	printf("PE PSe\n\004");
X	exit(0);
X}
Xcopy_postscript()
X{	register char *cp;
X
X	if (draft_flag)
X		printf("%s", draft_string);
X	while (!feof(fp)) {
X		if (fgets(lbuf, sizeof lbuf - 1, fp) == NULL)
X			break;
X		for (cp = lbuf; *cp; cp++) {
X			if (*cp == '\\') {
X				printf("\\%c", cp[1]);
X				cp++;
X				continue;
X				}
X			if (*cp == '(')
X				putchar('\n');
X			putchar(*cp);
X			}
X		if (lbuf[0] == 'P' && lbuf[1] == 'E' &&
X		    (lbuf[2] == '\n' || lbuf[2] == NULL || lbuf[2] == ' '))
X			if (draft_flag)
X				printf("%s", draft_string);
X		}
X}
Xprint_line(str)
Xchar	*str;
X{	char *detab();
X	char *cp = detab(str);
X	unsigned char *ap = attr;
X	unsigned char last_attr = 0;
X	BOOL	in_bracket = FALSE;
X	int	col = 0;
X	int	width = 20;
X# define	MAX_WIDTH 	60
X	if (*cp == NULL || *cp == '\n') {
X		putchar('\n');
X		return;
X		}
X
X	set_up_attributes(cp);
X
X	while (*cp) {
X		unsigned char x = *ap ^ last_attr;
X
X		if (x && in_bracket) {
X			printf(") S ");
X			in_bracket = FALSE;
X			width += 3;
X			}
X
X		if (x & A_BOLD) {
X			printf("%s ", *ap & A_BOLD ? "B" : "E");
X			width += 2;
X			}
X		if (x & A_UNDERLINE) {
X			printf("%s ", *ap & A_UNDERLINE ? "LU" : "LE");
X			width += 3;
X			}
X		if (x & A_ITALIC) {
X			printf("%s ", *ap & A_ITALIC ? "I" : "E");
X			width += 2;
X			}
X		last_attr = *ap++;
X
X		if (!in_bracket) {
X			putchar('(');
X			in_bracket= TRUE;
X			width++;
X			}
X		switch (*cp) {
X			case '\r': case '\n':
X				break;
X			case '(': case ')': case '\\':
X				putchar('\\');
X				width++;
X			default:
X				putchar(*cp);
X			}
X		cp++;
X		col++;
X		if (++width >= MAX_WIDTH) {
X			printf(") S ");
X			if (last_attr & A_BOLD) printf("E ");
X			if (last_attr & A_UNDERLINE) printf("LE ");
X			if (last_attr & A_ITALIC) printf("E ");
X			putchar('\n');
X			if (last_attr & A_BOLD) printf("B ");
X			if (last_attr & A_UNDERLINE) printf("LU ");
X			if (last_attr & A_ITALIC) printf("I ");
X			putchar('(');
X			width = 1;
X			}
X		}
X	printf(") S ");
X	if (last_attr & A_BOLD)
X		printf("E ");
X	if (last_attr & A_UNDERLINE)
X		printf("LE ");
X	printf("\n");
X}
Xdo_switches(argc, argv)
Xchar	**argv;
X
X{	char	*cp;
X	int	i;
X	BOOL	title = FALSE;
X
X	for (i = 1; i < argc; i++) {
X		if (argv[i][0] != '-')
X			return i;
X		for (cp = argv[i]+1; *cp; cp++) {
X			title = FALSE;
X			switch (*cp) {
X			case '2':	num_cols = 2;
X					col_width = COL_WIDTH / 2;
X					break;
X			case 'd':
X					draft_flag = TRUE;
X					break;
X			case 'f':
X					decode_font_name(title, cp+1);
X					cp = " ";
X					break;
X			case 'h':	do_header = TRUE;
X					break;
X			case 'i':	sscanf(cp+1, "%ld", &y);
X					cp = " ";
X					break;
X			case 'n':	do_header = FALSE;
X					break;
X			case 'l':	sscanf(cp+1, "%d", &page_size);
X					cp = " ";
X					break;
X			case 'p':	p_flag = TRUE;
X					break;
X			case 's':	sscanf(cp+1, "%d", title ?
X							&tfont_size : &font_size);
X					cp = " ";
X					break;
X			case 't':	title = TRUE;
X					break;
X			default:
X				usage();
X			}
X			}
X		}
X	return i;
X}
Xusage()
X{
X	fprintf(stderr, "pscript version %s\n\n", version);
X	fprintf(stderr, "Convert text file to PostScript file for APPLE\n");
X	fprintf(stderr, "Laser printer.\n\n");
X	fprintf(stderr, "Usage: pscript [-ln] [-ffont] [-sn] [file]\n\n");
X	fprintf(stderr, "	-2	Two column output.\n");
X	fprintf(stderr, "	-d	Print DRAFT across each page.\n");
X	fprintf(stderr, "	-ffont Print using font 'font':\n");
X	fprintf(stderr, "		courier  (default)\n");
X	fprintf(stderr, "		roman or times-roman\n");
X	fprintf(stderr, "		symbol\n");
X	fprintf(stderr, "		helvetica\n");
X	fprintf(stderr, "	-h	Print header.\n");
X	fprintf(stderr, "	-in	Set indent to n (default 1200)\n");
X	fprintf(stderr, "	-n	Dont print header.\n");
X	fprintf(stderr, "	-ln	Set page size to n lines (default %d)\n",
X			page_size);
X	fprintf(stderr, "	-p	File is already in Postscript.\n");
X	fprintf(stderr,	"		(Used with -d to put DRAFT across\n");
X	fprintf(stderr, "	a postscript document.)\n");
X	fprintf(stderr, "	-sn	Set font size to n (default 12)\n");
X	fprintf(stderr, "	-tffont	Set title font name.\n");
X	fprintf(stderr, "	-tsn	Set title font size.\n");
X	
X	exit(1);
X}
Xchar *
Xdetab(str)
Xchar	*str;
X{
X	static char	buf[BSIZE];
X	register char * cp = buf;
X	int	col = 0;
X
X	while (*str) {
X		if (*str++ == '\t') {
X			*cp++ = ' ';
X			col++;
X			while (col & 7) {
X				*cp++ = ' ';
X				col++;
X				}
X			}
X		else {
X			*cp++ = str[-1];
X			col++;
X			}
X		}
X	*cp = NULL;
X	return buf;
X}
Xset_up_attributes(str)
Xregister char *str;
X{	char	*strchr();
X	char	*line1 = strchr(str, '\r');
X	unsigned char *ap = attr;
X	int i = strlen(str);
X	register char	*cp = str;
X	int	nbytes;
X	static char static_attr = 0;
X
X	/*-------------------------------------------*
X	 * Clear out the attribute array.            *
X	 *-------------------------------------------*/
X	while (i-- > 0)
X		*ap++ = 0;
X
X	/*-------------------------------------------*
X	 * Process bold and underline when they are  *
X	 * done by overstriking.                     *
X	 *-------------------------------------------*/
X	if (line1) {
X		*line1++ = NULL;
X		for (ap = attr; *line1; ap++, cp++, line1++) {
X			if (*line1 == '_')
X				*ap |= A_UNDERLINE;
X			else if (*cp == '_') {
X				*ap |= A_UNDERLINE;
X				*cp = *line1;
X				}
X			else if (*line1 == *cp)
X				*ap |= A_BOLD;
X			}
X		}
X	/*-------------------------------------------*
X	 * Process bold and underline when they are  *
X	 * done by backspacing.                      *
X	 *-------------------------------------------*/
X	nbytes = strlen(cp = str);
X	for (ap = attr; *cp; ) {
X		if (*cp != BS) {
X			cp++, ap++, nbytes--;
X			continue;
X			}
X		ap--;
X		if (cp[1] == '_') {
X			*ap |= A_UNDERLINE;
X			}
X		else if (cp[-1] == '_') {
X			cp[-1] = cp[1];
X			*ap |= A_UNDERLINE;
X			}
X		else if (cp[1] == cp[-1])
X			*ap |= A_BOLD;
X		strcpy(cp, cp+2);
X		nbytes -= 2;
X		memcpy(ap+1, ap+3, nbytes);
X		ap++;
X		}
X
X	nbytes = strlen(str);
X	for (ap = attr, cp = str; *cp; nbytes--) {
X		if (*cp != ESC) {
X			*ap++ |= static_attr;
X			cp++;
X			continue;
X			}
X		if (cp[1] == BON || cp[1] == BON1 || cp[1] == BON2)
X			static_attr |= A_BOLD;
X		else if (cp[1] == BOFF || cp[1] == BOFF1 || cp[1] == BOFF2)
X			static_attr &= ~A_BOLD;
X		else if (cp[1] == ION)
X			static_attr |= A_ITALIC;
X		else if (cp[1] == IOFF)
X			static_attr &= ~A_ITALIC;
X		else {
X			*ap++ |= static_attr;
X			cp++;
X			continue;
X			}
X		strcpy(cp, cp+2);
X		memcpy(ap, ap+2, nbytes);
X		nbytes--;
X		}
X	
X}
Xdecode_font_name(title, str)
Xchar *str;
X{	struct font_table *fp = font_table;
X	char	*cp;
X
X	for (cp = str; *cp; cp++)
X		if (*cp >= 'a')
X			cp -= 0x20;
X	while (fp->name) {
X		if (strncmp(str, fp->name, strlen(str)) == 0) {
X			if (title)
X				tfont = fp->value;
X			else
X				font = fp->value;
X			return ;
X			}
X		fp++;
X		}
X	usage();
X}
Xget_line()
X{
X	register char *cp;
X	int	 ch;
X
X	for (cp = lbuf; !feof(fp); ) {
X		if ((ch = getc(fp)) == EOF || ch == '\n' || ch == '\f')
X			break;
X		if (ch == CTRL_Z)
X			continue;
X		*cp++ = ch;
X		}
X	if (cp > lbuf && cp[-1] == '\r')
X		cp--;
X	*cp = NULL;
X	return ch;
X}
Xdo_top_line()
X{
X	char	*cp = file_name;
X	char	buf[80];
X	int	i;
X	char	*date();
X
X	if (do_header == FALSE)
X		return;
X	printf("1000 800 P 8308 SLL %d %d F B ", tfont, tfont_size);
X	for (i = 0; i < sizeof buf; )
X		buf[i++] = ' ';
X	buf[79] = NULL;
X	buf[0] = 'F'; buf[1] = 'i'; buf[2] = 'l'; buf[3] = 'e'; buf[4] = ':';
X	strcpy(buf+6, cp);
X	buf[strlen(buf)] = ' ';
X	strcpy(buf+23, date());
X	buf[strlen(buf)] = ' ';
X	sprintf(buf+54, "Page %d of %d", page_no++, num_pages);
X	printf("(%s) S E\n", buf);
X}
X# include	<time.h>
Xchar	*days[] = {
X	"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
X	"Saturday"};
Xchar	*months[] = {
X	"January", "February", "March", "April", "May", "June", 
X	"July", "August", "September", "October", "November", "December"
X	};
Xchar *
Xdate()
X{
X	char	buf[64];
X	struct tm *tp;
X	long	l = time((long *) 0);
X
X	tp = localtime(&l);
X	sprintf(buf, "%s, %d %s %d", days[tp->tm_wday], tp->tm_mday, 
X		months[tp->tm_mon], 1900+tp->tm_year);
X	return buf;
X}
X
________This_Is_The_END________
if test `wc -l < pscript.c` -ne 530; then
	echo 'shar: pscript.c was damaged during transit (should have been 530 bytes)'
fi
fi		; : end of overwriting check
exit 0

fox@alice.marlow.reuters.co.uk (Paul Fox) (02/23/88)

The ASCII to postscript translator I sent out needs as a requisite
a file we call 'APPLASER.INI' dowloaded to the printer
first. This file we got from Microsoft Word. It defines
the macros (such as PS etc) which pscript needs to run with.

I have not posted it, since it may be copyright Apple. Does
anyone know the status of this ? 

There is a copy of this file in the Postscript cookbook. I'm not
sure which chapter its in. Anyone else know ?